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