Exemple #1
0
    def _parse_subnets(self, subnets, link_name):
        networks = []

        if not subnets or not isinstance(subnets, list):
            LOG.warning("Subnets '%s' is empty or not a list.", subnets)
            return networks

        for subnet in subnets:
            if not isinstance(subnet, dict):
                LOG.warning("Subnet '%s' is not a dictionary", subnet)
                continue

            if subnet.get("type") in ["dhcp", "dhcp6"]:
                continue

            routes = []
            for route_data in subnet.get("routes", []):
                route_netmask = route_data.get("netmask")
                route_network = route_data.get("network")
                route_network_cidr = network_utils.ip_netmask_to_cidr(
                    route_network, route_netmask)

                route_gateway = route_data.get("gateway")
                route = network_model.Route(network_cidr=route_network_cidr,
                                            gateway=route_gateway)
                routes.append(route)

            address_cidr = subnet.get("address")
            netmask = subnet.get("netmask")
            if netmask:
                address_cidr = network_utils.ip_netmask_to_cidr(
                    address_cidr, netmask)

            gateway = subnet.get("gateway")
            if gateway:
                # Map the gateway as a default route, depending on the
                # IP family / version (4 or 6)
                gateway_net_cidr = "0.0.0.0/0"
                if netaddr.valid_ipv6(gateway):
                    gateway_net_cidr = "::/0"

                routes.append(
                    network_model.Route(network_cidr=gateway_net_cidr,
                                        gateway=gateway))

            networks.append(
                network_model.Network(
                    link=link_name,
                    address_cidr=address_cidr,
                    dns_nameservers=subnet.get("dns_nameservers"),
                    routes=routes))

        return networks
    def _parse_network_data_networks(networks_data):
        networks = []
        for network_data in networks_data:
            network_type = network_data.get("type")
            if network_type not in [NETWORK_TYPE_IPV4, NETWORK_TYPE_IPV6]:
                continue

            link_id = network_data.get("link")
            ip_address = network_data.get("ip_address")
            netmask = network_data.get("netmask")
            address_cidr = network_utils.ip_netmask_to_cidr(
                ip_address, netmask)

            routes = []
            for route_data in network_data.get("routes", []):
                gateway = route_data.get("gateway")
                network = route_data.get("network")
                netmask = route_data.get("netmask")
                network_cidr = network_utils.ip_netmask_to_cidr(
                    network, netmask)

                route = network_model.Route(network_cidr=network_cidr,
                                            gateway=gateway)
                routes.append(route)

            dns_nameservers = BaseOpenStackService._parse_dns_data(
                network_data.get("services", []))

            network = network_model.Network(link=link_id,
                                            address_cidr=address_cidr,
                                            dns_nameservers=dns_nameservers,
                                            routes=routes)
            networks.append(network)

        return networks
    def _get_network_details_v2(self):
        links = []
        link1 = network_model.Link(id=mock.sentinel.link_id1,
                                   name=mock.sentinel.link_name1,
                                   type=network_model.LINK_TYPE_PHYSICAL,
                                   enabled=mock.sentinel.link_enabled1,
                                   mac_address=mock.sentinel.link_mac1,
                                   mtu=mock.sentinel.link_mtu1,
                                   bond=None,
                                   vlan_link=None,
                                   vlan_id=None)
        links.append(link1)

        bond1 = network_model.Bond(members=[mock.sentinel.link_id1],
                                   type=mock.sentinel.bond_type1,
                                   lb_algorithm=mock.sentinel.bond_lb_algo1,
                                   lacp_rate=mock.sentinel.lacp_rate1)

        bond_link1 = network_model.Link(
            id=mock.sentinel.bond_link_id1,
            name=mock.sentinel.bond_link_name1,
            type=network_model.LINK_TYPE_BOND,
            enabled=mock.sentinel.bond_link_enabled1,
            mac_address=mock.sentinel.bond_link_mac1,
            mtu=mock.sentinel.bond_link_mtu1,
            bond=bond1,
            vlan_link=None,
            vlan_id=None)
        links.append(bond_link1)

        vlan_link1 = network_model.Link(
            id=mock.sentinel.vlan_link_id1,
            name=mock.sentinel.vlan_link_name1,
            type=network_model.LINK_TYPE_VLAN,
            enabled=mock.sentinel.vlan_link_enabled1,
            mac_address=mock.sentinel.vlan_link_mac1,
            mtu=mock.sentinel.vlan_link_mtu1,
            bond=None,
            vlan_link=mock.sentinel.bond_link_id1,
            vlan_id=mock.sentinel.vlan_id1)
        links.append(vlan_link1)

        networks = []
        route1 = network_model.Route(network_cidr=mock.sentinel.network_cidr1,
                                     gateway=mock.sentinel.gateway1)

        route2 = network_model.Route(network_cidr=mock.sentinel.network_cidr2,
                                     gateway=mock.sentinel.gateway2)

        network1 = network_model.Network(
            link=mock.sentinel.link_id1,
            address_cidr=mock.sentinel.address_cidr1,
            dns_nameservers=mock.sentinel.network_dns_list1,
            routes=[route1, route2])
        networks.append(network1)

        services = []
        service1 = network_model.NameServerService(
            addresses=[mock.sentinel.dns1, mock.sentinel.dns3],
            search=mock.sentinel.dns_search1)
        services.append(service1)

        return network_model.NetworkDetailsV2(links=links,
                                              networks=networks,
                                              services=services)
    def _test_get_network_details_v2(self,
                                     mock_get_network_data,
                                     unsupported_version=False,
                                     invalid_bond_type=False,
                                     invalid_bond_lb_algo=False,
                                     unsupported_config_type=False):
        mock.sentinel.bond_subnet_address1 = "10.0.0.1/24"
        mock.sentinel.bond_subnet_gateway1 = "10.0.0.254"
        mock.sentinel.bond_subnet_address2 = "172.16.0.1/16"
        mock.sentinel.vlan_subnet_address1 = "2001:cdba::3257:9652/24"
        mock.sentinel.vlan_subnet_gateway1 = "2001:cdba::3257:1"

        if invalid_bond_type:
            mock.sentinel.bond_mode1 = "invalid bond type"
        else:
            mock.sentinel.bond_mode1 = network_model.BOND_TYPE_BALANCE_ALB

        if invalid_bond_lb_algo:
            mock.sentinel.bond_lb_algo1 = "invalid lb algorithm"
        else:
            mock.sentinel.bond_lb_algo1 = network_model.BOND_LB_ALGO_L2

        if unsupported_version:
            mock.sentinel.network_data_version = "unsupported"
        else:
            mock.sentinel.network_data_version = 1

        if unsupported_config_type:
            mock.sentinel.nameserver_config_type = "unsupported"
        else:
            mock.sentinel.nameserver_config_type = "nameserver"

        network_data = self._get_network_data()
        mock_get_network_data.return_value = network_data

        if (unsupported_version or invalid_bond_type or invalid_bond_lb_algo
                or unsupported_config_type):
            with self.assertRaises(exception.CloudbaseInitException):
                self._maasservice.get_network_details_v2()
            return

        network_details = self._maasservice.get_network_details_v2()

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_PHYSICAL and l.id ==
                mock.sentinel.link_id1 and l.name == mock.sentinel.link_name1
                and l.enabled is True and l.mac_address ==
                mock.sentinel.link_mac1 and l.mtu == mock.sentinel.link_mtu1
            ]))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_PHYSICAL and l.id ==
                mock.sentinel.link_id2 and l.name == mock.sentinel.link_name2
                and l.enabled is True and l.mac_address ==
                mock.sentinel.link_mac2 and l.mtu == mock.sentinel.link_mtu2
            ]))

        # Disconnected network adapter, ensure it's not enabled
        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_PHYSICAL and l.id ==
                mock.sentinel.link_id3 and l.name == mock.sentinel.link_name3
                and l.enabled is False and l.mac_address ==
                mock.sentinel.link_mac3 and l.mtu == mock.sentinel.link_mtu3
            ]))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_BOND
                and l.id == mock.sentinel.bond_id1 and l.enabled is True
                and l.name == mock.sentinel.bond_name1 and l.mtu == mock.
                sentinel.bond_mtu1 and l.mac_address == mock.sentinel.bond_mac1
                and l.vlan_link is None and l.vlan_id is None and l.bond.type
                == network_model.BOND_TYPE_BALANCE_ALB and l.bond.members ==
                [mock.sentinel.link_id1, mock.sentinel.link_id2]
                and l.bond.lb_algorithm == network_model.BOND_LB_ALGO_L2
                and l.bond.lacp_rate == network_model.BOND_LACP_RATE_FAST
            ]))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_VLAN and l.id == mock.
                sentinel.vlan_link_id1 and l.name == mock.sentinel.vlan_name1
                and l.enabled is True and l.mac_address is None
                and l.mtu == mock.sentinel.vlan_mtu1 and l.vlan_link ==
                mock.sentinel.bond_id1 and l.vlan_id == mock.sentinel.vlan_id1
            ]))

        self.assertEqual(3, len(network_details.networks))

        network_bond1 = [
            n for n in network_details.networks
            if n.address_cidr == mock.sentinel.bond_subnet_address1
            and n.dns_nameservers ==
            [mock.sentinel.bond_subnet_dns1, mock.sentinel.bond_subnet_dns2]
            and n.link == mock.sentinel.bond_id1 and n.routes == [
                network_model.Route(network_cidr=u'0.0.0.0/0',
                                    gateway=mock.sentinel.bond_subnet_gateway1)
            ]
        ]
        self.assertEqual(1, len(network_bond1))

        network_bond2 = [
            n for n in network_details.networks
            if n.address_cidr == mock.sentinel.bond_subnet_address2
            and n.dns_nameservers == [] and n.link == mock.sentinel.bond_id1
            and n.routes == []
        ]
        self.assertEqual(1, len(network_bond2))

        network_vlan1 = [
            n for n in network_details.networks
            if n.address_cidr == mock.sentinel.vlan_subnet_address1
            and n.dns_nameservers == []
            and n.link == mock.sentinel.vlan_link_id1 and n.routes == [
                network_model.Route(network_cidr=u'::/0',
                                    gateway=mock.sentinel.vlan_subnet_gateway1)
            ]
        ]
        self.assertEqual(1, len(network_vlan1))

        self.assertEqual([
            network_model.NameServerService(addresses=[
                mock.sentinel.bond_subnet_dns1, mock.sentinel.bond_subnet_dns2
            ],
                                            search=[mock.sentinel.dns_search1])
        ], network_details.services)
    def _parse_config_link(config):
        link_id = config.get("id")
        name = config.get("name")
        mac = config.get("mac_address")
        mtu = config.get("mtu")
        maas_link_type = config.get("type")
        subnets = config.get("subnets", [])
        params = config.get("params", {})
        bond = None
        vlan_id = None
        vlan_link = None
        link_enabled = False

        if maas_link_type == MAAS_CONFIG_TYPE_PHYSICAL:
            link_type = network_model.LINK_TYPE_PHYSICAL
            link_enabled = MaaSHttpService._is_link_enabled(subnets)
        elif maas_link_type == MAAS_CONFIG_TYPE_BOND:
            link_type = network_model.LINK_TYPE_BOND
            bond_interfaces = config.get("bond_interfaces")
            bond_mode = params.get("bond-mode")
            bond_xmit_hash_policy = params.get("bond-xmit-hash-policy")
            maas_bond_lacp_rate = params.get("bond-lacp-rate")

            if bond_mode not in network_model.AVAILABLE_BOND_TYPES:
                raise exception.CloudbaseInitException(
                    "Unsupported bond mode: %s" % bond_mode)

            if (bond_xmit_hash_policy is not None and bond_xmit_hash_policy
                    not in network_model.AVAILABLE_BOND_LB_ALGORITHMS):
                raise exception.CloudbaseInitException(
                    "Unsupported bond hash policy: %s" % bond_xmit_hash_policy)

            bond = network_model.Bond(
                members=bond_interfaces,
                type=bond_mode,
                lb_algorithm=bond_xmit_hash_policy,
                lacp_rate=BOND_LACP_RATE_MAP.get(maas_bond_lacp_rate))
            link_enabled = True
        elif maas_link_type == MAAS_CONFIG_TYPE_VLAN:
            link_type = network_model.LINK_TYPE_VLAN
            vlan_link = config.get("vlan_link")
            vlan_id = config.get("vlan_id")
            link_enabled = True
        else:
            raise exception.CloudbaseInitException(
                "Unsupported MAAS link type: %s" % maas_link_type)

        link = network_model.Link(id=link_id,
                                  name=name,
                                  type=link_type,
                                  enabled=link_enabled,
                                  mac_address=mac,
                                  mtu=mtu,
                                  bond=bond,
                                  vlan_id=vlan_id,
                                  vlan_link=vlan_link)

        networks = []
        subnets = config.get("subnets", [])
        for subnet in subnets:
            maas_subnet_type = subnet.get("type")
            if maas_subnet_type == MAAS_SUBNET_TYPE_STATIC:
                address_cidr = subnet.get("address")
                gateway = subnet.get("gateway")
                dns_nameservers = subnet.get("dns_nameservers")

                # TODO(alexpilotti): Add support for extra routes
                if gateway is not None:
                    if netaddr.valid_ipv6(gateway):
                        default_network_cidr = u"::/0"
                    else:
                        default_network_cidr = u"0.0.0.0/0"

                    routes = [
                        network_model.Route(network_cidr=default_network_cidr,
                                            gateway=gateway)
                    ]
                else:
                    routes = []
                net = network_model.Network(
                    link=link_id,
                    address_cidr=address_cidr,
                    dns_nameservers=dns_nameservers,
                    routes=routes,
                )
                networks.append(net)

        return link, networks
Exemple #6
0
    def _test_get_network_details_v2(self,
                                     mock_get_network_data,
                                     invalid_bond_type=False,
                                     invalid_bond_lb_algo=False):
        mock.sentinel.ip_address1 = "10.0.0.1"
        mock.sentinel.netmask1 = "255.255.255.0"
        mock.sentinel.route_network1 = "172.16.0.0"
        mock.sentinel.route_netmask1 = "255.255.0.0"
        mock.sentinel.route_gateway1 = "172.16.1.1"
        mock.sentinel.route_network2 = "0.0.0.0"
        mock.sentinel.route_netmask2 = "0.0.0.0"
        mock.sentinel.route_gateway2 = "10.0.0.254"
        mock.sentinel.ip_address_ipv61 = "2001:cdba::3257:9652/24"
        mock.sentinel.route_network_ipv61 = "::/0"
        mock.sentinel.route_gateway_ipv61 = "fd00::1"

        if invalid_bond_type:
            mock.sentinel.bond_type1 = "invalid bond type"
        else:
            mock.sentinel.bond_type1 = network_model.BOND_TYPE_ACTIVE_BACKUP

        if invalid_bond_lb_algo:
            mock.sentinel.bond_lb_algo1 = "invalid lb algorithm"
        else:
            mock.sentinel.bond_lb_algo1 = network_model.BOND_LB_ALGO_L2

        network_data = self._get_network_data()

        mock_get_network_data.return_value = network_data

        if invalid_bond_type or invalid_bond_lb_algo:
            with self.assertRaises(exception.CloudbaseInitException):
                self._service.get_network_details_v2()
            return

        network_details = self._service.get_network_details_v2()

        self.assertEqual(len(network_data["links"]),
                         len(network_details.links))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_PHYSICAL and l.id ==
                mock.sentinel.link_id1 and l.name == mock.sentinel.link_id1
                and l.mac_address == mock.sentinel.link_mac1
                and l.mtu == mock.sentinel.link_mtu1
            ]))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_PHYSICAL and l.id ==
                mock.sentinel.link_id2 and l.name == mock.sentinel.link_id2
                and l.mac_address == mock.sentinel.link_mac2
                and l.mtu == mock.sentinel.link_mtu2
            ]))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_BOND and l.id ==
                mock.sentinel.bond_id1 and l.name == mock.sentinel.bond_id1
                and l.mtu == mock.sentinel.bond_mtu1
                and l.mac_address == mock.sentinel.bond_mac1
                and l.vlan_link is None and l.vlan_id is None and l.bond.type
                == network_model.BOND_TYPE_ACTIVE_BACKUP and l.bond.members ==
                [mock.sentinel.link_id1, mock.sentinel.link_id2]
                and l.bond.lb_algorithm == network_model.BOND_LB_ALGO_L2
                and l.bond.lacp_rate is None
            ]))

        self.assertEqual(
            1,
            len([
                l for l in network_details.links
                if l.type == network_model.LINK_TYPE_VLAN and l.id ==
                mock.sentinel.vlan_link_id1 and l.name == mock.sentinel.
                vlan_link_id1 and l.mac_address == mock.sentinel.vlan_mac1
                and l.mtu == mock.sentinel.vlan_mtu1 and l.vlan_link ==
                mock.sentinel.bond_id1 and l.vlan_id == mock.sentinel.vlan_id1
            ]))

        self.assertEqual(
            len([
                n for n in network_data["networks"] if n["type"] in [
                    baseopenstackservice.NETWORK_TYPE_IPV4,
                    baseopenstackservice.NETWORK_TYPE_IPV6
                ]
            ]), len(network_details.networks))

        def _get_cidr_address(ip_address, netmask):
            prefix_len = netaddr.IPNetwork(u"%s/%s" %
                                           (ip_address, netmask)).prefixlen
            return u"%s/%s" % (ip_address, prefix_len)

        address_cidr = _get_cidr_address(mock.sentinel.ip_address1,
                                         mock.sentinel.netmask1)

        network = [
            n for n in network_details.networks
            if n.address_cidr == address_cidr
            and n.dns_nameservers == [mock.sentinel.dns1, mock.sentinel.dns2]
            and n.link == mock.sentinel.bond_id1
        ]
        self.assertEqual(1, len(network))

        network_cidr1 = _get_cidr_address(mock.sentinel.route_network1,
                                          mock.sentinel.route_netmask1)

        network_cidr2 = _get_cidr_address(mock.sentinel.route_network2,
                                          mock.sentinel.route_netmask2)

        self.assertEqual([
            network_model.Route(network_cidr=network_cidr1,
                                gateway=mock.sentinel.route_gateway1),
            network_model.Route(network_cidr=network_cidr2,
                                gateway=mock.sentinel.route_gateway2)
        ], network[0].routes)

        network_ipv6 = [
            n for n in network_details.networks
            if n.address_cidr == mock.sentinel.ip_address_ipv61
            and n.link == mock.sentinel.bond_id1
        ]
        self.assertEqual(1, len(network_ipv6))

        self.assertEqual([
            network_model.NameServerService(
                addresses=[mock.sentinel.dns3, mock.sentinel.dns4],
                search=None)
        ], network_details.services)
    def test_network_details_v2(self):
        expected_bond = nm.Bond(
            members=["gbe0", "gbe1"],
            type=nm.BOND_TYPE_ACTIVE_BACKUP,
            lb_algorithm=None,
            lacp_rate=None,
        )
        expected_link_bond = nm.Link(
            id='bond0',
            name='bond0',
            type=nm.LINK_TYPE_BOND,
            enabled=True,
            mac_address="52:54:00:12:34:00",
            mtu=1450,
            bond=expected_bond,
            vlan_link=None,
            vlan_id=None,
        )
        expected_link = nm.Link(
            id='interface0',
            name='interface0',
            type=nm.LINK_TYPE_PHYSICAL,
            enabled=True,
            mac_address="52:54:00:12:34:00",
            mtu=1450,
            bond=None,
            vlan_link=None,
            vlan_id=None,
        )
        expected_link_vlan = nm.Link(
            id='vlan0',
            name='vlan0',
            type=nm.LINK_TYPE_VLAN,
            enabled=True,
            mac_address="52:54:00:12:34:00",
            mtu=1450,
            bond=None,
            vlan_link='eth1',
            vlan_id=150,
        )
        expected_network = nm.Network(
            link='interface0',
            address_cidr='192.168.1.10/24',
            dns_nameservers=['192.168.1.11'],
            routes=[nm.Route(network_cidr='0.0.0.0/0', gateway="192.168.1.1")])

        expected_network_bond = nm.Network(
            link='bond0',
            address_cidr='192.168.1.10/24',
            dns_nameservers=['192.168.1.11'],
            routes=[],
        )

        expected_network_vlan = nm.Network(
            link='vlan0',
            address_cidr='192.168.1.10/24',
            dns_nameservers=['192.168.1.11'],
            routes=[],
        )
        expected_nameservers = nm.NameServerService(
            addresses=['192.168.23.2', '8.8.8.8'], search='acme.local')

        parser_data = """
           - type: physical
             name: interface0
             mac_address: "52:54:00:12:34:00"
             mtu: 1450
             subnets:
                - type: static
                  address: 192.168.1.10
                  netmask: 255.255.255.0
                  gateway: 192.168.1.1
                  dns_nameservers:
                    - 192.168.1.11
           - type: bond
             name: bond0
             bond_interfaces:
               - gbe0
               - gbe1
             mac_address: "52:54:00:12:34:00"
             params:
               bond-mode: active-backup
               bond-lacp-rate: false
             mtu: 1450
             subnets:
                - type: static
                  address: 192.168.1.10
                  netmask: 255.255.255.0
                  dns_nameservers:
                    - 192.168.1.11
           - type: vlan
             name: vlan0
             vlan_link: eth1
             vlan_id: 150
             mac_address: "52:54:00:12:34:00"
             mtu: 1450
             subnets:
                - type: static
                  address: 192.168.1.10
                  netmask: 255.255.255.0
                  dns_nameservers:
                    - 192.168.1.11
           - type: nameserver
             address:
               - 192.168.23.2
               - 8.8.8.8
             search: acme.local
        """

        result = self._parser.parse(serialization.parse_json_yaml(parser_data))

        self.assertEqual(result.links[0], expected_link)
        self.assertEqual(result.networks[0], expected_network)

        self.assertEqual(result.links[1], expected_link_bond)
        self.assertEqual(result.networks[1], expected_network_bond)

        self.assertEqual(result.links[2], expected_link_vlan)
        self.assertEqual(result.networks[2], expected_network_vlan)

        self.assertEqual(result.services[0], expected_nameservers)