From 8acb206778cc7f5e9cb7104455a73fe5954af67e Mon Sep 17 00:00:00 2001 From: Neetha John Date: Thu, 15 Jul 2021 17:33:07 -0700 Subject: [PATCH] [202012] [minigraph] Update parsing logic for Storage backend devices (#8004) Backport #7944 #### Why I did it The current logic generates 'VLAN_SUB_INTERFACE' table if the device type is backend and cluster name contains 'str'. This is not a reliable method to determine a storage backend device #### How I did it Updated the logic to generate 'VLAN_SUB_INTERFACE' table if any of the following conditions hold true 1. device is of type backend and ResourceType attribute is None 2. device is of type backend and ResourceType attribute contains "Storage" 3. device is of type backend and graph contains "Subinterface" section Also updated the logic to set "is_storage_device" to True 1. for Backend, if any of the above conditions hold true 2. for Frontend, if ResourceType attribute contains "Storage" #### How to verify it Added new tests to verify the code changes and built sonic_config_engine-1.0-py3-none-any.whl successfully --- src/sonic-config-engine/minigraph.py | 48 +- .../tests/sample-graph-resource-type.xml | 446 ++++++++++++++++++ .../tests/sample-graph-subintf.xml | 439 +++++++++++++++++ .../tests/simple-sample-graph-case.xml | 5 + src/sonic-config-engine/tests/test_cfggen.py | 128 +++-- .../tests/test_minigraph_case.py | 35 +- 6 files changed, 1040 insertions(+), 61 deletions(-) create mode 100644 src/sonic-config-engine/tests/sample-graph-resource-type.xml create mode 100644 src/sonic-config-engine/tests/sample-graph-subintf.xml diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 39d5948061..b422af4e64 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -181,7 +181,6 @@ def parse_png(png, hname, dpg_ecmp_content = None): port_speeds = {} console_ports = {} mux_cable_ports = {} - is_storage_device = False port_device_map = {} png_ecmp_content = {} FG_NHG_MEMBER = {} @@ -254,10 +253,6 @@ def parse_png(png, hname, dpg_ecmp_content = None): device_data['lo_addr_v6'] = lo_prefix_v6 devices[name] = device_data - if name == hname: - if cluster and "str" in cluster.lower(): - is_storage_device = True - if child.tag == str(QName(ns, "DeviceInterfaceLinks")): for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))): if str(QName(ns3, "type")) in if_link.attrib: @@ -294,7 +289,7 @@ def parse_png(png, hname, dpg_ecmp_content = None): png_ecmp_content = {"FG_NHG_MEMBER": FG_NHG_MEMBER, "FG_NHG": FG_NHG, "NEIGH": NEIGH} - return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content) + return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports, mux_cable_ports, png_ecmp_content) def parse_asic_external_link(link, asic_name, hostname): @@ -403,6 +398,7 @@ def parse_loopback_intf(child): def parse_dpg(dpg, hname): aclintfs = None mgmtintfs = None + subintfs = None tunnelintfs = defaultdict(dict) for child in dpg: """ @@ -442,6 +438,16 @@ def parse_dpg(dpg, hname): ip_intfs_map[ipprefix] = intfalias lo_intfs = parse_loopback_intf(child) + subintfs = child.find(str(QName(ns, "SubInterfaces"))) + if subintfs is not None: + for subintf in subintfs.findall(str(QName(ns, "SubInterface"))): + intfalias = subintf.find(str(QName(ns, "AttachTo"))).text + intfname = port_alias_map.get(intfalias, intfalias) + ipprefix = subintf.find(str(QName(ns, "Prefix"))).text + subintfvlan = subintf.find(str(QName(ns, "Vlan"))).text + subintfname = intfname + VLAN_SUB_INTERFACE_SEPARATOR + subintfvlan + intfs[(subintfname, ipprefix)] = {} + mvrfConfigs = child.find(str(QName(ns, "MgmtVrfConfigs"))) mvrf = {} if mvrfConfigs != None: @@ -1157,7 +1163,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw elif child.tag == str(QName(ns, "CpgDec")): (bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname) elif child.tag == str(QName(ns, "PngDec")): - (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content) = parse_png(child, hostname, dpg_ecmp_content) + (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports, mux_cable_ports, png_ecmp_content) = parse_png(child, hostname, dpg_ecmp_content) elif child.tag == str(QName(ns, "UngDec")): (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname, None) elif child.tag == str(QName(ns, "MetadataDeclaration")): @@ -1223,9 +1229,6 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw results['DEVICE_METADATA']['localhost']['peer_switch'] = list(results['PEER_SWITCH'].keys())[0] - if is_storage_device: - results['DEVICE_METADATA']['localhost']['storage_device'] = "true" - # for this hostname, if sub_role is defined, add sub_role in # device_metadata if sub_role is not None: @@ -1304,6 +1307,9 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw elif intf[0][0:11] == 'PortChannel': pc_intfs[intf] = {} pc_intfs[intf[0]] = {} + elif VLAN_SUB_INTERFACE_SEPARATOR in intf[0]: + vlan_sub_intfs[intf] = {} + vlan_sub_intfs[intf[0]] = {'admin_status': 'up'} else: phyport_intfs[intf] = {} phyport_intfs[intf[0]] = {} @@ -1382,6 +1388,13 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw if port[0] in ports: ports.get(port[0])['admin_status'] = 'up' + if len(vlan_sub_intfs): + for subintf in vlan_sub_intfs: + if not isinstance(subintf, tuple): + parent_port = subintf.split(".")[0] + if parent_port in ports: + ports.get(parent_port)['admin_status'] = 'up' + for member in list(pc_members.keys()) + list(vlan_members.keys()): port = ports.get(member[1]) if port: @@ -1421,9 +1434,16 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw results['PORTCHANNEL_INTERFACE'] = pc_intfs - if current_device['type'] in backend_device_types and is_storage_device: + # for storage backend subinterface info present in minigraph takes precedence over ResourceType + if current_device['type'] in backend_device_types and bool(vlan_sub_intfs): del results['INTERFACE'] del results['PORTCHANNEL_INTERFACE'] + is_storage_device = True + results['VLAN_SUB_INTERFACE'] = vlan_sub_intfs + elif current_device['type'] in backend_device_types and (resource_type is None or 'Storage' in resource_type): + del results['INTERFACE'] + del results['PORTCHANNEL_INTERFACE'] + is_storage_device = True for intf in phyport_intfs.keys(): if isinstance(intf, tuple): @@ -1444,8 +1464,12 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw else: sub_intf = pc_intf + VLAN_SUB_INTERFACE_SEPARATOR + VLAN_SUB_INTERFACE_VLAN_ID vlan_sub_intfs[sub_intf] = {"admin_status" : "up"} - results['VLAN_SUB_INTERFACE'] = vlan_sub_intfs + elif resource_type is not None and 'Storage' in resource_type: + is_storage_device = True + + if is_storage_device: + results['DEVICE_METADATA']['localhost']['storage_device'] = "true" results['VLAN'] = vlans results['VLAN_MEMBER'] = vlan_members diff --git a/src/sonic-config-engine/tests/sample-graph-resource-type.xml b/src/sonic-config-engine/tests/sample-graph-resource-type.xml new file mode 100644 index 0000000000..31f9fc43f2 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-graph-resource-type.xml @@ -0,0 +1,446 @@ + + + + + + switch-t0 + 10.1.0.32 + BGPMonitor + 10.20.30.40 + 30 + 10 + 3 + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 0 + + BGPMonitor + + + BGPPeer +
10.1.0.32
+ + + +
+
+ +
+ + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + PortChannel1001 + fortyGigE0/1;fortyGigE0/2 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + kk1 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2020 + 2020 + Tagged + 192.168.0.0/28 + + + ab2 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2000 + 2000 + 192.168.0.240/27 + + + ab3 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2001 + 2001 + 192.168.0.240/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel1001 + 10.0.0.57/31 + + + + PortChannel1001 + FC00::72/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + 1000 + ARISTA01T1 + et1 + true + switch-t0 + fortyGigE0/8 + true + + + DeviceInterfaceLink + 10000 + switch-t0 + fortyGigE0/1 + true + ARISTA05T1 + Ethernet1/32 + true + + + DeviceInterfaceLink + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA06T1 + Ethernet1/33 + true + + + DeviceMgmtLink + 1000 + switch-t0 + fortyGigE0/16 + true + ChassisMTS1 + mgmt0 + true + + + DeviceMgmtLink + 1000 + switch-t0 + Management1 + switch-m0 + Management1 + true + + + + + switch-t0 + Force10-S6000 + AAA00PrdStr00 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + + DeviceInterface + + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + 1 + Ethernet1 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + 1 + Ethernet2 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + DeviceInterface + + true + 1 + fortyGigE0/16 + + false + 0 + 0 + 100000 + + + true + 0 + Force10-S6000 + + + DeviceInterface + + 1 + Management1 + false + mgmt1 + 1000 + + + + + + + + switch-t0 + + + ResourceType + + Storage + + + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/sample-graph-subintf.xml b/src/sonic-config-engine/tests/sample-graph-subintf.xml new file mode 100644 index 0000000000..4a7ffe2f76 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-graph-subintf.xml @@ -0,0 +1,439 @@ + + + + + + switch-t0 + 10.1.0.32 + BGPMonitor + 10.20.30.40 + 30 + 10 + 3 + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 0 + + BGPMonitor + + + BGPPeer +
10.1.0.32
+ + + +
+
+ +
+ + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + PortChannel1001 + fortyGigE0/1;fortyGigE0/2 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + kk1 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2020 + 2020 + Tagged + 192.168.0.0/28 + + + ab2 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2000 + 2000 + 192.168.0.240/27 + + + ab3 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2001 + 2001 + 192.168.0.240/27 + + + + + + fortyGigE0/0 + 10 + dot1q + 10.0.0.58/31 + 10 + + + + fortyGigE0/0 + 10 + dot1q + FC00::75/126 + 10 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel1001 + 10.0.0.57/31 + + + + PortChannel1001 + FC00::72/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + 1000 + ARISTA01T1 + et1 + true + switch-t0 + fortyGigE0/8 + true + + + DeviceInterfaceLink + 10000 + switch-t0 + fortyGigE0/1 + true + ARISTA05T1 + Ethernet1/32 + true + + + DeviceInterfaceLink + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA06T1 + Ethernet1/33 + true + + + DeviceMgmtLink + 1000 + switch-t0 + fortyGigE0/16 + true + ChassisMTS1 + mgmt0 + true + + + DeviceMgmtLink + 1000 + switch-t0 + Management1 + switch-m0 + Management1 + true + + + + + switch-t0 + Force10-S6000 + AAA00PrdStr00 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + + DeviceInterface + + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + 1 + Ethernet1 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + 1 + Ethernet2 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + DeviceInterface + + true + 1 + fortyGigE0/16 + + false + 0 + 0 + 100000 + + + true + 0 + Force10-S6000 + + + DeviceInterface + + 1 + Management1 + false + mgmt1 + 1000 + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml index 7717157f18..c1015b6b53 100644 --- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -457,6 +457,11 @@ 10.10.10.10 + + ResourceType + + Storage + diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py index c488a3be12..e3f74fb9cf 100644 --- a/src/sonic-config-engine/tests/test_cfggen.py +++ b/src/sonic-config-engine/tests/test_cfggen.py @@ -28,6 +28,8 @@ class TestCfgGen(TestCase): self.output_file = os.path.join(self.test_dir, 'output') self.output2_file = os.path.join(self.test_dir, 'output2') self.ecmp_graph = os.path.join(self.test_dir, 'fg-ecmp-sample-minigraph.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') def tearDown(self): try: @@ -120,8 +122,9 @@ class TestCfgGen(TestCase): output = self.run_script(argument) self.assertEqual(utils.to_dict(output.strip()), utils.to_dict('{\n "k11": "v11"\n}')) - def test_var_json_data(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" --var-json VLAN_MEMBER' + def test_var_json_data(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" --var-json VLAN_MEMBER' output = self.run_script(argument) self.assertEqual( utils.to_dict(output.strip()), @@ -207,8 +210,9 @@ class TestCfgGen(TestCase): output = self.run_script(argument) self.assertEqual(output.strip(), "[('Ethernet0', '10.0.0.58/31'), 'Ethernet0', ('Ethernet0', 'FC00::75/126')]") - def test_minigraph_vlans(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN' + def test_minigraph_vlans(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v VLAN' output = self.run_script(argument) self.assertEqual( utils.to_dict(output.strip()), @@ -220,8 +224,9 @@ class TestCfgGen(TestCase): ) ) - def test_minigraph_vlan_members(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN_MEMBER' + def test_minigraph_vlan_members(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v VLAN_MEMBER' output = self.run_script(argument) self.assertEqual( utils.to_dict(output.strip()), @@ -233,8 +238,9 @@ class TestCfgGen(TestCase): ) ) - def test_minigraph_vlan_interfaces(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()|list"' + def test_minigraph_vlan_interfaces(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()|list"' output = self.run_script(argument) self.assertEqual(output.strip(), "[('Vlan1000', '192.168.0.1/27'), 'Vlan1000']") @@ -265,8 +271,9 @@ class TestCfgGen(TestCase): " 'Vlan31|200:200:200:200::2', 'Vlan31|200:200:200:200::3', 'Vlan31|200:200:200:200::4', 'Vlan31|200:200:200:200::5', " "'Vlan31|200:200:200:200::6', 'Vlan31|200:200:200:200::7', 'Vlan31|200:200:200:200::8', 'Vlan31|200:200:200:200::9']") - def test_minigraph_portchannels(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v PORTCHANNEL' + def test_minigraph_portchannels(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v PORTCHANNEL' output = self.run_script(argument) self.assertEqual( utils.to_dict(output.strip()), @@ -451,14 +458,15 @@ class TestCfgGen(TestCase): output = self.run_script(argument) self.assertEqual(output.strip(), "1") - def test_minigraph_ethernet_interfaces(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet8\']"' + def test_minigraph_ethernet_interfaces(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet8\']"' output = self.run_script(argument) self.assertEqual( utils.to_dict(output.strip()), utils.to_dict("{'lanes': '37,38,39,40', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '1000'}") ) - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet12\']"' + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet12\']"' output = self.run_script(argument) self.assertEqual( utils.to_dict(output.strip()), @@ -507,8 +515,9 @@ class TestCfgGen(TestCase): ) ) - def test_minigraph_extra_ethernet_interfaces(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT"' + def test_minigraph_extra_ethernet_interfaces(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "PORT"' output = self.run_script(argument) self.assertEqual( @@ -568,13 +577,15 @@ class TestCfgGen(TestCase): output = self.run_script(argument) self.assertEqual(utils.to_dict(output.strip()), utils.to_dict("{'10.0.10.1': {}, '10.0.10.2': {}}")) - def test_minigraph_vnet(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VNET"' + def test_minigraph_vnet(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "VNET"' output = self.run_script(argument) self.assertEqual(output.strip(), "") - def test_minigraph_vxlan(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VXLAN_TUNNEL"' + def test_minigraph_vxlan(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "VXLAN_TUNNEL"' output = self.run_script(argument) self.assertEqual(output.strip(), "") @@ -587,61 +598,82 @@ class TestCfgGen(TestCase): ) def test_minigraph_sub_port_interfaces(self, check_stderr=True): + self.verify_sub_intf(check_stderr=check_stderr) + + def test_minigraph_sub_port_intf_resource_type(self, check_stderr=True): + self.verify_sub_intf(graph_file=self.sample_resource_graph, check_stderr=check_stderr) + + def test_minigraph_sub_port_intf_sub(self, check_stderr=True): + self.verify_sub_intf(graph_file=self.sample_subintf_graph, check_stderr=check_stderr) + + def verify_sub_intf(self, **kwargs): + graph_file = kwargs.get('graph_file', self.sample_graph_simple) + check_stderr = kwargs.get('check_stderr', True) try: print('\n Change device type to %s' % (BACKEND_TOR_ROUTER)) if check_stderr: - output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, self.sample_graph_simple), stderr=subprocess.STDOUT, shell=True) + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, graph_file), stderr=subprocess.STDOUT, shell=True) else: - output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, self.sample_graph_simple), shell=True) - - self.test_jinja_expression(self.sample_graph_simple, BACKEND_TOR_ROUTER) + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, graph_file), shell=True) + self.test_jinja_expression(graph_file, BACKEND_TOR_ROUTER) # INTERFACE table does not exist - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "INTERFACE"' + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "INTERFACE"' output = self.run_script(argument) self.assertEqual(output.strip(), "") # PORTCHANNEL_INTERFACE table does not exist - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORTCHANNEL_INTERFACE"' + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "PORTCHANNEL_INTERFACE"' output = self.run_script(argument) self.assertEqual(output.strip(), "") # All the other tables stay unchanged - self.test_var_json_data() - self.test_minigraph_vlans() - self.test_minigraph_vlan_members() - self.test_minigraph_vlan_interfaces() - self.test_minigraph_portchannels() - self.test_minigraph_ethernet_interfaces() - self.test_minigraph_extra_ethernet_interfaces() - self.test_minigraph_vnet() - self.test_minigraph_vxlan() + self.test_var_json_data(graph_file=graph_file) + self.test_minigraph_vlans(graph_file=graph_file) + self.test_minigraph_vlan_members(graph_file=graph_file) + self.test_minigraph_vlan_interfaces(graph_file=graph_file) + self.test_minigraph_portchannels(graph_file=graph_file) + self.test_minigraph_ethernet_interfaces(graph_file=graph_file) + self.test_minigraph_extra_ethernet_interfaces(graph_file=graph_file) + self.test_minigraph_vnet(graph_file=graph_file) + self.test_minigraph_vxlan(graph_file=graph_file) # VLAN_SUB_INTERFACE - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN_SUB_INTERFACE' + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v VLAN_SUB_INTERFACE' output = self.run_script(argument) print(output.strip()) - self.assertEqual( - utils.to_dict(output.strip()), - utils.to_dict( - "{('PortChannel01.10', '10.0.0.56/31'): {}, " - "'Ethernet0.10': {'admin_status': 'up'}, " - "('Ethernet0.10', '10.0.0.58/31'): {}, " - "('PortChannel01.10', 'FC00::71/126'): {}, " - "'PortChannel01.10': {'admin_status': 'up'}, " - "('Ethernet0.10', 'FC00::75/126'): {}}" + # not a usecase to parse SubInterfaces under PortChannel + if 'subintf' in graph_file: + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'Ethernet0.10': {'admin_status': 'up'}, " + "('Ethernet0.10', '10.0.0.58/31'): {}, " + "('Ethernet0.10', 'FC00::75/126'): {}}" + ) + ) + else: + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{('PortChannel01.10', '10.0.0.56/31'): {}, " + "'Ethernet0.10': {'admin_status': 'up'}, " + "('Ethernet0.10', '10.0.0.58/31'): {}, " + "('PortChannel01.10', 'FC00::71/126'): {}, " + "'PortChannel01.10': {'admin_status': 'up'}, " + "('Ethernet0.10', 'FC00::75/126'): {}}" + ) ) - ) finally: print('\n Change device type back to %s' % (TOR_ROUTER)) if check_stderr: - output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, self.sample_graph_simple), stderr=subprocess.STDOUT, shell=True) + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, graph_file), stderr=subprocess.STDOUT, shell=True) else: - output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, self.sample_graph_simple), shell=True) + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, graph_file), shell=True) - self.test_jinja_expression(self.sample_graph_simple, TOR_ROUTER) + self.test_jinja_expression(graph_file, TOR_ROUTER) def test_show_run_acl(self): argument = '-a \'{"key1":"value"}\' --var-json ACL_RULE' diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py index abee457a0d..3308c5641f 100644 --- a/src/sonic-config-engine/tests/test_minigraph_case.py +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -7,13 +7,18 @@ import minigraph from unittest import TestCase +TOR_ROUTER = 'ToRRouter' +BACKEND_TOR_ROUTER = 'BackEndToRRouter' class TestCfgGenCaseInsensitive(TestCase): def setUp(self): self.test_dir = os.path.dirname(os.path.realpath(__file__)) self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_simple_graph = os.path.join(self.test_dir, 'simple-sample-graph.xml') self.sample_graph = os.path.join(self.test_dir, 'simple-sample-graph-case.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.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') def run_script(self, argument, check_stderr=False): @@ -284,7 +289,35 @@ class TestCfgGenCaseInsensitive(TestCase): argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'storage_device\']"' output = self.run_script(argument) self.assertEqual(output.strip(), "true") - + + def test_minigraph_storage_backend_no_resource_type(self): + self.verify_storage_device_set(self.sample_simple_graph) + + def test_minigraph_storage_backend_resource_type(self): + self.verify_storage_device_set(self.sample_resource_graph) + + def test_minigraph_storage_backend_subintf(self): + self.verify_storage_device_set(self.sample_subintf_graph) + + def verify_storage_device_set(self, graph_file, check_stderr=False): + try: + print('\n Change device type to %s' % (BACKEND_TOR_ROUTER)) + if check_stderr: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, graph_file), stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, graph_file), shell=True) + + argument = '-m "' + graph_file + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'storage_device\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "true") + + finally: + print('\n Change device type back to %s' % (TOR_ROUTER)) + if check_stderr: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, graph_file), stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, graph_file), shell=True) + def test_minigraph_tunnel_table(self): argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "TUNNEL"' expected_tunnel = {