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)
Beispiel #4
0
    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
Beispiel #5
0
    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))
Beispiel #7
0
    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, '')
Beispiel #8
0
    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
Beispiel #9
0
    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
Beispiel #10
0
    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)
Beispiel #12
0
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)
Beispiel #13
0
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)
Beispiel #15
0
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)