forked from sonic-net/sonic-buildimage
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[chassis]: Configure and show for platform chassis_modules (sonic-net…
…#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 ```
- Loading branch information
1 parent
d5eb2f8
commit 40377d3
Showing
7 changed files
with
260 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#!/usr/sbin/env python | ||
|
||
import click | ||
|
||
import utilities_common.cli as clicommon | ||
|
||
# | ||
# 'chassis_modules' group ('config chassis_modules ...') | ||
# | ||
@click.group(cls=clicommon.AliasedGroup) | ||
def chassis_modules(): | ||
"""Configure chassis-modules options""" | ||
pass | ||
|
||
# | ||
# 'shutdown' subcommand ('config chassis_modules shutdown ...') | ||
# | ||
@chassis_modules.command('shutdown') | ||
@clicommon.pass_db | ||
@click.argument('chassis_module_name', metavar='<module_name>', required=True) | ||
def shutdown_chassis_module(db, chassis_module_name): | ||
"""Chassis-module shutdown of module""" | ||
config_db = db.cfgdb | ||
ctx = click.get_current_context() | ||
|
||
if not chassis_module_name.startswith("SUPERVISOR") and \ | ||
not chassis_module_name.startswith("LINE-CARD") and \ | ||
not chassis_module_name.startswith("FABRIC-CARD"): | ||
ctx.fail("'module_name' has to begin with 'SUPERVISOR', 'LINE-CARD' or 'FABRIC-CARD'") | ||
|
||
fvs = {'admin_status': 'down'} | ||
config_db.set_entry('CHASSIS_MODULE', chassis_module_name, fvs) | ||
|
||
# | ||
# 'startup' subcommand ('config chassis_modules startup ...') | ||
# | ||
@chassis_modules.command('startup') | ||
@clicommon.pass_db | ||
@click.argument('chassis_module_name', metavar='<module_name>', required=True) | ||
def startup_chassis_module(db, chassis_module_name): | ||
"""Chassis-module startup of module""" | ||
config_db = db.cfgdb | ||
|
||
config_db.set_entry('CHASSIS_MODULE', chassis_module_name, None) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import click | ||
from natsort import natsorted | ||
from tabulate import tabulate | ||
from swsssdk import SonicV2Connector | ||
|
||
import utilities_common.cli as clicommon | ||
|
||
CHASSIS_MODULE_INFO_TABLE = 'CHASSIS_MODULE_TABLE' | ||
CHASSIS_MODULE_INFO_KEY_TEMPLATE = 'CHASSIS_MODULE {}' | ||
CHASSIS_MODULE_INFO_DESC_FIELD = 'desc' | ||
CHASSIS_MODULE_INFO_SLOT_FIELD = 'slot' | ||
CHASSIS_MODULE_INFO_OPERSTATUS_FIELD = 'oper_status' | ||
CHASSIS_MODULE_INFO_ADMINSTATUS_FIELD = 'admin_status' | ||
|
||
@click.group(cls=clicommon.AliasedGroup) | ||
def chassis_modules(): | ||
"""Show chassis-modules information""" | ||
pass | ||
|
||
@chassis_modules.command() | ||
@clicommon.pass_db | ||
@click.argument('chassis_module_name', metavar='<module_name>', required=False) | ||
def status(db, chassis_module_name): | ||
"""Show chassis-modules status""" | ||
|
||
header = ['Name', 'Description', 'Physical-Slot', 'Oper-Status', 'Admin-Status'] | ||
chassis_cfg_table = db.cfgdb.get_table('CHASSIS_MODULE') | ||
|
||
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_MODULE_INFO_TABLE + key_pattern) | ||
if not keys: | ||
print('Key {} not found in {} table'.format(key_pattern, CHASSIS_MODULE_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_MODULE_INFO_TABLE)) | ||
continue | ||
|
||
data_dict = state_db.get_all(state_db.STATE_DB, key) | ||
desc = data_dict[CHASSIS_MODULE_INFO_DESC_FIELD] | ||
slot = data_dict[CHASSIS_MODULE_INFO_SLOT_FIELD] | ||
oper_status = data_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] | ||
|
||
admin_status = 'up' | ||
config_data = chassis_cfg_table.get(key_list[1]) | ||
if config_data is not None: | ||
admin_status = config_data.get(CHASSIS_MODULE_INFO_ADMINSTATUS_FIELD) | ||
|
||
table.append((key_list[1], desc, slot, oper_status, admin_status)) | ||
|
||
if table: | ||
click.echo(tabulate(table, header, tablefmt='simple', stralign='right')) | ||
else: | ||
click.echo('No data available in CHASSIS_MODULE_TABLE\n') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import sys | ||
import os | ||
from click.testing import CliRunner | ||
|
||
test_path = os.path.dirname(os.path.abspath(__file__)) | ||
modules_path = os.path.dirname(test_path) | ||
sys.path.insert(0, modules_path) | ||
|
||
import show.main as show | ||
import config.main as config | ||
import tests.mock_tables.dbconnector | ||
from utilities_common.db import Db | ||
|
||
show_linecard0_shutdown_output="""\ | ||
LINE-CARD0 line-card 1 Empty down | ||
""" | ||
|
||
show_linecard0_startup_output="""\ | ||
LINE-CARD0 line-card 1 Empty up | ||
""" | ||
header_lines = 2 | ||
warning_lines = 0 | ||
|
||
class TestChassisModules(object): | ||
@classmethod | ||
def setup_class(cls): | ||
print("SETUP") | ||
os.environ["UTILITIES_UNIT_TESTING"] = "1" | ||
|
||
def test_show_all_count_lines(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], []) | ||
print(result.output) | ||
result_lines = result.output.strip('\n').split('\n') | ||
modules = ["FABRIC-CARD0", "FABRIC-CARD1", "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_show_single_count_lines(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["chassis-modules"].commands["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_show_module_down(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD1"]) | ||
result_lines = result.output.strip('\n').split('\n') | ||
assert result.exit_code == 0 | ||
result_out = (result_lines[header_lines]).split() | ||
assert result_out[4] == 'down' | ||
|
||
def test_show_incorrect_command(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["chassis-modules"], []) | ||
print(result.output) | ||
print(result.exit_code) | ||
assert result.exit_code == 0 | ||
|
||
def test_show_incorrect_module(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["TEST-CARD1"]) | ||
print(result.output) | ||
print(result.exit_code) | ||
assert result.exit_code == 0 | ||
|
||
def test_config_shutdown_module(self): | ||
runner = CliRunner() | ||
db = Db() | ||
result = runner.invoke(config.config.commands["chassis-modules"].commands["shutdown"], ["LINE-CARD0"], obj=db) | ||
print(result.exit_code) | ||
print(result.output) | ||
assert result.exit_code == 0 | ||
|
||
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD0"], obj=db) | ||
print(result.exit_code) | ||
print(result.output) | ||
result_lines = result.output.strip('\n').split('\n') | ||
assert result.exit_code == 0 | ||
header_lines = 2 | ||
result_out = " ".join((result_lines[header_lines]).split()) | ||
assert result_out.strip('\n') == show_linecard0_shutdown_output.strip('\n') | ||
#db.cfgdb.set_entry("CHASSIS_MODULE", "LINE-CARD0", { "admin_status" : "down" }) | ||
#db.get_data("CHASSIS_MODULE", "LINE-CARD0") | ||
|
||
def test_config_startup_module(self): | ||
runner = CliRunner() | ||
db = Db() | ||
result = runner.invoke(config.config.commands["chassis-modules"].commands["startup"], ["LINE-CARD0"], obj=db) | ||
print(result.exit_code) | ||
print(result.output) | ||
assert result.exit_code == 0 | ||
|
||
result = runner.invoke(show.cli.commands["chassis-modules"].commands["status"], ["LINE-CARD0"], obj=db) | ||
print(result.exit_code) | ||
print(result.output) | ||
result_lines = result.output.strip('\n').split('\n') | ||
assert result.exit_code == 0 | ||
result_out = " ".join((result_lines[header_lines]).split()) | ||
assert result_out.strip('\n') == show_linecard0_startup_output.strip('\n') | ||
|
||
def test_config_incorrect_module(self): | ||
runner = CliRunner() | ||
db = Db() | ||
result = runner.invoke(config.config.commands["chassis-modules"].commands["shutdown"], ["TEST-CARD0"], obj=db) | ||
print(result.exit_code) | ||
print(result.output) | ||
assert result.exit_code != 0 | ||
|
||
@classmethod | ||
def teardown_class(cls): | ||
print("TEARDOWN") | ||
os.environ["UTILITIES_UNIT_TESTING"] = "0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters