def get_network_details_v2(self): network_data = self._get_network_data() if not network_data: return version = network_data.get("version") if version != 1: raise exception.CloudbaseInitException( 'Unsupported MAAS network metadata version: %s' % version) links = [] networks = [] services = [] config = network_data.get("config", []) for config_item in config: link, link_networks, service = self._parse_config_item(config_item) if link: links.append(link) if link_networks: networks.extend(link_networks), if service: services.append(service) self._enable_bond_physical_links(links) return network_model.NetworkDetailsV2(links=links, networks=networks, services=services)
def _parse_nameserver_config_item(self, item): return network_model.NetworkDetailsV2( links=[], networks=[], services=[ network_model.NameServerService(addresses=item.get( 'address', []), search=item.get('search')) ])
def get_network_details_v2(self): network_data = self._get_network_data() links = self._parse_network_data_links(network_data.get("links", [])) networks = self._parse_network_data_networks( network_data.get("networks", [])) services = self._parse_network_data_services( network_data.get("services", [])) return network_model.NetworkDetailsV2(links=links, networks=networks, services=services)
def _parse_bond_config_item(self, item): if not item.get('name'): LOG.warning("Bond does not have a name.") return bond_params = item.get('params') if not bond_params: LOG.warning("Bond does not have parameters") return bond_mode = bond_params.get('bond-mode') if bond_mode not in network_model.AVAILABLE_BOND_TYPES: raise exception.CloudbaseInitException( "Unsupported bond mode: %s" % bond_mode) bond_lacp_rate = None if bond_mode == network_model.BOND_TYPE_8023AD: bond_lacp_rate = bond_params.get('bond-lacp-rate') if (bond_lacp_rate and bond_lacp_rate not in network_model.AVAILABLE_BOND_LACP_RATES): raise exception.CloudbaseInitException( "Unsupported bond lacp rate: %s" % bond_lacp_rate) bond_xmit_hash_policy = bond_params.get('xmit_hash_policy') if (bond_xmit_hash_policy 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_interfaces = item.get('bond_interfaces') bond = network_model.Bond( members=bond_interfaces, type=bond_mode, lb_algorithm=bond_xmit_hash_policy, lacp_rate=bond_lacp_rate, ) link = network_model.Link(id=item.get('name'), name=item.get('name'), type=network_model.LINK_TYPE_BOND, enabled=True, mac_address=item.get('mac_address'), mtu=item.get('mtu'), bond=bond, vlan_link=None, vlan_id=None) return network_model.NetworkDetailsV2(links=[link], networks=self._parse_subnets( item.get("subnets"), link.name), services=[])
def get_network_details_v2(self): try: network_data = self._get_network_data() except base.NotExistingMetadataException: LOG.info("V2 network metadata not found") return links = self._parse_network_data_links(network_data.get("links", [])) networks = self._parse_network_data_networks( network_data.get("networks", [])) services = self._parse_network_data_services( network_data.get("services", [])) return network_model.NetworkDetailsV2(links=links, networks=networks, services=services)
def _parse_physical_config_item(self, item): if not item.get('name'): LOG.warning("Physical NIC does not have a name.") return link = network_model.Link(id=item.get('name'), name=item.get('name'), type=network_model.LINK_TYPE_PHYSICAL, enabled=True, mac_address=item.get('mac_address'), mtu=item.get('mtu'), bond=None, vlan_link=None, vlan_id=None) return network_model.NetworkDetailsV2(links=[link], networks=self._parse_subnets( item.get("subnets"), link.name), services=[])
def parse(self, network_config): links = [] networks = [] services = [] if not network_config: LOG.warning("Network configuration is empty") return if not isinstance(network_config, list): LOG.warning("Network config '%s' is not a list.", network_config) return for network_config_item in network_config: if not isinstance(network_config_item, dict): LOG.warning("Network config item '%s' is not a dictionary", network_config_item) continue net_conf_type = network_config_item.get("type") if net_conf_type not in self.SUPPORTED_NETWORK_CONFIG_TYPES: LOG.warning("Network config type '%s' is not supported", net_conf_type) continue net_details = (self._get_network_config_parser(net_conf_type)( network_config_item)) if net_details: links += net_details.links networks += net_details.networks services += net_details.services return network_model.NetworkDetailsV2(links=links, networks=networks, services=services)
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)
class TestNoCloudNetworkConfigV1Parser(unittest.TestCase): def setUp(self): module = importlib.import_module(MODULE_PATH) self._parser = module.NoCloudNetworkConfigV1Parser() self.snatcher = testutils.LogSnatcher(MODULE_PATH) @ddt.data( ('', ('Network configuration is empty', None)), ('{t: 1}', ("Network config '{'t': 1}' is not a list", None)), ('["1"]', ("Network config item '1' is not a dictionary", nm.NetworkDetailsV2(links=[], networks=[], services=[]))), ('[{"type": "router"}]', ("Network config type 'router' is not supported", nm.NetworkDetailsV2(links=[], networks=[], services=[])))) @ddt.unpack def test_parse_empty_result(self, input, expected_result): with self.snatcher: result = self._parser.parse(serialization.parse_json_yaml(input)) self.assertEqual(True, expected_result[0] in self.snatcher.output[0]) self.assertEqual(result, expected_result[1]) 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)