From cd86abae40d4a8eb35fa0a8462d2c663e3938949 Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Fri, 17 Mar 2017 16:40:34 -0700 Subject: [PATCH] [sonic-cfggen]: Add -p option and add teamd.j2 test - Add -p --port-config option to feed sonic-cfggen with port_config.ini file when necessary. - Update minigraph.py file to accept the -p option - Add test_j2files.py test to test config.sh and all .j2 templates * Currently test_teamd is added to test both the config.sh and teamd.j2 file works well with the t0 sample minigraph and sample port config file * The sample output is added to the folder sample_output for comparison Signed-off-by: Shuotian Cheng --- dockers/docker-teamd/teamd.j2 | 6 +- src/sonic-config-engine/minigraph.py | 9 +- src/sonic-config-engine/setup.py | 0 src/sonic-config-engine/sonic-cfggen | 11 +- src/sonic-config-engine/tests/.gitignore | 1 + .../tests/sample_output/PortChannel01.conf | 16 + .../tests/sample_output/PortChannel02.conf | 16 + .../tests/sample_output/PortChannel03.conf | 16 + .../tests/sample_output/PortChannel04.conf | 16 + .../tests/t0-sample-graph.xml | 315 ++++++++++++++++++ .../tests/t0-sample-port-config.ini | 33 ++ src/sonic-config-engine/tests/test_j2files.py | 40 +++ 12 files changed, 470 insertions(+), 9 deletions(-) mode change 100644 => 100755 src/sonic-config-engine/setup.py create mode 100644 src/sonic-config-engine/tests/.gitignore create mode 100644 src/sonic-config-engine/tests/sample_output/PortChannel01.conf create mode 100644 src/sonic-config-engine/tests/sample_output/PortChannel02.conf create mode 100644 src/sonic-config-engine/tests/sample_output/PortChannel03.conf create mode 100644 src/sonic-config-engine/tests/sample_output/PortChannel04.conf create mode 100644 src/sonic-config-engine/tests/t0-sample-graph.xml create mode 100644 src/sonic-config-engine/tests/t0-sample-port-config.ini create mode 100644 src/sonic-config-engine/tests/test_j2files.py diff --git a/dockers/docker-teamd/teamd.j2 b/dockers/docker-teamd/teamd.j2 index 386f4465713b..e2ef239c8266 100644 --- a/dockers/docker-teamd/teamd.j2 +++ b/dockers/docker-teamd/teamd.j2 @@ -11,10 +11,10 @@ "name": "ethtool" }, "ports": { - {% for member in minigraph_portchannels[pc]['members'] %} -"{{member}}": {}{% if not loop.last %},{% endif %} +{% for member in minigraph_portchannels[pc]['members'] %} + "{{member}}": {}{% if not loop.last %},{% endif %} - {% endfor %} +{% endfor %} } } diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 33f927a4b29e..54f9efe3c16e 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -328,8 +328,10 @@ def get_mgmt_info(devices, dev, port): return ret_val -def get_alias_map_list(hwsku, platform=None): +def get_alias_map_list(hwsku, platform=None, port_config_file=None): port_config_candidates = [] + if port_config_file != None: + port_config_candidates.append(port_config_file) port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini') if platform != None: port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini')) @@ -354,7 +356,7 @@ def get_alias_map_list(hwsku, platform=None): alias_map_list.append({'sonic': tokens[0], 'origin': tokens[2].strip()}) return alias_map_list -def parse_xml(filename, platform=None): +def parse_xml(filename, platform=None, port_config_file=None): root = ET.parse(filename).getroot() mini_graph_path = filename @@ -385,7 +387,7 @@ def parse_xml(filename, platform=None): if child.tag == str(hostname_qn): hostname = child.text - alias_map_list = get_alias_map_list(hwsku, platform) + alias_map_list = get_alias_map_list(hwsku, platform, port_config_file) if alias_map_list != None: for item in alias_map_list: port_alias_map[item['origin']] = item['sonic'] @@ -438,7 +440,6 @@ def parse_xml(filename, platform=None): port_alias_map = {} - def print_parse_xml(filename): results = parse_xml(filename) print(json.dumps(results, indent=3, cls=minigraph_encoder)) diff --git a/src/sonic-config-engine/setup.py b/src/sonic-config-engine/setup.py old mode 100644 new mode 100755 diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index 93f27a30442d..c10fb8c104cd 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -60,6 +60,7 @@ def get_machine_info(): def main(): parser=argparse.ArgumentParser(description="Render configuration file from minigraph data and jinja2 template.") parser.add_argument("-m", "--minigraph", help="minigraph xml file") + parser.add_argument("-p", "--port-config", help="port config file, used with -m") parser.add_argument("-y", "--yaml", help="yaml file that contains addtional variables") parser.add_argument("-a", "--additional-data", help="addition data, in json string") group = parser.add_mutually_exclusive_group() @@ -83,9 +84,15 @@ def main(): if args.minigraph != None: minigraph = args.minigraph if data.has_key('platform'): - data.update(parse_xml(minigraph, data['platform'])) + if args.port_config != None: + data.update(parse_xml(minigraph, data['platform'], args.port_config)) + else: + data.update(parse_xml(minigraph, data['platform'])) else: - data.update(parse_xml(minigraph)) + if args.port_config != None: + data.update(parse_xml(minigraph, port_config_file=args.port_config)) + else: + data.update(parse_xml(minigraph)) if args.yaml != None: with open(args.yaml, 'r') as stream: diff --git a/src/sonic-config-engine/tests/.gitignore b/src/sonic-config-engine/tests/.gitignore new file mode 100644 index 000000000000..bee8a64b79a9 --- /dev/null +++ b/src/sonic-config-engine/tests/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/src/sonic-config-engine/tests/sample_output/PortChannel01.conf b/src/sonic-config-engine/tests/sample_output/PortChannel01.conf new file mode 100644 index 000000000000..95369ce06a2e --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/PortChannel01.conf @@ -0,0 +1,16 @@ +{ + "device": "PortChannel01", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet112": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/PortChannel02.conf b/src/sonic-config-engine/tests/sample_output/PortChannel02.conf new file mode 100644 index 000000000000..960ca2d0db65 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/PortChannel02.conf @@ -0,0 +1,16 @@ +{ + "device": "PortChannel02", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet116": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/PortChannel03.conf b/src/sonic-config-engine/tests/sample_output/PortChannel03.conf new file mode 100644 index 000000000000..d26ad7795e54 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/PortChannel03.conf @@ -0,0 +1,16 @@ +{ + "device": "PortChannel03", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet120": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/PortChannel04.conf b/src/sonic-config-engine/tests/sample_output/PortChannel04.conf new file mode 100644 index 000000000000..76c97b3f7c03 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/PortChannel04.conf @@ -0,0 +1,16 @@ +{ + "device": "PortChannel04", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet124": {} + } +} + diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml new file mode 100644 index 000000000000..413aedf7e234 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-graph.xml @@ -0,0 +1,315 @@ + + + + + + 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 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 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/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-port-config.ini b/src/sonic-config-engine/tests/t0-sample-port-config.ini new file mode 100644 index 000000000000..06898f1d7964 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-port-config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 29,30,31,32 fortyGigE0/0 +Ethernet4 25,26,27,28 fortyGigE0/4 +Ethernet8 37,38,39,40 fortyGigE0/8 +Ethernet12 33,34,35,36 fortyGigE0/12 +Ethernet16 41,42,43,44 fortyGigE0/16 +Ethernet20 45,46,47,48 fortyGigE0/20 +Ethernet24 5,6,7,8 fortyGigE0/24 +Ethernet28 1,2,3,4 fortyGigE0/28 +Ethernet32 9,10,11,12 fortyGigE0/32 +Ethernet36 13,14,15,16 fortyGigE0/36 +Ethernet40 21,22,23,24 fortyGigE0/40 +Ethernet44 17,18,19,20 fortyGigE0/44 +Ethernet48 49,50,51,52 fortyGigE0/48 +Ethernet52 53,54,55,56 fortyGigE0/52 +Ethernet56 61,62,63,64 fortyGigE0/56 +Ethernet60 57,58,59,60 fortyGigE0/60 +Ethernet64 65,66,67,68 fortyGigE0/64 +Ethernet68 69,70,71,72 fortyGigE0/68 +Ethernet72 77,78,79,80 fortyGigE0/72 +Ethernet76 73,74,75,76 fortyGigE0/76 +Ethernet80 105,106,107,108 fortyGigE0/80 +Ethernet84 109,110,111,112 fortyGigE0/84 +Ethernet88 117,118,119,120 fortyGigE0/88 +Ethernet92 113,114,115,116 fortyGigE0/92 +Ethernet96 121,122,123,124 fortyGigE0/96 +Ethernet100 125,126,127,128 fortyGigE0/100 +Ethernet104 85,86,87,88 fortyGigE0/104 +Ethernet108 81,82,83,84 fortyGigE0/108 +Ethernet112 89,90,91,92 fortyGigE0/112 +Ethernet116 93,94,95,96 fortyGigE0/116 +Ethernet120 97,98,99,100 fortyGigE0/120 +Ethernet124 101,102,103,104 fortyGigE0/124 diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py new file mode 100644 index 000000000000..e2ad2f54a2ac --- /dev/null +++ b/src/sonic-config-engine/tests/test_j2files.py @@ -0,0 +1,40 @@ +import filecmp +import os +import subprocess + +from unittest import TestCase + +class TestJ2Files(TestCase): + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.t0_minigraph = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.t0_port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + self.output_file = os.path.join(self.test_dir, 'output') + + def run_script(self, argument): + print 'CMD: sonic-cfggen ' + argument + return subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + def test_teamd(self): + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -v "minigraph_portchannels.keys() | join(\' \')"' + output = self.run_script(argument) # Mock the output via config.sh in docker-teamd + pc_list = output.split() + + def test_render_teamd(self, pc): + teamd_file = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-teamd', 'teamd.j2') + sample_output_file = os.path.join(self.test_dir, 'sample_output',pc + '.conf') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -a \'{\"pc\":\"' + pc + '\"}\' -t ' + teamd_file + ' > ' + self.output_file + self.run_script(argument) + assert filecmp.cmp(sample_output_file, self.output_file) + + for i in range(1, 5): + pc_name = 'PortChannel0' + str(i) + assert pc_name in pc_list + test_render_teamd(self, pc_name) + + def tearDown(self): + try: + os.remove(self.output_file) + except OSError: + pass