diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index 362143e369..88e1908d2d 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -9,8 +9,8 @@ Table of Contents * [SSH Login](#ssh-login) * [Configuring Management Interface](#configuring-management-interface) * [Config Help](#config-help) - * [Show Help](#show-help) * [Show Versions](#show-versions) + * [Show Help](#show-help) * [Show System Status](#show-system-status) * [Show Hardware Platform](#show-hardware-platform) * [Transceivers](#transceivers) @@ -109,6 +109,7 @@ After logging into the device, SONiC software can be configured in following thr 2) [config_db.json](https://github.com/Azure/SONiC/wiki/Configuration) 3) [minigraph.xml](https://github.com/Azure/SONiC/wiki/Configuration-with-Minigraph-(~Sep-2017)) + This document explains the first method and gives the complete list of commands that are supported in SONiC 201904 version (build#19). All the configuration commands need root privileges to execute them. Note that show commands can be executed by all users without the root privileges. Root privileges can be obtained either by using "sudo" keyword in front of all config commands, or by going to root prompt using "sudo -i". @@ -128,6 +129,7 @@ Note that the command list given in this document is just a subset of all possib Please follow config_db.json based configuration for the complete list of configuration options. **Scope Of The Document** + It is assumed that all configuration commands start with the keyword “config” as prefix. Any other scripts/utilities/commands that need user configuration control are wrapped as sub-commands under the “config” command. The direct scripts/utilities/commands (examples given below) that are not wrapped under the "config" command are not in the scope of this document. @@ -149,7 +151,9 @@ This section covers the basic configurations related to the following ## SSH Login All SONiC devices support both the serial console based login and the SSH based login by default. + The default credential (if not modified at image build time) for login is `admin/YourPaSsWoRd`. + In case of SSH login, users can login to the management interface (eth0) IP address after configuring the same using serial console. Refer the following section for configuring the IP address for management interface. @@ -166,6 +170,7 @@ Refer the following section for configuring the IP address for management interf admin@sonic's password: ``` + By default, login takes the user to the default prompt from which all the show commands can be executed. Go Back To [Beginning of the document](#SONiC-COMMAND-LINE-INTERFACE-GUIDE) or [Beginning of this section](#Basic-Configuration-And-Show) @@ -840,9 +845,6 @@ When this command is executed, the configured tacacs+ server addresses are updat auth [success=done new_authtok_reqd=done default=ignore] pam_tacplus.so server=10.11.12.13:50 secret=testing789 login=mschap timeout=10 try_first_pass auth [success=1 default=ignore] pam_unix.so nullok try_first_pass - NOTE: In the above example, the servers are stored (sorted) based on the priority value configured for the server. - - ``` **config tacacs delete** @@ -1730,35 +1732,83 @@ This command displays information regarding port-channel interfaces 8 PortChannel8 LACP(A)(Up) Ethernet8(S) Ethernet12(S) ``` -**show interface status** +## Interface status Show Commands -This command displays some more fields such as Lanes, Speed, MTU, Type, Asymmetric PFC status and also the operational and administrative status of the interfaces +This sub-section lists all the possible show commands for the interfaces status available in the device. Following example gives the list of possible shows on interface status. -- Usage: - show interfaces status [INTERFACENAME] +- Example: + ``` + admin@lnos-x1-a-csw02:~$ show interfaces status -? + Usage: show interfaces status [OPTIONS] COMMAND [ARGS]... + + Show interface status information + + Options: + -?, -h, --help Show this message and exit. + + Commands: + brief Show Interface status brief information + details Show Interface status details information + admin@lnos-x1-a-csw02:~$ + ``` + +**show interface status brief** + +This command displays fields such as Lanes, Speed, MTU, Vlan and also the operational and administrative status of the interfaces + + - Usage: + show interfaces status brief [INTERFACENAME] - Example: ``` - show interface status of all interfaces + show interface status brief of all interfaces - admin@sonic:~$ show interfaces status - Interface Lanes Speed MTU Alias Oper Admin Type Asym PFC - ----------- --------------- ------- ----- --------------- ------ ------- ------ ---------- - Ethernet0 49,50,51,52 100G 9100 hundredGigE1/1 down up N/A off - Ethernet4 53,54,55,56 100G 9100 hundredGigE1/2 down up N/A off - Ethernet8 57,58,59,60 100G 9100 hundredGigE1/3 down down N/A off - + admin@lnos-x1-a-csw02:~$ show interfaces status brief + Interface Lanes Speed MTU Alias Vlan Oper Admin + ---------- --------------- ------- ----- ------- ------ ------ ------- + Ethernet0 65,66,67,68 100G 9100 Eth1 routed down up + Ethernet4 69,70,71,72 100G 9100 Eth2 routed up up + Ethernet8 73,74,75,76 100G 9100 Eth3 routed down up + Ethernet9 77,78,79,80 100G 9100 Eth4 routed down up + ``` ``` + show interface status brief for one particular interface + admin@lnos-x1-a-csw02:~$ show interfaces status brief Ethernet4 + Interface Lanes Speed MTU Alias Vlan Oper Admin + ---------- ----------- ------- ----- ------- ------ ------ ------- + Ethernet4 69,70,71,72 100G 9100 Eth2 routed up up + admin@lnos-x1-a-csw02:~$ ``` - show interface status for one particular interface - admin@sonic:~$ show interface status Ethernet0 - Interface Lanes Speed MTU Alias Oper Admin - ----------- -------- ------- ----- -------------- ------ ------- - Ethernet0 101,102 40G 9100 fortyGigE1/1/1 up up +**show interface status details** +This command displays some more additional fields such as Type, Asymmetric PFC status, Flap count and Last flap time + + - Usage: + show interfaces status details [INTERFACENAME] + +- Example: + ``` + show interfaces status details of all interfaces + + admin@lnos-x1-a-csw02:~$ show interfaces status details + Interface Lanes Speed MTU Alias Vlan Oper Admin Type Asym PFC Flaps Last Flap (in UTC) + ---------- --------------- ------- ----- ------- ------ ------ ------- --------------- ---------- ------- ------------------------ + Ethernet0 65,66,67,68 100G 9100 Eth1 routed down up QSFP28 or later N/A 0 N/A + Ethernet4 69,70,71,72 100G 9100 Eth2 routed up up QSFP28 or later N/A 2 Wed Jun 12 09:38:28 2019 + + ``` + + ``` + show interfaces status details for one particular interface + + admin@lnos-x1-a-csw02:~$ show interfaces status details Ethernet4 + Interface Lanes Speed MTU Alias Vlan Oper Admin Type Asym PFC Flaps Last Flap (in UTC) + ---------- ----------- ------- ----- ------- ------ ------ ------- --------------- ---------- ------- ------------------------ + Ethernet4 69,70,71,72 100G 9100 Eth2 routed up up QSFP28 or later N/A 2 Wed Jun 12 09:38:28 2019 + admin@lnos-x1-a-csw02:~$ ``` **show interfaces transceiver** @@ -1909,6 +1959,7 @@ NOTE: In versions until 201811, syntax is "config interface spe Go Back To [Beginning of the document](#SONiC-COMMAND-LINE-INTERFACE-GUIDE) or [Beginning of this section](#interface-configuration-and-show-commands) + # Interface Naming Mode ## Interface naming mode show commands @@ -3341,6 +3392,7 @@ Go Back To [Beginning of the document](#SONiC-COMMAND-LINE-INTERFACE-GUIDE) or [ ### VLAN show commands + **show vlan brief** This command displays brief information about all the vlans configured in the device. It displays the vlan ID, IP address (if configured for the vlan), list of vlan member ports, whether the port is tagged or in untagged mode and the DHCP Helper Address. diff --git a/scripts/intfutil b/scripts/intfutil index f8509db93f..4480cd7e2d 100755 --- a/scripts/intfutil +++ b/scripts/intfutil @@ -8,6 +8,8 @@ from tabulate import tabulate from natsort import natsorted from swsssdk import ConfigDBConnector from pprint import pprint +from collections import OrderedDict +import portstat # ========================== Common interface-utils logic ========================== @@ -24,16 +26,20 @@ PORT_MTU_STATUS = "mtu" PORT_DESCRIPTION = "description" PORT_OPTICS_TYPE = "type" PORT_PFC_ASYM_STATUS = "pfc_asym" +PORT_FLAP_COUNTER = "flap_counter" +PORT_LAST_FLAP_TIME = "last_flap" +NStats = portstat.NStats + def db_connect_configdb(): """ Connect to configdb """ config_db = ConfigDBConnector() - if config_db is None: - return None + if config_db is None: + return None config_db.connect() - return config_db + return config_db def get_frontpanel_port_list(config_db): ports_dict = config_db.get_table('PORT') @@ -68,7 +74,7 @@ def config_db_vlan_port_keys_get(int_to_vlan_dict, front_panel_ports_list, intf_ if intf_name in int_to_vlan_dict.keys(): vlan = int_to_vlan_dict[intf_name] if "Vlan" in vlan: - vlan = "trunk" + vlan = "trunk" return vlan @@ -123,9 +129,9 @@ def state_db_port_optics_get(state_db, intf_name, type): """ full_table_id = PORT_TRANSCEIVER_TABLE_PREFIX + intf_name optics_type = state_db.get(state_db.STATE_DB, full_table_id, type) - if optics_type is None: - return "N/A" - return optics_type + if optics_type is None: + return "N/A" + return optics_type def merge_dicts(x,y): # store a copy of x, but overwrite with y's values where applicable @@ -142,7 +148,7 @@ def merge_dicts(x,y): def tuple_to_dict(tup, new_dict): """ From a tuple create a dictionary that uses the first item in the tuple as a key - and the 2nd item in the tuple as a value. + and the 2nd item in the tuple as a value. """ for a, b in tup: new_dict.setdefault(a, []).append(b) @@ -170,7 +176,7 @@ def get_portchannel_list(get_raw_po_int_configdb_info): >>> portchannel_list = get_portchannel_list(get_raw_po_int_configdb_info) >>> pprint(portchannel_list) ['PortChannel0001', 'PortChannel0002', 'PortChannel0003', 'PortChannel0004'] - >>> + >>> """ portchannel_list = [] for po in get_raw_po_int_configdb_info: @@ -189,7 +195,7 @@ def create_po_int_tuple_list(get_raw_po_int_configdb_info): ('PortChannel0004', 'Ethernet124'), ('PortChannel0003', 'Ethernet120'), ('PortChannel0001', 'Ethernet112')] - >>> + >>> """ po_int_tuple_list = get_raw_po_int_configdb_info.keys() return po_int_tuple_list @@ -217,11 +223,11 @@ def create_int_to_portchannel_dict(po_int_tuple_list): def po_speed_dict(po_int_dict, appl_db): """ - This function takes the portchannel to interface dictionary + This function takes the portchannel to interface dictionary and the appl_db and then creates a portchannel to speed - dictionary. + dictionary. """ - if po_int_dict: + if po_int_dict: po_list = [] for key, value in po_int_dict.iteritems(): agg_speed_list = [] @@ -263,17 +269,18 @@ def appl_db_portchannel_status_get(appl_db, config_db, po_name, status_type, por return status status = appl_db.get(appl_db.APPL_DB, full_table_id, status_type) #print(status) - if status is None: + if status is None: return "N/A" - return status + return status # ========================== interface-status logic ========================== -header_stat = ['Interface', 'Lanes', 'Speed', 'MTU', 'Alias', 'Vlan', 'Oper', 'Admin', 'Type', 'Asym PFC'] +header_stat = ['Interface', 'Lanes', 'Speed', 'MTU', 'Alias', 'Vlan', 'Oper', 'Admin'] +header_stat_details = ['Interface', 'Lanes', 'Speed', 'MTU', 'Alias', 'Vlan', 'Oper', 'Admin', 'Type', 'Asym PFC', 'Flaps', 'Last Flap (in UTC)'] class IntfStatus(object): - def display_intf_status(self, appl_db_keys, front_panel_ports_list, portchannel_speed_dict): + def display_intf_status(self, appl_db_keys, front_panel_ports_list, portchannel_speed_dict, brief, details): """ Generate interface-status output """ @@ -282,6 +289,18 @@ class IntfStatus(object): table = [] key = [] + cnstat_cached_dict = OrderedDict() + port_obj = portstat.Portstat() + final_header = header_stat + + # + # Get the flap count from last cached file + # when the counters were cleared + # + cached_stats_file_hidden = port_obj.cached_stats_file_hidden + cnstat_fqn_file = port_obj.get_file_path(cached_stats_file_hidden) + cnstat_dict = port_obj.get_cnstat() + cnstat_cached_dict = port_obj.get_cache_dict(cnstat_fqn_file, cnstat_dict) # # Iterate through all the keys and append port's associated state to # the result table. @@ -289,16 +308,33 @@ class IntfStatus(object): for i in appl_db_keys: key = re.split(':', i, maxsplit=1)[-1].strip() if key in front_panel_ports_list: - table.append((key, - appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS), - appl_db_port_status_get(self.appl_db, key, PORT_SPEED), - appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS), - appl_db_port_status_get(self.appl_db, key, PORT_ALIAS), - config_db_vlan_port_keys_get(self.combined_int_to_vlan_po_dict, self.front_panel_ports_list, key), - appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS), - appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS), - state_db_port_optics_get(self.state_db, key, PORT_OPTICS_TYPE), - appl_db_port_status_get(self.appl_db, key, PORT_PFC_ASYM_STATUS))) + if brief or details: + temp_table_tuple = (key, + appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS), + appl_db_port_status_get(self.appl_db, key, PORT_SPEED), + appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS), + appl_db_port_status_get(self.appl_db, key, PORT_ALIAS), + config_db_vlan_port_keys_get(self.combined_int_to_vlan_po_dict, self.front_panel_ports_list, key), + appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS), + appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS)) + table_tuple = temp_table_tuple + + if details: + # + # To diplay the flap count calculate the diff between appl_db and last cached value + # when counters were cleared + # + final_header = header_stat_details + db_flap = long(appl_db_port_status_get(self.appl_db, key, PORT_FLAP_COUNTER)) + cache_flap = long(cnstat_cached_dict[key].flap_counter) + final_flap = str(db_flap - cache_flap) + table_list = list(temp_table_tuple) + table_list.extend((state_db_port_optics_get(self.state_db, key, PORT_OPTICS_TYPE), + appl_db_port_status_get(self.appl_db, key, PORT_PFC_ASYM_STATUS), + final_flap, + appl_db_port_status_get(self.appl_db, key, PORT_LAST_FLAP_TIME))) + table_tuple = tuple(table_list) + table.append(table_tuple) # Sorting and tabulating the result table. for po, value in portchannel_speed_dict.iteritems(): if po: @@ -314,22 +350,22 @@ class IntfStatus(object): appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_PFC_ASYM_STATUS, self.portchannel_speed_dict))) sorted_table = natsorted(table) - print tabulate(sorted_table, header_stat, tablefmt="simple", stralign='right') + print tabulate(sorted_table, final_header, tablefmt="simple", stralign='right') - def __init__(self, intf_name): + def __init__(self, intf_name, brief, details): """ Class constructor method - :param self: + :param self: :param intf_name: string of interface - :return: + :return: """ self.appl_db = db_connect_appl() self.state_db = db_connect_state() self.config_db = db_connect_configdb() if self.appl_db is None: return - if self.state_db is None: + if self.state_db is None: return if self.config_db is None: return @@ -346,7 +382,7 @@ class IntfStatus(object): self.portchannel_keys = self.portchannel_speed_dict.keys() if appl_db_keys is None: return - self.display_intf_status(appl_db_keys, self.front_panel_ports_list, self.portchannel_speed_dict) + self.display_intf_status(appl_db_keys, self.front_panel_ports_list, self.portchannel_speed_dict, brief, details) @@ -402,6 +438,10 @@ class IntfDescription(object): def main(args): + args_len = len(args) + details = False + brief = False + intf_name = None if len(args) == 0: print "No valid arguments provided" return @@ -411,10 +451,27 @@ def main(args): print "No valid command provided" return - intf_name = args[1] if len(args) == 2 else None + valid = command == "status" and (args[1] == "details" or args[1] == "brief") + if args_len == 1: + pass + elif args_len <=3 and valid: + if args_len == 3: + if args[2].startswith('Ethernet'): + intf_name = args[2] + else: + print "No valid command provided" + return + if args[1] == "details": + details = True + else: + brief = True + else: + print "No valid command provided" + return + #intf_name = args[1] if len(args) == 2 else None if command == "status": - interface_stat = IntfStatus(intf_name) + interface_stat = IntfStatus(intf_name, brief, details) elif command == "description": interface_desc = IntfDescription(intf_name) diff --git a/scripts/portstat b/scripts/portstat index 3ba57caa54..19313b7624 100755 --- a/scripts/portstat +++ b/scripts/portstat @@ -2,7 +2,7 @@ ##################################################################### # -# portstat is a tool for summarizing network statistics. +# portstat is a tool for summarizing network statistics. # ##################################################################### @@ -26,7 +26,7 @@ from utilities_common import get_uptime PORT_RATE = 40 NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\ - tx_err, tx_drop, tx_ovr, rx_byt, tx_byt") + tx_err, tx_drop, tx_ovr, rx_byt, tx_byt, flap_counter") header_all = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR', 'TX_OK', 'TX_BPS', 'Tx_PPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR'] @@ -59,27 +59,56 @@ PORT_OPER_STATUS_FIELD = "oper_status" PORT_ADMIN_STATUS_FIELD = "admin_status" PORT_STATUS_VALUE_UP = 'UP' PORT_STATUS_VALUE_DOWN = 'DOWN' +PORT_FLAP_COUNTER = "flap_counter" PORT_SPEED_FIELD = "speed" PORT_STATE_UP = 'U' PORT_STATE_DOWN = 'D' PORT_STATE_DISABLED = 'X' +FIELD_COUNT = 11 class Portstat(object): + + cached_stats_file_hidden = ".__CaChEd_StAtS__" + cnstat_dir = "/tmp/portstat" + def __init__(self): self.db = swsssdk.SonicV2Connector(host='127.0.0.1') self.db.connect(self.db.COUNTERS_DB) self.db.connect(self.db.APPL_DB) + def get_cache_dict(self, cnstat_fqn_file, cnstat_dict): + + cached_dict = OrderedDict() + if os.path.isfile(cnstat_fqn_file): + try: + cached_dict = pickle.load(open(cnstat_fqn_file, 'r')) + print "Last cached time was " + str(cached_dict.get('time')) + except IOError as e: + print e.errno, e + else: + # Cached Stats file does not exist, so use boot time for Bps calculation. + fields = list("0" * FIELD_COUNT) + cntr = NStats._make(fields) + for key in cnstat_dict: + cached_dict[key] = cntr + with open('/proc/uptime', 'r') as uptime_f: + time_diff = datetime.timedelta(seconds = float(uptime_f.readline().split()[0])) + cached_dict['time'] = cnstat_dict.get('time') - time_diff + + return cached_dict + def get_cnstat(self): """ Get the counters info from database. """ - def get_counters(table_id): + def get_counters(port, table_id): """ Get the counters from specific table. """ - fields = ["0","0","0","0","0","0","0","0","0","0"] + fields = list("0" * FIELD_COUNT) + flap_table_id = PORT_STATUS_TABLE_PREFIX + port + flap_data = self.db.get(self.db.APPL_DB, flap_table_id, PORT_FLAP_COUNTER) for counter_name, pos in counter_bucket_dict.iteritems(): full_table_id = COUNTER_TABLE_PREFIX + table_id counter_data = self.db.get(self.db.COUNTERS_DB, full_table_id, counter_name) @@ -87,6 +116,7 @@ class Portstat(object): fields[pos] = STATUS_NA elif fields[pos] != STATUS_NA: fields[pos] = str(int(fields[pos]) + int(counter_data)) + fields[FIELD_COUNT-1] = str(int(fields[FIELD_COUNT-1]) + int(flap_data)) cntr = NStats._make(fields) return cntr @@ -98,7 +128,7 @@ class Portstat(object): if counter_port_name_map is None: return cnstat_dict for port in natsorted(counter_port_name_map): - cnstat_dict[port] = get_counters(counter_port_name_map[port]) + cnstat_dict[port] = get_counters(port, counter_port_name_map[port]) return cnstat_dict def get_port_speed(self, port_name): @@ -191,6 +221,11 @@ class Portstat(object): else: print tabulate(table, header, tablefmt='simple', stralign='right') + def get_file_path(self, cnstat_file): + + cnstat_fqn_file = self.cnstat_dir + "/" + cnstat_file + return cnstat_fqn_file + def main(): parser = argparse.ArgumentParser(description='Display the ports state and counters', @@ -228,20 +263,22 @@ Examples: wait_time_in_seconds = args.period print_all = args.all + portstat = Portstat() + cnstat_directory = portstat.cnstat_dir + if tag_name is not None: - cnstat_file = uid + "-" + tag_name + cnstat_file = portstat.cached_stats_file_hidden + tag_name else: - cnstat_file = uid + cnstat_file = portstat.cached_stats_file_hidden - cnstat_dir = "/tmp/portstat-" + uid - cnstat_fqn_file = cnstat_dir + "/" + cnstat_file + cnstat_fqn_file = portstat.get_file_path(cnstat_file) if delete_all_stats: - for file in os.listdir(cnstat_dir): - os.remove(cnstat_dir + "/" + file) + for file in os.listdir(cnstat_directory): + os.remove(cnstat_directory + "/" + file) try: - os.rmdir(cnstat_dir) + os.rmdir(cnstat_directory) sys.exit(0) except IOError as e: print e.errno, e @@ -255,11 +292,10 @@ Examples: print e.errno, e sys.exit(1) finally: - if os.listdir(cnstat_dir) == []: - os.rmdir(cnstat_dir) + if os.listdir(cnstat_directory) == []: + os.rmdir(cnstat_directory) sys.exit(0) - portstat = Portstat() cnstat_dict = portstat.get_cnstat() # Now decide what information to display @@ -268,9 +304,9 @@ Examples: sys.exit(0) # At this point, either we'll create a file or open an existing one. - if not os.path.exists(cnstat_dir): + if not os.path.exists(cnstat_directory): try: - os.makedirs(cnstat_dir) + os.makedirs(cnstat_directory) except IOError as e: print e.errno, e sys.exit(1) @@ -287,19 +323,13 @@ Examples: if wait_time_in_seconds == 0: cnstat_cached_dict = OrderedDict() - if os.path.isfile(cnstat_fqn_file): - try: - cnstat_cached_dict = pickle.load(open(cnstat_fqn_file, 'r')) - print "Last cached time was " + str(cnstat_cached_dict.get('time')) - portstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, use_json, print_all) - except IOError as e: - print e.errno, e + if not os.path.isfile(cnstat_fqn_file) and tag_name: + print "\nFile '%s' does not exist" % cnstat_fqn_file + print "Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name) else: - if tag_name: - print "\nFile '%s' does not exist" % cnstat_fqn_file - print "Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name) - else: - portstat.cnstat_diff_print(cnstat_dict, {}, use_json, print_all) + cnstat_cached_dict = portstat.get_cache_dict(cnstat_fqn_file, cnstat_dict) + portstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, use_json, print_all) + else: #wait for the specified time and then gather the new stats and output the difference. time.sleep(wait_time_in_seconds) diff --git a/scripts/portstat.py b/scripts/portstat.py new file mode 120000 index 0000000000..aa50b73ae6 --- /dev/null +++ b/scripts/portstat.py @@ -0,0 +1 @@ +portstat \ No newline at end of file diff --git a/setup.py b/setup.py index d12d9880b8..b543fcd969 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,8 @@ 'scripts/teamshow', 'scripts/warm-reboot', 'scripts/watermarkstat', - 'scripts/watermarkcfg' + 'scripts/watermarkcfg', + 'scripts/portstat.py', ], data_files=[ ('/etc/bash_completion.d', glob.glob('data/etc/bash_completion.d/*')), diff --git a/show/main.py b/show/main.py index b644adaac9..0e7d93ebe8 100755 --- a/show/main.py +++ b/show/main.py @@ -530,6 +530,12 @@ def transceiver(): pass +@interfaces.group(cls=AliasedGroup, default_if_no_args=False) +def status(): + """Show interface status information""" + pass + + @transceiver.command() @click.argument('interfacename', required=False) @click.option('-d', '--dom', 'dump_dom', is_flag=True, help="Also display Digital Optical Monitoring (DOM) data") @@ -601,18 +607,27 @@ def description(interfacename, verbose): run_command(cmd, display_cmd=verbose) -@interfaces.command() +@status.command() @click.argument('interfacename', required=False) @click.option('--verbose', is_flag=True, help="Enable verbose output") -def status(interfacename, verbose): - """Show Interface status information""" - - cmd = "intfutil status" +def details(interfacename, verbose): + """Show Interface status details information""" + cmd = "intfutil status details" if interfacename is not None: - if get_interface_mode() == "alias": - interfacename = iface_alias_converter.alias_to_name(interfacename) + cmd += " {}".format(interfacename) + run_command(cmd, display_cmd=verbose) + + +@status.command() +@click.argument('interfacename', required=False) +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def brief(interfacename, verbose): + """Show Interface status brief information""" + + cmd = "intfutil status brief" + if interfacename is not None: cmd += " {}".format(interfacename) run_command(cmd, display_cmd=verbose) @@ -1200,7 +1215,7 @@ def table(verbose): def get_hw_info_dict(): """ - This function is used to get the HW info helper function + This function is used to get the HW info helper function """ hw_info_dict = {} machine_info = sonic_device_util.get_machine_info() @@ -1208,7 +1223,7 @@ def get_hw_info_dict(): config_db = ConfigDBConnector() config_db.connect() data = config_db.get_table('DEVICE_METADATA') - try: + try: hwsku = data['localhost']['hwsku'] except KeyError: hwsku = "Unknown" @@ -1298,7 +1313,7 @@ def version(verbose): version_info = sonic_device_util.get_sonic_version_info() hw_info_dict = get_hw_info_dict() serial_number_cmd = "sudo decode-syseeprom -s" - serial_number = subprocess.Popen(serial_number_cmd, shell=True, stdout=subprocess.PIPE) + serial_number = subprocess.Popen(serial_number_cmd, shell=True, stdout=subprocess.PIPE) sys_uptime_cmd = "uptime" sys_uptime = subprocess.Popen(sys_uptime_cmd, shell=True, stdout=subprocess.PIPE) click.echo("\nSONiC Software Version: SONiC.{}".format(version_info['build_version']))