Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[multi-asic] show_transceiver changes #1081

Merged
merged 6 commits into from
Sep 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 1 addition & 52 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from minigraph import parse_device_desc_xml
from portconfig import get_child_ports
from sonic_py_common import device_info, multi_asic
from sonic_py_common.interface import front_panel_prefix, portchannel_prefix, vlan_prefix, loopback_prefix
from sonic_py_common.interface import get_interface_table_name, get_port_table_name
from swsssdk import ConfigDBConnector, SonicV2Connector, SonicDBConfig
from utilities_common.db import Db
from utilities_common.intf_filter import parse_interface_in_filter
Expand Down Expand Up @@ -264,18 +264,6 @@ def _get_device_type():

return device_type

# TODO move to sonic-py-common package
# Validate whether a given namespace name is valid in the device.
def validate_namespace(namespace):
if not multi_asic.is_multi_asic():
return True

namespaces = multi_asic.get_all_namespaces()
if namespace in namespaces['front_ns'] + namespaces['back_ns']:
return True
else:
return False

def interface_alias_to_name(config_db, interface_alias):
"""Return default interface name if alias name is given as argument
"""
Expand Down Expand Up @@ -371,25 +359,6 @@ def interface_name_to_alias(config_db, interface_name):

return None

# TODO move to sonic-py-common package
def get_interface_table_name(interface_name):
"""Get table name by interface_name prefix
"""
if interface_name.startswith(front_panel_prefix()):
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
return "VLAN_SUB_INTERFACE"
return "INTERFACE"
elif interface_name.startswith(portchannel_prefix()):
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
return "VLAN_SUB_INTERFACE"
return "PORTCHANNEL_INTERFACE"
elif interface_name.startswith(vlan_prefix()):
return "VLAN_INTERFACE"
elif interface_name.startswith(loopback_prefix()):
return "LOOPBACK_INTERFACE"
else:
return ""

def interface_ipaddr_dependent_on_interface(config_db, interface_name):
"""Get table keys including ipaddress
"""
Expand All @@ -414,26 +383,6 @@ def is_interface_bind_to_vrf(config_db, interface_name):
return True
return False

# TODO move to sonic-py-common package
# Get the table name based on the interface type
def get_port_table_name(interface_name):
"""Get table name by port_name prefix
"""
if interface_name.startswith(front_panel_prefix()):
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
return "VLAN_SUB_INTERFACE"
return "PORT"
elif interface_name.startswith(portchannel_prefix()):
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
return "VLAN_SUB_INTERFACE"
return "PORTCHANNEL"
elif interface_name.startswith(vlan_prefix()):
return "VLAN_INTERFACE"
elif interface_name.startswith(loopback_prefix()):
return "LOOPBACK_INTERFACE"
else:
return ""

# Return the namespace where an interface belongs
# The port name input could be in default mode or in alias mode.
def get_port_namespace(port):
Expand Down
113 changes: 78 additions & 35 deletions scripts/sfpshow
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ import operator
import os

from natsort import natsorted
from swsssdk import SonicV2Connector
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

# Mock the redis for unit test purposes #
try:
if os.environ["UTILITIES_UNIT_TESTING"] == "2":
Expand All @@ -21,6 +24,9 @@ try:
sys.path.insert(0, modules_path)
sys.path.insert(0, test_path)
import mock_tables.dbconnector
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
import mock_tables.mock_multi_asic
mock_tables.dbconnector.load_namespace_config()
except KeyError:
pass

Expand Down Expand Up @@ -126,18 +132,27 @@ dom_value_unit_map = {'rx1power': 'dBm', 'rx2power': 'dBm',
'tx3power': 'dBm', 'tx4power': 'dBm',
'temperature': 'C', 'voltage': 'Volts'}

def display_invalid_intf_eeprom(intf_name):
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):
def __init__(self, intf_name, namespace_option, dump_dom=False):
super(SFPShow,self).__init__()
self.adb = SonicV2Connector(host="127.0.0.1")
self.adb.connect(self.adb.APPL_DB)

self.sdb = SonicV2Connector(host="127.0.0.1")
self.sdb.connect(self.sdb.STATE_DB)
return
self.db = None
self.config_db = None
self.intf_name = intf_name
self.dump_dom = dump_dom
self.table = []
self.output = ''
self.multi_asic = multi_asic_util.MultiAsic(namespace_option=namespace_option)

# Convert dict values to cli output string
def format_dict_value_to_string(self, sorted_key_table,
Expand Down Expand Up @@ -291,53 +306,61 @@ class SFPShow(object):

return out_put

def display_eeprom(self, interfacename, dump_dom):
@multi_asic_util.run_on_multi_asic
def get_eeprom(self):
out_put = ''

if interfacename is not None:
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interfacename))
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.sdb, interfacename, dump_dom)
out_put = self.convert_interface_sfp_info_to_cli_output_string(self.db, self.intf_name, self.dump_dom)
else:
out_put = out_put + interfacename + ': ' + 'SFP EEPROM Not detected' + '\n'
out_put = out_put + self.intf_name + ': ' + 'SFP EEPROM Not detected' + '\n'
else:
port_table_keys = self.adb.keys(self.adb.APPL_DB, "PORT_TABLE:*")
port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*")
sorted_table_keys = natsorted(port_table_keys)
for i in sorted_table_keys:
interface = re.split(':', i, maxsplit=1)[-1].strip()
if interface and interface.startswith('Ethernet'):
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface))
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.sdb, interface, dump_dom)
out_put = out_put + 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'

out_put = out_put + '\n'
out_put = out_put + '\n'

click.echo(out_put)
self.output += out_put

def display_presence(self, interfacename):
@multi_asic_util.run_on_multi_asic
def get_presence(self):
port_table = []
header = ['Port', 'Presence']

if interfacename is not None:
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interfacename))
if self.intf_name is not None:
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(self.intf_name))
if presence:
port_table.append((interfacename, 'Present'))
port_table.append((self.intf_name, 'Present'))
else:
port_table.append((interfacename, 'Not present'))
port_table.append((self.intf_name, 'Not present'))
else:
port_table_keys = self.adb.keys(self.adb.APPL_DB, "PORT_TABLE:*")
port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*")
for i in port_table_keys:
key = re.split(':', i, maxsplit=1)[-1].strip()
if key and key.startswith('Ethernet'):
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(key))
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'))
else:
port_table.append((key,'Not present'))

sorted_port_table = natsorted(port_table)
self.table += port_table

def display_eeprom(self):
click.echo(self.output)

def display_presence(self):
header = ['Port', 'Presence']
sorted_port_table = natsorted(self.table)
click.echo(tabulate(sorted_port_table, header))

# This is our main entrypoint - the main 'sfpshow' command
Expand All @@ -350,16 +373,36 @@ def cli():
@cli.command()
@click.option('-p', '--port', metavar='<port_name>', help="Display SFP EEPROM data for port <port_name> only")
@click.option('-d', '--dom', 'dump_dom', is_flag=True, help="Also display Digital Optical Monitoring (DOM) data")
def eeprom(port, dump_dom):
sfp = SFPShow()
sfp.display_eeprom(port, dump_dom)
@click.option('-n', '--namespace', default=None, help="Display interfaces for specific namespace")
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
except Exception:
display_invalid_intf_eeprom(port)
sys.exit(1)

sfp = SFPShow(port, namespace, dump_dom)
sfp.get_eeprom()
sfp.display_eeprom()

# 'presence' subcommand
@cli.command()
@click.option('-p', '--port', metavar='<port_name>', help="Display SFP presence for port <port_name> only")
def presence(port):
sfp = SFPShow()
sfp.display_presence(port)
@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
except Exception:
display_invalid_intf_presence(port)
sys.exit(1)

sfp = SFPShow(port, namespace)
sfp.get_presence()
sfp.display_presence()

if __name__ == "__main__":
cli()
14 changes: 12 additions & 2 deletions show/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,10 @@ def transceiver():
@transceiver.command()
@click.argument('interfacename', required=False)
@click.option('-d', '--dom', 'dump_dom', is_flag=True, help="Also display Digital Optical Monitoring (DOM) data")
@click.option('--namespace', '-n', 'namespace', default=None, show_default=True,
type=click.Choice(multi_asic_util.multi_asic_ns_choices()), help='Namespace name or all')
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def eeprom(interfacename, dump_dom, verbose):
def eeprom(interfacename, dump_dom, namespace, verbose):
"""Show interface transceiver EEPROM information"""

ctx = click.get_current_context()
Expand All @@ -300,6 +302,9 @@ def eeprom(interfacename, dump_dom, verbose):

cmd += " -p {}".format(interfacename)

if namespace is not None:
cmd += " -n {}".format(namespace)

clicommon.run_command(cmd, display_cmd=verbose)

@transceiver.command()
Expand All @@ -321,9 +326,11 @@ def lpmode(interfacename, verbose):

@transceiver.command()
@click.argument('interfacename', required=False)
@click.option('--namespace', '-n', 'namespace', default=None, show_default=True,
type=click.Choice(multi_asic_util.multi_asic_ns_choices()), help='Namespace name or all')
@click.option('--verbose', is_flag=True, help="Enable verbose output")
@clicommon.pass_db
def presence(db, interfacename, verbose):
def presence(db, interfacename, namespace, verbose):
"""Show interface transceiver presence"""

ctx = click.get_current_context()
Expand All @@ -335,6 +342,9 @@ def presence(db, interfacename, verbose):

cmd += " -p {}".format(interfacename)

if namespace is not None:
cmd += " -n {}".format(namespace)

clicommon.run_command(cmd, display_cmd=verbose)


Expand Down
Loading