예제 #1
0
def _parse_dp(dp_key, dp_conf, acls_conf, meters_conf, routers_conf,
              vlans_conf):
    test_config_condition(not isinstance(dp_conf, dict), '')
    dp = DP(dp_key, dp_conf.get('dp_id', None), dp_conf)
    test_config_condition(dp.name != dp_key,
                          ('DP key %s and DP name must match' % dp_key))
    dp_id = dp.dp_id
    vlans = {}
    vids = set()
    for vlan_key, vlan_conf in vlans_conf.items():
        vlan = VLAN(vlan_key, dp_id, vlan_conf)
        test_config_condition(
            str(vlan_key) not in (str(vlan.vid), vlan.name),
            ('VLAN %s key must match VLAN name or VLAN VID' % vlan_key))
        test_config_condition(vlan.vid in vids,
                              ('VLAN VID %u multiply configured' % vlan.vid))
        vlans[vlan_key] = vlan
        vids.add(vlan.vid)
    for acl_key, acl_conf in acls_conf.items():
        acl = ACL(acl_key, dp_id, acl_conf)
        dp.add_acl(acl_key, acl)
    for router_key, router_conf in routers_conf.items():
        router = Router(router_key, dp_id, router_conf)
        dp.add_router(router_key, router)
    for meter_key, meter_conf in meters_conf.items():
        meter = Meter(meter_key, dp_id, meter_conf)
        dp.meters[meter_key] = meter
    _dp_add_ports(dp, dp_conf, dp_id, vlans)
    return dp
예제 #2
0
def _dp_parser_v2(acls_conf, dps_conf, meters_conf, routers_conf, vlans_conf):
    dps = []

    def _get_vlan_by_key(dp_id, vlan_key, vlans):
        test_config_condition(
            not isinstance(vlan_key, (str, int)),
            ('VLAN key must not be type %s' % type(vlan_key)))
        if vlan_key in vlans:
            return vlans[vlan_key]
        for vlan in list(vlans.values()):
            if vlan_key == str(vlan.vid):
                return vlan
        # Create VLAN with VID, if not defined.
        return vlans.setdefault(vlan_key, VLAN(vlan_key, dp_id))

    def _dp_parse_port(dp_id, port_key, port_conf, vlans):
        port = Port(port_key, dp_id, port_conf)
        test_config_condition(
            str(port_key) not in (str(port.number), port.name),
            ('Port key %s match port name or port number' % port_key))

        def _dp_parse_native_port_vlan():
            if port.native_vlan is not None:
                vlan = _get_vlan_by_key(dp_id, port.native_vlan, vlans)
                port.native_vlan = vlan

        def _dp_parse_tagged_port_vlans():
            if port.tagged_vlans:
                port_tagged_vlans = [
                    _get_vlan_by_key(dp_id, vlan_key, vlans)
                    for vlan_key in port.tagged_vlans
                ]
                port.tagged_vlans = port_tagged_vlans

        _dp_parse_native_port_vlan()
        _dp_parse_tagged_port_vlans()
        return port

    def _dp_add_ports(dp, dp_conf, dp_id, vlans):
        ports_conf = dp_conf.get('interfaces', {})
        port_ranges_conf = dp_conf.get('interface_ranges', {})
        # as users can config port vlan by using vlan name, we store vid in
        # Port instance instead of vlan name for data consistency
        test_config_condition(not isinstance(ports_conf, dict),
                              ('Invalid syntax in interface config'))
        test_config_condition(not isinstance(port_ranges_conf, dict),
                              ('Invalid syntax in interface ranges config'))
        port_num_to_port_conf = {}
        for port_key, port_conf in list(ports_conf.items()):
            test_config_condition(not isinstance(port_conf, dict),
                                  'Invalid syntax in port config')
            if 'number' in port_conf:
                port_num = port_conf['number']
            else:
                port_num = port_key
            try:
                port_num_to_port_conf[port_num] = (port_key, port_conf)
            except TypeError:
                raise InvalidConfigError('Invalid syntax in port config')
        for port_range, port_conf in list(port_ranges_conf.items()):
            # port range format: 1-6 OR 1-6,8-9 OR 1-3,5,7-9
            test_config_condition(not isinstance(port_conf, dict),
                                  'Invalid syntax in port config')
            port_nums = set()
            if 'number' in port_conf:
                del port_conf['number']
            for range_ in re.findall(r'(\d+-\d+)', str(port_range)):
                start_num, end_num = [int(num) for num in range_.split('-')]
                test_config_condition(start_num >= end_num,
                                      ('Incorrect port range (%d - %d)' %
                                       (start_num, end_num)))
                port_nums.update(list(range(start_num, end_num + 1)))
                port_range = re.sub(range_, '', port_range)
            other_nums = [int(p) for p in re.findall(r'\d+', str(port_range))]
            port_nums.update(other_nums)
            test_config_condition(not port_nums,
                                  'interface-ranges contain invalid config')
            for port_num in port_nums:
                if port_num in port_num_to_port_conf:
                    # port range config has lower priority than individual port config
                    for attr, value in list(port_conf.items()):
                        port_num_to_port_conf[port_num][1].setdefault(
                            attr, value)
                else:
                    port_num_to_port_conf[port_num] = (port_num, port_conf)
        for port_num, port_conf in list(port_num_to_port_conf.values()):
            port = _dp_parse_port(dp_id, port_num, port_conf, vlans)
            dp.add_port(port)
        dp.reset_refs(vlans=vlans)

    for dp_key, dp_conf in list(dps_conf.items()):
        test_config_condition(not isinstance(dp_conf, dict), '')
        dp = DP(dp_key, dp_conf.get('dp_id', None), dp_conf)
        test_config_condition(dp.name != dp_key,
                              ('DP key %s and DP name must match' % dp_key))
        dp_id = dp.dp_id

        vlans = {}
        for vlan_key, vlan_conf in list(vlans_conf.items()):
            vlan = VLAN(vlan_key, dp_id, vlan_conf)
            vlans[vlan_key] = vlan
            test_config_condition(
                str(vlan_key) not in (str(vlan.vid), vlan.name),
                ('VLAN %s key must match VLAN name or VLAN VID' % vlan_key))
        for acl_key, acl_conf in list(acls_conf.items()):
            acl = ACL(acl_key, dp_id, acl_conf)
            dp.add_acl(acl_key, acl)
        for router_key, router_conf in list(routers_conf.items()):
            router = Router(router_key, dp_id, router_conf)
            dp.add_router(router_key, router)
        for meter_key, meter_conf in list(meters_conf.items()):
            meter = Meter(meter_key, dp_id, meter_conf)
            dp.meters[meter_key] = meter
        _dp_add_ports(dp, dp_conf, dp_id, vlans)
        dps.append(dp)

    for dp in dps:
        dp.finalize_config(dps)
    for dp in dps:
        dp.resolve_stack_topology(dps)

    router_ref_dps = collections.defaultdict(set)
    for dp in dps:
        for router in list(dp.routers.keys()):
            router_ref_dps[router].add(dp)
    for router in list(routers_conf.keys()):
        test_config_condition(
            not router_ref_dps[router],
            ('router %s configured but not used by any DP' % router))

    return dps
예제 #3
0
def _dp_parser_v2(logger, acls_conf, dps_conf, meters_conf, routers_conf,
                  vlans_conf):
    dps = []
    vid_dp = collections.defaultdict(set)

    def _get_vlan_by_identifier(dp_id, vlan_ident, vlans):
        if vlan_ident in vlans:
            return vlans[vlan_ident]
        for vlan in list(vlans.values()):
            if int(vlan_ident) == vlan.vid:
                return vlan
        try:
            vid = int(vlan_ident, 0)
        except ValueError:
            assert False, 'VLAN VID value (%s) is invalid' % vlan_ident

        return vlans.setdefault(vlan_ident, VLAN(vid, dp_id))

    def _dp_add_vlan(dp, vlan):
        if vlan not in dp.vlans:
            dp.add_vlan(vlan)
            vid_dp[vlan.vid].add(dp.name)

            if len(vid_dp[vlan.vid]) > 1:
                assert not vlan.bgp_routerid, (
                    'DPs %s sharing a BGP speaker VLAN is unsupported' %
                    (str.join(', ', vid_dp[vlan.vid])))

    def _dp_parse_port(dp_id, p_identifier, port_conf, vlans):
        port = Port(p_identifier, port_conf)

        if port.native_vlan is not None:
            v_identifier = port.native_vlan
            vlan = _get_vlan_by_identifier(dp_id, v_identifier, vlans)
            port.native_vlan = vlan
            vlan.add_untagged(port)
        port_tagged_vlans = [
            _get_vlan_by_identifier(dp_id, v_identifier, vlans)
            for v_identifier in port.tagged_vlans
        ]
        port.tagged_vlans = port_tagged_vlans
        for vlan in port.tagged_vlans:
            vlan.add_tagged(port)

        for vlan in port.vlans():
            _dp_add_vlan(dp, vlan)

        return port

    def _dp_add_ports(dp, dp_conf, dp_id, vlans):
        ports_conf = dp_conf.pop('interfaces', {})
        # as users can config port vlan by using vlan name, we store vid in
        # Port instance instead of vlan name for data consistency
        for port_num, port_conf in list(ports_conf.items()):
            port = _dp_parse_port(dp_id, port_num, port_conf, vlans)
            dp.add_port(port)

    try:
        for identifier, dp_conf in list(dps_conf.items()):
            dp = DP(identifier, dp_conf)
            dp.sanity_check()
            dp_id = dp.dp_id

            vlans = {}
            for vlan_ident, vlan_conf in list(vlans_conf.items()):
                vlans[vlan_ident] = VLAN(vlan_ident, dp_id, vlan_conf)
            acls = []
            for acl_ident, acl_conf in list(acls_conf.items()):
                acls.append((acl_ident, ACL(acl_ident, acl_conf)))
            for router_ident, router_conf in list(routers_conf.items()):
                router = Router(router_ident, router_conf)
                dp.add_router(router_ident, router)
            for meter_ident, meter_conf in list(meters_conf.items()):
                dp.meters[meter_ident] = Meter(meter_ident, meter_conf)
            _dp_add_ports(dp, dp_conf, dp_id, vlans)
            for acl_ident, acl in acls:
                dp.add_acl(acl_ident, acl)
            dps.append(dp)

        for dp in dps:
            dp.finalize_config(dps)
        for dp in dps:
            dp.resolve_stack_topology(dps)

    except AssertionError as err:
        logger.exception('Error in config file: %s', err)
        return None

    return dps
예제 #4
0
def _parse_meters(dp, meters_conf):
    for meter_key, meter_conf in meters_conf.items():
        meter = Meter(meter_key, dp.dp_id, meter_conf)
        dp.meters[meter_key] = meter
예제 #5
0
def _parse_meters(dp, meters_conf): # pylint: disable=invalid-name
    for meter_key, meter_conf in meters_conf.items():
        meter = Meter(meter_key, dp.dp_id, meter_conf)
        dp.meters[meter_key] = meter
예제 #6
0
def _dp_parser_v2(acls_conf, dps_conf, meters_conf,
                  routers_conf, vlans_conf):
    dps = []
    vid_dp = collections.defaultdict(set)

    def _get_vlan_by_identifier(dp_id, vlan_ident, vlans):
        if vlan_ident in vlans:
            return vlans[vlan_ident]
        for vlan in list(vlans.values()):
            if vlan_ident == str(vlan.vid):
                return vlan
        # Create VLAN with VID, if not defined.
        return vlans.setdefault(vlan_ident, VLAN(vlan_ident, dp_id))

    def _dp_add_vlan(dp, vlan):
        if vlan not in dp.vlans:
            dp.add_vlan(vlan)
            vid_dp[vlan.vid].add(dp.name)

            if len(vid_dp[vlan.vid]) > 1:
                assert not vlan.bgp_routerid, (
                    'DPs %s sharing a BGP speaker VLAN is unsupported' % (
                        str.join(', ', vid_dp[vlan.vid])))

    def _dp_parse_port(dp_id, p_identifier, port_conf, vlans):
        port = Port(p_identifier, dp_id, port_conf)

        if port.native_vlan is not None:
            v_identifier = port.native_vlan
            vlan = _get_vlan_by_identifier(dp_id, v_identifier, vlans)
            port.native_vlan = vlan
            vlan.add_untagged(port)
        port_tagged_vlans = [
            _get_vlan_by_identifier(dp_id, v_identifier, vlans) for v_identifier in port.tagged_vlans]
        port.tagged_vlans = port_tagged_vlans
        for vlan in port.tagged_vlans:
            vlan.add_tagged(port)
        return port

    def _dp_add_ports(dp, dp_conf, dp_id, vlans):
        ports_conf = dp_conf.get('interfaces', {})
        port_ranges_conf = dp_conf.get('interface_ranges', {})
        # as users can config port vlan by using vlan name, we store vid in
        # Port instance instead of vlan name for data consistency
        assert isinstance(ports_conf, dict), 'Invalid syntax in interface config '
        assert isinstance(port_ranges_conf, dict), 'Invalid syntax in interface ranges config'
        port_num_to_port_conf = {}
        for port_ident, port_conf in list(ports_conf.items()):
            assert isinstance(port_conf, dict), 'Invalid syntax in port config'
            if 'number' in port_conf:
                port_num = port_conf['number']
            else:
                port_num = port_ident
            try:
                port_num_to_port_conf[port_num] = (port_ident, port_conf)
            except TypeError:
                assert False, 'Invalid syntax in port config'
        for port_range, port_conf in list(port_ranges_conf.items()):
            # port range format: 1-6 OR 1-6,8-9 OR 1-3,5,7-9
            assert isinstance(port_conf, dict), 'Invalid syntax in port conig'
            port_nums = set()
            if 'number' in port_conf:
                del port_conf['number']
            for range_ in re.findall(r'(\d+-\d+)', port_range):
                start_num, end_num = [int(num) for num in range_.split('-')]
                assert start_num < end_num, (
                    'Incorrect port range (%d - %d)' % (start_num, end_num))
                port_nums.update(list(range(start_num, end_num + 1)))
                port_range = re.sub(range_, '', port_range)
            other_nums = [int(p) for p in re.findall(r'\d+', port_range)]
            port_nums.update(other_nums)
            assert len(port_nums) > 0, 'interface-ranges contain invalid config'
            for port_num in port_nums:
                if port_num in port_num_to_port_conf:
                    # port range config has lower priority than individual port config
                    for attr, value in list(port_conf.items()):
                        port_num_to_port_conf[port_num][1].setdefault(attr, value)
                else:
                    port_num_to_port_conf[port_num] = (port_num, port_conf)
        for port_num, port_conf in list(port_num_to_port_conf.values()):
            port = _dp_parse_port(dp_id, port_num, port_conf, vlans)
            dp.add_port(port)
        for vlan in list(vlans.values()):
            if vlan.get_ports():
                _dp_add_vlan(dp, vlan)

    for identifier, dp_conf in list(dps_conf.items()):
        assert isinstance(dp_conf, dict)
        dp = DP(identifier, dp_conf.get('dp_id', None), dp_conf)
        dp_id = dp.dp_id

        vlans = {}
        for vlan_ident, vlan_conf in list(vlans_conf.items()):
            vlans[vlan_ident] = VLAN(vlan_ident, dp_id, vlan_conf)
        for acl_ident, acl_conf in list(acls_conf.items()):
            acl = ACL(acl_ident, dp_id, acl_conf)
            dp.add_acl(acl_ident, acl)
        for router_ident, router_conf in list(routers_conf.items()):
            router = Router(router_ident, dp_id, router_conf)
            dp.add_router(router_ident, router)
        for meter_ident, meter_conf in list(meters_conf.items()):
            dp.meters[meter_ident] = Meter(meter_ident, dp_id, meter_conf)
        _dp_add_ports(dp, dp_conf, dp_id, vlans)
        dps.append(dp)

    for dp in dps:
        dp.finalize_config(dps)
    for dp in dps:
        dp.resolve_stack_topology(dps)

    return dps