summaryrefslogtreecommitdiffhomepage
path: root/test/scenario_test/bgp_router_test.py
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-07-02 15:29:05 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-07-03 06:29:07 +0900
commit34c88c4771a5dd4fb687fe225cebfc6fc99381f0 (patch)
treeb6144f582473b2aea9127cbbcb113d1b16b57a77 /test/scenario_test/bgp_router_test.py
parent64f5846bc6e1a12b0a9bf3fb8d56d33ebe46b811 (diff)
test: introduce modular test library
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'test/scenario_test/bgp_router_test.py')
-rw-r--r--test/scenario_test/bgp_router_test.py453
1 files changed, 202 insertions, 251 deletions
diff --git a/test/scenario_test/bgp_router_test.py b/test/scenario_test/bgp_router_test.py
index f965d224..a424d625 100644
--- a/test/scenario_test/bgp_router_test.py
+++ b/test/scenario_test/bgp_router_test.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,273 +13,224 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import time
+import unittest
+from fabric.api import local
+from lib.gobgp import *
+from lib.quagga import *
import sys
+import os
+import time
import nose
-import quagga_access as qaccess
-import docker_control as fab
-from gobgp_test import GoBGPTestBase
-from gobgp_test import ADJ_RIB_OUT, GLOBAL_RIB
-from gobgp_test import NEIGHBOR
-from noseplugin import OptionParser
-from noseplugin import parser_option
-
-class GoBGPTest(GoBGPTestBase):
- quagga_num = 3
- append_quagga = 10
- remove_quagga = 10
- append_quagga_best = 20
-
- def __init__(self, *args, **kwargs):
- super(GoBGPTest, self).__init__(*args, **kwargs)
+from noseplugin import OptionParser, parser_option
+
+
+class GoBGPTestBase(unittest.TestCase):
+
+ wait_per_retry = 5
+ retry_limit = 15
+
+ @classmethod
+ def setUpClass(cls):
+ gobgp_ctn_image_name = 'osrg/gobgp'
+ if parser_option.use_local:
+ make_gobgp_ctn()
+ gobgp_ctn_image_name = 'gobgp'
+
+ g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1',
+ ctn_image_name=gobgp_ctn_image_name,
+ log_level=parser_option.gobgp_log_level)
+ q1 = QuaggaBGPContainer(name='q1', asn=65001, router_id='192.168.0.2')
+ q2 = QuaggaBGPContainer(name='q2', asn=65002, router_id='192.168.0.3')
+ q3 = QuaggaBGPContainer(name='q3', asn=65003, router_id='192.168.0.4')
+
+ qs = [q1, q2, q3]
+ ctns = [g1, q1, q2, q3]
+
+ # advertise a route from q1, q2, q3
+ for idx, q in enumerate(qs):
+ route = '10.0.{0}.0/24'.format(idx+1)
+ q.add_route(route)
+
+ initial_wait_time = max(ctn.run() for ctn in ctns)
+
+ time.sleep(initial_wait_time)
+
+ br01 = Bridge(name='br01', subnet='192.168.10.0/24')
+ [br01.addif(ctn) for ctn in ctns]
+
+ for q in qs:
+ g1.add_peer(q)
+ q.add_peer(g1)
+
+ cls.gobgp = g1
+ cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3}
+ cls.bridges = {'br01': br01}
# test each neighbor state is turned establish
def test_01_neighbor_established(self):
- print "test_neighbor_established"
-
- use_local = parser_option.use_local
- go_path = parser_option.go_path
- log_debug = parser_option.gobgp_log_debug
- fab.init_test_env_executor(self.quagga_num, use_local, go_path, log_debug, is_route_server=False)
-
- print "please wait " + str(self.initial_wait_time) + " second"
- time.sleep(self.initial_wait_time)
- if self.check_load_config() is False:
- return
-
- addresses = self.get_neighbor_address(self.gobgp_config)
- self.retry_routine_for_state(addresses, "BGP_FSM_ESTABLISHED")
-
- for address in addresses:
- # get neighbor state and remote ip from gobgp connections
- print "check of [ " + address + " ]"
- neighbor = self.ask_gobgp(NEIGHBOR, address)
- state = neighbor['info']['bgp_state']
- remote_ip = neighbor['conf']['remote_ip']
- self.assertEqual(address, remote_ip)
- self.assertEqual(state, "BGP_FSM_ESTABLISHED")
-
- # Test of advertised route gobgp from each quagga
-
-
- def test_02_received_route(self):
- print "test_received_route"
- if self.check_load_config() is False:
- return
-
- self.assert_global_rib()
-
- # Test of advertising route to each quagga form gobgp
- def test_03_advertising_route(self):
- print "test_advertising_route"
- if self.check_load_config() is False:
- return
-
- for address in self.get_neighbor_address(self.gobgp_config):
- print "check of [ " + address + " ]"
- rib = self.ask_gobgp(ADJ_RIB_OUT, address)
- print rib
- self.assert_quagga_rib(address)
-
- # check if quagga that is appended can establish connection with gobgp
- def test_04_established_with_appended_quagga(self):
- print "test_established_with_appended_quagga"
- if self.check_load_config() is False:
- return
-
- go_path = parser_option.go_path
- # append new quagga container
- fab.docker_container_quagga_append_executor(self.append_quagga, go_path, is_route_server=False)
- print "please wait " + str(self.initial_wait_time) + " second"
- time.sleep(self.initial_wait_time)
- append_quagga_address = "10.0.0." + str(self.append_quagga)
- self.retry_routine_for_state([append_quagga_address], "BGP_FSM_ESTABLISHED")
-
- # get neighbor state and remote ip of new quagga
- print "check of [" + append_quagga_address + " ]"
- neighbor = self.ask_gobgp(NEIGHBOR, append_quagga_address)
- state = neighbor['info']['bgp_state']
- remote_ip = neighbor['conf']['remote_ip']
- self.assertEqual(append_quagga_address, remote_ip)
- self.assertEqual(state, "BGP_FSM_ESTABLISHED")
-
- # Test of advertised route gobgp from each quagga when append quagga container
- def test_05_received_route_when_appended_quagga(self):
- print "test_received_route_by_appended_quagga"
- if self.check_load_config() is False:
- return
-
- self.assert_global_rib()
-
- # Test of advertising route to each quagga form gobgp when append quagga container
- def test_06_advertising_route_when_appended_quagga(self):
- print "test_advertising_route_to_appended_quagga"
- if self.check_load_config() is False:
- return
-
- for address in self.get_neighbor_address(self.gobgp_config):
- print "check of [ " + address + " ]"
- self.assert_quagga_rib(address)
-
- def test_07_active_when_quagga_removed(self):
- print "test_active_when_removed_quagga"
- if self.check_load_config() is False:
- return
-
- # remove quagga container
- fab.docker_container_quagga_removed_executor(self.remove_quagga)
- print "please wait " + str(self.initial_wait_time) + " second"
- time.sleep(self.initial_wait_time)
- removed_quagga_address = "10.0.0." + str(self.remove_quagga)
- self.retry_routine_for_state([removed_quagga_address], "BGP_FSM_ACTIVE")
-
- # get neighbor state and remote ip of removed quagga
- print "check of [" + removed_quagga_address + " ]"
- neighbor = self.ask_gobgp(NEIGHBOR, removed_quagga_address)
- state = neighbor['info']['bgp_state']
- remote_ip = neighbor['conf']['remote_ip']
- self.assertEqual(removed_quagga_address, remote_ip)
- self.assertEqual(state, "BGP_FSM_ACTIVE")
-
- def test_08_received_route_when_quagga_removed(self):
- print "test_received_route_when_removed_quagga"
- if self.check_load_config() is False:
- return
-
- retry_count = 0
- still_exists = False
- while retry_count < self.dest_check_limit:
-
- rib = self.ask_gobgp(GLOBAL_RIB)
-
- removed_prefix = "10.0.0.%d/24" % self.remove_quagga
- still_exists = False
- for dst in rib:
- for path in dst['paths']:
- if path['nlri']['prefix'] == removed_prefix:
- still_exists = True
-
- if not still_exists:
- print "compare OK"
- break
- else:
- retry_count += 1
- print "compare NG -> retry ( %d / %d )" % (retry_count, self.dest_check_limit)
- time.sleep(self.wait_per_retry)
-
- self.assertEqual(still_exists, False)
-
- def test_09_advertising_route_when_quagga_removed(self):
- print "test_advertising_route_when_removed_quagga"
- if self.check_load_config() is False:
- return
-
- remove_quagga_address = "10.0.0." + str(self.remove_quagga)
- removed_prefix = "10.0.0.%d/24" % self.remove_quagga
- for address in self.get_neighbor_address(self.gobgp_config):
- if remove_quagga_address == address:
+ for q in self.quaggas.itervalues():
+ self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q)
+
+ def test_02_check_gobgp_global_rib(self):
+ for q in self.quaggas.itervalues():
+ # paths expected to exist in gobgp's global rib
+ routes = q.routes.keys()
+ # gobgp's global rib
+ global_rib = [p['prefix'] for p in self.gobgp.get_global_rib()]
+
+ for p in global_rib:
+ if p in routes:
+ routes.remove(p)
+
+ if len(routes) == 0:
continue
- print "check of [ " + address + " ]"
+ gobgp = '/go/bin/gobgp'
+ cmd = 'docker exec {0} {1}' \
+ ' monitor global rib -j'.format(self.gobgp.name, gobgp)
+
+ process = subprocess.Popen(cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ poll = select.epoll()
+ poll.register(process.stdout, select.POLLIN)
- retry_count = 0
- cmp_result = False
- while retry_count < self.dest_check_limit:
+ timeout = 10.0
- tn = qaccess.login(address)
- q_rib = qaccess.show_rib(tn)
- still_exists = False
- for q_path in q_rib:
- if q_path['Network'] == removed_prefix:
- still_exists = True
- #self.assertEqual(still_exists, False)
+ while True:
+ result = poll.poll(timeout)
+ if result:
+ line = process.stdout.readline()
+ path = json.loads(line)['nlri']['prefix']
+ if path in routes:
+ routes.remove(path)
- cmp_result = self.compare_route_with_quagga_configs(address, q_rib, route_server=False)
+ if len(routes) == 0:
+ return
+ continue
+ raise Exception('timeout')
- if cmp_result and not still_exists:
- print "compare OK"
+
+ # check routes are properly advertised to all BGP speaker
+ def test_03_check_quagga_global_rib(self):
+ for q in self.quaggas.itervalues():
+ done = False
+ for _ in range(self.retry_limit):
+ if done:
break
- else:
- retry_count += 1
- print "compare NG -> retry ( %d / %d )" % (retry_count, self.dest_check_limit)
+ global_rib = q.get_global_rib()
+ global_rib = [p['prefix'] for p in global_rib]
+ if len(global_rib) < len(self.quaggas):
time.sleep(self.wait_per_retry)
+ continue
+
+ self.assertTrue(len(global_rib) == len(self.quaggas))
+
+ for c in self.quaggas.itervalues():
+ for r in c.routes:
+ self.assertTrue(r in global_rib)
+ done = True
+ if done:
+ continue
+ # should not reach here
+ self.assertTrue(False)
+
+ def test_04_add_quagga(self):
+ q4 = QuaggaBGPContainer(name='q4', asn=65004, router_id='192.168.0.5')
+ self.quaggas['q4'] = q4
+
+ q4.add_route('10.0.4.0/24')
+
+ initial_wait_time = q4.run()
+ time.sleep(initial_wait_time)
+ self.bridges['br01'].addif(q4)
+ self.gobgp.add_peer(q4)
+ q4.add_peer(self.gobgp)
+
+ self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4)
+
+ def test_05_check_global_rib(self):
+ self.test_02_check_gobgp_global_rib()
+ self.test_03_check_quagga_global_rib()
+
+ def test_06_stop_one_quagga(self):
+ q4 = self.quaggas['q4']
+ q4.stop()
+ self.gobgp.wait_for(expected_state=BGP_FSM_ACTIVE, peer=q4)
+ del self.quaggas['q4']
+
+ # check gobgp properly send withdrawal message with q4's route
+ def test_07_check_global_rib(self):
+ self.test_02_check_gobgp_global_rib()
+ self.test_03_check_quagga_global_rib()
+
+ def test_08_add_distant_relative(self):
+ q1 = self.quaggas['q1']
+ q2 = self.quaggas['q2']
+ q3 = self.quaggas['q3']
+ q5 = QuaggaBGPContainer(name='q5', asn=65005, router_id='192.168.0.6')
+
+ initial_wait_time = q5.run()
+ time.sleep(initial_wait_time)
+
+ br02 = Bridge(name='br02', subnet='192.168.20.0/24')
+ br02.addif(q5)
+ br02.addif(q2)
+
+ br03 = Bridge(name='br03', subnet='192.168.30.0/24')
+ br03.addif(q5)
+ br03.addif(q3)
+
+ for q in [q2, q3]:
+ q5.add_peer(q)
+ q.add_peer(q5)
+
+ med200 = {'name': 'med200',
+ 'type': 'permit',
+ 'match': '0.0.0.0/0',
+ 'direction': 'out',
+ 'med': 200}
+ q2.add_policy(med200, self.gobgp)
+ med100 = {'name': 'med100',
+ 'type': 'permit',
+ 'match': '0.0.0.0/0',
+ 'direction': 'out',
+ 'med': 100}
+ q3.add_policy(med100, self.gobgp)
+
+ q5.add_route('10.0.6.0/24')
+
+ self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q2)
+ self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q3)
+ q2.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q5)
+ q3.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q5)
+
+ done = False
+ for _ in range(self.retry_limit):
+ paths = q1.get_global_rib('10.0.6.0/24')
+ if len(paths) > 0:
+ path = paths[0]
+ print "{0}'s nexthop is {1}".format(path['prefix'],
+ path['nexthop'])
+ n_addrs = [i[1].split('/')[0] for i in self.gobgp.ip_addrs]
+ if path['nexthop'] in n_addrs:
+ done = True
+ break
+ time.sleep(self.wait_per_retry)
+
+ if not done:
+ self.assertTrue(False)
- self.assertEqual(still_exists, False)
- self.assertEqual(cmp_result, True)
-
- def test_10_bestpath_selection_of_received_route(self):
- print "test_bestpath_selection_of_received_route"
- if self.check_load_config() is False:
- return
-
- go_path = parser_option.go_path
- fab.docker_container_make_bestpath_env_executor(self.append_quagga_best, go_path, is_route_server=False)
- print "please wait " + str(self.initial_wait_time) + " second"
- time.sleep(self.initial_wait_time)
-
- print "add neighbor setting"
- tn = qaccess.login("11.0.0.20")
- qaccess.add_neighbor(tn, "65020", "11.0.0.2", "65002")
- qaccess.add_neighbor(tn, "65020", "12.0.0.3", "65003")
-
- tn = qaccess.login("11.0.0.2")
- tn = qaccess.add_metric(tn, "200", "192.168.20.0")
- qaccess.add_neighbor(tn, "65002", "11.0.0.20", "65020")
- qaccess.add_neighbor_metric(tn, "65002", "10.0.255.1", "200")
-
- tn = qaccess.login("10.0.0.3")
- tn = qaccess.add_metric(tn, "100", "192.168.20.0")
- qaccess.add_neighbor(tn, "65003", "12.0.0.20", "65020")
- qaccess.add_neighbor_metric(tn, "65003", "10.0.255.1", "100")
-
- print "please wait " + str(self.initial_wait_time) + " second"
- time.sleep(self.initial_wait_time)
-
- target_network = "192.168.20.0/24"
- ans_nexthop = "10.0.0.3"
-
- print "check whether target network %s 's nexthop is %s" % (target_network, ans_nexthop)
- self.retry_routine_for_bestpath("", target_network, ans_nexthop)
-
- def assert_quagga_rib(self, address):
- retry_count = 0
- cmp_result = False
- while retry_count < self.dest_check_limit:
- tn = qaccess.login(address)
- q_rib = qaccess.show_rib(tn)
- cmp_result = self.compare_route_with_quagga_configs(address, q_rib, route_server=False)
-
- if cmp_result:
- print "compare OK"
- break
- else:
- retry_count += 1
- print "compare NG -> retry ( %d / %d )" % (retry_count, self.dest_check_limit)
- time.sleep(self.wait_per_retry)
- self.assertTrue(cmp_result)
-
- def assert_global_rib(self):
- retry_count = 0
- cmp_result = False
- while retry_count < self.dest_check_limit:
- rib = self.ask_gobgp(GLOBAL_RIB)
- cmp_result = self.compare_global_rib_with_quagga_configs(rib)
-
- if cmp_result:
- print "compare OK"
- break
- else:
- retry_count += 1
- print "compare NG -> retry ( %d / %d )" % (retry_count, self.dest_check_limit)
- time.sleep(self.wait_per_retry)
- self.assertTrue(cmp_result)
if __name__ == '__main__':
- if fab.test_user_check() is False:
+ if os.geteuid() is not 0:
print "you are not root."
sys.exit(1)
- if fab.docker_pkg_check() is False:
- print "not install docker package."
+ output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True)
+ if int(output) is not 0:
+ print "docker not found"
sys.exit(1)
- nose.main(argv=sys.argv, addplugins=[OptionParser()], defaultTest=sys.argv[0])
+ nose.main(argv=sys.argv, addplugins=[OptionParser()],
+ defaultTest=sys.argv[0])