Skip to content

Commit 40377d3

Browse files
[chassis]: Configure and show for platform chassis_modules (#1145)
* Configure and show for platform chassis_modules Adding support for below CLI commands $config plaform chassis_modules admin_down <chassis_module_name> <instance> <module_type> $show platform chassis_modules ``` admin@sonic:~$ show chassis-modules status Name Description Slot Oper-Status Admin-Status ------------- ----------------- ------ ------------- -------------- CONTROL-CARD1 cpm2-ixr 16 Online up FABRIC-CARD1 SFM1 17 Empty up FABRIC-CARD2 SFM2 18 Empty up FABRIC-CARD3 SFM3 19 Empty up FABRIC-CARD4 SFM4 20 Empty up FABRIC-CARD5 SFM5 21 Online up FABRIC-CARD6 SFM6 22 Empty up LINE-CARD1 imm36-400g-qsfpdd 1 Online down LINE-CARD2 imm36-400g-qsfpdd 2 Online up LINE-CARD3 line-card 3 Empty up LINE-CARD4 line-card 4 Empty up admin@sonic:~$ show chassis-modules status LINE-CARD1 Name Description Slot Oper-Status Admin-Status ------------- ----------------- ------ ------------- -------------- LINE-CARD1 imm36-400g-qsfpdd 1 Online down ```
1 parent d5eb2f8 commit 40377d3

File tree

7 files changed

+260
-2
lines changed

7 files changed

+260
-2
lines changed

config/chassis_modules.py

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/sbin/env python
2+
3+
import click
4+
5+
import utilities_common.cli as clicommon
6+
7+
#
8+
# 'chassis_modules' group ('config chassis_modules ...')
9+
#
10+
@click.group(cls=clicommon.AliasedGroup)
11+
def chassis_modules():
12+
"""Configure chassis-modules options"""
13+
pass
14+
15+
#
16+
# 'shutdown' subcommand ('config chassis_modules shutdown ...')
17+
#
18+
@chassis_modules.command('shutdown')
19+
@clicommon.pass_db
20+
@click.argument('chassis_module_name', metavar='<module_name>', required=True)
21+
def shutdown_chassis_module(db, chassis_module_name):
22+
"""Chassis-module shutdown of module"""
23+
config_db = db.cfgdb
24+
ctx = click.get_current_context()
25+
26+
if not chassis_module_name.startswith("SUPERVISOR") and \
27+
not chassis_module_name.startswith("LINE-CARD") and \
28+
not chassis_module_name.startswith("FABRIC-CARD"):
29+
ctx.fail("'module_name' has to begin with 'SUPERVISOR', 'LINE-CARD' or 'FABRIC-CARD'")
30+
31+
fvs = {'admin_status': 'down'}
32+
config_db.set_entry('CHASSIS_MODULE', chassis_module_name, fvs)
33+
34+
#
35+
# 'startup' subcommand ('config chassis_modules startup ...')
36+
#
37+
@chassis_modules.command('startup')
38+
@clicommon.pass_db
39+
@click.argument('chassis_module_name', metavar='<module_name>', required=True)
40+
def startup_chassis_module(db, chassis_module_name):
41+
"""Chassis-module startup of module"""
42+
config_db = db.cfgdb
43+
44+
config_db.set_entry('CHASSIS_MODULE', chassis_module_name, None)

config/main.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import nat
3333
import vlan
3434
from config_mgmt import ConfigMgmtDPB
35+
import chassis_modules
3536

3637
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help', '-?'])
3738

@@ -887,7 +888,7 @@ def config(ctx):
887888
config.add_command(kube.kubernetes)
888889
config.add_command(nat.nat)
889890
config.add_command(vlan.vlan)
890-
891+
config.add_command(chassis_modules.chassis_modules)
891892

892893
@config.command()
893894
@click.option('-y', '--yes', is_flag=True, callback=_abort_if_false,

show/chassis_modules.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import click
2+
from natsort import natsorted
3+
from tabulate import tabulate
4+
from swsssdk import SonicV2Connector
5+
6+
import utilities_common.cli as clicommon
7+
8+
CHASSIS_MODULE_INFO_TABLE = 'CHASSIS_MODULE_TABLE'
9+
CHASSIS_MODULE_INFO_KEY_TEMPLATE = 'CHASSIS_MODULE {}'
10+
CHASSIS_MODULE_INFO_DESC_FIELD = 'desc'
11+
CHASSIS_MODULE_INFO_SLOT_FIELD = 'slot'
12+
CHASSIS_MODULE_INFO_OPERSTATUS_FIELD = 'oper_status'
13+
CHASSIS_MODULE_INFO_ADMINSTATUS_FIELD = 'admin_status'
14+
15+
@click.group(cls=clicommon.AliasedGroup)
16+
def chassis_modules():
17+
"""Show chassis-modules information"""
18+
pass
19+
20+
@chassis_modules.command()
21+
@clicommon.pass_db
22+
@click.argument('chassis_module_name', metavar='<module_name>', required=False)
23+
def status(db, chassis_module_name):
24+
"""Show chassis-modules status"""
25+
26+
header = ['Name', 'Description', 'Physical-Slot', 'Oper-Status', 'Admin-Status']
27+
chassis_cfg_table = db.cfgdb.get_table('CHASSIS_MODULE')
28+
29+
state_db = SonicV2Connector(host="127.0.0.1")
30+
state_db.connect(state_db.STATE_DB)
31+
32+
key_pattern = '*'
33+
if chassis_module_name:
34+
key_pattern = '|'+chassis_module_name
35+
36+
keys = state_db.keys(state_db.STATE_DB, CHASSIS_MODULE_INFO_TABLE + key_pattern)
37+
if not keys:
38+
print('Key {} not found in {} table'.format(key_pattern, CHASSIS_MODULE_INFO_TABLE))
39+
return
40+
41+
table = []
42+
for key in natsorted(keys):
43+
key_list = key.split('|')
44+
if len(key_list) != 2: # error data in DB, log it and ignore
45+
print('Warn: Invalid Key {} in {} table'.format(key, CHASSIS_MODULE_INFO_TABLE))
46+
continue
47+
48+
data_dict = state_db.get_all(state_db.STATE_DB, key)
49+
desc = data_dict[CHASSIS_MODULE_INFO_DESC_FIELD]
50+
slot = data_dict[CHASSIS_MODULE_INFO_SLOT_FIELD]
51+
oper_status = data_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD]
52+
53+
admin_status = 'up'
54+
config_data = chassis_cfg_table.get(key_list[1])
55+
if config_data is not None:
56+
admin_status = config_data.get(CHASSIS_MODULE_INFO_ADMINSTATUS_FIELD)
57+
58+
table.append((key_list[1], desc, slot, oper_status, admin_status))
59+
60+
if table:
61+
click.echo(tabulate(table, header, tablefmt='simple', stralign='right'))
62+
else:
63+
click.echo('No data available in CHASSIS_MODULE_TABLE\n')

show/main.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import vlan
2020
import system_health
2121
import fgnhg
22+
import chassis_modules
2223

2324
from sonic_py_common import device_info, multi_asic
2425
from swsssdk import ConfigDBConnector
@@ -133,6 +134,7 @@ def cli(ctx):
133134
cli.add_command(vlan.vlan)
134135
cli.add_command(system_health.system_health)
135136
cli.add_command(fgnhg.fgnhg)
137+
cli.add_command(chassis_modules.chassis_modules)
136138

137139
#
138140
# 'vrf' command ("show vrf")
@@ -1780,7 +1782,6 @@ def counts(group, counter_type, verbose):
17801782

17811783
run_command(cmd, display_cmd=verbose)
17821784

1783-
17841785
#
17851786
# 'ecn' command ("show ecn")
17861787
#

tests/chassis_modules_test.py

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import sys
2+
import os
3+
from click.testing import CliRunner
4+
5+
test_path = os.path.dirname(os.path.abspath(__file__))
6+
modules_path = os.path.dirname(test_path)
7+
sys.path.insert(0, modules_path)
8+
9+
import show.main as show
10+
import config.main as config
11+
import tests.mock_tables.dbconnector
12+
from utilities_common.db import Db
13+
14+
show_linecard0_shutdown_output="""\
15+
LINE-CARD0 line-card 1 Empty down
16+
"""
17+
18+
show_linecard0_startup_output="""\
19+
LINE-CARD0 line-card 1 Empty up
20+
"""
21+
header_lines = 2
22+
warning_lines = 0
23+
24+
class TestChassisModules(object):
25+
@classmethod
26+
def setup_class(cls):
27+
print("SETUP")
28+
os.environ["UTILITIES_UNIT_TESTING"] = "1"
29+
30+
def test_show_all_count_lines(self):
31+
runner = CliRunner()
32+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], [])
33+
print(result.output)
34+
result_lines = result.output.strip('\n').split('\n')
35+
modules = ["FABRIC-CARD0", "FABRIC-CARD1", "LINE-CARD0", "LINE-CARD1", "SUPERVISOR0"]
36+
for i, module in enumerate(modules):
37+
assert module in result_lines[i + warning_lines + header_lines]
38+
assert len(result_lines) == warning_lines + header_lines + len(modules)
39+
40+
def test_show_single_count_lines(self):
41+
runner = CliRunner()
42+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD0"])
43+
print(result.output)
44+
result_lines = result.output.strip('\n').split('\n')
45+
modules = ["LINE-CARD0"]
46+
for i, module in enumerate(modules):
47+
assert module in result_lines[i+header_lines]
48+
assert len(result_lines) == header_lines + len(modules)
49+
50+
def test_show_module_down(self):
51+
runner = CliRunner()
52+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD1"])
53+
result_lines = result.output.strip('\n').split('\n')
54+
assert result.exit_code == 0
55+
result_out = (result_lines[header_lines]).split()
56+
assert result_out[4] == 'down'
57+
58+
def test_show_incorrect_command(self):
59+
runner = CliRunner()
60+
result = runner.invoke(show.cli.commands["chassis-modules"], [])
61+
print(result.output)
62+
print(result.exit_code)
63+
assert result.exit_code == 0
64+
65+
def test_show_incorrect_module(self):
66+
runner = CliRunner()
67+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["TEST-CARD1"])
68+
print(result.output)
69+
print(result.exit_code)
70+
assert result.exit_code == 0
71+
72+
def test_config_shutdown_module(self):
73+
runner = CliRunner()
74+
db = Db()
75+
result = runner.invoke(config.config.commands["chassis-modules"].commands["shutdown"], ["LINE-CARD0"], obj=db)
76+
print(result.exit_code)
77+
print(result.output)
78+
assert result.exit_code == 0
79+
80+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD0"], obj=db)
81+
print(result.exit_code)
82+
print(result.output)
83+
result_lines = result.output.strip('\n').split('\n')
84+
assert result.exit_code == 0
85+
header_lines = 2
86+
result_out = " ".join((result_lines[header_lines]).split())
87+
assert result_out.strip('\n') == show_linecard0_shutdown_output.strip('\n')
88+
#db.cfgdb.set_entry("CHASSIS_MODULE", "LINE-CARD0", { "admin_status" : "down" })
89+
#db.get_data("CHASSIS_MODULE", "LINE-CARD0")
90+
91+
def test_config_startup_module(self):
92+
runner = CliRunner()
93+
db = Db()
94+
result = runner.invoke(config.config.commands["chassis-modules"].commands["startup"], ["LINE-CARD0"], obj=db)
95+
print(result.exit_code)
96+
print(result.output)
97+
assert result.exit_code == 0
98+
99+
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD0"], obj=db)
100+
print(result.exit_code)
101+
print(result.output)
102+
result_lines = result.output.strip('\n').split('\n')
103+
assert result.exit_code == 0
104+
result_out = " ".join((result_lines[header_lines]).split())
105+
assert result_out.strip('\n') == show_linecard0_startup_output.strip('\n')
106+
107+
def test_config_incorrect_module(self):
108+
runner = CliRunner()
109+
db = Db()
110+
result = runner.invoke(config.config.commands["chassis-modules"].commands["shutdown"], ["TEST-CARD0"], obj=db)
111+
print(result.exit_code)
112+
print(result.output)
113+
assert result.exit_code != 0
114+
115+
@classmethod
116+
def teardown_class(cls):
117+
print("TEARDOWN")
118+
os.environ["UTILITIES_UNIT_TESTING"] = "0"

tests/mock_tables/config_db.json

+3
Original file line numberDiff line numberDiff line change
@@ -1299,5 +1299,8 @@
12991299
"acl_entry_high_threshold": "85",
13001300
"fdb_entry_low_threshold": "70",
13011301
"ipv6_nexthop_high_threshold": "85"
1302+
},
1303+
"CHASSIS_MODULE|LINE-CARD1": {
1304+
"admin_status": "down"
13021305
}
13031306
}

tests/mock_tables/state_db.json

+28
Original file line numberDiff line numberDiff line change
@@ -272,5 +272,33 @@
272272
"29" : "200.200.200.5@Vlan1000",
273273
"30" : "200.200.200.5@Vlan1000",
274274
"31" : "200.200.200.5@Vlan1000"
275+
},
276+
"CHASSIS_TABLE|CHASSIS 1": {
277+
"module_num": "5"
278+
},
279+
"CHASSIS_MODULE_TABLE|SUPERVISOR0": {
280+
"desc": "supervisor-card",
281+
"oper_status": "Online",
282+
"slot": "16"
283+
},
284+
"CHASSIS_MODULE_TABLE|LINE-CARD0": {
285+
"desc": "line-card",
286+
"oper_status": "Empty",
287+
"slot": "1"
288+
},
289+
"CHASSIS_MODULE_TABLE|LINE-CARD1": {
290+
"desc": "line-card",
291+
"oper_status": "Online",
292+
"slot": "2"
293+
},
294+
"CHASSIS_MODULE_TABLE|FABRIC-CARD0": {
295+
"desc": "fabric-card",
296+
"oper_status": "Online",
297+
"slot": "17"
298+
},
299+
"CHASSIS_MODULE_TABLE|FABRIC-CARD1": {
300+
"desc": "fabric-card",
301+
"oper_status": "Offline",
302+
"slot": "18"
275303
}
276304
}

0 commit comments

Comments
 (0)