diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index b1ad117d25..15d6682359 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -87,6 +87,7 @@ def parse_device(device): lo_prefix = None lo_prefix_v6 = None mgmt_prefix = None + mgmt_prefix_v6 = None d_type = None # don't shadow type() hwsku = None name = None @@ -101,6 +102,8 @@ def parse_device(device): lo_prefix_v6 = node.find(str(QName(ns2, "IPPrefix"))).text elif node.tag == str(QName(ns, "ManagementAddress")): mgmt_prefix = node.find(str(QName(ns2, "IPPrefix"))).text + elif node.tag == str(QName(ns, "ManagementAddressV6")): + mgmt_prefix_v6 = node.find(str(QName(ns2, "IPPrefix"))).text elif node.tag == str(QName(ns, "Hostname")): name = node.text elif node.tag == str(QName(ns, "HwSku")): @@ -117,7 +120,7 @@ def parse_device(device): if d_type is None and str(QName(ns3, "type")) in device.attrib: d_type = device.attrib[str(QName(ns3, "type"))] - return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster, d_subtype) + return (lo_prefix, lo_prefix_v6, mgmt_prefix, mgmt_prefix_v6, name, hwsku, d_type, deployment_id, cluster, d_subtype) def calculate_lcm_for_ecmp (nhdevices_bank_map, nhip_bank_map): @@ -254,7 +257,7 @@ def parse_png(png, hname, dpg_ecmp_content = None): if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): - (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster, d_subtype) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, mgmt_prefix_v6, name, hwsku, d_type, deployment_id, cluster, d_subtype) = parse_device(device) device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku} if cluster: device_data['cluster'] = cluster @@ -387,7 +390,7 @@ def parse_asic_png(png, asic_name, hostname): if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): - (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster, _) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, mgmt_prefix_v6, name, hwsku, d_type, deployment_id, cluster, _) = parse_device(device) device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } if cluster: device_data['cluster'] = cluster @@ -1836,7 +1839,7 @@ def get_mux_cable_entries(mux_cable_ports, neighbors, devices): def parse_device_desc_xml(filename): root = ET.parse(filename).getroot() - (lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _, _, _) = parse_device(root) + (lo_prefix, lo_prefix_v6, mgmt_prefix, mgmt_prefix_v6, hostname, hwsku, d_type, _, _, _) = parse_device(root) results = {} results['DEVICE_METADATA'] = {'localhost': { @@ -1848,10 +1851,18 @@ def parse_device_desc_xml(filename): if lo_prefix_v6: results['LOOPBACK_INTERFACE'] = {('lo_v6', lo_prefix_v6): {}} - mgmt_intf = {} - mgmtipn = ipaddress.ip_network(UNICODE_TYPE(mgmt_prefix), False) - gwaddr = ipaddress.ip_address((next(mgmtipn.hosts()))) - results['MGMT_INTERFACE'] = {('eth0', mgmt_prefix): {'gwaddr': gwaddr}} + results['MGMT_INTERFACE'] = {} + if mgmt_prefix: + mgmtipn = ipaddress.ip_network(UNICODE_TYPE(mgmt_prefix), False) + if mgmtipn != ipaddress.ip_network(u'0.0.0.0/0', False): + gwaddr = ipaddress.ip_address((next(mgmtipn.hosts()))) + results['MGMT_INTERFACE'].update({('eth0', mgmt_prefix): {'gwaddr': gwaddr}}) + + if mgmt_prefix_v6: + mgmtipn_v6 = ipaddress.ip_network(UNICODE_TYPE(mgmt_prefix_v6), False) + if mgmtipn != ipaddress.ip_network(u'::/0', False): + gwaddr_v6 = ipaddress.ip_address((next(mgmtipn_v6.hosts()))) + results['MGMT_INTERFACE'].update({('eth0', mgmt_prefix_v6): {'gwaddr': gwaddr_v6}}) return results diff --git a/src/sonic-config-engine/tests/simple-sample-device-desc-ipv6-only.xml b/src/sonic-config-engine/tests/simple-sample-device-desc-ipv6-only.xml new file mode 100644 index 0000000000..c35d2354a9 --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-device-desc-ipv6-only.xml @@ -0,0 +1,11 @@ + + switch-t0 + Force10-S6000 + AAA00PrdStr00 + + 0.0.0.0/0 + + + FC00:1::32/64 + + diff --git a/src/sonic-config-engine/tests/simple-sample-device-desc.xml b/src/sonic-config-engine/tests/simple-sample-device-desc.xml new file mode 100644 index 0000000000..72941dfcd9 --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-device-desc.xml @@ -0,0 +1,11 @@ + + switch-t0 + Force10-S6000 + AAA00PrdStr00 + + 10.0.0.100/24 + + + FC00:1::32/64 + + diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py index b475621939..16ad019032 100644 --- a/src/sonic-config-engine/tests/test_minigraph_case.py +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -1,6 +1,7 @@ import json import os import subprocess +import ipaddress import tests.common_utils as utils import minigraph @@ -21,6 +22,8 @@ class TestCfgGenCaseInsensitive(TestCase): self.sample_simple_graph = os.path.join(self.test_dir, 'simple-sample-graph.xml') self.sample_resource_graph = os.path.join(self.test_dir, 'sample-graph-resource-type.xml') self.sample_subintf_graph = os.path.join(self.test_dir, 'sample-graph-subintf.xml') + self.sample_simple_device_desc = os.path.join(self.test_dir, 'simple-sample-device-desc.xml') + self.sample_simple_device_desc_ipv6_only = os.path.join(self.test_dir, 'simple-sample-device-desc-ipv6-only.xml') self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') def run_script(self, argument, check_stderr=False): @@ -463,5 +466,19 @@ class TestCfgGenCaseInsensitive(TestCase): expected_ports.sort() ) + def test_parse_device_desc_xml_mgmt_interface(self): + # Regular device_desc.xml with both IPv4 and IPv6 mgmt address + result = minigraph.parse_device_desc_xml(self.sample_simple_device_desc) + mgmt_intf = result['MGMT_INTERFACE'] + self.assertEqual(len(mgmt_intf.keys()), 2) + self.assertTrue(('eth0', '10.0.0.100/24') in mgmt_intf.keys()) + self.assertTrue(('eth0', 'FC00:1::32/64') in mgmt_intf.keys()) + self.assertTrue(ipaddress.ip_address(u'10.0.0.1') == mgmt_intf[('eth0', '10.0.0.100/24')]['gwaddr']) + self.assertTrue(ipaddress.ip_address(u'fc00:1::1') == mgmt_intf[('eth0', 'FC00:1::32/64')]['gwaddr']) - + # Special device_desc.xml with IPv6 mgmt address only + result = minigraph.parse_device_desc_xml(self.sample_simple_device_desc_ipv6_only) + mgmt_intf = result['MGMT_INTERFACE'] + self.assertEqual(len(mgmt_intf.keys()), 1) + self.assertTrue(('eth0', 'FC00:1::32/64') in mgmt_intf.keys()) + self.assertTrue(ipaddress.ip_address(u'fc00:1::1') == mgmt_intf[('eth0', 'FC00:1::32/64')]['gwaddr'])