From 01a1c063254aeb81e80c31c63000c80c4b864fae Mon Sep 17 00:00:00 2001 From: mprabhu Date: Mon, 23 Nov 2020 23:07:25 -0800 Subject: [PATCH 1/4] Modular-Chassis: Show midplane status --- show/chassis_modules.py | 41 +++++++++++++++++++++++++++++++++ tests/chassis_modules_test.py | 37 +++++++++++++++++++++++++++++ tests/mock_tables/state_db.json | 12 ++++++++++ 3 files changed, 90 insertions(+) diff --git a/show/chassis_modules.py b/show/chassis_modules.py index 5a13a32419..9626c2b07e 100644 --- a/show/chassis_modules.py +++ b/show/chassis_modules.py @@ -12,6 +12,10 @@ CHASSIS_MODULE_INFO_OPERSTATUS_FIELD = 'oper_status' CHASSIS_MODULE_INFO_ADMINSTATUS_FIELD = 'admin_status' +CHASSIS_MIDPLANE_INFO_TABLE = 'CHASSIS_MIDPLANE_TABLE' +CHASSIS_MIDPLANE_INFO_IP_FIELD = 'ip_address' +CHASSIS_MIDPLANE_INFO_ACCESS_FIELD = 'access' + @click.group(cls=clicommon.AliasedGroup) def chassis_modules(): """Show chassis-modules information""" @@ -61,3 +65,40 @@ def status(db, chassis_module_name): click.echo(tabulate(table, header, tablefmt='simple', stralign='right')) else: click.echo('No data available in CHASSIS_MODULE_TABLE\n') + +@chassis_modules.command() +@click.argument('chassis_module_name', metavar='', required=False) +def midplane_status(chassis_module_name): + """Show chassis-modules midplane-status""" + + header = ['Name', 'IP-Address', 'Reachability'] + + state_db = SonicV2Connector(host="127.0.0.1") + state_db.connect(state_db.STATE_DB) + + key_pattern = '*' + if chassis_module_name: + key_pattern = '|'+chassis_module_name + + keys = state_db.keys(state_db.STATE_DB, CHASSIS_MIDPLANE_INFO_TABLE + key_pattern) + if not keys: + print('Key {} not found in {} table'.format(key_pattern, CHASSIS_MIDPLANE_INFO_TABLE)) + return + + table = [] + for key in natsorted(keys): + key_list = key.split('|') + if len(key_list) != 2: # error data in DB, log it and ignore + print('Warn: Invalid Key {} in {} table'.format(key, CHASSIS_MIDPLANE_INFO_TABLE)) + continue + + data_dict = state_db.get_all(state_db.STATE_DB, key) + ip = data_dict[CHASSIS_MIDPLANE_INFO_IP_FIELD] + access = data_dict[CHASSIS_MIDPLANE_INFO_ACCESS_FIELD] + + table.append((key_list[1], ip, access)) + + if table: + click.echo(tabulate(table, header, tablefmt='simple', stralign='right')) + else: + click.echo('No data available in CHASSIS_MIDPLANE_TABLE\n') diff --git a/tests/chassis_modules_test.py b/tests/chassis_modules_test.py index 754845eba2..aba6c10430 100644 --- a/tests/chassis_modules_test.py +++ b/tests/chassis_modules_test.py @@ -112,6 +112,43 @@ def test_config_incorrect_module(self): print(result.output) assert result.exit_code != 0 + def test_midplane_show_all_count_lines(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], []) + print(result.output) + result_lines = result.output.strip('\n').split('\n') + modules = ["LINE-CARD0", "LINE-CARD1", "SUPERVISOR0"] + for i, module in enumerate(modules): + assert module in result_lines[i + warning_lines + header_lines] + assert len(result_lines) == warning_lines + header_lines + len(modules) + + def test_midplane_show_single_count_lines(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], ["LINE-CARD0"]) + print(result.output) + result_lines = result.output.strip('\n').split('\n') + modules = ["LINE-CARD0"] + for i, module in enumerate(modules): + assert module in result_lines[i+header_lines] + assert len(result_lines) == header_lines + len(modules) + + def test_midplane_show_module_down(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], ["LINE-CARD1"]) + print(result.output) + result_lines = result.output.strip('\n').split('\n') + assert result.exit_code == 0 + result_out = (result_lines[header_lines]).split() + print(result_out) + assert result_out[2] == 'False' + + def test_midplane_show_incorrect_module(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], ["TEST-CARD1"]) + print(result.output) + print(result.exit_code) + assert result.exit_code == 0 + @classmethod def teardown_class(cls): print("TEARDOWN") diff --git a/tests/mock_tables/state_db.json b/tests/mock_tables/state_db.json index 7f563d8842..c7d56da133 100644 --- a/tests/mock_tables/state_db.json +++ b/tests/mock_tables/state_db.json @@ -377,5 +377,17 @@ "xon": "18432", "xoff": "32768", "size": "51200" + }, + "CHASSIS_MIDPLANE_TABLE|SUPERVISOR0": { + "ip_address": "192.168.1.100", + "access": "True" + }, + "CHASSIS_MIDPLANE_TABLE|LINE-CARD0": { + "ip_address": "192.168.1.1", + "access": "True" + }, + "CHASSIS_MIDPLANE_TABLE|LINE-CARD1": { + "ip_address": "192.168.1.2", + "access": "False" } } From e3b92309bb98ef3e64b2926cfa6ff6c264eed3ec Mon Sep 17 00:00:00 2001 From: mprabhu Date: Wed, 2 Dec 2020 23:51:18 -0800 Subject: [PATCH 2/4] Moving SonicV2Connector to swsscommon --- show/chassis_modules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/show/chassis_modules.py b/show/chassis_modules.py index 9626c2b07e..a24f40cef1 100644 --- a/show/chassis_modules.py +++ b/show/chassis_modules.py @@ -1,7 +1,7 @@ import click from natsort import natsorted from tabulate import tabulate -from swsssdk import SonicV2Connector +from swsscommon.swsscommon import SonicV2Connector import utilities_common.cli as clicommon From 4701b00d92a88f2382446e275c4ffc03a0d1623d Mon Sep 17 00:00:00 2001 From: mprabhu Date: Wed, 6 Jan 2021 14:49:23 -0800 Subject: [PATCH 3/4] Fix issues caught by autopep --- show/chassis_modules.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/show/chassis_modules.py b/show/chassis_modules.py index a24f40cef1..8a9d22ae35 100644 --- a/show/chassis_modules.py +++ b/show/chassis_modules.py @@ -35,7 +35,7 @@ def status(db, chassis_module_name): key_pattern = '*' if chassis_module_name: - key_pattern = '|'+chassis_module_name + key_pattern = '|' + chassis_module_name keys = state_db.keys(state_db.STATE_DB, CHASSIS_MODULE_INFO_TABLE + key_pattern) if not keys: @@ -45,7 +45,7 @@ def status(db, chassis_module_name): table = [] for key in natsorted(keys): key_list = key.split('|') - if len(key_list) != 2: # error data in DB, log it and ignore + if len(key_list) != 2: # error data in DB, log it and ignore print('Warn: Invalid Key {} in {} table'.format(key, CHASSIS_MODULE_INFO_TABLE)) continue @@ -78,7 +78,7 @@ def midplane_status(chassis_module_name): key_pattern = '*' if chassis_module_name: - key_pattern = '|'+chassis_module_name + key_pattern = '|' + chassis_module_name keys = state_db.keys(state_db.STATE_DB, CHASSIS_MIDPLANE_INFO_TABLE + key_pattern) if not keys: @@ -88,7 +88,7 @@ def midplane_status(chassis_module_name): table = [] for key in natsorted(keys): key_list = key.split('|') - if len(key_list) != 2: # error data in DB, log it and ignore + if len(key_list) != 2: # error data in DB, log it and ignore print('Warn: Invalid Key {} in {} table'.format(key, CHASSIS_MIDPLANE_INFO_TABLE)) continue From a754ad5cba37a432e8f56d85207cffcb6c73271a Mon Sep 17 00:00:00 2001 From: mprabhu Date: Mon, 11 Jan 2021 16:49:17 -0800 Subject: [PATCH 4/4] Tests to verify mock show outputs Show Output verification for: show chassis-modules status show chassis-modules midplane-status --- tests/chassis_modules_test.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/chassis_modules_test.py b/tests/chassis_modules_test.py index aba6c10430..fb63488ecd 100644 --- a/tests/chassis_modules_test.py +++ b/tests/chassis_modules_test.py @@ -21,12 +21,36 @@ header_lines = 2 warning_lines = 0 +show_chassis_modules_output="""\ + Name Description Physical-Slot Oper-Status Admin-Status +------------ --------------- --------------- ------------- -------------- +FABRIC-CARD0 fabric-card 17 Online up +FABRIC-CARD1 fabric-card 18 Offline up + LINE-CARD0 line-card 1 Empty up + LINE-CARD1 line-card 2 Online down + SUPERVISOR0 supervisor-card 16 Online up +""" + +show_chassis_midplane_output="""\ + Name IP-Address Reachability +----------- ------------- -------------- + LINE-CARD0 192.168.1.1 True + LINE-CARD1 192.168.1.2 False +SUPERVISOR0 192.168.1.100 True +""" + class TestChassisModules(object): @classmethod def setup_class(cls): print("SETUP") os.environ["UTILITIES_UNIT_TESTING"] = "1" + def test_show_and_verify_output(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], []) + print(result.output) + assert(result.output == show_chassis_modules_output) + def test_show_all_count_lines(self): runner = CliRunner() result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], []) @@ -112,6 +136,12 @@ def test_config_incorrect_module(self): print(result.output) assert result.exit_code != 0 + def test_show_and_verify_midplane_output(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], []) + print(result.output) + assert(result.output == show_chassis_midplane_output) + def test_midplane_show_all_count_lines(self): runner = CliRunner() result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], [])