def validate_route_target(cls, route_target_name, global_asn=None): ok, result = cls._parse_route_target_name(route_target_name) if not ok: return False, result, None asn, target = result if not global_asn: try: global_asn = cls.server.global_autonomous_system except VncError as e: return False, (400, str(e)), None if type(asn) == int: ok, result = cls.server.get_resource_class( 'global_system_config').check_asn_range(asn) if not ok: return ok, result, None ret_val = "target:" + str(asn) + ":" + str(target) # If the ASN of Route Target matches Global ASN, we need to check # for its target range. The target should not clash with contrail # RT target reserved space as detailed below if asn == global_asn: global_4byte_flag = cls.server.enable_4byte_as if global_4byte_flag: # Case when 4 byte ASN flag is set # Target should be # 1. 1 <= target < _BGP_RTGT_MIN_ID_TYPE1_2 # 2. _BGP_RTGT_MAX_ID_TYPE1_2 < target <= 0xFFFF # This is because contrail allocates RT targets in the range of # 8000-32768 if ((1 <= target < get_bgp_rtgt_min_id(asn)) or (get_bgp_rtgt_max_id(asn) < target <= 0xFFFF)): return True, True, ret_val else: return True, False, ret_val else: # Case when 2 byte ASN flag is set # Target should be: # 1. 1 <= target < _BGP_RTGT_MIN_ID_TYPE0 # 2. _BGP_RTGT_MAX_ID_TYPE0 < target <= 0xFFFFFFFF if ((1 <= target < get_bgp_rtgt_min_id(asn)) or (get_bgp_rtgt_max_id(asn) < target <= 0xFFFFFFFF)): return True, True, ret_val else: return True, False, ret_val return True, True, ret_val
def _check_route_targets(cls, obj_dict): rt_dict = obj_dict.get('configured_route_target_list') if not rt_dict: return True, '' route_target_list = rt_dict.get('route_target') if not route_target_list: return True, '' global_asn = cls.server.global_autonomous_system for idx, rt in enumerate(route_target_list): ok, result, new_rt = cls.server.get_resource_class( 'route_target').validate_route_target(rt) if not ok: return False, result user_defined_rt = result if not user_defined_rt: return (False, "Configured route target must use ASN that is " "different from global ASN or route target value must" " be less than %d and greater than %d" % (get_bgp_rtgt_min_id(global_asn), get_bgp_rtgt_max_id(global_asn))) if new_rt: route_target_list[idx] = new_rt return (True, '')
def test_create_vn_with_configured_rt_in_system_range(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) vn = VirtualNetwork('%s-vn' % self.id()) rt_name = 'target:%d:%d' % (gsc.autonomous_system, get_bgp_rtgt_min_id( gsc.autonomous_system) + 1000) vn.set_route_target_list(RouteTargetList([rt_name])) self.assertRaises(BadRequest, self.api.virtual_network_create, vn)
def is_user_defined(cls, route_target_name, global_asn=None): ok, result = cls._parse_route_target_name(route_target_name) if not ok: return False, result asn, target = result if not global_asn: try: global_asn = cls.server.global_autonomous_system except VncError as e: return False, (400, str(e)) if (asn == global_asn and target >= get_bgp_rtgt_min_id(global_asn)): return True, False return True, True
def test_route_target_is_in_system_range(self): # RT name, global ASN, expected result tested_values = [ ('target:1:1', 42, True), ('target:42:1', 42, True), # We now allow suffix 'L' for an ASN ('target:40L:10', 42, True), # Don't allow target value to be greater than 0xFFFF # when ASN is appended with 'L' ('target:40L:70000', 42, False), # Test with same ASN as global ASN(42). But target value # being greater than get_bgp_rtgt_min_id ('target:42:%d' % (get_bgp_rtgt_min_id(42) + 1000), 42, False), # Test with same ASN as global ASN(42). But target value # being greater than get_bgp_rtgt_max_id ('target:42:%d' % (get_bgp_rtgt_max_id(42) + 1000), 42, True), # Test with ASN different from global ASN(42). # Target value can be either greater than get_bgp_rtgt_max_id # or greater than get_bgp_rtgt_max_id ('target:40:%d' % (get_bgp_rtgt_min_id(42) + 1000), 42, True), ('target:40:%d' % (get_bgp_rtgt_max_id(42) + 1000), 42, True) ] for rt_name, global_asn, expected_result in tested_values: ok, result, _ = RouteTargetServer.validate_route_target( rt_name, global_asn) if not ok: self.assertEqual( ok, expected_result, "For rt_name: %s, expected result is %s" % (rt_name, expected_result)) else: self.assertEqual( result, expected_result, "Route target: %s and global ASN: %d" % (rt_name, global_asn))
def test_route_target_is_in_system_range(self): # RT name, global ASN, expected result tested_values = [ ('target:1:1', 42, True), ('target:42:1', 42, True), ('target:42:%d' % (get_bgp_rtgt_min_id(42) + 1000), 42, False), ] for rt_name, global_asn, expected_result in tested_values: ok, result = RouteTargetServer.is_user_defined(rt_name, global_asn) if not ok: self.fail( "Cannot determine if it is a user defined route " "target: %s", result[1]) self.assertEqual( result, expected_result, "Route target: %s and global ASN: %d" % (rt_name, global_asn))
def _check_route_targets(cls, obj_dict): rt_dict = obj_dict.get('route_target_list') if not rt_dict: return True, '' global_asn = cls.server.global_autonomous_system for rt in rt_dict.get('route_target') or []: ok, result = cls.server.get_resource_class( 'route_target').is_user_defined(rt) if not ok: return False, result user_defined_rt = result if not user_defined_rt: return (False, "Configured route target must use ASN that is " "different from global ASN or route target value must" " be less than %d" % get_bgp_rtgt_min_id(global_asn)) return (True, '')
def alloc_route_target(self, ri_fq_name, asn, zk_only=False): alloc_new = False self.current_rt_allocator = self.get_zk_route_target_allocator(asn) if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.get_bgp_rtgt_min_id(asn): alloc_new = True else: rtgt_ri_fq_name_str = self.current_rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self.current_rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num
def __init__(self, name, obj=None): self.name = name self.virtual_machine_interfaces = set() self.virtual_networks = set() self.route_tables = set() self.rt_list = set() self.configured_route_target_list = None self.bgpvpns = set() self.bgpvpn_rt_list = set() self.bgpvpn_import_rt_list = set() self.bgpvpn_export_rt_list = set() self.update_vnc_obj() self.logical_router_type = self.obj.get_logical_router_type() rt_ref = self.obj.get_route_target_refs() old_rt_key = None if rt_ref: rt_key = rt_ref[0]['to'][0] rtgt_num = int(rt_key.split(':')[-1]) asn = ResourceBaseST.get_obj_type_map().get( 'global_system_config').get_autonomous_system() if rtgt_num < common.get_bgp_rtgt_min_id(asn): old_rt_key = rt_key rt_ref = None if not rt_ref: asn = ResourceBaseST.get_obj_type_map().get( 'global_system_config').get_autonomous_system() rtgt_num = self._object_db.alloc_route_target(name, asn, True) rt_key = "target:%s:%d" % (asn, rtgt_num) rtgt_obj = ResourceBaseST.get_obj_type_map().get( 'route_target').locate(rt_key) self.obj.set_route_target(rtgt_obj.obj) self._vnc_lib.logical_router_update(self.obj) if old_rt_key: ResourceBaseST.get_obj_type_map().get( 'route_target').delete_vnc_obj(old_rt_key) self.route_target = rt_key
def update_autonomous_system(cls, new_asn): if int(new_asn) == cls._autonomous_system: return False # From the global route target list, pick ones with the # changed ASN, and update the routing instances' referred # by the route target for route_tgt in list(ResourceBaseST.get_obj_type_map().get( 'route_target').values()): _, asn, target = route_tgt.obj.get_fq_name()[0].split(':') if int(asn) != cls.get_autonomous_system(): continue if int(target) < common.get_bgp_rtgt_min_id(asn): continue asn = cls._autonomous_system new_target = target if ((new_asn > 0xFFFF) and (asn <= 0xFFFF) or (new_asn <= 0xFFFF and asn > 0xFFFF)): ri_fq_name_in_str = cls._object_db.get_ri_from_route_target( int(target), asn) if ri_fq_name_in_str is None or ri_fq_name_in_str == '': continue # free_route_target has to be called before alloc_route_target. # as get_route_target(ri_fq_name) inside free_route_target # will return wrong values if this order is changed. cls._object_db.free_route_target(ri_fq_name_in_str, asn) new_target = cls._object_db.alloc_route_target( ri_fq_name_in_str, new_asn) new_rtgt_name = "target:%s:%s" % (new_asn, new_target) new_rtgt_obj = ResourceBaseST.get_obj_type_map().get( 'route_target').locate(new_rtgt_name) old_rtgt_name = "target:%d:%s" % (cls._autonomous_system, target) old_rtgt_obj = RouteTarget(old_rtgt_name) route_tgt.obj = ResourceBaseST.get_obj_type_map().get( 'route_target').read_vnc_obj(fq_name=[old_rtgt_name], fields=[ 'logical_router_back_refs', 'routing_instance_back_refs' ]) for ri_ref in route_tgt.obj.get_routing_instance_back_refs() or []: rt_inst = ResourceBaseST.get_obj_type_map().get( 'routing_instance').get(':'.join(ri_ref['to'])) if rt_inst: ri = rt_inst.obj else: continue inst_tgt_data = InstanceTargetType() ri.del_route_target(old_rtgt_obj) ri.add_route_target(new_rtgt_obj.obj, inst_tgt_data) cls._vnc_lib.routing_instance_update(ri) # Also, update the static_routes, if any, in the routing # instance with the new route target static_route_entries = ri.get_static_route_entries() if static_route_entries is None: continue for static_route in static_route_entries.get_route() or []: if old_rtgt_name in static_route.route_target: static_route.route_target.remove(old_rtgt_name) static_route.route_target.append(new_rtgt_name) ri.set_static_route_entries(static_route_entries) cls._vnc_lib.routing_instance_update(ri) # Updating the logical router referred by the route target with # new route target. for router_ref in route_tgt.obj.get_logical_router_back_refs() \ or []: lr = ResourceBaseST.get_obj_type_map().get( 'logical_router').get(':'.join(router_ref['to'])) if lr: logical_router = lr.obj else: continue logical_router.del_route_target(old_rtgt_obj) logical_router.add_route_target(new_rtgt_obj.obj) cls._vnc_lib.logical_router_update(logical_router) # We need to execute this code only in case of SNAT routing. # If vxlan_routing is enabled, LR RTs will not have a back_ref # to the Routing Instance of all the connected VNs proj_obj = ResourceBaseST.get_obj_type_map().get( 'logical_router').read_vnc_obj(logical_router.parent_uuid, obj_type='project', fields=['vxlan_routing']) vxlan_routing = proj_obj.get_vxlan_routing() if not vxlan_routing: for vn in lr.virtual_networks: vn_obj = ResourceBaseST.get_obj_type_map().get( 'virtual_network').get(vn) if vn_obj is not None: ri_obj = vn_obj.get_primary_routing_instance() ri_obj.update_route_target_list( rt_del=[old_rtgt_name], rt_add=[new_rtgt_name]) lr.route_target = new_rtgt_name ResourceBaseST.get_obj_type_map().get( 'route_target').delete_vnc_obj(old_rtgt_obj.get_fq_name()[0]) cls._autonomous_system = int(new_asn) return True
def locate_route_target(self): old_rtgt = self._object_db.get_route_target(self.name) asn = ResourceBaseST.get_obj_type_map().get( 'global_system_config').get_autonomous_system() rtgt_num = self._object_db.alloc_route_target(self.name, asn) rt_key = "target:%s:%d" % (asn, rtgt_num) rtgt_obj = ResourceBaseST.get_obj_type_map().get( 'route_target').locate(rt_key).obj if self.is_default: inst_tgt_data = InstanceTargetType() elif ResourceBaseST.get_obj_type_map().get( 'virtual_network')._ri_needs_external_rt( self.virtual_network, self.name): inst_tgt_data = InstanceTargetType(import_export="export") else: inst_tgt_data = None vn = ResourceBaseST.get_obj_type_map().get('virtual_network').get( self.virtual_network) if vn is None: self._logger.error("Parent VN not found for RI: " + self.name) return try: if self.obj.parent_uuid != vn.obj.uuid: # Stale object. Delete it. self._vnc_lib.routing_instance_delete(id=self.obj.uuid) self.obj = None else: update_ri = False self.stale_route_targets = \ [':'.join(rt_ref['to']) for rt_ref in self.obj.get_route_target_refs() or []] if rt_key not in self.stale_route_targets: self.obj.add_route_target(rtgt_obj, InstanceTargetType()) update_ri = True else: self.stale_route_targets.remove(rt_key) if inst_tgt_data: for rt in vn.rt_list | vn.bgpvpn_rt_list: if rt not in self.stale_route_targets: rtgt_obj = ResourceBaseST.get_obj_type_map().get( 'route_target').locate(rt) self.obj.add_route_target(rtgt_obj.obj, inst_tgt_data) update_ri = True else: self.stale_route_targets.remove(rt) if self.is_default: for rt in (vn.export_rt_list | vn.bgpvpn_export_rt_list): if rt not in self.stale_route_targets: rtgt_obj = \ ResourceBaseST.get_obj_type_map().get( 'route_target').locate(rt) self.obj.add_route_target( rtgt_obj.obj, InstanceTargetType('export')) update_ri = True else: self.stale_route_targets.remove(rt) for rt in (vn.import_rt_list | vn.bgpvpn_import_rt_list): if rt not in self.stale_route_targets: rtgt_obj = \ ResourceBaseST.get_obj_type_map().get( 'route_target').locate(rt) self.obj.add_route_target( rtgt_obj.obj, InstanceTargetType('import')) update_ri = True else: self.stale_route_targets.remove(rt) elif vn.allow_transit: if vn.get_route_target() not in \ self.stale_route_targets: rtgt_obj = RouteTarget(vn.get_route_target()) self.obj.add_route_target(rtgt_obj, inst_tgt_data) update_ri = True else: self.stale_route_targets.remove( vn.get_route_target()) update_ri |= \ self.import_default_ri_route_target_to_service_ri() if update_ri: try: self._vnc_lib.routing_instance_update(self.obj) except Exception as e: # error due to inconsistency in db self._logger.error( "Error while updating routing instance: " + str(e)) return except NoIdError as e: self._logger.error("Error while updating routing instance: " + str(e)) raise self.route_target = rt_key if self.is_default: vn.set_route_target(rt_key) asn = ResourceBaseST.get_obj_type_map().get( 'global_system_config').get_autonomous_system() if 0 < old_rtgt < common.get_bgp_rtgt_min_id(asn): rt_key = "target:%s:%d" % (asn, old_rtgt) ResourceBaseST.get_obj_type_map().get( 'route_target').delete_vnc_obj(rt_key)
class TestGlobalSystemConfig(test_case.ApiServerTestCase): DEFAULT_ASN = 64512 NEW_ASN = 42 ASN_4_BYTES = 6553692 FAKE_VN_LIST = [ { 'fq_name': ['fake-vn-name1'], 'uuid': 'fake_vn_uuid1', 'route_target_list': { 'route_target': [ 'target:%d:%d' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN) + 1000), ] }, 'import_route_target_list': { 'route_target': [ 'target:%d:%d' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN) + 1001), ] }, 'export_route_target_list': { 'route_target': [ 'target:%d:%d' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN) + 1002), ] } }, { 'fq_name': ['fake-vn-name2'], 'uuid': 'fake_vn_uuid2', 'route_target_list': { 'route_target': [ 'target:%s:%s' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN)), 'target:%d:%d' % (NEW_ASN + 1, get_bgp_rtgt_min_id(NEW_ASN)), 'target:%d:%d' % (NEW_ASN + 2, get_bgp_rtgt_min_id(NEW_ASN)), ] }, }, { 'fq_name': ['fake-vn-name3'], 'uuid': 'fake_vn_uuid3', 'import_route_target_list': { 'route_target': [ 'target:%s:%s' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN)), ] }, }, { 'fq_name': ['fake-vn-name4'], 'uuid': 'fake_vn_uuid4', 'export_route_target_list': { 'route_target': [ 'target:%s:%s' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN)), ] }, }, ] FAKE_LR_LIST = [ { 'fq_name': ['fake-lr-name1'], 'uuid': 'fake_lr_uuid1', 'configured_route_target_list': { 'route_target': [ 'target:%s:%s' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN)), 'target:%s:%s' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN)), 'target:%s:%s' % (NEW_ASN + 1, get_bgp_rtgt_min_id(NEW_ASN)), ] }, }, ] @classmethod def setUpClass(cls, *args, **kwargs): cls.console_handler = logging.StreamHandler() cls.console_handler.setLevel(logging.DEBUG) logger.addHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).setUpClass(*args, **kwargs) @classmethod def tearDownClass(cls, *args, **kwargs): logger.removeHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).tearDownClass(*args, **kwargs) def tearDown(self, *args, **kwargs): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = self.DEFAULT_ASN gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) self._api_server._global_asn = None test_case.ApiServerTestCase.tearDown(self) @property def api(self): return self._vnc_lib def test_only_one_global_system_config_can_exists(self): gsc = GlobalSystemConfig('gsc-%s' % self.id()) self.assertRaises(BadRequest, self.api.global_system_config_create, gsc) @mock.patch.object(GlobalSystemConfigServer, 'locate', return_value=(True, {'autonomous_system': DEFAULT_ASN})) def test_global_asn_populated(self, locate_mock): self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_called_once_with( uuid=self._api_server._gsc_uuid, create_it=False, fields=['autonomous_system'], ) locate_mock.reset_mock() self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_not_called() def test_update_global_asn(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(self.DEFAULT_ASN, gsc.autonomous_system) gsc.autonomous_system = self.NEW_ASN gsc = self.api.global_system_config_update(gsc) self.assertEqual(self.NEW_ASN, self._api_server.global_autonomous_system) def test_update_global_asn_with_valid_4_byte(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True self.api.global_system_config_update(gsc) # Read back the GSC gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(True, gsc.enable_4byte_as) # Update global ASN to a 4 byte value gsc.autonomous_system = 700000 self.api.global_system_config_update(gsc) # Read back the GSC gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(700000, gsc.autonomous_system) def test_update_both_global_asn_and_asn_flag(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True gsc.autonomous_system = 61450 self.api.global_system_config_update(gsc) def test_update_2_byte_asn_range_check(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = 70000 self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) def test_update_4_byte_asn_range_check(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True self.api.global_system_config_update(gsc) # Update ASN to greater than 0xFFffFFff gsc.autonomous_system = 0x1FFFFFFFF self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) def test_cannot_update_global_asn_if_used_by_user(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) tests = [ {'autonomous_system': self.NEW_ASN, 'mock_return_value': (True, self.FAKE_VN_LIST, None), 'expected_rt_count': 6}, {'autonomous_system': self.NEW_ASN + 1, 'mock_return_value': (True, self.FAKE_VN_LIST, None), 'expected_rt_count': 1}, {'autonomous_system': self.NEW_ASN + 2, 'mock_return_value': (True, self.FAKE_VN_LIST, None), 'expected_rt_count': 1}, {'autonomous_system': self.NEW_ASN, 'mock_return_value': (True, self.FAKE_LR_LIST, None), 'expected_rt_count': 2}, {'autonomous_system': self.NEW_ASN + 1, 'mock_return_value': (True, self.FAKE_LR_LIST, None), 'expected_rt_count': 1}, ] for t in tests: gsc.autonomous_system = t['autonomous_system'] with mock.patch.object(self._api_server._db_conn, 'dbe_list', return_value=t['mock_return_value']): try: self.api.global_system_config_update(gsc) except Exception as exc: self.assertIsInstance(exc, BadRequest) self.assertEqual(exc.status_code, 400) # The first line of exception is a generic message. # The remaining lines are list of Route Targets # that are invalid. # We want to count all invalid Route Targets, # so we start with the second element of the list. existing_rt = exc.content.split('\t')[1:] self.assertEqual(len(existing_rt), t['expected_rt_count']) def test_can_update_global_asn_if_not_used_by_user(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.enable_4byte_as = False tests = [ {'autonomous_system': self.NEW_ASN + 10, 'mock_return_value': (True, self.FAKE_VN_LIST, None)}, {'autonomous_system': self.NEW_ASN + 2, 'mock_return_value': (True, self.FAKE_LR_LIST, None)}, ] for t in tests: with mock.patch.object(self._api_server._db_conn, 'dbe_list', return_value=t['mock_return_value']): gsc.autonomous_system = t['autonomous_system'] self.api.global_system_config_update(gsc) gsc = self.api.global_system_config_read( GlobalSystemConfig().fq_name) self.assertEqual(gsc.autonomous_system, t['autonomous_system']) def test_update_asn_if_any_rt_uses_4_byte(self): """ Test scenario. 1. Set enable_4byte_as to true 2. Create RT with 4 bytes ASN 3. Set enable_4byte_as to false 4. Change global ASN to different 2 bytes numbers """ gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # Set enable_4byte_as to True gsc.enable_4byte_as = True gsc.autonomous_system = self.ASN_4_BYTES self.api.global_system_config_update(gsc) # reread gsc gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(gsc.enable_4byte_as, True) # create VN and RT with 4bytes ASN vn = VirtualNetwork('%s-vn' % self.id()) rt_name = 'target:%d:%d' % (self.ASN_4_BYTES, 1000) vn.set_route_target_list(RouteTargetList([rt_name])) self.api.virtual_network_create(vn) # Set enable_4byte_as to false gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) # Change global ASN to 2 bytes numbers (must be in separate step) gsc.autonomous_system = self.NEW_ASN self.api.global_system_config_update(gsc) # reread gsc to confirm change gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(gsc.autonomous_system, self.NEW_ASN) # cleanup self.api.virtual_network_delete(id=vn.uuid)
class TestGlobalSystemConfig(test_case.ApiServerTestCase): DEFAULT_ASN = 64512 NEW_ASN = 42 FAKE_VN_LIST = [{ 'fq_name': ['fake-name1'], 'uuid': 'fake_uuid1', 'route_target_list': { 'route_target': [ 'target:%d:%d' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN) + 1000), ] } }] @classmethod def setUpClass(cls, *args, **kwargs): cls.console_handler = logging.StreamHandler() cls.console_handler.setLevel(logging.DEBUG) logger.addHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).setUpClass(*args, **kwargs) @classmethod def tearDownClass(cls, *args, **kwargs): logger.removeHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).tearDownClass(*args, **kwargs) @property def api(self): return self._vnc_lib def test_only_one_global_system_config_can_exists(self): gsc = GlobalSystemConfig('gsc-%s' % self.id()) self.assertRaises(BadRequest, self.api.global_system_config_create, gsc) @mock.patch.object(GlobalSystemConfigServer, 'locate', return_value=(True, { 'autonomous_system': DEFAULT_ASN })) def test_global_asn_populated(self, locate_mock): self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_called_once_with( uuid=self._api_server._gsc_uuid, create_it=False, fields=['autonomous_system'], ) locate_mock.reset_mock() self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_not_called() def test_update_global_asn(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(self.DEFAULT_ASN, gsc.autonomous_system) gsc.autonomous_system = self.NEW_ASN gsc = self.api.global_system_config_update(gsc) self.assertEqual(self.NEW_ASN, self._api_server.global_autonomous_system) def test_cannot_update_global_asn_if_used_by_user(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = self.NEW_ASN with mock.patch.object(self._api_server._db_conn, 'dbe_list', return_value=(True, self.FAKE_VN_LIST, None)): self.assertRaises(BadRequest, self.api.global_system_config_update, gsc)
class TestGlobalSystemConfig(test_case.ApiServerTestCase): DEFAULT_ASN = 64512 NEW_ASN = 42 FAKE_VN_LIST = [ { 'fq_name': ['fake-name1'], 'uuid': 'fake_uuid1', 'route_target_list': { 'route_target': [ 'target:%d:%d' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN) + 1000), ] } } ] @classmethod def setUpClass(cls, *args, **kwargs): cls.console_handler = logging.StreamHandler() cls.console_handler.setLevel(logging.DEBUG) logger.addHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).setUpClass(*args, **kwargs) @classmethod def tearDownClass(cls, *args, **kwargs): logger.removeHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).tearDownClass(*args, **kwargs) @property def api(self): return self._vnc_lib def test_only_one_global_system_config_can_exists(self): gsc = GlobalSystemConfig('gsc-%s' % self.id()) self.assertRaises(BadRequest, self.api.global_system_config_create, gsc) @mock.patch.object(GlobalSystemConfigServer, 'locate', return_value=(True, {'autonomous_system': DEFAULT_ASN})) def test_global_asn_populated(self, locate_mock): self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_called_once_with( uuid=self._api_server._gsc_uuid, create_it=False, fields=['autonomous_system'], ) locate_mock.reset_mock() self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_not_called() def test_update_global_asn(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(self.DEFAULT_ASN, gsc.autonomous_system) gsc.autonomous_system = self.NEW_ASN gsc = self.api.global_system_config_update(gsc) self.assertEqual(self.NEW_ASN, self._api_server.global_autonomous_system) def test_update_global_asn_with_valid_4_byte(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True self.api.global_system_config_update(gsc) # Read back the GSC gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(True, gsc.enable_4byte_as) # Update global ASN to a 4 byte value gsc.autonomous_system = 700000 self.api.global_system_config_update(gsc) # Read back the GSC gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(700000, gsc.autonomous_system) # Set the DEFAULT ASN and enable_4byte_as flag back to default as in # CI, the order of test cases can change gsc.autonomous_system = self.DEFAULT_ASN self.api.global_system_config_update(gsc) gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) def test_update_both_global_asn_and_asn_flag(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True gsc.autonomous_system = 61450 self.api.global_system_config_update(gsc) # Set the enable_4_byte back to false gsc.enable_4byte_as = False gsc.autonomous_system = self.DEFAULT_ASN self.api.global_system_config_update(gsc) def test_update_2_byte_asn_range_check(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = 70000 self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) def test_update_4_byte_asn_range_check(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True self.api.global_system_config_update(gsc) # Update ASN to greater than 0xFFffFFff gsc.autonomous_system = 0x1FFFFFFFF self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) # Set enable_4byte_as flag back to default gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) def test_cannot_update_global_asn_if_used_by_user(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = self.NEW_ASN with mock.patch.object(self._api_server._db_conn, 'dbe_list', return_value=(True, self.FAKE_VN_LIST, None)): self.assertRaises(BadRequest, self.api.global_system_config_update, gsc)
class TestGlobalSystemConfig(test_case.ApiServerTestCase): DEFAULT_ASN = 64512 NEW_ASN = 42 ASN_4_BYTES = 6553692 FAKE_VN_LIST = [{ 'fq_name': ['fake-name1'], 'uuid': 'fake_uuid1', 'route_target_list': { 'route_target': [ 'target:%d:%d' % (NEW_ASN, get_bgp_rtgt_min_id(NEW_ASN) + 1000), ] } }] @classmethod def setUpClass(cls, *args, **kwargs): cls.console_handler = logging.StreamHandler() cls.console_handler.setLevel(logging.DEBUG) logger.addHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).setUpClass(*args, **kwargs) @classmethod def tearDownClass(cls, *args, **kwargs): logger.removeHandler(cls.console_handler) super(TestGlobalSystemConfig, cls).tearDownClass(*args, **kwargs) @property def api(self): return self._vnc_lib def test_only_one_global_system_config_can_exists(self): gsc = GlobalSystemConfig('gsc-%s' % self.id()) self.assertRaises(BadRequest, self.api.global_system_config_create, gsc) @mock.patch.object(GlobalSystemConfigServer, 'locate', return_value=(True, { 'autonomous_system': DEFAULT_ASN })) def test_global_asn_populated(self, locate_mock): self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_called_once_with( uuid=self._api_server._gsc_uuid, create_it=False, fields=['autonomous_system'], ) locate_mock.reset_mock() self.assertEqual(self.DEFAULT_ASN, self._api_server.global_autonomous_system) locate_mock.assert_not_called() def test_update_global_asn(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(self.DEFAULT_ASN, gsc.autonomous_system) gsc.autonomous_system = self.NEW_ASN gsc = self.api.global_system_config_update(gsc) self.assertEqual(self.NEW_ASN, self._api_server.global_autonomous_system) def test_update_global_asn_with_valid_4_byte(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True self.api.global_system_config_update(gsc) # Read back the GSC gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(True, gsc.enable_4byte_as) # Update global ASN to a 4 byte value gsc.autonomous_system = 700000 self.api.global_system_config_update(gsc) # Read back the GSC gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(700000, gsc.autonomous_system) # Set the DEFAULT ASN and enable_4byte_as flag back to default as in # CI, the order of test cases can change gsc.autonomous_system = self.DEFAULT_ASN self.api.global_system_config_update(gsc) gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) def test_update_both_global_asn_and_asn_flag(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True gsc.autonomous_system = 61450 self.api.global_system_config_update(gsc) # Set the enable_4_byte back to false gsc.enable_4byte_as = False gsc.autonomous_system = self.DEFAULT_ASN self.api.global_system_config_update(gsc) def test_update_2_byte_asn_range_check(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = 70000 self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) def test_update_4_byte_asn_range_check(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # First, enable 4byte AS flag. gsc.enable_4byte_as = True self.api.global_system_config_update(gsc) # Update ASN to greater than 0xFFffFFff gsc.autonomous_system = 0x1FFFFFFFF self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) # Set enable_4byte_as flag back to default gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) def test_cannot_update_global_asn_if_used_by_user(self): gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) gsc.autonomous_system = self.NEW_ASN with mock.patch.object(self._api_server._db_conn, 'dbe_list', return_value=(True, self.FAKE_VN_LIST, None)): self.assertRaises(BadRequest, self.api.global_system_config_update, gsc) def test_update_asn_if_any_rt_uses_4_byte(self): """ Test scenario. 1. Set enable_4byte_as to true 2. Create RT with 4 bytes ASN 3. Set enable_4byte_as to false 4. Change global ASN to different 2 bytes numbers """ gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) # Set enable_4byte_as to True gsc.enable_4byte_as = True gsc.autonomous_system = self.ASN_4_BYTES self.api.global_system_config_update(gsc) # reread gsc gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(gsc.enable_4byte_as, True) # create VN and RT with 4bytes ASN vn = VirtualNetwork('%s-vn' % self.id()) rt_name = 'target:%d:%d' % (self.ASN_4_BYTES, 1000) vn.set_route_target_list(RouteTargetList([rt_name])) self.api.virtual_network_create(vn) # Set enable_4byte_as to false gsc.enable_4byte_as = False self.api.global_system_config_update(gsc) # Change global ASN to 2 bytes numbers (must be in separate step) gsc.autonomous_system = self.NEW_ASN self.api.global_system_config_update(gsc) # reread gsc to confirm change gsc = self.api.global_system_config_read(GlobalSystemConfig().fq_name) self.assertEqual(gsc.autonomous_system, self.NEW_ASN) # cleanup self.api.virtual_network_delete(id=vn.uuid) gsc.autonomous_system = self.DEFAULT_ASN self.api.global_system_config_update(gsc)