From 8572f3cee5dd29a05bdf3634947fef8211675323 Mon Sep 17 00:00:00 2001 From: Renuka Manavalan <47282725+renukamanavalan@users.noreply.github.com> Date: Tue, 2 Feb 2021 11:16:37 -0800 Subject: [PATCH] Update minigraph.py to parse kubernetes config from minigraph.xml (#6633) Update minigraph parser to retrieve kubernetes server info from minigraph.xml and update "KUBERNETES_MASTER|SERVER" in running config. Update minigraph parser to include clusterName from minigraph.xml into "DEVICE_METADATA|localhost" --- src/sonic-config-engine/minigraph.py | 41 +++++++++++++++---- .../tests/simple-sample-graph-case.xml | 10 +++++ .../tests/test_minigraph_case.py | 13 +++++- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index ba81e8faf771..06b799cdeff7 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -84,6 +84,7 @@ def parse_device(device): hwsku = None name = None deployment_id = None + cluster = None for node in device: if node.tag == str(QName(ns, "Address")): @@ -100,11 +101,13 @@ def parse_device(device): deployment_id = node.text elif node.tag == str(QName(ns, "ElementType")): d_type = node.text + elif node.tag == str(QName(ns, "ClusterName")): + cluster = node.text 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) + return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) def calculate_lcm_for_ecmp (nhdevices_bank_map, nhip_bank_map): banks_enumerated = {} @@ -244,8 +247,10 @@ 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) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, 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 if deployment_id: device_data['deployment_id'] = deployment_id if lo_prefix_v6: @@ -253,9 +258,7 @@ def parse_png(png, hname, dpg_ecmp_content = None): devices[name] = device_data if name == hname: - cluster = device.find(str(QName(ns, "ClusterName"))) - - if cluster != None and cluster.text != None and "str" in cluster.text.lower(): + if cluster and "str" in cluster.lower(): is_storage_device = True if child.tag == str(QName(ns, "DeviceInterfaceLinks")): @@ -380,8 +383,10 @@ 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) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, 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 if deployment_id: device_data['deployment_id'] = deployment_id if lo_prefix_v6: @@ -780,6 +785,7 @@ def parse_meta(meta, hname): region = None cloudtype = None resource_type = None + kube_data = {} device_metas = meta.find(str(QName(ns, "Devices"))) for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): if device.find(str(QName(ns1, "Name"))).text.lower() == hname.lower(): @@ -808,7 +814,11 @@ def parse_meta(meta, hname): cloudtype = value elif name == "ResourceType": resource_type = value - return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type + elif name == "KubernetesEnabled": + kube_data["enable"] = value + elif name == "KubernetesServerIp": + kube_data["ip"] = value + return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type, kube_data def parse_linkmeta(meta, hname): @@ -1097,6 +1107,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw host_lo_intfs = None is_storage_device = False local_devices = [] + kube_data = {} # hostname is the asic_name, get the asic_id from the asic_name if asic_name is not None: @@ -1133,7 +1144,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw elif child.tag == str(QName(ns, "UngDec")): (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname, None) elif child.tag == str(QName(ns, "MetadataDeclaration")): - (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type) = parse_meta(child, hostname) + (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type, kube_data) = parse_meta(child, hostname) elif child.tag == str(QName(ns, "LinkMetadataDeclaration")): linkmetas = parse_linkmeta(child, hostname) elif child.tag == str(QName(ns, "DeviceInfos")): @@ -1174,6 +1185,18 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw } } + cluster = [devices[key] for key in devices if key.lower() == hostname.lower()][0].get('cluster', "") + if cluster: + results['DEVICE_METADATA']['localhost']['cluster'] = cluster + + if kube_data: + results['KUBERNETES_MASTER'] = { + 'SERVER': { + 'disable': str(kube_data.get('enable', '0') == '0'), + 'ip': kube_data.get('ip', '') + } + } + results['PEER_SWITCH'] = get_peer_switch_info(linkmetas, devices) if bool(results['PEER_SWITCH']): @@ -1524,7 +1547,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, hostname, hwsku, d_type, _, _) = parse_device(root) results = {} results['DEVICE_METADATA'] = {'localhost': { 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 ce0174adc8dd..95f501200c83 100644 --- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -390,6 +390,16 @@ 10.0.10.7;10.0.10.8 + + KubernetesEnabled + + 0 + + + KubernetesServerIp + + 10.10.10.10 + diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py index 6fa7c5352d05..64e0bb09d730 100644 --- a/src/sonic-config-engine/tests/test_minigraph_case.py +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -1,3 +1,4 @@ +import json import os import subprocess @@ -145,6 +146,11 @@ def test_minigraph_deployment_id(self): output = self.run_script(argument) self.assertEqual(output.strip(), "1") + def test_minigraph_cluster(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'cluster\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "AAA00PrdStr00") + def test_minigraph_neighbor_metadata(self): argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR_METADATA"' @@ -195,6 +201,12 @@ def test_metadata_tacacs(self): output = self.run_script(argument) self.assertEqual(output.strip(), "{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}") + def test_metadata_kube(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "KUBERNETES_MASTER[\'SERVER\']"' + output = self.run_script(argument) + self.assertEqual(json.loads(output.strip().replace("'", "\"")), + json.loads('{"ip": "10.10.10.10", "disable": "True"}')) + def test_minigraph_mgmt_port(self): argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MGMT_PORT"' output = self.run_script(argument) @@ -289,4 +301,3 @@ def test_minigraph_mux_cable_table(self): utils.to_dict(output.strip()), expected_table ) - \ No newline at end of file