Skip to content

Commit 983d340

Browse files
[show] Add subcommand to show midplane status for modular chassis (sonic-net#1267)
Add subcommand to show midplane status for modular chassis and related unit tests
1 parent edc32ab commit 983d340

3 files changed

Lines changed: 123 additions & 3 deletions

File tree

show/chassis_modules.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import click
22
from natsort import natsorted
33
from tabulate import tabulate
4-
from swsssdk import SonicV2Connector
4+
from swsscommon.swsscommon import SonicV2Connector
55

66
import utilities_common.cli as clicommon
77

@@ -12,6 +12,10 @@
1212
CHASSIS_MODULE_INFO_OPERSTATUS_FIELD = 'oper_status'
1313
CHASSIS_MODULE_INFO_ADMINSTATUS_FIELD = 'admin_status'
1414

15+
CHASSIS_MIDPLANE_INFO_TABLE = 'CHASSIS_MIDPLANE_TABLE'
16+
CHASSIS_MIDPLANE_INFO_IP_FIELD = 'ip_address'
17+
CHASSIS_MIDPLANE_INFO_ACCESS_FIELD = 'access'
18+
1519
@click.group(cls=clicommon.AliasedGroup)
1620
def chassis_modules():
1721
"""Show chassis-modules information"""
@@ -31,7 +35,7 @@ def status(db, chassis_module_name):
3135

3236
key_pattern = '*'
3337
if chassis_module_name:
34-
key_pattern = '|'+chassis_module_name
38+
key_pattern = '|' + chassis_module_name
3539

3640
keys = state_db.keys(state_db.STATE_DB, CHASSIS_MODULE_INFO_TABLE + key_pattern)
3741
if not keys:
@@ -41,7 +45,7 @@ def status(db, chassis_module_name):
4145
table = []
4246
for key in natsorted(keys):
4347
key_list = key.split('|')
44-
if len(key_list) != 2: # error data in DB, log it and ignore
48+
if len(key_list) != 2: # error data in DB, log it and ignore
4549
print('Warn: Invalid Key {} in {} table'.format(key, CHASSIS_MODULE_INFO_TABLE))
4650
continue
4751

@@ -61,3 +65,40 @@ def status(db, chassis_module_name):
6165
click.echo(tabulate(table, header, tablefmt='simple', stralign='right'))
6266
else:
6367
click.echo('No data available in CHASSIS_MODULE_TABLE\n')
68+
69+
@chassis_modules.command()
70+
@click.argument('chassis_module_name', metavar='<module_name>', required=False)
71+
def midplane_status(chassis_module_name):
72+
"""Show chassis-modules midplane-status"""
73+
74+
header = ['Name', 'IP-Address', 'Reachability']
75+
76+
state_db = SonicV2Connector(host="127.0.0.1")
77+
state_db.connect(state_db.STATE_DB)
78+
79+
key_pattern = '*'
80+
if chassis_module_name:
81+
key_pattern = '|' + chassis_module_name
82+
83+
keys = state_db.keys(state_db.STATE_DB, CHASSIS_MIDPLANE_INFO_TABLE + key_pattern)
84+
if not keys:
85+
print('Key {} not found in {} table'.format(key_pattern, CHASSIS_MIDPLANE_INFO_TABLE))
86+
return
87+
88+
table = []
89+
for key in natsorted(keys):
90+
key_list = key.split('|')
91+
if len(key_list) != 2: # error data in DB, log it and ignore
92+
print('Warn: Invalid Key {} in {} table'.format(key, CHASSIS_MIDPLANE_INFO_TABLE))
93+
continue
94+
95+
data_dict = state_db.get_all(state_db.STATE_DB, key)
96+
ip = data_dict[CHASSIS_MIDPLANE_INFO_IP_FIELD]
97+
access = data_dict[CHASSIS_MIDPLANE_INFO_ACCESS_FIELD]
98+
99+
table.append((key_list[1], ip, access))
100+
101+
if table:
102+
click.echo(tabulate(table, header, tablefmt='simple', stralign='right'))
103+
else:
104+
click.echo('No data available in CHASSIS_MIDPLANE_TABLE\n')

tests/chassis_modules_test.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,36 @@
2121
header_lines = 2
2222
warning_lines = 0
2323

24+
show_chassis_modules_output="""\
25+
Name Description Physical-Slot Oper-Status Admin-Status
26+
------------ --------------- --------------- ------------- --------------
27+
FABRIC-CARD0 fabric-card 17 Online up
28+
FABRIC-CARD1 fabric-card 18 Offline up
29+
LINE-CARD0 line-card 1 Empty up
30+
LINE-CARD1 line-card 2 Online down
31+
SUPERVISOR0 supervisor-card 16 Online up
32+
"""
33+
34+
show_chassis_midplane_output="""\
35+
Name IP-Address Reachability
36+
----------- ------------- --------------
37+
LINE-CARD0 192.168.1.1 True
38+
LINE-CARD1 192.168.1.2 False
39+
SUPERVISOR0 192.168.1.100 True
40+
"""
41+
2442
class TestChassisModules(object):
2543
@classmethod
2644
def setup_class(cls):
2745
print("SETUP")
2846
os.environ["UTILITIES_UNIT_TESTING"] = "1"
2947

48+
def test_show_and_verify_output(self):
49+
runner = CliRunner()
50+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], [])
51+
print(result.output)
52+
assert(result.output == show_chassis_modules_output)
53+
3054
def test_show_all_count_lines(self):
3155
runner = CliRunner()
3256
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], [])
@@ -112,6 +136,49 @@ def test_config_incorrect_module(self):
112136
print(result.output)
113137
assert result.exit_code != 0
114138

139+
def test_show_and_verify_midplane_output(self):
140+
runner = CliRunner()
141+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], [])
142+
print(result.output)
143+
assert(result.output == show_chassis_midplane_output)
144+
145+
def test_midplane_show_all_count_lines(self):
146+
runner = CliRunner()
147+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], [])
148+
print(result.output)
149+
result_lines = result.output.strip('\n').split('\n')
150+
modules = ["LINE-CARD0", "LINE-CARD1", "SUPERVISOR0"]
151+
for i, module in enumerate(modules):
152+
assert module in result_lines[i + warning_lines + header_lines]
153+
assert len(result_lines) == warning_lines + header_lines + len(modules)
154+
155+
def test_midplane_show_single_count_lines(self):
156+
runner = CliRunner()
157+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], ["LINE-CARD0"])
158+
print(result.output)
159+
result_lines = result.output.strip('\n').split('\n')
160+
modules = ["LINE-CARD0"]
161+
for i, module in enumerate(modules):
162+
assert module in result_lines[i+header_lines]
163+
assert len(result_lines) == header_lines + len(modules)
164+
165+
def test_midplane_show_module_down(self):
166+
runner = CliRunner()
167+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], ["LINE-CARD1"])
168+
print(result.output)
169+
result_lines = result.output.strip('\n').split('\n')
170+
assert result.exit_code == 0
171+
result_out = (result_lines[header_lines]).split()
172+
print(result_out)
173+
assert result_out[2] == 'False'
174+
175+
def test_midplane_show_incorrect_module(self):
176+
runner = CliRunner()
177+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["midplane-status"], ["TEST-CARD1"])
178+
print(result.output)
179+
print(result.exit_code)
180+
assert result.exit_code == 0
181+
115182
@classmethod
116183
def teardown_class(cls):
117184
print("TEARDOWN")

tests/mock_tables/state_db.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,5 +377,17 @@
377377
"xon": "18432",
378378
"xoff": "32768",
379379
"size": "51200"
380+
},
381+
"CHASSIS_MIDPLANE_TABLE|SUPERVISOR0": {
382+
"ip_address": "192.168.1.100",
383+
"access": "True"
384+
},
385+
"CHASSIS_MIDPLANE_TABLE|LINE-CARD0": {
386+
"ip_address": "192.168.1.1",
387+
"access": "True"
388+
},
389+
"CHASSIS_MIDPLANE_TABLE|LINE-CARD1": {
390+
"ip_address": "192.168.1.2",
391+
"access": "False"
380392
}
381393
}

0 commit comments

Comments
 (0)