Skip to content

Commit

Permalink
[show] add support for muxcable metrics (#1615)
Browse files Browse the repository at this point in the history
* [show] add support for muxcable metrics
What I did
Added support for show muxcable metrics. This essentially records what events came to different modules per se
for toggling the mux from one state to another.
for example

admin@sonic$ show muxcable metrics Ethernet0 --json

{
"linkmgrd_switch_active_start": "2021-May-13 10:00:21.420898",
"linkmgrd_switch_standby_end": "2021-May-13 10:01:15.696728",
"linkmgrd_switch_unknown_end": "2021-May-13 10:00:26.123319",
"xcvrd_switch_standby_end": "2021-May-13 10:01:15.696051",
"xcvrd_switch_standby_start": "2021-May-13 10:01:15.690835"
}

or

admin@sonic:$ show muxcable metrics Ethernet0

PORT EVENT TIME
--------- ---------------------------- ---------------------------
Ethernet0 linkmgrd_switch_active_start 2021-May-13 10:00:21.420898
Ethernet0 linkmgrd_switch_standby_end 2021-May-13 10:01:15.696728
Ethernet0 linkmgrd_switch_unknown_end 2021-May-13 10:00:26.123319
Ethernet0 xcvrd_switch_standby_end 2021-May-13 10:01:15.696051
Ethernet0 xcvrd_switch_standby_start 2021-May-13 10:01:15.690835

How I did it
added changes in show/muxcable.py by reading and publishing the state DB contents for the corresponding table


Signed-off-by: vaibhav-dahiya <vdahiya@microsoft.com>
  • Loading branch information
vdahiya12 authored May 21, 2021
1 parent feeab29 commit 5d1ad05
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
60 changes: 60 additions & 0 deletions show/muxcable.py
Original file line number Diff line number Diff line change
Expand Up @@ -925,3 +925,63 @@ def version(port):
sys.exit(CONFIG_FAIL)
else:
click.echo("there is not a valid asic table for this asic_index".format(asic_index))

@muxcable.command()
@click.argument('port', metavar='<port_name>', required=True, default=None)
@click.option('--json', 'json_output', required=False, is_flag=True, type=click.BOOL, help="display the output in json format")
def metrics(port, json_output):
"""Show muxcable metrics <port>"""

metrics_table_keys = {}
per_npu_statedb = {}
metrics_dict = {}

# Getting all front asic namespace and correspding config and state DB connector

namespaces = multi_asic.get_front_end_namespaces()
for namespace in namespaces:
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
# replace these with correct macros
per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

metrics_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
per_npu_statedb[asic_id].STATE_DB, 'MUX_METRICS_TABLE|*')

if port is not None:

logical_port_list = platform_sfputil_helper.get_logical_list()

if port not in logical_port_list:
click.echo(("ERR: Not a valid logical port for muxcable firmware {}".format(port)))
sys.exit(CONFIG_FAIL)

asic_index = None
if platform_sfputil is not None:
asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
if asic_index is None:
# TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
# is fully mocked
import sonic_platform_base.sonic_sfp.sfputilhelper
asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
if asic_index is None:
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))


metrics_dict[asic_index] = per_npu_statedb[asic_index].get_all(
per_npu_statedb[asic_index].STATE_DB, 'MUX_METRICS_TABLE|{}'.format(port))

if json_output:
click.echo("{}".format(json.dumps(metrics_dict[asic_index], indent=4)))
else:
print_data = []
for key, val in metrics_dict[asic_index].items():
print_port_data = []
print_port_data.append(port)
print_port_data.append(key)
print_port_data.append(val)
print_data.append(print_port_data)

headers = ['PORT', 'EVENT', 'TIME']

click.echo(tabulate(print_data, headers=headers))
6 changes: 6 additions & 0 deletions tests/mock_tables/state_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -708,5 +708,11 @@
"non_fatal|Undefined": "0",
"non_fatal|UnsupReq": "0",
"non_fatal|UnxCmplt": "0"
},
"MUX_METRICS_TABLE|Ethernet0": {
"linkmgrd_switch_active_start": "2021-May-13 10:00:21.420898",
"linkmgrd_switch_standby_end": "2021-May-13 10:01:15.696728",
"xcvrd_switch_standby_end": "2021-May-13 10:01:15.696051",
"xcvrd_switch_standby_start": "2021-May-13 10:01:15.690835"
}
}
43 changes: 43 additions & 0 deletions tests/muxcable_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,23 @@
}
"""

show_muxcable_metrics_expected_output = """\
PORT EVENT TIME
--------- ---------------------------- ---------------------------
Ethernet0 linkmgrd_switch_active_start 2021-May-13 10:00:21.420898
Ethernet0 linkmgrd_switch_standby_end 2021-May-13 10:01:15.696728
Ethernet0 xcvrd_switch_standby_end 2021-May-13 10:01:15.696051
Ethernet0 xcvrd_switch_standby_start 2021-May-13 10:01:15.690835
"""

show_muxcable_metrics_expected_output_json = """\
{
"linkmgrd_switch_active_start": "2021-May-13 10:00:21.420898",
"linkmgrd_switch_standby_end": "2021-May-13 10:01:15.696728",
"xcvrd_switch_standby_end": "2021-May-13 10:01:15.696051",
"xcvrd_switch_standby_start": "2021-May-13 10:01:15.690835"
}
"""

class TestMuxcable(object):
@classmethod
Expand Down Expand Up @@ -780,6 +797,32 @@ def test_config_muxcable_rollback_firmware(self):
"Ethernet0"], obj=db)
assert result.exit_code == 0

@mock.patch('utilities_common.platform_sfputil_helper.get_logical_list', mock.MagicMock(return_value=["Ethernet0", "Ethernet12"]))
@mock.patch('utilities_common.platform_sfputil_helper.get_asic_id_for_logical_port', mock.MagicMock(return_value=0))
@mock.patch('show.muxcable.platform_sfputil', mock.MagicMock(return_value={0: ["Ethernet12", "Ethernet0"]}))
@mock.patch('utilities_common.platform_sfputil_helper.logical_port_name_to_physical_port_list', mock.MagicMock(return_value=[0]))
def test_show_muxcable_metrics_port(self):
runner = CliRunner()
db = Db()

result = runner.invoke(show.cli.commands["muxcable"].commands["metrics"],
["Ethernet0"], obj=db)
assert result.exit_code == 0
assert result.output == show_muxcable_metrics_expected_output

@mock.patch('utilities_common.platform_sfputil_helper.get_logical_list', mock.MagicMock(return_value=["Ethernet0", "Ethernet12"]))
@mock.patch('utilities_common.platform_sfputil_helper.get_asic_id_for_logical_port', mock.MagicMock(return_value=0))
@mock.patch('show.muxcable.platform_sfputil', mock.MagicMock(return_value={0: ["Ethernet12", "Ethernet0"]}))
@mock.patch('utilities_common.platform_sfputil_helper.logical_port_name_to_physical_port_list', mock.MagicMock(return_value=[0]))
def test_show_muxcable_metrics_port(self):
runner = CliRunner()
db = Db()

result = runner.invoke(show.cli.commands["muxcable"].commands["metrics"],
["Ethernet0", "--json"], obj=db)
assert result.exit_code == 0
assert result.output == show_muxcable_metrics_expected_output_json

@classmethod
def teardown_class(cls):
os.environ['UTILITIES_UNIT_TESTING'] = "0"
Expand Down

0 comments on commit 5d1ad05

Please sign in to comment.