From 12c3ed58b51f44b0a17a3a67448a906e782bd159 Mon Sep 17 00:00:00 2001 From: Neetha John Date: Fri, 13 May 2022 13:31:42 -0700 Subject: [PATCH] [201811] Minigraph parser changes to select mmu profiles based on SonicQosProfile attribute (#10698) Why I did it There is a need to select different mmu profiles based on deployment type How I did it There will be separate subfolders (RDMA-CENTRIC, TCP-CENTRIC, BALANCED) in each hwsku folder which contains deployment specific mmu and qos settings. SonicQosProfile attribute in the minigraph will be used to determine which settings to use. If that attribute is not present, the default settings that exist in the hwsku folder will be used How to verify it Manually verified by creating subfolders under DX010 folder and updated minigraph on the device with SonicQosProfile pointing to one of the subfolders. Verified by loading minigraph and confirming the mmu and ecn settings are as expected. Unit tests have been updated to include the SonicQosProfile attribute in the minigraphs used for buffer and qos rendering. Since the dir structure does not exist now, code flow will take no action. Once the dir structure exists, the profile selection path will get executed but since all 3 subfolders have identical values, existing test cases should hold good. Build sonic-config-engine python wheel with the changes and build was successful. --- src/sonic-config-engine/minigraph.py | 34 +++++++++++++++++-- .../tests/sample-dell-6100-t0-minigraph.xml | 5 +++ src/sonic-config-engine/tests/test_j2files.py | 29 +++++++++++++++- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 97848782b9..b025c3041c 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -410,6 +410,7 @@ def parse_meta(meta, hname): mgmt_routes = [] erspan_dst = [] deployment_id = None + qos_profile = None 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(): @@ -432,7 +433,9 @@ def parse_meta(meta, hname): erspan_dst = value_group elif name == "DeploymentId": deployment_id = value - return syslog_servers, dhcp_servers, dhcpv6_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id + elif name == "SonicQosProfile": + qos_profile = value + return syslog_servers, dhcp_servers, dhcpv6_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, qos_profile def parse_linkmeta(meta, hname): @@ -517,6 +520,31 @@ def filter_acl_mirror_table_bindings(acls, neighbors, port_channels): return acls +def select_mmu_profiles(profile, platform, hwsku): + """ + Select MMU files based on the device metadata attribute - SonicQosProfile + if no QosProfile exists in the minigraph, then no action is needed. + if a profile exists in the minigraph, + - create a dir path to search 1 level down from the base path. + - if no such dir path exists, no action is needed. + - if a dir path exists, check for the presence of each file from + the copy list in the dir path and copy it over to the base path. + """ + if not profile: + return + + files_to_copy = ['pg_profile_lookup.ini', 'qos.json.j2', 'buffers_defaults_t0.j2', 'buffers_defaults_t1.j2'] + + path = os.path.join('/usr/share/sonic/device', platform, hwsku) + + dir_path = os.path.join(path, profile) + if os.path.exists(dir_path): + for file_item in files_to_copy: + file_in_dir = os.path.join(dir_path, file_item) + if os.path.isfile(file_in_dir): + base_file = os.path.join(path, file_item) + exec_cmd("sudo cp {} {}".format(file_in_dir, base_file)) + ############################################################################### # # Main functions @@ -559,6 +587,7 @@ def parse_xml(filename, platform=None, port_config_file=None): bgp_peers_with_range = None deployment_id = None linkmetas = {} + qos_profile = [] hwsku_qn = QName(ns, "HwSku") hostname_qn = QName(ns, "Hostname") @@ -583,12 +612,13 @@ def parse_xml(filename, platform=None, port_config_file=None): elif child.tag == str(QName(ns, "UngDec")): (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname) elif child.tag == str(QName(ns, "MetadataDeclaration")): - (syslog_servers, dhcp_servers, dhcpv6_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id) = parse_meta(child, hostname) + (syslog_servers, dhcp_servers, dhcpv6_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, qos_profile) = parse_meta(child, hostname) elif child.tag == str(QName(ns, "LinkMetadataDeclaration")): linkmetas = parse_linkmeta(child, hostname) elif child.tag == str(QName(ns, "DeviceInfos")): (port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku) + select_mmu_profiles(qos_profile, platform, hwsku) current_device = [devices[key] for key in devices if key.lower() == hostname.lower()][0] results = {} results['DEVICE_METADATA'] = {'localhost': { diff --git a/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml b/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml index 7cea7decfc..42be801a84 100644 --- a/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml +++ b/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml @@ -716,6 +716,11 @@ 10.0.0.16 + + SonicQosProfile + + RDMA-CENTRIC + diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py index 98a3d374c0..f3b8598690 100644 --- a/src/sonic-config-engine/tests/test_j2files.py +++ b/src/sonic-config-engine/tests/test_j2files.py @@ -27,6 +27,27 @@ class TestJ2Files(TestCase): def run_diff(self, file1, file2): return subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True) + def create_machine_conf(self, platform): + file_exist = True + dir_exist = True + echo_cmd = "echo 'onie_platform={}' | sudo tee -a /host/machine.conf > /dev/null".format(platform) + if not os.path.exists('/host/machine.conf'): + file_exist = False + if not os.path.isdir('/host'): + dir_exist = False + os.system('sudo mkdir /host') + os.system('sudo touch /host/machine.conf') + os.system(echo_cmd) + + return file_exist, dir_exist + + def remove_machine_conf(self, file_exist, dir_exist): + if not file_exist: + os.system('sudo rm -f /host/machine.conf') + + if not dir_exist: + os.system('sudo rmdir /host') + def test_interfaces(self): interfaces_template = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'interfaces', 'interfaces.j2') argument = '-m ' + self.t0_minigraph + ' -a \'{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}\' -t ' + interfaces_template + ' > ' + self.output_file @@ -115,6 +136,7 @@ class TestJ2Files(TestCase): assert filecmp.cmp(sample_output_file, self.output_file) def test_qos_dell6100_render_template(self): + file_exist, dir_exist = self.create_machine_conf('x86_64-dell_s6100_c2538-r0') dell_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'dell', 'x86_64-dell_s6100_c2538-r0', 'Force10-S6100') qos_file = os.path.join(dell_dir_path, 'qos.json.j2') port_config_ini_file = os.path.join(dell_dir_path, 'port_config.ini') @@ -130,10 +152,13 @@ class TestJ2Files(TestCase): qos_config_file_new = os.path.join(dell_dir_path, 'qos_config.j2') os.remove(qos_config_file_new) + self.remove_machine_conf(file_exist, dir_exist) + sample_output_file = os.path.join(self.test_dir, 'sample_output', 'qos-dell6100.json') assert filecmp.cmp(sample_output_file, self.output_file) def test_buffers_dell6100_render_template(self): + file_exist, dir_exist = self.create_machine_conf('x86_64-dell_s6100_c2538-r0') dell_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'dell', 'x86_64-dell_s6100_c2538-r0', 'Force10-S6100') buffers_file = os.path.join(dell_dir_path, 'buffers.json.j2') port_config_ini_file = os.path.join(dell_dir_path, 'port_config.ini') @@ -142,13 +167,15 @@ class TestJ2Files(TestCase): buffers_config_file = os.path.join(self.test_dir, '..', '..', '..', 'files', 'build_templates', 'buffers_config.j2') shutil.copy2(buffers_config_file, dell_dir_path) - argument = '-m ' + self.dell6100_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + buffers_file + ' > ' + self.output_file + argument = '-m ' + self.dell6100_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + buffers_file + ' > ' + self.output_file self.run_script(argument) # cleanup buffers_config_file_new = os.path.join(dell_dir_path, 'buffers_config.j2') os.remove(buffers_config_file_new) + self.remove_machine_conf(file_exist, dir_exist) + sample_output_file = os.path.join(self.test_dir, 'sample_output', 'buffers-dell6100.json') assert filecmp.cmp(sample_output_file, self.output_file)