diff --git a/scripts/sfpshow b/scripts/sfpshow index 64ec647078..119e1252e9 100755 --- a/scripts/sfpshow +++ b/scripts/sfpshow @@ -1,23 +1,23 @@ #!/usr/bin/env python3 """ - Script to show sfp eeprom and presence status. - Not like sfputil this scripts get the sfp data from DB directly. + Script to show SFP EEPROM and presence status. + This script gets the SFP data from State DB, unlike sfputil + which accesses the transceiver directly. """ -import sys -import click -import re -import operator + import os +import re +import sys +import click from natsort import natsorted -from tabulate import tabulate - -from utilities_common import multi_asic as multi_asic_util from sonic_py_common.interface import front_panel_prefix, backplane_prefix from sonic_py_common import multi_asic +from tabulate import tabulate +from utilities_common import multi_asic as multi_asic_util -# Mock the redis for unit test purposes # +# Mock the redis DB for unit test purposes try: if os.environ["UTILITIES_UNIT_TESTING"] == "2": modules_path = os.path.join(os.path.dirname(__file__), "..") @@ -31,151 +31,206 @@ try: except KeyError: pass -qsfp_data_map = {'model': 'Vendor PN', - 'vendor_oui': 'Vendor OUI', - 'vendor_date': 'Vendor Date Code(YYYY-MM-DD Lot)', - 'manufacturer': 'Vendor Name', - 'hardware_rev': 'Vendor Rev', - 'serial': 'Vendor SN', - 'type': 'Identifier', - 'ext_identifier': 'Extended Identifier', - 'ext_rateselect_compliance': 'Extended RateSelect Compliance', - 'cable_length': 'cable_length', - 'cable_type': 'Length', - 'nominal_bit_rate': 'Nominal Bit Rate(100Mbs)', - 'specification_compliance': 'Specification compliance', - 'encoding': 'Encoding', - 'connector': 'Connector', - 'application_advertisement': 'Application Advertisement' - } - -sfp_dom_channel_monitor_map = {'rx1power': 'RXPower', - 'tx1bias': 'TXBias', - 'tx1power': 'TXPower'} - -sfp_dom_channel_threshold_map = { - 'txpowerhighalarm': 'TxPowerHighAlarm', - 'txpowerlowalarm': 'TxPowerLowAlarm', - 'txpowerhighwarning': 'TxPowerHighWarning', - 'txpowerlowwarning': 'TxPowerLowWarning', - 'rxpowerhighalarm': 'RxPowerHighAlarm', - 'rxpowerlowalarm': 'RxPowerLowAlarm', - 'rxpowerhighwarning': 'RxPowerHighWarning', - 'rxpowerlowwarning': 'RxPowerLowWarning', - 'txbiashighalarm': 'TxBiasHighAlarm', - 'txbiaslowalarm': 'TxBiasLowAlarm', - 'txbiashighwarning': 'TxBiasHighWarning', - 'txbiaslowwarning': 'TxBiasLowWarning', - } - -qsfp_dom_channel_threshold_map = { - 'rxpowerhighalarm': 'RxPowerHighAlarm', - 'rxpowerlowalarm': 'RxPowerLowAlarm', - 'rxpowerhighwarning': 'RxPowerHighWarning', - 'rxpowerlowwarning': 'RxPowerLowWarning', - 'txbiashighalarm': 'TxBiasHighAlarm', - 'txbiaslowalarm': 'TxBiasLowAlarm', - 'txbiashighwarning': 'TxBiasHighWarning', - 'txbiaslowwarning': 'TxBiasLowWarning', - } - -dom_module_threshold_map = { - 'temphighalarm': 'TempHighAlarm', - 'templowalarm': 'TempLowAlarm', - 'temphighwarning':'TempHighWarning', - 'templowwarning': 'TempLowWarning', - 'vcchighalarm': 'VccHighAlarm', - 'vcclowalarm': 'VccLowAlarm', - 'vcchighwarning': 'VccHighWarning', - 'vcclowwarning': 'VccLowWarning' - } - -qsfp_dom_channel_monitor_map = {'rx1power': 'RX1Power', 'rx2power': 'RX2Power', - 'rx3power': 'RX3Power', 'rx4power': 'RX4Power', - 'tx1bias': 'TX1Bias', 'tx2bias': 'TX2Bias', - 'tx3bias': 'TX3Bias', 'tx4bias': 'TX4Bias', - 'tx1power': 'TX1Power', 'tx2power': 'TX2Power', - 'tx3power': 'TX3Power', 'tx4power': 'TX4Power'} - -qsfp_dd_dom_channel_monitor_map = {'rx1power': 'RX1Power', 'rx2power': 'RX2Power', - 'rx3power': 'RX3Power', 'rx4power': 'RX4Power', - 'rx5power': 'RX5Power', 'rx6power': 'RX6Power', - 'rx7power': 'RX7Power', 'rx8power': 'RX8Power', - 'tx1bias': 'TX1Bias', 'tx2bias': 'TX2Bias', - 'tx3bias': 'TX3Bias', 'tx4bias': 'TX4Bias', - 'tx5bias': 'TX5Bias', 'tx6bias': 'TX6Bias', - 'tx7bias': 'TX7Bias', 'tx8bias': 'TX8Bias', - 'tx1power': 'TX1Power', 'tx2power': 'TX2Power', - 'tx3power': 'TX3Power', 'tx4power': 'TX4Power', - 'tx5power': 'TX5Power', 'tx6power': 'TX6Power', - 'tx7power': 'TX7Power', 'tx8power': 'TX8Power'} - -dom_module_monitor_map = {'temperature': 'Temperature', 'voltage': 'Vcc'} - -dom_channel_threshold_unit_map = { - 'txpowerhighalarm': 'dBm', - 'txpowerlowalarm': 'dBm', - 'txpowerhighwarning': 'dBm', - 'txpowerlowwarning': 'dBm', - 'rxpowerhighalarm': 'dBm', - 'rxpowerlowalarm': 'dBm', - 'rxpowerhighwarning': 'dBm', - 'rxpowerlowwarning': 'dBm', - 'txbiashighalarm': 'mA', - 'txbiaslowalarm': 'mA', - 'txbiashighwarning': 'mA', - 'txbiaslowwarning': 'mA', - } - -dom_module_threshold_unit_map = { - 'temphighalarm': 'C', - 'templowalarm': 'C', - 'temphighwarning': 'C', - 'templowwarning': 'C', - 'vcchighalarm': 'Volts', - 'vcclowalarm': 'Volts', - 'vcchighwarning': 'Volts', - 'vcclowwarning': 'Volts' - } - -dom_value_unit_map = {'rx1power': 'dBm', 'rx2power': 'dBm', - 'rx3power': 'dBm', 'rx4power': 'dBm', - 'tx1bias': 'mA', 'tx2bias': 'mA', - 'tx3bias': 'mA', 'tx4bias': 'mA', - 'tx1power': 'dBm', 'tx2power': 'dBm', - 'tx3power': 'dBm', 'tx4power': 'dBm', - 'temperature': 'C', 'voltage': 'Volts'} - -qsfp_dd_dom_value_unit_map = {'rx1power': 'dBm', 'rx2power': 'dBm', - 'rx3power': 'dBm', 'rx4power': 'dBm', - 'rx5power': 'dBm', 'rx6power': 'dBm', - 'rx7power': 'dBm', 'rx8power': 'dBm', - 'tx1bias': 'mA', 'tx2bias': 'mA', - 'tx3bias': 'mA', 'tx4bias': 'mA', - 'tx5bias': 'mA', 'tx6bias': 'mA', - 'tx7bias': 'mA', 'tx8bias': 'mA', - 'tx1power': 'dBm', 'tx2power': 'dBm', - 'tx3power': 'dBm', 'tx4power': 'dBm', - 'tx5power': 'dBm', 'tx6power': 'dBm', - 'tx7power': 'dBm', 'tx8power': 'dBm', - 'temperature': 'C', 'voltage': 'Volts'} +# TODO: We should share these maps and the formatting functions between sfputil and sfpshow +QSFP_DATA_MAP = { + 'model': 'Vendor PN', + 'vendor_oui': 'Vendor OUI', + 'vendor_date': 'Vendor Date Code(YYYY-MM-DD Lot)', + 'manufacturer': 'Vendor Name', + 'hardware_rev': 'Vendor Rev', + 'serial': 'Vendor SN', + 'type': 'Identifier', + 'ext_identifier': 'Extended Identifier', + 'ext_rateselect_compliance': 'Extended RateSelect Compliance', + 'cable_length': 'cable_length', + 'cable_type': 'Length', + 'nominal_bit_rate': 'Nominal Bit Rate(100Mbs)', + 'specification_compliance': 'Specification compliance', + 'encoding': 'Encoding', + 'connector': 'Connector', + 'application_advertisement': 'Application Advertisement' +} + +SFP_DOM_CHANNEL_MONITOR_MAP = { + 'rx1power': 'RXPower', + 'tx1bias': 'TXBias', + 'tx1power': 'TXPower' +} + +SFP_DOM_CHANNEL_THRESHOLD_MAP = { + 'txpowerhighalarm': 'TxPowerHighAlarm', + 'txpowerlowalarm': 'TxPowerLowAlarm', + 'txpowerhighwarning': 'TxPowerHighWarning', + 'txpowerlowwarning': 'TxPowerLowWarning', + 'rxpowerhighalarm': 'RxPowerHighAlarm', + 'rxpowerlowalarm': 'RxPowerLowAlarm', + 'rxpowerhighwarning': 'RxPowerHighWarning', + 'rxpowerlowwarning': 'RxPowerLowWarning', + 'txbiashighalarm': 'TxBiasHighAlarm', + 'txbiaslowalarm': 'TxBiasLowAlarm', + 'txbiashighwarning': 'TxBiasHighWarning', + 'txbiaslowwarning': 'TxBiasLowWarning' +} + +QSFP_DOM_CHANNEL_THRESHOLD_MAP = { + 'rxpowerhighalarm': 'RxPowerHighAlarm', + 'rxpowerlowalarm': 'RxPowerLowAlarm', + 'rxpowerhighwarning': 'RxPowerHighWarning', + 'rxpowerlowwarning': 'RxPowerLowWarning', + 'txbiashighalarm': 'TxBiasHighAlarm', + 'txbiaslowalarm': 'TxBiasLowAlarm', + 'txbiashighwarning': 'TxBiasHighWarning', + 'txbiaslowwarning': 'TxBiasLowWarning' +} + +DOM_MODULE_THRESHOLD_MAP = { + 'temphighalarm': 'TempHighAlarm', + 'templowalarm': 'TempLowAlarm', + 'temphighwarning': 'TempHighWarning', + 'templowwarning': 'TempLowWarning', + 'vcchighalarm': 'VccHighAlarm', + 'vcclowalarm': 'VccLowAlarm', + 'vcchighwarning': 'VccHighWarning', + 'vcclowwarning': 'VccLowWarning' +} + +QSFP_DOM_CHANNEL_MONITOR_MAP = { + 'rx1power': 'RX1Power', + 'rx2power': 'RX2Power', + 'rx3power': 'RX3Power', + 'rx4power': 'RX4Power', + 'tx1bias': 'TX1Bias', + 'tx2bias': 'TX2Bias', + 'tx3bias': 'TX3Bias', + 'tx4bias': 'TX4Bias', + 'tx1power': 'TX1Power', + 'tx2power': 'TX2Power', + 'tx3power': 'TX3Power', + 'tx4power': 'TX4Power' +} + +QSFP_DD_DOM_CHANNEL_MONITOR_MAP = { + 'rx1power': 'RX1Power', + 'rx2power': 'RX2Power', + 'rx3power': 'RX3Power', + 'rx4power': 'RX4Power', + 'rx5power': 'RX5Power', + 'rx6power': 'RX6Power', + 'rx7power': 'RX7Power', + 'rx8power': 'RX8Power', + 'tx1bias': 'TX1Bias', + 'tx2bias': 'TX2Bias', + 'tx3bias': 'TX3Bias', + 'tx4bias': 'TX4Bias', + 'tx5bias': 'TX5Bias', + 'tx6bias': 'TX6Bias', + 'tx7bias': 'TX7Bias', + 'tx8bias': 'TX8Bias', + 'tx1power': 'TX1Power', + 'tx2power': 'TX2Power', + 'tx3power': 'TX3Power', + 'tx4power': 'TX4Power', + 'tx5power': 'TX5Power', + 'tx6power': 'TX6Power', + 'tx7power': 'TX7Power', + 'tx8power': 'TX8Power' +} + +DOM_MODULE_MONITOR_MAP = { + 'temperature': 'Temperature', + 'voltage': 'Vcc' +} + +DOM_CHANNEL_THRESHOLD_UNIT_MAP = { + 'txpowerhighalarm': 'dBm', + 'txpowerlowalarm': 'dBm', + 'txpowerhighwarning': 'dBm', + 'txpowerlowwarning': 'dBm', + 'rxpowerhighalarm': 'dBm', + 'rxpowerlowalarm': 'dBm', + 'rxpowerhighwarning': 'dBm', + 'rxpowerlowwarning': 'dBm', + 'txbiashighalarm': 'mA', + 'txbiaslowalarm': 'mA', + 'txbiashighwarning': 'mA', + 'txbiaslowwarning': 'mA' +} + +DOM_MODULE_THRESHOLD_UNIT_MAP = { + 'temphighalarm': 'C', + 'templowalarm': 'C', + 'temphighwarning': 'C', + 'templowwarning': 'C', + 'vcchighalarm': 'Volts', + 'vcclowalarm': 'Volts', + 'vcchighwarning': 'Volts', + 'vcclowwarning': 'Volts' +} + +DOM_VALUE_UNIT_MAP = { + 'rx1power': 'dBm', + 'rx2power': 'dBm', + 'rx3power': 'dBm', + 'rx4power': 'dBm', + 'tx1bias': 'mA', + 'tx2bias': 'mA', + 'tx3bias': 'mA', + 'tx4bias': 'mA', + 'tx1power': 'dBm', + 'tx2power': 'dBm', + 'tx3power': 'dBm', + 'tx4power': 'dBm', + 'temperature': 'C', + 'voltage': 'Volts' +} + +QSFP_DD_DOM_VALUE_UNIT_MAP = { + 'rx1power': 'dBm', + 'rx2power': 'dBm', + 'rx3power': 'dBm', + 'rx4power': 'dBm', + 'rx5power': 'dBm', + 'rx6power': 'dBm', + 'rx7power': 'dBm', + 'rx8power': 'dBm', + 'tx1bias': 'mA', + 'tx2bias': 'mA', + 'tx3bias': 'mA', + 'tx4bias': 'mA', + 'tx5bias': 'mA', + 'tx6bias': 'mA', + 'tx7bias': 'mA', + 'tx8bias': 'mA', + 'tx1power': 'dBm', + 'tx2power': 'dBm', + 'tx3power': 'dBm', + 'tx4power': 'dBm', + 'tx5power': 'dBm', + 'tx6power': 'dBm', + 'tx7power': 'dBm', + 'tx8power': 'dBm', + 'temperature': 'C', + 'voltage': 'Volts' +} + def display_invalid_intf_eeprom(intf_name): - output = intf_name + ': ' + 'SFP EEPROM Not detected' + '\n' + output = intf_name + ': SFP EEPROM Not detected\n' click.echo(output) + def display_invalid_intf_presence(intf_name): header = ['Port', 'Presence'] port_table = [] port_table.append((intf_name, 'Not present')) click.echo(tabulate(port_table, header)) + class SFPShow(object): def __init__(self, intf_name, namespace_option, dump_dom=False): - super(SFPShow,self).__init__() + super(SFPShow, self).__init__() self.db = None - self.config_db = None self.intf_name = intf_name self.dump_dom = dump_dom self.table = [] @@ -185,180 +240,172 @@ class SFPShow(object): # Convert dict values to cli output string def format_dict_value_to_string(self, sorted_key_table, dom_info_dict, dom_value_map, - dom_unit_map, alignment = 0): - out_put='' - ident = ' ' - seperator = ": " + dom_unit_map, alignment=0): + output = '' + indent = ' ' * 8 + separator = ": " for key in sorted_key_table: if dom_info_dict is not None and key in dom_info_dict and dom_info_dict[key] != 'N/A': - current_val = (ident + ident + - dom_value_map[key]) - current_val = (current_val + seperator.rjust(len(seperator) + - alignment - len(dom_value_map[key]))) - if dom_info_dict[key] == 'Unknown': - current_val = (current_val + dom_info_dict[key]) + value = dom_info_dict[key] + units = '' + if type(value) != str or (value != 'Unknown' and not value.endswith(dom_unit_map[key])): + units = dom_unit_map[key] + output += '{}{}{}{}{}\n'.format((indent * 2), + dom_value_map[key], + separator.rjust(len(separator) + alignment - len(dom_value_map[key])), + value, + units) + return output + + # Convert sfp info in DB to cli output string + def convert_sfp_info_to_output_string(self, sfp_info_dict): + indent = ' ' * 8 + output = '' + + sorted_qsfp_data_map_keys = sorted(QSFP_DATA_MAP, key=QSFP_DATA_MAP.get) + for key in sorted_qsfp_data_map_keys: + if key == 'cable_type': + output += '{}{}: {}\n'.format(indent, sfp_info_dict['cable_type'], sfp_info_dict['cable_length']) + elif key == 'cable_length': + pass + elif key == 'specification_compliance': + if sfp_info_dict['type'] == "QSFP-DD Double Density 8X Pluggable Transceiver": + output += '{}{}: {}\n'.format(indent, QSFP_DATA_MAP[key], sfp_info_dict[key]) else: - current_val = (current_val + dom_info_dict[key] + - dom_unit_map[key]) - out_put = out_put + current_val + '\n' - return out_put + output += '{}{}:\n'.format(indent, QSFP_DATA_MAP['specification_compliance']) + spefic_compliance_dict = eval(sfp_info_dict['specification_compliance']) + sorted_compliance_key_table = natsorted(spefic_compliance_dict) + for compliance_key in sorted_compliance_key_table: + output += '{}{}: {}\n'.format((indent * 2), compliance_key, spefic_compliance_dict[compliance_key]) + else: + output += '{}{}: {}\n'.format(indent, QSFP_DATA_MAP[key], sfp_info_dict[key]) + + return output - # Convert dom sensor info in DB to cli output string + # Convert DOM sensor info in DB to CLI output string def convert_dom_to_output_string(self, sfp_type, dom_info_dict): - ident = ' ' - out_put_dom = '' - newline_ident = ': ' + '\n' + indent = ' ' * 8 + output_dom = '' channel_threshold_align = 18 module_threshold_align = 15 if sfp_type.startswith('QSFP'): - #Channel Monitor + # Channel Monitor if sfp_type.startswith('QSFP-DD'): - out_put_dom = (out_put_dom + ident + 'ChannelMonitorValues' - + newline_ident) - sorted_key_table = natsorted(qsfp_dd_dom_channel_monitor_map) - out_put_channel = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - qsfp_dd_dom_channel_monitor_map, - qsfp_dd_dom_value_unit_map) - out_put_dom = out_put_dom + out_put_channel + output_dom += (indent + 'ChannelMonitorValues:\n') + sorted_key_table = natsorted(QSFP_DD_DOM_CHANNEL_MONITOR_MAP) + output_channel = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + QSFP_DD_DOM_CHANNEL_MONITOR_MAP, + QSFP_DD_DOM_VALUE_UNIT_MAP) + output_dom += output_channel else: - out_put_dom = (out_put_dom + ident + 'ChannelMonitorValues' - + newline_ident) - sorted_key_table = natsorted(qsfp_dom_channel_monitor_map) - out_put_channel = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - qsfp_dom_channel_monitor_map, - dom_value_unit_map) - out_put_dom = out_put_dom + out_put_channel - - #Channel Threshold + output_dom += (indent + 'ChannelMonitorValues:\n') + sorted_key_table = natsorted(QSFP_DOM_CHANNEL_MONITOR_MAP) + output_channel = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + QSFP_DOM_CHANNEL_MONITOR_MAP, + DOM_VALUE_UNIT_MAP) + output_dom += output_channel + + # Channel Threshold if sfp_type.startswith('QSFP-DD'): - dom_map = sfp_dom_channel_threshold_map + dom_map = SFP_DOM_CHANNEL_THRESHOLD_MAP else: - dom_map = qsfp_dom_channel_threshold_map + dom_map = QSFP_DOM_CHANNEL_THRESHOLD_MAP - out_put_dom = (out_put_dom + ident + 'ChannelThresholdValues' - + newline_ident) + output_dom += (indent + 'ChannelThresholdValues:\n') sorted_key_table = natsorted(dom_map) - out_put_channel_threshold = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - dom_map, - dom_channel_threshold_unit_map, - channel_threshold_align) - out_put_dom = out_put_dom + out_put_channel_threshold + output_channel_threshold = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + dom_map, + DOM_CHANNEL_THRESHOLD_UNIT_MAP, + channel_threshold_align) + output_dom += output_channel_threshold # Module Monitor - out_put_dom = (out_put_dom + ident + 'ModuleMonitorValues' - + newline_ident) - sorted_key_table = natsorted(dom_module_monitor_map) - out_put_module = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - dom_module_monitor_map, - dom_value_unit_map) - out_put_dom = out_put_dom + out_put_module - - #Module Threshold - out_put_dom = (out_put_dom + ident + 'ModuleThresholdValues' - + newline_ident) - sorted_key_table = natsorted(dom_module_threshold_map) - out_put_module_threshold = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - dom_module_threshold_map, - dom_module_threshold_unit_map, - module_threshold_align) - out_put_dom = out_put_dom + out_put_module_threshold + output_dom += (indent + 'ModuleMonitorValues:\n') + sorted_key_table = natsorted(DOM_MODULE_MONITOR_MAP) + output_module = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + DOM_MODULE_MONITOR_MAP, + DOM_VALUE_UNIT_MAP) + output_dom += output_module + + # Module Threshold + output_dom += (indent + 'ModuleThresholdValues:\n') + sorted_key_table = natsorted(DOM_MODULE_THRESHOLD_MAP) + output_module_threshold = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + DOM_MODULE_THRESHOLD_MAP, + DOM_MODULE_THRESHOLD_UNIT_MAP, + module_threshold_align) + output_dom += output_module_threshold else: - out_put_dom = out_put_dom + ident + 'MonitorData' + newline_ident - sorted_key_table = natsorted(sfp_dom_channel_monitor_map) - out_put_channel = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - sfp_dom_channel_monitor_map, - dom_value_unit_map) - out_put_dom = out_put_dom + out_put_channel - - sorted_key_table = natsorted(dom_module_monitor_map) - out_put_module = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - dom_module_monitor_map, - dom_value_unit_map) - out_put_dom = out_put_dom + out_put_module - - out_put_dom = (out_put_dom + ident + 'ThresholdData' - + newline_ident) - #Module Threshold - sorted_key_table = natsorted(dom_module_threshold_map) - out_put_module_threshold = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - dom_module_threshold_map, - dom_module_threshold_unit_map, - module_threshold_align) - out_put_dom = out_put_dom + out_put_module_threshold - - #Channel Threshold - sorted_key_table = natsorted(sfp_dom_channel_threshold_map) - out_put_channel_threshold = self.format_dict_value_to_string( - sorted_key_table, dom_info_dict, - sfp_dom_channel_threshold_map, - dom_channel_threshold_unit_map, - channel_threshold_align) - out_put_dom = out_put_dom + out_put_channel_threshold - - return out_put_dom - - # Convert sfp info in DB to cli output string - def convert_sfp_info_to_output_string(self, sfp_info_dict): - ident = ' ' - out_put = '' - - sorted_qsfp_data_map = sorted(qsfp_data_map.items(), key=operator.itemgetter(1)) - for key in sorted_qsfp_data_map: - key1 = key[0] - if key1 == 'cable_type': - out_put = out_put + ident + sfp_info_dict['cable_type'] + ': ' + sfp_info_dict['cable_length'] + '\n' - elif key1 == 'cable_length': - pass - elif key1 == 'specification_compliance': - if sfp_info_dict['type'] == "QSFP-DD Double Density 8X Pluggable Transceiver": - out_put = out_put + ident + qsfp_data_map[key1] + ': ' + sfp_info_dict[key1] + '\n' - else: - out_put = out_put + ident + qsfp_data_map['specification_compliance'] + ': ' + '\n' - spefic_compliance_dict = eval(sfp_info_dict['specification_compliance']) - sorted_compliance_key_table = natsorted(spefic_compliance_dict) - for compliance_key in sorted_compliance_key_table: - out_put = out_put + ident + ident + compliance_key + ': ' + spefic_compliance_dict[compliance_key] + '\n' - else: - out_put = out_put + ident + qsfp_data_map[key1] + ': ' + sfp_info_dict[key1] + '\n' - - return out_put + output_dom += (indent + 'MonitorData:\n') + sorted_key_table = natsorted(SFP_DOM_CHANNEL_MONITOR_MAP) + output_channel = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + SFP_DOM_CHANNEL_MONITOR_MAP, + DOM_VALUE_UNIT_MAP) + output_dom += output_channel + + sorted_key_table = natsorted(DOM_MODULE_MONITOR_MAP) + output_module = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + DOM_MODULE_MONITOR_MAP, + DOM_VALUE_UNIT_MAP) + output_dom += output_module + + output_dom += (indent + 'ThresholdData:\n') + + # Module Threshold + sorted_key_table = natsorted(DOM_MODULE_THRESHOLD_MAP) + output_module_threshold = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + DOM_MODULE_THRESHOLD_MAP, + DOM_MODULE_THRESHOLD_UNIT_MAP, + module_threshold_align) + output_dom += output_module_threshold + + # Channel Threshold + sorted_key_table = natsorted(SFP_DOM_CHANNEL_THRESHOLD_MAP) + output_channel_threshold = self.format_dict_value_to_string( + sorted_key_table, dom_info_dict, + SFP_DOM_CHANNEL_THRESHOLD_MAP, + DOM_CHANNEL_THRESHOLD_UNIT_MAP, + channel_threshold_align) + output_dom += output_channel_threshold + + return output_dom # Convert sfp info and dom sensor info in DB to cli output string def convert_interface_sfp_info_to_cli_output_string(self, state_db, interface_name, dump_dom): - out_put = '' + output = '' + sfp_info_dict = state_db.get_all(state_db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface_name)) - out_put = interface_name + ': ' + 'SFP EEPROM detected' + '\n' + output = interface_name + ': ' + 'SFP EEPROM detected' + '\n' sfp_info_output = self.convert_sfp_info_to_output_string(sfp_info_dict) - out_put = out_put + sfp_info_output + output += sfp_info_output if dump_dom: sfp_type = sfp_info_dict['type'] dom_info_dict = state_db.get_all(state_db.STATE_DB, 'TRANSCEIVER_DOM_SENSOR|{}'.format(interface_name)) dom_output = self.convert_dom_to_output_string(sfp_type, dom_info_dict) - out_put = out_put + dom_output + output += dom_output - return out_put + return output @multi_asic_util.run_on_multi_asic def get_eeprom(self): - out_put = '' - if self.intf_name is not None: presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(self.intf_name)) if presence: - out_put = self.convert_interface_sfp_info_to_cli_output_string(self.db, self.intf_name, self.dump_dom) + self.output = self.convert_interface_sfp_info_to_cli_output_string( + self.db, self.intf_name, self.dump_dom) else: - out_put = out_put + self.intf_name + ': ' + 'SFP EEPROM Not detected' + '\n' + self.output += (self.intf_name + ': ' + 'SFP EEPROM Not detected' + '\n') else: port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*") sorted_table_keys = natsorted(port_table_keys) @@ -367,13 +414,12 @@ class SFPShow(object): if interface and interface.startswith(front_panel_prefix()) and not interface.startswith(backplane_prefix()): presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface)) if presence: - out_put = out_put + self.convert_interface_sfp_info_to_cli_output_string(self.db, interface, self.dump_dom) + self.output += self.convert_interface_sfp_info_to_cli_output_string( + self.db, interface, self.dump_dom) else: - out_put = out_put + interface + ': ' + 'SFP EEPROM Not detected' + '\n' + self.output += (interface + ': ' + 'SFP EEPROM Not detected' + '\n') - out_put = out_put + '\n' - - self.output += out_put + self.output += '\n' @multi_asic_util.run_on_multi_asic def get_presence(self): @@ -392,9 +438,9 @@ class SFPShow(object): if key and key.startswith(front_panel_prefix()) and not key.startswith(backplane_prefix()): presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(key)) if presence: - port_table.append((key,'Present')) + port_table.append((key, 'Present')) else: - port_table.append((key,'Not present')) + port_table.append((key, 'Not present')) self.table += port_table @@ -407,12 +453,16 @@ class SFPShow(object): click.echo(tabulate(sorted_port_table, header)) # This is our main entrypoint - the main 'sfpshow' command + + @click.group() def cli(): """sfpshow - Command line utility for display SFP transceivers information""" pass # 'eeprom' subcommand + + @cli.command() @click.option('-p', '--port', metavar='', help="Display SFP EEPROM data for port only") @click.option('-d', '--dom', 'dump_dom', is_flag=True, help="Also display Digital Optical Monitoring (DOM) data") @@ -420,8 +470,7 @@ def cli(): def eeprom(port, dump_dom, namespace): if port and multi_asic.is_multi_asic() and namespace is None: try: - ns = multi_asic.get_namespace_for_port(port) - namespace=ns + namespace = multi_asic.get_namespace_for_port(port) except Exception: display_invalid_intf_eeprom(port) sys.exit(1) @@ -431,14 +480,15 @@ def eeprom(port, dump_dom, namespace): sfp.display_eeprom() # 'presence' subcommand + + @cli.command() @click.option('-p', '--port', metavar='', help="Display SFP presence for port only") @click.option('-n', '--namespace', default=None, help="Display interfaces for specific namespace") def presence(port, namespace): if port and multi_asic.is_multi_asic() and namespace is None: try: - ns = multi_asic.get_namespace_for_port(port) - namespace=ns + namespace = multi_asic.get_namespace_for_port(port) except Exception: display_invalid_intf_presence(port) sys.exit(1) @@ -447,5 +497,6 @@ def presence(port, namespace): sfp.get_presence() sfp.display_presence() + if __name__ == "__main__": cli()