Skip to content

Commit 96cb359

Browse files
authored
[multi-asic] show_transceiver changes (#1081)
* show_interface transceiver changes for multi-asic, takes care of sub commands eeprom Show interface transceiver EEPROM information lpmode Show interface transceiver low-power mode... presence Show interface transceiver presence * Rearranging of common functions in config/main.py to py-common * Updates to show command and testcases
1 parent aeaada0 commit 96cb359

File tree

10 files changed

+788
-121
lines changed

10 files changed

+788
-121
lines changed

config/main.py

+1-52
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from minigraph import parse_device_desc_xml
1616
from portconfig import get_child_ports
1717
from sonic_py_common import device_info, multi_asic
18-
from sonic_py_common.interface import front_panel_prefix, portchannel_prefix, vlan_prefix, loopback_prefix
18+
from sonic_py_common.interface import get_interface_table_name, get_port_table_name
1919
from swsssdk import ConfigDBConnector, SonicV2Connector, SonicDBConfig
2020
from utilities_common.db import Db
2121
from utilities_common.intf_filter import parse_interface_in_filter
@@ -265,18 +265,6 @@ def _get_device_type():
265265

266266
return device_type
267267

268-
# TODO move to sonic-py-common package
269-
# Validate whether a given namespace name is valid in the device.
270-
def validate_namespace(namespace):
271-
if not multi_asic.is_multi_asic():
272-
return True
273-
274-
namespaces = multi_asic.get_all_namespaces()
275-
if namespace in namespaces['front_ns'] + namespaces['back_ns']:
276-
return True
277-
else:
278-
return False
279-
280268
def interface_alias_to_name(config_db, interface_alias):
281269
"""Return default interface name if alias name is given as argument
282270
"""
@@ -372,25 +360,6 @@ def interface_name_to_alias(config_db, interface_name):
372360

373361
return None
374362

375-
# TODO move to sonic-py-common package
376-
def get_interface_table_name(interface_name):
377-
"""Get table name by interface_name prefix
378-
"""
379-
if interface_name.startswith(front_panel_prefix()):
380-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
381-
return "VLAN_SUB_INTERFACE"
382-
return "INTERFACE"
383-
elif interface_name.startswith(portchannel_prefix()):
384-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
385-
return "VLAN_SUB_INTERFACE"
386-
return "PORTCHANNEL_INTERFACE"
387-
elif interface_name.startswith(vlan_prefix()):
388-
return "VLAN_INTERFACE"
389-
elif interface_name.startswith(loopback_prefix()):
390-
return "LOOPBACK_INTERFACE"
391-
else:
392-
return ""
393-
394363
def interface_ipaddr_dependent_on_interface(config_db, interface_name):
395364
"""Get table keys including ipaddress
396365
"""
@@ -415,26 +384,6 @@ def is_interface_bind_to_vrf(config_db, interface_name):
415384
return True
416385
return False
417386

418-
# TODO move to sonic-py-common package
419-
# Get the table name based on the interface type
420-
def get_port_table_name(interface_name):
421-
"""Get table name by port_name prefix
422-
"""
423-
if interface_name.startswith(front_panel_prefix()):
424-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
425-
return "VLAN_SUB_INTERFACE"
426-
return "PORT"
427-
elif interface_name.startswith(portchannel_prefix()):
428-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
429-
return "VLAN_SUB_INTERFACE"
430-
return "PORTCHANNEL"
431-
elif interface_name.startswith(vlan_prefix()):
432-
return "VLAN_INTERFACE"
433-
elif interface_name.startswith(loopback_prefix()):
434-
return "LOOPBACK_INTERFACE"
435-
else:
436-
return ""
437-
438387
# Return the namespace where an interface belongs
439388
# The port name input could be in default mode or in alias mode.
440389
def get_port_namespace(port):

scripts/sfpshow

+78-35
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ import operator
1010
import os
1111

1212
from natsort import natsorted
13-
from swsssdk import SonicV2Connector
1413
from tabulate import tabulate
1514

15+
from utilities_common import multi_asic as multi_asic_util
16+
from sonic_py_common.interface import front_panel_prefix, backplane_prefix
17+
from sonic_py_common import multi_asic
18+
1619
# Mock the redis for unit test purposes #
1720
try:
1821
if os.environ["UTILITIES_UNIT_TESTING"] == "2":
@@ -21,6 +24,9 @@ try:
2124
sys.path.insert(0, modules_path)
2225
sys.path.insert(0, test_path)
2326
import mock_tables.dbconnector
27+
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
28+
import mock_tables.mock_multi_asic
29+
mock_tables.dbconnector.load_namespace_config()
2430
except KeyError:
2531
pass
2632

@@ -126,18 +132,27 @@ dom_value_unit_map = {'rx1power': 'dBm', 'rx2power': 'dBm',
126132
'tx3power': 'dBm', 'tx4power': 'dBm',
127133
'temperature': 'C', 'voltage': 'Volts'}
128134

135+
def display_invalid_intf_eeprom(intf_name):
136+
output = intf_name + ': ' + 'SFP EEPROM Not detected' + '\n'
137+
click.echo(output)
129138

139+
def display_invalid_intf_presence(intf_name):
140+
header = ['Port', 'Presence']
141+
port_table = []
142+
port_table.append((intf_name, 'Not present'))
143+
click.echo(tabulate(port_table, header))
130144

131145
class SFPShow(object):
132146

133-
def __init__(self):
147+
def __init__(self, intf_name, namespace_option, dump_dom=False):
134148
super(SFPShow,self).__init__()
135-
self.adb = SonicV2Connector(host="127.0.0.1")
136-
self.adb.connect(self.adb.APPL_DB)
137-
138-
self.sdb = SonicV2Connector(host="127.0.0.1")
139-
self.sdb.connect(self.sdb.STATE_DB)
140-
return
149+
self.db = None
150+
self.config_db = None
151+
self.intf_name = intf_name
152+
self.dump_dom = dump_dom
153+
self.table = []
154+
self.output = ''
155+
self.multi_asic = multi_asic_util.MultiAsic(namespace_option=namespace_option)
141156

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

292307
return out_put
293308

294-
def display_eeprom(self, interfacename, dump_dom):
309+
@multi_asic_util.run_on_multi_asic
310+
def get_eeprom(self):
295311
out_put = ''
296312

297-
if interfacename is not None:
298-
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interfacename))
313+
if self.intf_name is not None:
314+
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(self.intf_name))
299315
if presence:
300-
out_put = self.convert_interface_sfp_info_to_cli_output_string(self.sdb, interfacename, dump_dom)
316+
out_put = self.convert_interface_sfp_info_to_cli_output_string(self.db, self.intf_name, self.dump_dom)
301317
else:
302-
out_put = out_put + interfacename + ': ' + 'SFP EEPROM Not detected' + '\n'
318+
out_put = out_put + self.intf_name + ': ' + 'SFP EEPROM Not detected' + '\n'
303319
else:
304-
port_table_keys = self.adb.keys(self.adb.APPL_DB, "PORT_TABLE:*")
320+
port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*")
305321
sorted_table_keys = natsorted(port_table_keys)
306322
for i in sorted_table_keys:
307323
interface = re.split(':', i, maxsplit=1)[-1].strip()
308-
if interface and interface.startswith('Ethernet'):
309-
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface))
324+
if interface and interface.startswith(front_panel_prefix()) and not interface.startswith(backplane_prefix()):
325+
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface))
310326
if presence:
311-
out_put = out_put + self.convert_interface_sfp_info_to_cli_output_string(self.sdb, interface, dump_dom)
327+
out_put = out_put + self.convert_interface_sfp_info_to_cli_output_string(self.db, interface, self.dump_dom)
312328
else:
313329
out_put = out_put + interface + ': ' + 'SFP EEPROM Not detected' + '\n'
314330

315-
out_put = out_put + '\n'
331+
out_put = out_put + '\n'
316332

317-
click.echo(out_put)
333+
self.output += out_put
318334

319-
def display_presence(self, interfacename):
335+
@multi_asic_util.run_on_multi_asic
336+
def get_presence(self):
320337
port_table = []
321-
header = ['Port', 'Presence']
322338

323-
if interfacename is not None:
324-
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interfacename))
339+
if self.intf_name is not None:
340+
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(self.intf_name))
325341
if presence:
326-
port_table.append((interfacename, 'Present'))
342+
port_table.append((self.intf_name, 'Present'))
327343
else:
328-
port_table.append((interfacename, 'Not present'))
344+
port_table.append((self.intf_name, 'Not present'))
329345
else:
330-
port_table_keys = self.adb.keys(self.adb.APPL_DB, "PORT_TABLE:*")
346+
port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*")
331347
for i in port_table_keys:
332348
key = re.split(':', i, maxsplit=1)[-1].strip()
333-
if key and key.startswith('Ethernet'):
334-
presence = self.sdb.exists(self.sdb.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(key))
349+
if key and key.startswith(front_panel_prefix()) and not key.startswith(backplane_prefix()):
350+
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(key))
335351
if presence:
336352
port_table.append((key,'Present'))
337353
else:
338354
port_table.append((key,'Not present'))
339355

340-
sorted_port_table = natsorted(port_table)
356+
self.table += port_table
357+
358+
def display_eeprom(self):
359+
click.echo(self.output)
360+
361+
def display_presence(self):
362+
header = ['Port', 'Presence']
363+
sorted_port_table = natsorted(self.table)
341364
click.echo(tabulate(sorted_port_table, header))
342365

343366
# This is our main entrypoint - the main 'sfpshow' command
@@ -350,16 +373,36 @@ def cli():
350373
@cli.command()
351374
@click.option('-p', '--port', metavar='<port_name>', help="Display SFP EEPROM data for port <port_name> only")
352375
@click.option('-d', '--dom', 'dump_dom', is_flag=True, help="Also display Digital Optical Monitoring (DOM) data")
353-
def eeprom(port, dump_dom):
354-
sfp = SFPShow()
355-
sfp.display_eeprom(port, dump_dom)
376+
@click.option('-n', '--namespace', default=None, help="Display interfaces for specific namespace")
377+
def eeprom(port, dump_dom, namespace):
378+
if port and multi_asic.is_multi_asic() and namespace is None:
379+
try:
380+
ns = multi_asic.get_namespace_for_port(port)
381+
namespace=ns
382+
except Exception:
383+
display_invalid_intf_eeprom(port)
384+
sys.exit(1)
385+
386+
sfp = SFPShow(port, namespace, dump_dom)
387+
sfp.get_eeprom()
388+
sfp.display_eeprom()
356389

357390
# 'presence' subcommand
358391
@cli.command()
359392
@click.option('-p', '--port', metavar='<port_name>', help="Display SFP presence for port <port_name> only")
360-
def presence(port):
361-
sfp = SFPShow()
362-
sfp.display_presence(port)
393+
@click.option('-n', '--namespace', default=None, help="Display interfaces for specific namespace")
394+
def presence(port, namespace):
395+
if port and multi_asic.is_multi_asic() and namespace is None:
396+
try:
397+
ns = multi_asic.get_namespace_for_port(port)
398+
namespace=ns
399+
except Exception:
400+
display_invalid_intf_presence(port)
401+
sys.exit(1)
402+
403+
sfp = SFPShow(port, namespace)
404+
sfp.get_presence()
405+
sfp.display_presence()
363406

364407
if __name__ == "__main__":
365408
cli()

show/interfaces/__init__.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,10 @@ def transceiver():
284284
@transceiver.command()
285285
@click.argument('interfacename', required=False)
286286
@click.option('-d', '--dom', 'dump_dom', is_flag=True, help="Also display Digital Optical Monitoring (DOM) data")
287+
@click.option('--namespace', '-n', 'namespace', default=None, show_default=True,
288+
type=click.Choice(multi_asic_util.multi_asic_ns_choices()), help='Namespace name or all')
287289
@click.option('--verbose', is_flag=True, help="Enable verbose output")
288-
def eeprom(interfacename, dump_dom, verbose):
290+
def eeprom(interfacename, dump_dom, namespace, verbose):
289291
"""Show interface transceiver EEPROM information"""
290292

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

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

305+
if namespace is not None:
306+
cmd += " -n {}".format(namespace)
307+
303308
clicommon.run_command(cmd, display_cmd=verbose)
304309

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

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

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

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

345+
if namespace is not None:
346+
cmd += " -n {}".format(namespace)
347+
338348
clicommon.run_command(cmd, display_cmd=verbose)
339349

340350

0 commit comments

Comments
 (0)