From 19eadbbb246a6afb516cc7b99e67528611283536 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 16 Feb 2017 22:08:35 +0000 Subject: [PATCH 01/13] Remove dpkg-buildpackage files --- LICENSE | 15 --------------- MAINTAINERS | 7 ------- README.md | 4 ---- ThirdPartyLicenses.txt | 31 ------------------------------- debian/changelog | 5 ----- debian/compat | 1 - debian/control | 12 ------------ debian/copyright | 0 debian/install | 3 --- debian/rules | 6 ------ 10 files changed, 84 deletions(-) delete mode 100644 LICENSE delete mode 100644 MAINTAINERS delete mode 100644 README.md delete mode 100644 ThirdPartyLicenses.txt delete mode 100644 debian/changelog delete mode 100644 debian/compat delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100644 debian/install delete mode 100755 debian/rules diff --git a/LICENSE b/LICENSE deleted file mode 100644 index e02a863769..0000000000 --- a/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -Copyright (C) 2016 Microsoft - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/MAINTAINERS b/MAINTAINERS deleted file mode 100644 index 2e0026cd9e..0000000000 --- a/MAINTAINERS +++ /dev/null @@ -1,7 +0,0 @@ -# This file describes the maintainers for sonic-buildimage -# See the SONiC project governance document for more information - -Name = "Shuotian Cheng" -Email = "shuche@microsoft.com" -Github = stcheng -Mailinglist = sonicproject@googlegroups.com diff --git a/README.md b/README.md deleted file mode 100644 index cb26ec110f..0000000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# sonic-utilities -Various command line utilities for the SONiC project - -See the [SONiC Website](http://azure.github.io/SONiC/) for more information about the SONiC project. diff --git a/ThirdPartyLicenses.txt b/ThirdPartyLicenses.txt deleted file mode 100644 index 2414f0d751..0000000000 --- a/ThirdPartyLicenses.txt +++ /dev/null @@ -1,31 +0,0 @@ -Third Party Notices - -This Microsoft Open Source project incorporates material from the project(s) listed below -(Third Party Code). Microsoft is not the original author of the Third Party Code. Microsoft -reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. - -1. bin/sfputil https://cumulusnetworks.com -2. bcmshell.py https://cumulusnetworks.com -3. eeprom_base.py https://cumulusnetworks.com -4. eeprom_fts.py https://cumulusnetworks.com -5. eeprom_tlvinfo.py https://cumulusnetworks.com -6. sff8472.py https://cumulusnetworks.com -7. sfputilbase.py https://cumulusnetworks.com - - -+ * Copyright (C) 2014 Cumulus Networks, LLC -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." - diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index b761a39988..0000000000 --- a/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -sonic-utilities (0.1) UNRELEASED; urgency=low - - * Initial release. (Closes: #XXXXXX) - - -- Shuotian Cheng Tue, 11 Aug 2015 14:00:00 -0700 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index ec635144f6..0000000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/debian/control b/debian/control deleted file mode 100644 index b6647bdd12..0000000000 --- a/debian/control +++ /dev/null @@ -1,12 +0,0 @@ -Source: sonic-utilities -Maintainer: Shuotian Cheng -Section: misc -Priority: optional -Standards-Version: 0.1 -Build-Depends: debhelper (>=9), python (>=2.7.9) - -Package: sonic-utilities -Architecture: amd64 -Depends: ${misc:Depends}, python-tabulate, psmisc, grub2-common -Description: collection of utilities - Including: sfputil, decode-syseeprom, generate_dump diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/debian/install b/debian/install deleted file mode 100644 index 7b04168cb5..0000000000 --- a/debian/install +++ /dev/null @@ -1,3 +0,0 @@ -bin/* usr/bin/ -ssw/* etc/ssw/ -dist-packages/* usr/lib/python2.7/dist-packages/ diff --git a/debian/rules b/debian/rules deleted file mode 100755 index a5e2f5acfc..0000000000 --- a/debian/rules +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/make -f - -build: - -%: - dh $@ From 96c51e25e5682b95650e42feabce3e7df9528d08 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 16 Feb 2017 22:10:02 +0000 Subject: [PATCH 02/13] Move standalone scripts from bin/ to scripts/ to follow standard Python setuptools convention --- {bin => scripts}/boot_part | 0 {bin => scripts}/coredump-compress | 0 {bin => scripts}/decode-syseeprom | 0 {bin => scripts}/generate_dump | 0 {bin => scripts}/portstat | 0 {bin => scripts}/sfputil | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {bin => scripts}/boot_part (100%) rename {bin => scripts}/coredump-compress (100%) rename {bin => scripts}/decode-syseeprom (100%) rename {bin => scripts}/generate_dump (100%) rename {bin => scripts}/portstat (100%) rename {bin => scripts}/sfputil (100%) diff --git a/bin/boot_part b/scripts/boot_part similarity index 100% rename from bin/boot_part rename to scripts/boot_part diff --git a/bin/coredump-compress b/scripts/coredump-compress similarity index 100% rename from bin/coredump-compress rename to scripts/coredump-compress diff --git a/bin/decode-syseeprom b/scripts/decode-syseeprom similarity index 100% rename from bin/decode-syseeprom rename to scripts/decode-syseeprom diff --git a/bin/generate_dump b/scripts/generate_dump similarity index 100% rename from bin/generate_dump rename to scripts/generate_dump diff --git a/bin/portstat b/scripts/portstat similarity index 100% rename from bin/portstat rename to scripts/portstat diff --git a/bin/sfputil b/scripts/sfputil similarity index 100% rename from bin/sfputil rename to scripts/sfputil From 5506d3c0e4979c99c82d0f328e53250987eefb6e Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 16 Feb 2017 22:15:30 +0000 Subject: [PATCH 03/13] Add 'show' command (SONiC CLI) and files for setuptools/stdeb --- setup.py | 56 ++++++ show/__init__.py | 0 show/aliases.ini | 5 + show/main.py | 453 +++++++++++++++++++++++++++++++++++++++++++++++ stdeb.cfg | 8 + 5 files changed, 522 insertions(+) create mode 100644 setup.py create mode 100644 show/__init__.py create mode 100644 show/aliases.ini create mode 100644 show/main.py create mode 100644 stdeb.cfg diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000..40804e0ff7 --- /dev/null +++ b/setup.py @@ -0,0 +1,56 @@ +from setuptools import setup + +setup( + name='sonic-utilities', + version='1.0', + description='Command-line utilities for SONiC', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-utilities', + maintainer='Joe LeVeque', + maintainer_email='jolevequ@microsoft.com', + packages=['show'], + package_data={ + 'show': ['aliases.ini'] + }, + scripts=[ + 'scripts/boot_part', + 'scripts/coredump-compress', + 'scripts/decode-syseeprom', + 'scripts/generate_dump', + 'scripts/portstat', + 'scripts/sfputil', + ], + data_files=[ + ('/usr/lib/python2.7/dist-packages', [ + 'dist-packages/bcmshell.py', + 'dist-packages/eeprom_base.py', + 'dist-packages/eeprom_dts.py', + 'dist-packages/eeprom_tlvinfo.py', + 'dist-packages/sff8436.py', + 'dist-packages/sff8472.py', + 'dist-packages/sffbase.py', + 'dist-packages/sfputilbase.py' + ] + ), + ], + entry_points={ + 'console_scripts': [ + 'show = show.main:cli', + ] + }, + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 2.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC utilities command line cli CLI', +) diff --git a/show/__init__.py b/show/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/show/aliases.ini b/show/aliases.ini new file mode 100644 index 0000000000..409231559c --- /dev/null +++ b/show/aliases.ini @@ -0,0 +1,5 @@ +[aliases] +running-configuration=runningconfiguration +running-config=runningconfiguration +startup-configuration=startupconfiguration +startup-config=startupconfiguration diff --git a/show/main.py b/show/main.py new file mode 100644 index 0000000000..9568feed6f --- /dev/null +++ b/show/main.py @@ -0,0 +1,453 @@ +#! /usr/bin/python -u + +import click +import os +import subprocess +from click_default_group import DefaultGroup + +try: + # noinspection PyPep8Naming + import ConfigParser as configparser +except ImportError: + # noinspection PyUnresolvedReferences + import configparser + + +# This is from the aliases example: +# https://github.com/pallets/click/blob/57c6f09611fc47ca80db0bd010f05998b3c0aa95/examples/aliases/aliases.py +class Config(object): + """Object to hold CLI config""" + + def __init__(self): + self.path = os.getcwd() + self.aliases = {} + + def read_config(self, filename): + parser = configparser.RawConfigParser() + parser.read([filename]) + try: + self.aliases.update(parser.items('aliases')) + except configparser.NoSectionError: + pass + + +# Global Config object +_config = None + + +# This aliased group has been modified from click examples to inherit from DefaultGroup instead of click.Group. +# DefaultFroup is a superclass of click.Group which calls a default subcommand instead of showing +# a help message if no subcommand is passed +class AliasedGroup(DefaultGroup): + """This subclass of a DefaultGroup supports looking up aliases in a config + file and with a bit of magic. + """ + + def get_command(self, ctx, cmd_name): + + # If we haven't instantiated our global config, do it now and load current config + if _config is None: + global _config + _config = Config() + + # Load our config file + cfg_file = os.path.join(os.path.dirname(__file__), 'aliases.ini') + _config.read_config(cfg_file) + + # Try to get builtin commands as normal + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + + # No builtin found. Look up an explicit command alias in the config + if cmd_name in _config.aliases: + actual_cmd = _config.aliases[cmd_name] + return click.Group.get_command(self, ctx, actual_cmd) + + # Alternative option: if we did not find an explicit alias we + # allow automatic abbreviation of the command. "status" for + # instance will match "st". We only allow that however if + # there is only one command. + matches = [x for x in self.list_commands(ctx) + if x.lower().startswith(cmd_name.lower())] + if not matches: + # No command name matched. Issue Default command. + ctx.arg0 = cmd_name + cmd_name = self.default_cmd_name + return DefaultGroup.get_command(self, ctx, cmd_name) + elif len(matches) == 1: + return DefaultGroup.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + + +def run_command(command, pager=False): + if pager is True: + click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green')) + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + click.echo_via_pager(p.stdout.read()) + else: + click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green')) + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + click.echo(p.stdout.read()) + + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help', '?']) + + +# +# 'cli' group (root group) ### +# + +# THis is our entrypoint - the main "show" command +# TODO: Consider changing function name to 'show' for better understandability +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def cli(): + """SONiC command line - 'show' command""" + pass + + +# +# 'ip' group ### +# + +# This allows us to add commands to both cli and ip groups, allowing for +# "show " and "show ip " to function the same +@cli.group() +def ip(): + """Show IP commands""" + pass + + +# +# 'interfaces' group #### +# + +# We use the "click.group()" decorator because we want to add this group +# to more than one group, which we do using the "add_command() methods below. +@click.group(cls=AliasedGroup, default_if_no_args=True) +def interfaces(): + pass + +# Add 'interfaces' group to both the root 'cli' group and the 'ip' subgroup +cli.add_command(interfaces) +ip.add_command(interfaces) + +# Default 'interfaces' command (called if no subcommands or their aliases were passed) +@interfaces.command(default=True) +@click.argument('interfacename', required=False) +@click.argument('sfp', required=False) +def default(interfacename, sfp): + """Show interface status and information""" + + cmd_ifconfig = "/sbin/ifconfig" + + if interfacename is not None and sfp is not None: + command = "sfputil -p {}".format(interfacename) + run_command(command, pager=True) + # FIXME: show sfp without an interface is bugged and doesn't work right. + elif sfp is not None: + run_command("sfputil") + elif interfacename is not None: + command = "{} {}".format(cmd_ifconfig, interfacename) + run_command(command) + else: + command = cmd_ifconfig + run_command(command, pager=True) + +# 'counters' subcommand +@interfaces.command() +def counters(): + """Show interface counters""" + run_command("portstat", pager=True) + + +# +# 'lldp' group #### +# + +@cli.group(cls=AliasedGroup, default_if_no_args=True) +def lldp(): + pass + +# Default 'lldp' command (called if no subcommands or their aliases were passed) +@lldp.command(default=True) +@click.argument('interfacename', required=False) +def neighbors(interfacename): + """Show LLDP neighbors""" + if interfacename is not None: + command = "lldpctl {}".format(interfacename) + run_command(command) + else: + run_command("lldpctl", pager=True) + +# 'tables' subcommand #### +@lldp.command() +def table(): + """Show LLDP neighbors in tabular format""" + run_command("lldpshow", pager=True) + +# +# 'bgp' group #### +# + +# We use the "click.group()" decorator because we want to add this group +# to more than one group, which we do using the "add_command() methods below. +@click.group(cls=AliasedGroup, default_if_no_args=False) +def bgp(): + """Show BGP (Border Gateway Protocol) information""" + pass + +# Add 'bgp' group to both the root 'cli' group and the 'ip' subgroup +cli.add_command(bgp) +ip.add_command(bgp) + +# 'neighbors' subcommand #### +@bgp.command() +@click.argument('ipaddress', required=False) +def neighbor(ipaddress): + """Show BGP neighbors""" + if ipaddress is not None: + command = 'vtysh -c "show ip bgp neighbor {} "'.format(ipaddress) + run_command(command) + else: + run_command('vtysh -c "show ip bgp neighbor"', pager=True) + +# 'summary' subcommand #### +@bgp.command() +def summary(): + """Show summarized information of BGP state""" + run_command('vtysh -c "show ip bgp summary"') + + +# +# 'platform' group #### +# + +@cli.group(invoke_without_command=True) +def platform(): + """Show hardware platform information""" + run_command("platform-detect") + +# 'syseeprom' subcommand #### +@platform.command() +def syseeprom(): + """Show system EEPROM information""" + run_command("decode-syseeprom") + + +# +# 'logging' group #### +# + +@cli.group(cls=AliasedGroup, default_if_no_args=True) +def logging(): + pass + +# Default 'lldp' command (called if no subcommands or their aliases were passed) +@logging.command(default=True) +@click.argument('process', required=False) +@click.option('--tail', required=False, default=10) +@click.option('--follow', required=False) +def default(process, tail, follow): + """Show system log""" + if process is not None: + command = "grep {} /var/log/syslog".format(process) + if tail is not None: + command += "| tail -{}".format(tail) + elif follow is not None: + command += "| tail -f" + run_command(command) + else: + run_command("cat /var/log/syslog", pager=True) + + +# +# 'version' command ### +# + +@cli.command() +def version(): + """Show version information""" + click.echo("") + command = 'cat /etc/ssw/sysDescription' + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + click.echo(p.stdout.read()) + click.echo("") + click.echo("Docker images:") + command = 'docker images --format "table {{.Repository}}\\t{{.Tag}}\\t{{.ID}}\\t{{.Size}}"' + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + click.echo(p.stdout.read()) + + command = 'uptime -p' + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + click.echo("Kernel uptime " + p.stdout.read()) + + +# +# 'environment' command ### +# + +@cli.command() +def environment(): + """Show environmentals (voltages, fans, temps)""" + run_command('sensors', pager=True) + + +# +# 'processes' group ### +# + +@cli.group() +def processes(): + """Display process information""" + pass + +# 'cpu' subcommand +@processes.command() +def cpu(): + """Show processes CPU info""" + # Run top batch mode to prevent unexpected newline after each newline + run_command('top -bn 1', pager=True) + + +# +# 'users' command ### +# + +@cli.command() +def users(): + """Show users""" + run_command('who') + + +# +# 'techsupport' command ### +# + +@cli.command() +def techsupport(): + """Gather information for troubleshooting""" + run_command('acs_support -v') + + +# +# 'runningconfiguration' group ### +# + +@cli.group(cls=AliasedGroup, default_if_no_args=False) +def runningconfiguration(): + """Show current running configuration information""" + pass + + +# 'bgp' subcommand +@runningconfiguration.command() +def bgp(): + """Show BGP running configuration""" + run_command('vtysh -c "show running-config"', pager=True) + + +# 'interfaces' subcommand +@runningconfiguration.command() +@click.argument('interfacename', required=False) +def interfaces(interfacename): + """Show interfaces running configuration""" + if interfacename is not None: + command = "cat /etc/network/interfaces | grep {} -A 4".format(interfacename) + run_command(command) + else: + run_command('cat /etc/network/interfaces', pager=True) + + +# 'snmp' subcommand +@runningconfiguration.command() +def snmp(): + """Show SNMP running configuration""" + command = 'docker exec -it snmp cat /etc/snmp/snmpd.conf' + run_command(command, pager=True) + + +# 'ntp' subcommand +@runningconfiguration.command() +def ntp(): + """Show NTP running configuration""" + run_command('cat /etc/ntp.conf', pager=True) + + +# 'startupconfiguration' group ### +# + +@cli.group(cls=AliasedGroup, default_if_no_args=False) +def startupconfiguration(): + """Show startup configuration information""" + pass + + +# 'bgp' subcommand +@startupconfiguration.command() +def bgp(): + """Show BGP startup configuration""" + run_command('docker exec -it bgp cat /etc/quagga/bgpd.conf') + + +# +# 'arp' command #### +# + +@click.command() +@click.argument('ipaddress', required=False) +def arp(ipaddress): + """Show ip arp table""" + cmd = "/usr/sbin/arp" + if ipaddress is not None: + command = '{} {}'.format(cmd, ipaddress) + run_command(command) + else: + run_command(cmd, pager=True) + +# Add 'arp' command to both the root 'cli' group and the 'ip' subgroup +cli.add_command(arp) +ip.add_command(arp) + + +# +# 'route' command #### +# + +@click.command() +@click.argument('ipaddress', required=False) +def route(ipaddress): + """Show ip routing table""" + if ipaddress is not None: + command = 'vtysh -c "show ip route {}"'.format(ipaddress) + run_command(command) + else: + run_command('vtysh -c "show ip route"', pager=True) + +# Add 'route' command to both the root 'cli' group and the 'ip' subgroup +cli.add_command(route) +ip.add_command(route) + + +# +# 'ntp' command #### +# + +@cli.command() +def ntp(): + """Show NTP information""" + run_command('ntpq -p') + + +# +# 'uptime' command #### +# + +@cli.command() +def uptime(): + """Show system uptime""" + run_command('uptime -p') + + +if __name__ == '__main__': + cli() diff --git a/stdeb.cfg b/stdeb.cfg new file mode 100644 index 0000000000..a8c711ada7 --- /dev/null +++ b/stdeb.cfg @@ -0,0 +1,8 @@ +# Note: For this package, we are not able to specify dependencies in setup.py +# under "install_requires=[]" because when packaging as a .deb, stdeb adds a "python-" +# prefix to all dependencies and attempts to install via apt. Unfortunately, +# 'click-group-default' does not follow this naming convention, so we must use +# this stdeb.cfg file instead. + +[DEFAULT] +Depends: python-click, click-default-group, python-tabulate, psmisc, grub2-common From 1b5f59e3031c6eb217282fd7caeb8d9c994b9620 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 16 Feb 2017 22:17:16 +0000 Subject: [PATCH 04/13] Merge changes from internal repo to decode-syseeprom --- scripts/decode-syseeprom | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/decode-syseeprom b/scripts/decode-syseeprom index 675f0c54ff..f07055a099 100755 --- a/scripts/decode-syseeprom +++ b/scripts/decode-syseeprom @@ -1,4 +1,4 @@ -#! /usr/bin/python +#!/usr/bin/env python ############################################################################# # @@ -121,15 +121,15 @@ def run(target, opts, args): elif opts.mgmtmac: mm = target.mgmtaddrstr(e) - if mm <> None: + if mm != None: print mm elif opts.serial: try: serial = target.serial_number_str(e) except NotImplemented, e: - print e + print e else: - print serial or "Undefined." + print serial or "Undefined." else: target.decode_eeprom(e) (is_valid, valid_crc) = target.is_checksum_valid(e) From 03df652c688bf9ef8cbaa60e8e9bad1b4b3889d1 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 16 Feb 2017 22:17:37 +0000 Subject: [PATCH 05/13] Merge changes from internal repo to portstat --- scripts/portstat | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/portstat b/scripts/portstat index e24650e2a7..a6c5e7244d 100755 --- a/scripts/portstat +++ b/scripts/portstat @@ -66,7 +66,6 @@ filter_bucket_dict = { 'RFCR': 1, 'RJBR': 1, 'RDBGC0': 2, - 'RDBGC2': 2, 'DROP_PKT_ING': 2, 'ROVR': 3, 'TPKT': 4, @@ -310,7 +309,7 @@ Examples: sys.exit(0) try: - bcmcmd_output = subprocess.Popen((['/usr/sbin/bcmcmd', + bcmcmd_output = subprocess.Popen((['/usr/bin/bcmcmd', 'show counters changed same nz']), stdout=subprocess.PIPE, shell=False).communicate()[0] @@ -365,9 +364,10 @@ Examples: for i in range(2, len(netstat_lines) - 1): netstats = netstat_lines[i].split() if ":" in netstats[0]: - continue # skip aliased interfaces - if "eth" in netstats[0] or "lo" in netstats[0] or "docker" in netstats[0]: - continue + continue # Skip aliased interfaces + if ("eth" in netstats[0] or "lo" in netstats[0] or "docker" in netstats[0] or + "Vlan" in netstats[0] or "PortChannel" in netstats[0]): + continue # Skip these types of interfaces else: cnstat_dict.update(cnstat_create_bcm_element(i, netstats, bcm_dict[netstats[0]])) From d2f8ff268cbe983dccb79a2c2cfbeda939fe135c Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Fri, 17 Feb 2017 00:58:53 +0000 Subject: [PATCH 06/13] Merge changes from internal repo to sfputil --- scripts/sfputil | 1181 +++++++++++++++++++++++------------------------ 1 file changed, 590 insertions(+), 591 deletions(-) diff --git a/scripts/sfputil b/scripts/sfputil index a7235b9386..418275f8dd 100755 --- a/scripts/sfputil +++ b/scripts/sfputil @@ -5,15 +5,15 @@ # #-------------------------------------------------------------------------- try: - import sys - import os - import getopt - import subprocess - import imp - import cPickle as pickle - import syslog - import types - import traceback + import sys + import os + import getopt + import subprocess + import imp + import cPickle as pickle + import syslog + import types + import traceback except ImportError, e: raise ImportError (str(e) + "- required module not found") @@ -22,14 +22,14 @@ version = '1.0' usage_help=""" Usage: sfputil [--help] [-p|--port ] [-d|--dom] [-o|--oneline] - [-v|--version] + [-v|--version] OPTIONS - -h,--help prints this usage - -p,--port prints sfp details for port_name - -d,--dom Includes diagnostic monitor data in output if supported - -o,--oneline prints oneline output for each port - -v,--version prints version string + -h,--help Prints this usage + -p,--port Prints sfp details for port_name + -d,--dom Includes diagnostic monitor data in output if supported + -o,--oneline Prints oneline output for each port + -v,--version Prints version string """ @@ -42,705 +42,704 @@ phytabfile = '/var/lib/cumulus/phytab' indent = '\t' def log_init(): - syslog.openlog('sfputil') + syslog.openlog('sfputil') def log_syslog(logmsg): - syslog.syslog(syslog.LOG_INFO, logmsg) + syslog.syslog(syslog.LOG_INFO, logmsg) def inc_indent(): - global indent - indent += '\t' + global indent + indent += '\t' def dec_indent(): - global indent - indent = indent[:-1] + global indent + indent = indent[:-1] def print_sfp_status(port, port_sfp_status): - if port_sfp_status == 1: - print '%s: ' %port + 'SFP detected' - else: - print '%s: ' %port + 'SFP not detected' + if port_sfp_status == 1: + print '%s: ' %port + 'SFP detected' + else: + print '%s: ' %port + 'SFP not detected' # Returns, -# port_num if physical -# logical_port:port_num if logical port and is a ganged port -# logical_port if logical and not ganged +# port_num if physical +# logical_port:port_num if logical port and is a ganged port +# logical_port if logical and not ganged # def get_port_name(logical_port, physical_port, ganged): - port_name = None + port_name = None - if logical_port == physical_port: - return logical_port - elif ganged == 1: - return logical_port + ':%d (ganged)' %physical_port - else: - return logical_port + if logical_port == physical_port: + return logical_port + elif ganged == 1: + return logical_port + ':%d (ganged)' %physical_port + else: + return logical_port def conv_port_to_physical_port_list(port): - if port.startswith('Ethernet'): - if csfputil.is_logical_port(port): - return csfputil.get_logical_to_physical(port) - else: - print 'Error: Invalid port ' + port - return None - else: - return [int(port)] + if port.startswith('Ethernet'): + if csfputil.is_logical_port(port): + return csfputil.get_logical_to_physical(port) + else: + print 'Error: Invalid port ' + port + return None + else: + return [int(port)] def print_valid_values_for_port_cmdoption(): - print 'Valid values for --port : ' + str(csfputil.logical) - print + print 'Valid values for --port : ' + str(csfputil.logical) + print #============ Functions to get and print sfp data ====================== # Get sfp port object def get_port_sfp_data(sfp_obj, port_num): - sfp_port_data = {} - - if sfp_obj == None: - print 'Error getting sfp data for port %d' %port_num - sfp_port_data[port_num] = None - else: - sfp_port_data[port_num] = sfp_obj.get_sfp_data(port_num) + sfp_port_data = {} - return sfp_port_data + if sfp_obj == None: + print 'Error getting sfp data for port %d' %port_num + sfp_port_data[port_num] = None + else: + sfp_port_data[port_num] = sfp_obj.get_sfp_data(port_num) + + return sfp_port_data # Returns sfp data for all ports def get_port_sfp_data_all(sfp_obj_all): - """{1: {'interface': {'version': '1.0', 'data': {}}, - 'dom': {'version' : '1.0', 'data' : {}}}, - {2: {'interface': {'version': '1.0', 'data': {}}, - 'dom': {'version' : '1.0', 'data' : {}}}}}""" + """{1: {'interface': {'version': '1.0', 'data': {}}, + 'dom': {'version' : '1.0', 'data' : {}}}, + {2: {'interface': {'version': '1.0', 'data': {}}, + 'dom': {'version' : '1.0', 'data' : {}}}}}""" - port_sfp_data_all = {} - port_start = csfputil.port_start - port_end = csfputil.port_end + port_sfp_data_all = {} + port_start = csfputil.port_start + port_end = csfputil.port_end - for p in range(port_start, port_end + 1): - port_sfp_data_all.update(get_port_sfp_data(sfp_obj_all.get(p), - p)) + for p in range(port_start, port_end + 1): + port_sfp_data_all.update(get_port_sfp_data(sfp_obj_all.get(p), + p)) - return port_sfp_data_all + return port_sfp_data_all # recursively pretty print dictionary def print_dict_pretty(indict): - for elem, elem_val in sorted(indict.iteritems()): - if type(elem_val) == types.DictType: - print indent, elem, ':' - inc_indent() - print_dict_pretty(elem_val) - dec_indent() - else: - print indent, elem, ':', elem_val + for elem, elem_val in sorted(indict.iteritems()): + if type(elem_val) == types.DictType: + print indent, elem, ':' + inc_indent() + print_dict_pretty(elem_val) + dec_indent() + else: + print indent, elem, ':', elem_val # Print pretty sfp port data def print_port_sfp_data_pretty(port_sfp_data, port, dump_dom): - ganged = 0 - i = 1 - - port_list = conv_port_to_physical_port_list(port) - if len(port_list) > 1: - ganged = 1 - - for p in port_list: - port_name = get_port_name(port, i, ganged) - sfp_data = port_sfp_data.get(p) - if sfp_data != None: - sfp_idata = sfp_data.get('interface') - idata = sfp_idata.get('data') - print_sfp_status(port_name, 1) - print_dict_pretty(idata) - if dump_dom == 1: - sfp_ddata = sfp_data.get('dom') - if sfp_ddata != None: - ddata = sfp_ddata.get('data') - print_dict_pretty(ddata) - else: - print_sfp_status(port_name, 0) - print - i += 1 + ganged = 0 + i = 1 + + port_list = conv_port_to_physical_port_list(port) + if len(port_list) > 1: + ganged = 1 + + for p in port_list: + port_name = get_port_name(port, i, ganged) + sfp_data = port_sfp_data.get(p) + if sfp_data != None: + sfp_idata = sfp_data.get('interface') + idata = sfp_idata.get('data') + print_sfp_status(port_name, 1) + print_dict_pretty(idata) + if dump_dom == 1: + sfp_ddata = sfp_data.get('dom') + if sfp_ddata != None: + ddata = sfp_ddata.get('data') + print_dict_pretty(ddata) + else: + print_sfp_status(port_name, 0) + print + i += 1 # Print pretty all sfp port data def print_port_sfp_data_pretty_all(port_sfp_data, dump_dom): - for p in csfputil.logical: - print_port_sfp_data_pretty(port_sfp_data, p, dump_dom) + for p in csfputil.logical: + print_port_sfp_data_pretty(port_sfp_data, p, dump_dom) # Recursively print dict elems into coma separated list def print_dict_comaseparated(indict, elem_blacklist, elemprefix, first): - iter = 0 - for elem, elem_val in sorted(indict.iteritems()): - if elem in elem_blacklist: - continue - if type(elem_val) == types.DictType: - if iter != 0: - print ',', - print_dict_comaseparated(elem_val, elem_blacklist, - elem, first) - else: - elemname = elemprefix + elem - if first == 1: - prbuf = elemname + ':' + str(elem_val) - first = 0 - else: - prbuf = ',' + elemname + ':' + str(elem_val) - sys.stdout.write(prbuf) - iter = iter + 1 + iter = 0 + for elem, elem_val in sorted(indict.iteritems()): + if elem in elem_blacklist: + continue + if type(elem_val) == types.DictType: + if iter != 0: + print ',', + print_dict_comaseparated(elem_val, elem_blacklist, + elem, first) + else: + elemname = elemprefix + elem + if first == 1: + prbuf = elemname + ':' + str(elem_val) + first = 0 + else: + prbuf = ',' + elemname + ':' + str(elem_val) + sys.stdout.write(prbuf) + iter = iter + 1 # Pretty print oneline all sfp data def print_port_sfp_data_pretty_oneline(port_sfp_data, - ifdata_blacklist, - domdata_blacklist, - port, dump_dom): - ganged = 0 - i = 1 - - port_list = conv_port_to_physical_port_list(port) - if len(port_list) > 1: - ganged = 1 - - for p in port_list: - port_name = get_port_name(port, i, ganged) - sfp_data = port_sfp_data.get(p) - if sfp_data != None: - sfp_idata = sfp_data.get('interface') - idata = sfp_idata.get('data') - print 'port:' + port_name + ',', - print_dict_comaseparated(idata, ifdata_blacklist, '', 1) - if dump_dom == 1: - sfp_ddata = sfp_data.get('dom') - if sfp_ddata != None: - ddata = sfp_ddata.get('data') - if ddata != None: - print_dict_comaseparated(ddata, - domdata_blacklist, '',1) - print - #Only print detected sfp ports for oneline - #else: - #print_sfp_status(port_name, 0) - i += 1 + ifdata_blacklist, + domdata_blacklist, + port, dump_dom): + ganged = 0 + i = 1 + + port_list = conv_port_to_physical_port_list(port) + if len(port_list) > 1: + ganged = 1 + + for p in port_list: + port_name = get_port_name(port, i, ganged) + sfp_data = port_sfp_data.get(p) + if sfp_data != None: + sfp_idata = sfp_data.get('interface') + idata = sfp_idata.get('data') + print 'port:' + port_name + ',', + print_dict_comaseparated(idata, ifdata_blacklist, '', 1) + if dump_dom == 1: + sfp_ddata = sfp_data.get('dom') + if sfp_ddata != None: + ddata = sfp_ddata.get('data') + if ddata != None: + print_dict_comaseparated(ddata, + domdata_blacklist, '',1) + print + #Only print detected sfp ports for oneline + #else: + #print_sfp_status(port_name, 0) + i += 1 def print_port_sfp_data_pretty_oneline_all(port_sfp_data, - ifdata_blacklist, - domdata_blacklist, - dump_dom): - for p in csfputil.logical: - print_port_sfp_data_pretty_oneline(port_sfp_data, - ifdata_blacklist, - domdata_blacklist, - p, dump_dom) + ifdata_blacklist, + domdata_blacklist, + dump_dom): + for p in csfputil.logical: + print_port_sfp_data_pretty_oneline(port_sfp_data, + ifdata_blacklist, + domdata_blacklist, + p, dump_dom) def get_port_sfp_object(port_num): - sfp_obj = {} - sfp_obj[port_num] = csfputil(int(port_num)) + sfp_obj = {} + sfp_obj[port_num] = csfputil(int(port_num)) - return sfp_obj + return sfp_obj # Return sfp objects for all ports def get_port_sfp_object_all(): - port_sfp_object_all = {} - port_start = csfputil.port_start - port_end = csfputil.port_end + port_sfp_object_all = {} + port_start = csfputil.port_start + port_end = csfputil.port_end - for p in range(port_start, port_end + 1): - port_sfp_object_all.update(get_port_sfp_object(p)) + for p in range(port_start, port_end + 1): + port_sfp_object_all.update(get_port_sfp_object(p)) - return port_sfp_object_all + return port_sfp_object_all def print_raw_bytes(bytes): - hexstr = '' - - for e in range(1, len(bytes)+1): - print bytes[e-1], - hexstr += bytes[e-1] - if e > 0 and (e % 8) == 0: - print ' ', - if e > 0 and (e % 16) == 0: - # XXX: Does not print some characters - # right, comment it to fix it later - #print binascii.unhexlify(hexstr), - hexstr = '' - print + hexstr = '' + + for e in range(1, len(bytes)+1): + print bytes[e-1], + hexstr += bytes[e-1] + if e > 0 and (e % 8) == 0: + print ' ', + if e > 0 and (e % 16) == 0: + # XXX: Does not print some characters + # right, comment it to fix it later + #print binascii.unhexlify(hexstr), + hexstr = '' + print def print_port_sfp_data_raw(sfp_obj_all, port): - ganged = 0 - i = 1 - - physical_port_list = conv_port_to_physical_port_list(port) - if len(physical_port_list) > 1: - ganged = 1 - - for p in physical_port_list: - port_name = get_port_name(port, i, ganged) - sfp_obj = sfp_obj_all.get(p) - if sfp_obj == None: - print ('Error: Unexpected error: sfp object for ' - 'port %d' %p + 'not found') - return - eeprom_if_raw = sfp_obj.get_interface_eeprom_bytes() - if eeprom_if_raw == None: - print_sfp_status(port_name, 0) - else: - print_sfp_status(port_name, 1) - print_raw_bytes(eeprom_if_raw) - print - i += 1 + ganged = 0 + i = 1 + + physical_port_list = conv_port_to_physical_port_list(port) + if len(physical_port_list) > 1: + ganged = 1 + + for p in physical_port_list: + port_name = get_port_name(port, i, ganged) + sfp_obj = sfp_obj_all.get(p) + if sfp_obj == None: + print ('Error: Unexpected error: sfp object for ' + 'port %d' %p + 'not found') + return + eeprom_if_raw = sfp_obj.get_interface_eeprom_bytes() + if eeprom_if_raw == None: + print_sfp_status(port_name, 0) + else: + print_sfp_status(port_name, 1) + print_raw_bytes(eeprom_if_raw) + print + i += 1 def print_port_sfp_data_raw_all(sfp_obj_all): - for p in csfputil.logical: - print_port_sfp_data_raw(sfp_obj_all, p) + for p in csfputil.logical: + print_port_sfp_data_raw(sfp_obj_all, p) #=========== Functions to check and report dom alarms ==================== #Returns list of keys that are different in the two dictionaries def diff_dict(dict_a, dict_b): - keys_diff = [] - for a_name, a_val in sorted(dict_a.iteritems()): - b_val = dict_b.get(a_name) - if b_val == None or a_val != b_val: - keys_diff.append(a_name) + keys_diff = [] + for a_name, a_val in sorted(dict_a.iteritems()): + b_val = dict_b.get(a_name) + if b_val == None or a_val != b_val: + keys_diff.append(a_name) - for b_name, b_val in sorted(dict_b.iteritems()): - a_val = dict_a.get(b_name) - if a_val == None: - keys_diff.append(b_name) + for b_name, b_val in sorted(dict_b.iteritems()): + a_val = dict_a.get(b_name) + if a_val == None: + keys_diff.append(b_name) - return keys_diff + return keys_diff # Logs alarms in syslog def sfp_dom_report_monitor_data_changes(port_num, old_if_data, old_monitor_data, - new_if_data, new_monitor_data): - # XXX: Only check power for now - power_tolerance = 5 - - for mkey, mval in sorted(new_monitor_data.iteritems()): - if mkey == 'RXPower' or mkey == 'TXPower': - if mval == 'Unknown': - # The module isn't reporting power data, skip it. - return - - try: - old_power = old_monitor_data.get(mkey) - new_powerf = float(mval[:-len('dBm')]) - old_powerf = float(old_power[:-len('dBm')]) - - diff = abs(new_powerf - old_powerf) - except TypeError, e: - print ('Error during reporting monitor ' + - 'data changes ' + str(e)) - return - except ValueError, e: - print ('Error during reporting monitor ' + - 'data changes ' + str(e)) - return - except: - # This is a non critical error. Just return - return - - if diff > power_tolerance: - logmsg = ('link %d' %port_num + - ' sfp (SerialNum: %s):' - %old_if_data.get('VendorSN', - 'Unknown') + ' %s' %mkey + - ' changed from %s ' - %old_power + ' to %s' %mval) - log_syslog(logmsg) + new_if_data, new_monitor_data): + # XXX: Only check power for now + power_tolerance = 5 + + for mkey, mval in sorted(new_monitor_data.iteritems()): + if mkey == 'RXPower' or mkey == 'TXPower': + if mval == 'Unknown': + # The module isn't reporting power data, skip it. + return + + try: + old_power = old_monitor_data.get(mkey) + new_powerf = float(mval[:-len('dBm')]) + old_powerf = float(old_power[:-len('dBm')]) + + diff = abs(new_powerf - old_powerf) + except TypeError, e: + print ('Error during reporting monitor ' + + 'data changes ' + str(e)) + return + except ValueError, e: + print ('Error during reporting monitor ' + + 'data changes ' + str(e)) + return + except: + # This is a non critical error. Just return + return + + if diff > power_tolerance: + logmsg = ('link %d' %port_num + + ' sfp (SerialNum: %s):' + %old_if_data.get('VendorSN', + 'Unknown') + ' %s' %mkey + + ' changed from %s ' + %old_power + ' to %s' %mval) + log_syslog(logmsg) # Logs alarms in syslog def sfp_dom_report_alarms(port_num, if_data, dom_alarm_data, keys_filter): - for alarm, alarm_status in sorted(dom_alarm_data.iteritems()): - if (keys_filter == None or - (keys_filter != None and (alarm in keys_filter))): - logmsg = ('link %d' %port_num + - ' sfp (SerialNum: %s): ' - %if_data.get('VendorSN', 'Unknown') + - '%s' %alarm) - if alarm_status == 1: - logmsg = logmsg + ' set' - log_syslog(logmsg) + for alarm, alarm_status in sorted(dom_alarm_data.iteritems()): + if (keys_filter == None or + (keys_filter != None and (alarm in keys_filter))): + logmsg = ('link %d' %port_num + + ' sfp (SerialNum: %s): ' + %if_data.get('VendorSN', 'Unknown') + + '%s' %alarm) + if alarm_status == 1: + logmsg = logmsg + ' set' + log_syslog(logmsg) - if keys_filter != None: - if alarm_status == 0: - logmsg = logmsg + ' cleared' - log_syslog(logmsg) + if keys_filter != None: + if alarm_status == 0: + logmsg = logmsg + ' cleared' + log_syslog(logmsg) # Check and report alarms def sfp_dom_check_and_report_alarms(port_num, port_sfp_data_old, - port_sfp_data_new): - - # For now only look for only alarm and warning flag status - keys_to_check = [ 'AlarmFlagStatus', 'WarningFlagStatus' ] - report_new = 0 - port_sfp_dom_old = None - port_sfp_if_old = None - port_sfp_dom_new = None - port_sfp_if_new = None - sub_keys_that_differ = [] - - if port_sfp_data_new != None: - port_sfp_if_new = port_sfp_data_new.get('interface') - port_sfp_dom_new = port_sfp_data_new.get('dom') - else: - return - - if port_sfp_dom_new == None: - return - - if port_sfp_data_old != None: - port_sfp_if_old = port_sfp_data_old.get('interface') - port_sfp_dom_old = port_sfp_data_old.get('dom') - - new_ddata = port_sfp_dom_new.get('data') - new_idata = port_sfp_if_new.get('data') - - # Check if new data or difference between new and old needs - # reporting - if (port_sfp_dom_old == None and port_sfp_dom_new != None): - report_new = 1 - elif port_sfp_dom_old != None and port_sfp_dom_new != None: - new_dom_ver = port_sfp_dom_new.get('version') - old_dom_ver = port_sfp_dom_old.get('version') - - old_ddata = port_sfp_dom_old.get('data') - old_idata = port_sfp_if_old.get('data') - - if old_idata.get('VendorSN') != new_idata.get('VendorSN'): - # If serial numbers between old and new diff, report new - report_new = 1 - elif new_dom_ver != old_dom_ver: - # If versions between old and new differ, report - report_new = 1 - else: - return - - if report_new == 1: - # Report only new object - for k in keys_to_check: - if k in new_ddata.keys(): - sfp_dom_report_alarms(port_num, new_idata, - new_ddata[k], None) - - else: - # Report what changed between old and new - for k in keys_to_check: - if k in new_ddata.keys() and k in old_ddata.keys(): - # Get keys that differ between the two - sub_keys_that_differ = diff_dict(new_ddata[k], - old_ddata[k]) - - if len(sub_keys_that_differ) > 0: - if k in new_ddata.keys(): - sfp_dom_report_alarms(port_num, - new_idata, new_ddata[k], - sub_keys_that_differ) - - # Check if monitor data changed beyond tolerance - # XXX: This might be redundant as we already report alarm - # and warning reports - key = 'MonitorData' - if key in new_ddata.keys() and key in old_ddata.keys(): - sfp_dom_report_monitor_data_changes(port_num, - new_idata, new_ddata[key], old_idata, - old_ddata[key]) - + port_sfp_data_new): + + # For now only look for only alarm and warning flag status + keys_to_check = [ 'AlarmFlagStatus', 'WarningFlagStatus' ] + report_new = 0 + port_sfp_dom_old = None + port_sfp_if_old = None + port_sfp_dom_new = None + port_sfp_if_new = None + sub_keys_that_differ = [] + + if port_sfp_data_new != None: + port_sfp_if_new = port_sfp_data_new.get('interface') + port_sfp_dom_new = port_sfp_data_new.get('dom') + else: + return + + if port_sfp_dom_new == None: + return + + if port_sfp_data_old != None: + port_sfp_if_old = port_sfp_data_old.get('interface') + port_sfp_dom_old = port_sfp_data_old.get('dom') + + new_ddata = port_sfp_dom_new.get('data') + new_idata = port_sfp_if_new.get('data') + + # Check if new data or difference between new and old needs + # reporting + if (port_sfp_dom_old == None and port_sfp_dom_new != None): + report_new = 1 + elif port_sfp_dom_old != None and port_sfp_dom_new != None: + new_dom_ver = port_sfp_dom_new.get('version') + old_dom_ver = port_sfp_dom_old.get('version') + + old_ddata = port_sfp_dom_old.get('data') + old_idata = port_sfp_if_old.get('data') + + if old_idata.get('VendorSN') != new_idata.get('VendorSN'): + # If serial numbers between old and new diff, report new + report_new = 1 + elif new_dom_ver != old_dom_ver: + # If versions between old and new differ, report + report_new = 1 + else: + return + + if report_new == 1: + # Report only new object + for k in keys_to_check: + if k in new_ddata.keys(): + sfp_dom_report_alarms(port_num, new_idata, + new_ddata[k], None) + + else: + # Report what changed between old and new + for k in keys_to_check: + if k in new_ddata.keys() and k in old_ddata.keys(): + # Get keys that differ between the two + sub_keys_that_differ = diff_dict(new_ddata[k], + old_ddata[k]) + + if len(sub_keys_that_differ) > 0: + if k in new_ddata.keys(): + sfp_dom_report_alarms(port_num, + new_idata, new_ddata[k], + sub_keys_that_differ) + + # Check if monitor data changed beyond tolerance + # XXX: This might be redundant as we already report alarm + # and warning reports + key = 'MonitorData' + if key in new_ddata.keys() and key in old_ddata.keys(): + sfp_dom_report_monitor_data_changes(port_num, + new_idata, new_ddata[key], old_idata, + old_ddata[key]) # Reads and Returns dom data from /var/cache/sfputil/ def get_saved_sfp_data(): - sfp_ports_dom_data = None - - # Create sfputil dir if does not already exist - if not os.path.exists(sfp_dom_data_cache_dir): - try: - os.mkdir(sfp_dom_data_cache_dir) - except OSError, e: - print ('Error creating dir ' + - sfp_dom_data_cache_dir + ' (' + str(e) + ')') - return -1 - - # if cache file exists - if os.path.exists(sfp_dom_data_cache_file): - # load dom data from cached file - try: - sfp_ports_dom_data = pickle.load(open( - sfp_dom_data_cache_file, "rb")) - except pickle.PickleError, e: - print 'Error unpicking dom data.' - traceback.print_exc(file=sys.stdout) - - return sfp_ports_dom_data - - + sfp_ports_dom_data = None + + # Create sfputil dir if does not already exist + if not os.path.exists(sfp_dom_data_cache_dir): + try: + os.mkdir(sfp_dom_data_cache_dir) + except OSError, e: + print ('Error creating dir ' + + sfp_dom_data_cache_dir + ' (' + str(e) + ')') + return -1 + + # if cache file exists + if os.path.exists(sfp_dom_data_cache_file): + # load dom data from cached file + try: + sfp_ports_dom_data = pickle.load(open( + sfp_dom_data_cache_file, "rb")) + except pickle.PickleError, e: + print 'Error unpicking dom data.' + traceback.print_exc(file=sys.stdout) + + return sfp_ports_dom_data + + # Checks dom data. Compares with cached dom file for any new alarms def sfp_dom_data_check(ports_sfp_data): - # get Old dom data from /var/cache/ - ports_sfp_data_old = get_saved_sfp_data() + # get Old dom data from /var/cache/ + ports_sfp_data_old = get_saved_sfp_data() + + # iterate through new dom data for all ports + for port, port_sfp_data_new in sorted( + ports_sfp_data.iteritems()): + if port_sfp_data_new == None: + continue - # iterate through new dom data for all ports - for port, port_sfp_data_new in sorted( - ports_sfp_data.iteritems()): - if port_sfp_data_new == None: - continue + port_sfp_data_old = None + if ports_sfp_data_old != None: + port_sfp_data_old = ports_sfp_data_old.get(port) - port_sfp_data_old = None - if ports_sfp_data_old != None: - port_sfp_data_old = ports_sfp_data_old.get(port) + if port_sfp_data_old != None: + # XXX: We should probably not proceed if dom versions + # differ - if port_sfp_data_old != None: - # XXX: We should probably not proceed if dom versions - # differ + # Check alarms in old and new data and report + sfp_dom_check_and_report_alarms(port, + port_sfp_data_old, + port_sfp_data_new) + else: + sfp_dom_check_and_report_alarms(port, None, + port_sfp_data_new) - # Check alarms in old and new data and report - sfp_dom_check_and_report_alarms(port, - port_sfp_data_old, - port_sfp_data_new) - else: - sfp_dom_check_and_report_alarms(port, None, - port_sfp_data_new) + # XXX: The above loop does not account for sfp's that were + # present in old data but dissappeared in new data. Only thing we + # could possibly do here is report faults were cleared on the old port. - # XXX: The above loop does not account for sfp's that were - # present in old data but dissappeared in new data. Only thing we - # could possibly do here is report faults were cleared on the old port. + # Dump new dom data into cached file + try: + pickle.dump(ports_sfp_data, open(sfp_dom_data_cache_file, + "wb")) + except pickle.PickleError, e: + print 'Error pickling dom data ' + str(e) + return + + print 'Saved new dom data to file ' + sfp_dom_data_cache_file - # Dump new dom data into cached file - try: - pickle.dump(ports_sfp_data, open(sfp_dom_data_cache_file, - "wb")) - except PickleError, e: - print 'Error pickling dom data ' + str(e) - return - print 'Saved new dom data to file ' + sfp_dom_data_cache_file - - #=========== Functions to load platform specific classes ==================== # Returns platform vendor and model def get_platform(): - try: - platform_detect = '/usr/bin/platform-detect' - - ph = subprocess.Popen((platform_detect), stdout=subprocess.PIPE, - shell=False, stderr=subprocess.STDOUT) - cmdout = ph.communicate()[0] - ph.wait() - except OSError, e: - raise OSError("cannot detect platform") + try: + platform_detect = '/usr/bin/platform-detect' - return cmdout.rstrip('\n') + ph = subprocess.Popen((platform_detect), stdout=subprocess.PIPE, + shell=False, stderr=subprocess.STDOUT) + cmdout = ph.communicate()[0] + ph.wait() + except OSError, e: + raise OSError("cannot detect platform") + return cmdout.rstrip('\n') # Loads platform specific sfputil module from source def load_platform_sfputil(): - global csfputil - global porttabfile - platform_root = '/etc/ssw/' - module_name = 'sfputil' + global csfputil + global porttabfile + platform_root = '/etc/ssw/' + module_name = 'sfputil' + + + # Get platform details + model = get_platform() + #Load platform module from source + platform_sfputil_module_path = '/'.join([platform_root, model, 'bin']) - # Get platform details - model = get_platform() + # First check for the presence of the new 'port_config.ini' file + porttabfile = '/'.join([platform_root, model, 'port_config.ini']) + if not os.path.isfile(porttabfile): + # port_config.ini doesn't exist. Try loading the older 'portmap.ini' file + porttabfile = '/'.join([platform_root, model, 'portmap.ini']) - #Load platform module from source - platform_sfputil_module_path = '/'.join([platform_root, model, 'bin']) - porttabfile = '/'.join([platform_root, model, 'portmap.ini']) + try: + module = imp.load_source(module_name, + '/'.join([platform_sfputil_module_path, + module_name + '.py'])) + except IOError, e: + print 'Error loading platform module ' + module_name + str(e) + return None - try: - module = imp.load_source(module_name, - '/'.join([platform_sfputil_module_path, - module_name + '.py'])) - except IOError, e: - print 'Error loading platform module ' + module_name + str(e) - return None + try: + csfputil = getattr(module, 'sfputil') + except AttributeError, e: + print 'Error finding sfputil class: ' + str(e) + return -1 - try: - csfputil = getattr(module, 'sfputil') - except AttributeError, e: - print 'Error finding sfputil class: ' + str(e) - return -1 + return 0 - return 0 - #========== Main =========================================================== # main -if __name__ == '__main__': - port_sfp_data = {} - port = '' - all_ports = 1 - pretty = 1 - oneline = 0 - dump_dom = 0 - dom_check = 0 - raw = 0 - canned_data_file = '' - sfp_objects = {} - port_list = [] - descr = "query sfp information for swp ports" - - if not os.geteuid() == 0: - print 'Error: Must be root to run this command' - exit(1) - - if (len(sys.argv) > 1): - # Parse options - try: - options, remainder = getopt.getopt(sys.argv[1:], - 'p:hdov', - ['port=', 'dom', 'help', - 'dom-check', 'porttab=', 'raw', - 'canned-data=', 'oneline', - 'version']) - except getopt.GetoptError, e: - print e - print usage_help - exit(1) - - for opt, arg in options: - if opt == '--port' or opt == '-p' : - try: - port = arg - except: - print usage_help - exit(1) - - all_ports = 0 - elif opt == '--help' or opt == '-h': - print usage_help - exit(1) - elif opt == '--dom' or opt == '-d': - dump_dom = 1 - elif opt == '--dom-check': - dom_check = 1 - elif opt == '--porttab': - try: - porttabfile = arg - except: - print usage_help - exit(1) - elif opt == '--canned-data': - try: - canned_data_file = arg - except: - print usage_help - exit(1) - elif opt == '--oneline' or opt == '-o': - oneline = 1 - elif opt == '--raw': - raw = 1 - elif opt == '--version' or opt == '-v': - print 'version : ' + version - exit(0) - - - # dom_check is mutually exclusive with all other options - if dom_check == 1 and port != '': - print '--dom-check and --port are mutually exclusive' - print usage_help - exit(1) - - if dom_check == 1: - dump_dom = 1 - - # Init log - log_init() - - # Load platform sfputil class - err = load_platform_sfputil() - if err != 0: - exit(1) - - try: - # csfputil.read_phytab_mappings(phytabfile) - csfputil.read_porttab_mappings(porttabfile) - # csfputil.read_port_mappings() - except Exception, e: - print 'error reading port info (%s)' %str(e) - exit(1) - - if all_ports == 0: - if csfputil.is_valid_sfputil_port(port) == 0: - print 'Error: invalid port' - print - print_valid_values_for_port_cmdoption() - exit(1) - - if all_ports == 0: - port_list = conv_port_to_physical_port_list(port) - if port_list == None: - exit(0) - - # Get all sfp objects - if all_ports == 1: - sfp_objects = get_port_sfp_object_all() - else: - for p in port_list: - sfp_objects.update(get_port_sfp_object(p)) - - if raw == 1: - # Print raw and return - if all_ports == 1: - print_port_sfp_data_raw_all(sfp_objects) - else: - print_port_sfp_data_raw(sfp_objects, port) - exit(0) - - if all_ports == 1: - port_sfp_data = get_port_sfp_data_all(sfp_objects) - else: - for p in port_list: - port_sfp_data.update(get_port_sfp_data( - sfp_objects.get(p), p)) - - # If dom check, Just check dom and return. - if dom_check == 1: - # For testing purposes, if canned data available use it - if canned_data_file != '': - if not os.path.exists(canned_data_file): - print ('Error: Cant find file ' + - canned_data_file) - exit(1) - port_sfp_data = pickle.load(open(canned_data_file, - "rb")) - sfp_dom_data_check(port_sfp_data) - exit(0) - - # Print all sfp data - if oneline == 1: - ifdata_out_blacklist = ['EncodingCodes', - 'ExtIdentOfTypeOfTransceiver', - 'NominalSignallingRate(UnitsOf100Mbd)'] - domdata_out_blacklist = ['AwThresholds', 'StatusControl'] - - if all_ports == 1: - print_port_sfp_data_pretty_oneline_all(port_sfp_data, - ifdata_out_blacklist, - domdata_out_blacklist, - dump_dom) - else: - print_port_sfp_data_pretty_oneline(port_sfp_data, - ifdata_out_blacklist, - domdata_out_blacklist, - port, dump_dom) - elif pretty == 1: - if all_ports == 1: - print_port_sfp_data_pretty_all(port_sfp_data, dump_dom) - else: - print_port_sfp_data_pretty(port_sfp_data, port, - dump_dom) +if __name__ == '__main__': + port_sfp_data = {} + port = '' + all_ports = 1 + pretty = 1 + oneline = 0 + dump_dom = 0 + dom_check = 0 + raw = 0 + canned_data_file = '' + sfp_objects = {} + port_list = [] + descr = "query sfp information for swp ports" + + if not os.geteuid() == 0: + print 'Error: Must be root to run this command' + exit(1) + + if (len(sys.argv) > 1): + # Parse options + try: + options, remainder = getopt.getopt(sys.argv[1:], + 'p:hdov', + ['port=', 'dom', 'help', + 'dom-check', 'porttab=', 'raw', + 'canned-data=', 'oneline', + 'version']) + except getopt.GetoptError, e: + print e + print usage_help + exit(1) + + for opt, arg in options: + if opt == '--port' or opt == '-p' : + try: + port = arg + except: + print usage_help + exit(1) + + all_ports = 0 + elif opt == '--help' or opt == '-h': + print usage_help + exit(1) + elif opt == '--dom' or opt == '-d': + dump_dom = 1 + elif opt == '--dom-check': + dom_check = 1 + elif opt == '--porttab': + try: + porttabfile = arg + except: + print usage_help + exit(1) + elif opt == '--canned-data': + try: + canned_data_file = arg + except: + print usage_help + exit(1) + elif opt == '--oneline' or opt == '-o': + oneline = 1 + elif opt == '--raw': + raw = 1 + elif opt == '--version' or opt == '-v': + print 'version : ' + version + exit(0) + + + # dom_check is mutually exclusive with all other options + if dom_check == 1 and port != '': + print '--dom-check and --port are mutually exclusive' + print usage_help + exit(1) + + if dom_check == 1: + dump_dom = 1 + + # Init log + log_init() + + # Load platform sfputil class + err = load_platform_sfputil() + if err != 0: + exit(1) + + try: + # csfputil.read_phytab_mappings(phytabfile) + csfputil.read_porttab_mappings(porttabfile) + # csfputil.read_port_mappings() + except Exception, e: + print 'error reading port info (%s)' %str(e) + exit(1) + + if all_ports == 0: + if csfputil.is_valid_sfputil_port(port) == 0: + print 'Error: invalid port' + print + print_valid_values_for_port_cmdoption() + exit(1) + + if all_ports == 0: + port_list = conv_port_to_physical_port_list(port) + if port_list == None: + exit(0) + + # Get all sfp objects + if all_ports == 1: + sfp_objects = get_port_sfp_object_all() + else: + for p in port_list: + sfp_objects.update(get_port_sfp_object(p)) + + if raw == 1: + # Print raw and return + if all_ports == 1: + print_port_sfp_data_raw_all(sfp_objects) + else: + print_port_sfp_data_raw(sfp_objects, port) + exit(0) + + if all_ports == 1: + port_sfp_data = get_port_sfp_data_all(sfp_objects) + else: + for p in port_list: + port_sfp_data.update(get_port_sfp_data(sfp_objects.get(p), p)) + + # If dom check, Just check dom and return. + if dom_check == 1: + # For testing purposes, if canned data available use it + if canned_data_file != '': + if not os.path.exists(canned_data_file): + print ('Error: Cant find file ' + canned_data_file) + exit(1) + port_sfp_data = pickle.load(open(canned_data_file, "rb")) + sfp_dom_data_check(port_sfp_data) + exit(0) + + # Print all sfp data + if oneline == 1: + ifdata_out_blacklist = ['EncodingCodes', + 'ExtIdentOfTypeOfTransceiver', + 'NominalSignallingRate(UnitsOf100Mbd)'] + domdata_out_blacklist = ['AwThresholds', 'StatusControl'] + + if all_ports == 1: + print_port_sfp_data_pretty_oneline_all(port_sfp_data, + ifdata_out_blacklist, + domdata_out_blacklist, + dump_dom) + else: + print_port_sfp_data_pretty_oneline(port_sfp_data, + ifdata_out_blacklist, + domdata_out_blacklist, + port, dump_dom) + elif pretty == 1: + if all_ports == 1: + print_port_sfp_data_pretty_all(port_sfp_data, dump_dom) + else: + print_port_sfp_data_pretty(port_sfp_data, port, dump_dom) From d7350ce0023b600b09269b10384d846ff9afd834 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sat, 18 Feb 2017 20:54:24 +0000 Subject: [PATCH 07/13] Restructure utilities - Rename 'show' package to 'sonic-cli' - Create 'sonic-eeprom' Python package to house EEPROM-releated modules in an organized fashion - Create 'sonic-sfp' Python package to house SFP-related modules - All scripts now reference the above packages - sfputilbase.py now correctly parses 2- and 3-column port_config.ini/portmap.ini files --- scripts/decode-syseeprom | 48 +++++++--- scripts/sfputil | 96 +++++++++++-------- setup.py | 19 +--- {show => sonic_cli}/__init__.py | 0 {show => sonic_cli}/aliases.ini | 0 {show => sonic_cli}/main.py | 0 sonic_eeprom/__init__.py | 0 .../eeprom_base.py | 2 +- {dist-packages => sonic_eeprom}/eeprom_dts.py | 0 .../eeprom_tlvinfo.py | 2 +- sonic_sfp/__init__.py | 0 {dist-packages => sonic_sfp}/bcmshell.py | 0 {dist-packages => sonic_sfp}/sff8436.py | 0 {dist-packages => sonic_sfp}/sff8472.py | 0 {dist-packages => sonic_sfp}/sffbase.py | 0 {dist-packages => sonic_sfp}/sfputilbase.py | 35 +++---- 16 files changed, 112 insertions(+), 90 deletions(-) rename {show => sonic_cli}/__init__.py (100%) rename {show => sonic_cli}/aliases.ini (100%) rename {show => sonic_cli}/main.py (100%) create mode 100644 sonic_eeprom/__init__.py rename {dist-packages => sonic_eeprom}/eeprom_base.py (99%) rename {dist-packages => sonic_eeprom}/eeprom_dts.py (100%) rename {dist-packages => sonic_eeprom}/eeprom_tlvinfo.py (99%) create mode 100644 sonic_sfp/__init__.py rename {dist-packages => sonic_sfp}/bcmshell.py (100%) rename {dist-packages => sonic_sfp}/sff8436.py (100%) rename {dist-packages => sonic_sfp}/sff8472.py (100%) rename {dist-packages => sonic_sfp}/sffbase.py (100%) rename {dist-packages => sonic_sfp}/sfputilbase.py (98%) diff --git a/scripts/decode-syseeprom b/scripts/decode-syseeprom index f07055a099..38811be5c1 100755 --- a/scripts/decode-syseeprom +++ b/scripts/decode-syseeprom @@ -15,34 +15,52 @@ try: import sys from array import array import imp - import eeprom_dts + from sonic_eeprom import eeprom_dts import glob except ImportError, e: raise ImportError (str(e) + "- required module not found") -platform_detect = '/usr/bin/platform-detect' -platform_root = '/etc/ssw' +SONIC_CFGGEN = '/usr/bin/sonic-cfggen' +MINIGRAPH_FILE = '/etc/sonic/minigraph.xml' +HWSKU_KEY = 'minigraph_hwsku' +PLATFORM_KEY = 'platform' + +PLATFORM_ROOT = '/usr/share/sonic/device' cache_root = '/var/cache/ssw/decode-syseeprom' +# Returns platform model (platform string) and submodel (HW SKU) +def get_platform(): + try: + proc = subprocess.Popen([SONIC_CFGGEN, '-v', PLATFORM_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + model = stdout.rstrip('\n') + + proc = subprocess.Popen([SONIC_CFGGEN, '-m', MINIGRAPH_FILE, '-v', HWSKU_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + submodel = stdout.rstrip('\n') + except OSError, e: + raise OSError("Cannot detect platform") + + return (model, submodel) + def main(): if not os.geteuid() == 0: raise RuntimeError("must be root to run") - # - # determine the platform - # - try: - ph = subprocess.Popen((platform_detect), stdout=subprocess.PIPE, - shell=False, stderr=subprocess.STDOUT) - cmdout = ph.communicate()[0] - ph.wait() - except OSError, e: - raise OSError("cannot detect platform") + # Get platform details + (model, submodel) = get_platform() - platform = cmdout.rstrip('\n') - platform_path = '/'.join([platform_root, platform]) + platform_path = '/'.join([PLATFORM_ROOT, model, submodel]) # # Currently we only support board eeprom decode. diff --git a/scripts/sfputil b/scripts/sfputil index 418275f8dd..0b1e883452 100755 --- a/scripts/sfputil +++ b/scripts/sfputil @@ -18,9 +18,9 @@ except ImportError, e: raise ImportError (str(e) + "- required module not found") -version = '1.0' +VERSION = '1.0' -usage_help=""" +USAGE_HELP=""" Usage: sfputil [--help] [-p|--port ] [-d|--dom] [-o|--oneline] [-v|--version] @@ -34,6 +34,13 @@ OPTIONS """ +SONIC_CFGGEN = '/usr/bin/sonic-cfggen' +MINIGRAPH_FILE = '/etc/sonic/minigraph.xml' +HWSKU_KEY = 'minigraph_hwsku' +PLATFORM_KEY = 'platform' + +PLATFORM_ROOT = '/usr/share/sonic/device' + csfputil = None sfp_dom_data_cache_dir = '/var/cache/ssw/sfputil' sfp_dom_data_cache_file = sfp_dom_data_cache_dir + '/' + 'sfputil.dat' @@ -41,6 +48,7 @@ porttabfile = None phytabfile = '/var/lib/cumulus/phytab' indent = '\t' + def log_init(): syslog.openlog('sfputil') @@ -118,8 +126,7 @@ def get_port_sfp_data_all(sfp_obj_all): port_end = csfputil.port_end for p in range(port_start, port_end + 1): - port_sfp_data_all.update(get_port_sfp_data(sfp_obj_all.get(p), - p)) + port_sfp_data_all.update(get_port_sfp_data(sfp_obj_all.get(p), p)) return port_sfp_data_all @@ -168,8 +175,8 @@ def print_port_sfp_data_pretty_all(port_sfp_data, dump_dom): print_port_sfp_data_pretty(port_sfp_data, p, dump_dom) -# Recursively print dict elems into coma separated list -def print_dict_comaseparated(indict, elem_blacklist, elemprefix, first): +# Recursively print dict elems into comma separated list +def print_dict_commaseparated(indict, elem_blacklist, elemprefix, first): iter = 0 for elem, elem_val in sorted(indict.iteritems()): if elem in elem_blacklist: @@ -177,8 +184,7 @@ def print_dict_comaseparated(indict, elem_blacklist, elemprefix, first): if type(elem_val) == types.DictType: if iter != 0: print ',', - print_dict_comaseparated(elem_val, elem_blacklist, - elem, first) + print_dict_commaseparated(elem_val, elem_blacklist, elem, first) else: elemname = elemprefix + elem if first == 1: @@ -209,14 +215,13 @@ def print_port_sfp_data_pretty_oneline(port_sfp_data, sfp_idata = sfp_data.get('interface') idata = sfp_idata.get('data') print 'port:' + port_name + ',', - print_dict_comaseparated(idata, ifdata_blacklist, '', 1) + print_dict_commaseparated(idata, ifdata_blacklist, '', 1) if dump_dom == 1: sfp_ddata = sfp_data.get('dom') if sfp_ddata != None: ddata = sfp_ddata.get('data') if ddata != None: - print_dict_comaseparated(ddata, - domdata_blacklist, '',1) + print_dict_commaseparated(ddata, domdata_blacklist, '', 1) print #Only print detected sfp ports for oneline #else: @@ -517,8 +522,7 @@ def sfp_dom_data_check(ports_sfp_data): # Dump new dom data into cached file try: - pickle.dump(ports_sfp_data, open(sfp_dom_data_cache_file, - "wb")) + pickle.dump(ports_sfp_data, open(sfp_dom_data_cache_file, "wb")) except pickle.PickleError, e: print 'Error pickling dom data ' + str(e) return @@ -528,45 +532,52 @@ def sfp_dom_data_check(ports_sfp_data): #=========== Functions to load platform specific classes ==================== -# Returns platform vendor and model +# Returns platform model (platform string) and submodel (HW SKU) def get_platform(): try: - platform_detect = '/usr/bin/platform-detect' - - ph = subprocess.Popen((platform_detect), stdout=subprocess.PIPE, - shell=False, stderr=subprocess.STDOUT) - cmdout = ph.communicate()[0] - ph.wait() + proc = subprocess.Popen([SONIC_CFGGEN, '-v', PLATFORM_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + model = stdout.rstrip('\n') + + proc = subprocess.Popen([SONIC_CFGGEN, '-m', MINIGRAPH_FILE, '-v', HWSKU_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + submodel = stdout.rstrip('\n') except OSError, e: - raise OSError("cannot detect platform") + raise OSError("Cannot detect platform") - return cmdout.rstrip('\n') + return (model, submodel) # Loads platform specific sfputil module from source def load_platform_sfputil(): global csfputil global porttabfile - platform_root = '/etc/ssw/' module_name = 'sfputil' - # Get platform details - model = get_platform() + (model, submodel) = get_platform() - #Load platform module from source - platform_sfputil_module_path = '/'.join([platform_root, model, 'bin']) + # Load platform module from source + platform_path = '/'.join([PLATFORM_ROOT, model, submodel]) # First check for the presence of the new 'port_config.ini' file - porttabfile = '/'.join([platform_root, model, 'port_config.ini']) + porttabfile = '/'.join([platform_path, 'port_config.ini']) if not os.path.isfile(porttabfile): # port_config.ini doesn't exist. Try loading the older 'portmap.ini' file - porttabfile = '/'.join([platform_root, model, 'portmap.ini']) + porttabfile = '/'.join([platform_path, 'portmap.ini']) try: - module = imp.load_source(module_name, - '/'.join([platform_sfputil_module_path, - module_name + '.py'])) + module_full_name = module_name + module_file = '/'.join([platform_path, 'bin', module_full_name + '.py']) + module = imp.load_source(module_name, module_file) except IOError, e: print 'Error loading platform module ' + module_name + str(e) return None @@ -583,7 +594,7 @@ def load_platform_sfputil(): #========== Main =========================================================== # main -if __name__ == '__main__': +def main(): port_sfp_data = {} port = '' all_ports = 1 @@ -612,7 +623,7 @@ if __name__ == '__main__': 'version']) except getopt.GetoptError, e: print e - print usage_help + print USAGE_HELP exit(1) for opt, arg in options: @@ -620,12 +631,12 @@ if __name__ == '__main__': try: port = arg except: - print usage_help + print USAGE_HELP exit(1) all_ports = 0 elif opt == '--help' or opt == '-h': - print usage_help + print USAGE_HELP exit(1) elif opt == '--dom' or opt == '-d': dump_dom = 1 @@ -633,29 +644,30 @@ if __name__ == '__main__': dom_check = 1 elif opt == '--porttab': try: + global porttabfile porttabfile = arg except: - print usage_help + print USAGE_HELP exit(1) elif opt == '--canned-data': try: canned_data_file = arg except: - print usage_help + print USAGE_HELP exit(1) elif opt == '--oneline' or opt == '-o': oneline = 1 elif opt == '--raw': raw = 1 elif opt == '--version' or opt == '-v': - print 'version : ' + version + print 'version : ' + VERSION exit(0) # dom_check is mutually exclusive with all other options if dom_check == 1 and port != '': print '--dom-check and --port are mutually exclusive' - print usage_help + print USAGE_HELP exit(1) if dom_check == 1: @@ -743,3 +755,7 @@ if __name__ == '__main__': print_port_sfp_data_pretty_all(port_sfp_data, dump_dom) else: print_port_sfp_data_pretty(port_sfp_data, port, dump_dom) + + +if __name__ == '__main__': + main() diff --git a/setup.py b/setup.py index 40804e0ff7..8d856d358b 100644 --- a/setup.py +++ b/setup.py @@ -10,9 +10,9 @@ url='https://github.com/Azure/sonic-utilities', maintainer='Joe LeVeque', maintainer_email='jolevequ@microsoft.com', - packages=['show'], + packages=['sonic_cli', 'sonic_eeprom', 'sonic_sfp'], package_data={ - 'show': ['aliases.ini'] + 'sonic_cli': ['aliases.ini'] }, scripts=[ 'scripts/boot_part', @@ -22,22 +22,9 @@ 'scripts/portstat', 'scripts/sfputil', ], - data_files=[ - ('/usr/lib/python2.7/dist-packages', [ - 'dist-packages/bcmshell.py', - 'dist-packages/eeprom_base.py', - 'dist-packages/eeprom_dts.py', - 'dist-packages/eeprom_tlvinfo.py', - 'dist-packages/sff8436.py', - 'dist-packages/sff8472.py', - 'dist-packages/sffbase.py', - 'dist-packages/sfputilbase.py' - ] - ), - ], entry_points={ 'console_scripts': [ - 'show = show.main:cli', + 'show = sonic_cli.main:cli', ] }, classifiers=[ diff --git a/show/__init__.py b/sonic_cli/__init__.py similarity index 100% rename from show/__init__.py rename to sonic_cli/__init__.py diff --git a/show/aliases.ini b/sonic_cli/aliases.ini similarity index 100% rename from show/aliases.ini rename to sonic_cli/aliases.ini diff --git a/show/main.py b/sonic_cli/main.py similarity index 100% rename from show/main.py rename to sonic_cli/main.py diff --git a/sonic_eeprom/__init__.py b/sonic_eeprom/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dist-packages/eeprom_base.py b/sonic_eeprom/eeprom_base.py similarity index 99% rename from dist-packages/eeprom_base.py rename to sonic_eeprom/eeprom_base.py index d7e4de667c..c41ea5967d 100644 --- a/dist-packages/eeprom_base.py +++ b/sonic_eeprom/eeprom_base.py @@ -23,7 +23,7 @@ raise ImportError (str(e) + "- required module not found") -class eepromDecoder(object): +class EepromDecoder(object): def __init__(self, path, format, start, status, readonly): self.p = path self.f = format diff --git a/dist-packages/eeprom_dts.py b/sonic_eeprom/eeprom_dts.py similarity index 100% rename from dist-packages/eeprom_dts.py rename to sonic_eeprom/eeprom_dts.py diff --git a/dist-packages/eeprom_tlvinfo.py b/sonic_eeprom/eeprom_tlvinfo.py similarity index 99% rename from dist-packages/eeprom_tlvinfo.py rename to sonic_eeprom/eeprom_tlvinfo.py index f631670451..ca4b073be0 100644 --- a/dist-packages/eeprom_tlvinfo.py +++ b/sonic_eeprom/eeprom_tlvinfo.py @@ -25,7 +25,7 @@ # and can be found here: # # -class TlvInfoDecoder(eeprom_base.eepromDecoder): +class TlvInfoDecoder(eeprom_base.EepromDecoder): # Header Field Constants _TLV_INFO_ID_STRING = "TlvInfo\x00" diff --git a/sonic_sfp/__init__.py b/sonic_sfp/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dist-packages/bcmshell.py b/sonic_sfp/bcmshell.py similarity index 100% rename from dist-packages/bcmshell.py rename to sonic_sfp/bcmshell.py diff --git a/dist-packages/sff8436.py b/sonic_sfp/sff8436.py similarity index 100% rename from dist-packages/sff8436.py rename to sonic_sfp/sff8436.py diff --git a/dist-packages/sff8472.py b/sonic_sfp/sff8472.py similarity index 100% rename from dist-packages/sff8472.py rename to sonic_sfp/sff8472.py diff --git a/dist-packages/sffbase.py b/sonic_sfp/sffbase.py similarity index 100% rename from dist-packages/sffbase.py rename to sonic_sfp/sffbase.py diff --git a/dist-packages/sfputilbase.py b/sonic_sfp/sfputilbase.py similarity index 98% rename from dist-packages/sfputilbase.py rename to sonic_sfp/sfputilbase.py index bd0b37a9b6..e7c5bfb3a4 100644 --- a/dist-packages/sfputilbase.py +++ b/sonic_sfp/sfputilbase.py @@ -5,22 +5,22 @@ # #-------------------------------------------------------------------------- try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import re - import bcmshell - import pprint - import eeprom_dts - from math import log10 - from sff8472 import sff8472InterfaceId - from sff8472 import sff8472Dom - from sff8436 import sff8436InterfaceId - from sff8436 import sff8436Dom + import fcntl + import struct + import sys + import time + import binascii + import os + import getopt + import re + import bcmshell + import pprint + from math import log10 + from sonic_eeprom import eeprom_dts + from sff8472 import sff8472InterfaceId + from sff8472 import sff8472Dom + from sff8436 import sff8436InterfaceId + from sff8436 import sff8436Dom except ImportError, e: raise ImportError (str(e) + "- required module not found") @@ -338,7 +338,8 @@ def read_porttab_mappings(cls, porttabfile): line.strip() if re.search('^#', line) != None: continue - (logical_port, bcm_port) = line.split('=')[1].split(',')[:2] + logical_port = line.split()[0] + bcm_port = line.split()[1].split(',')[0] physical_port = logical_port.split('Ethernet').pop() physical_port = int(physical_port.split('s').pop(0))/4 From 61322b5fedaf3f46213e4f7b1f345e243e8ab2c6 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Mon, 20 Feb 2017 01:12:27 +0000 Subject: [PATCH 08/13] Re-add ThirdPartyLicenses.txt --- ThirdPartyLicenses.txt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 ThirdPartyLicenses.txt diff --git a/ThirdPartyLicenses.txt b/ThirdPartyLicenses.txt new file mode 100644 index 0000000000..ce49efdded --- /dev/null +++ b/ThirdPartyLicenses.txt @@ -0,0 +1,31 @@ +Third Party Notices + +This Microsoft Open Source project incorporates material from the project(s) listed below +(Third Party Code). Microsoft is not the original author of the Third Party Code. Microsoft +reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. + +1. scripts/sfputil https://cumulusnetworks.com +2. sonic_eeprom/eeprom_base.py https://cumulusnetworks.com +3. sonic_eeprom/eeprom_fts.py https://cumulusnetworks.com +4. sonic_eepromeeprom_tlvinfo.py https://cumulusnetworks.com +5. sonic_sfp/bcmshell.py https://cumulusnetworks.com +6. sonic_sfp/sff8472.py https://cumulusnetworks.com +7. sonic_sfp/sfputilbase.py https://cumulusnetworks.com + + ++ * Copyright (C) 2014 Cumulus Networks, LLC ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." + From 5aa8b066ebbf6aaaa1a01c6631c0530adc933901 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 22 Feb 2017 01:18:10 +0000 Subject: [PATCH 09/13] Add 'portchannel' subcommand of interfaces; call teamshow --- sonic_cli/main.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sonic_cli/main.py b/sonic_cli/main.py index 9568feed6f..6d14b22cc6 100644 --- a/sonic_cli/main.py +++ b/sonic_cli/main.py @@ -160,6 +160,12 @@ def counters(): """Show interface counters""" run_command("portstat", pager=True) +# 'portchannel' subcommand +@interfaces.command() +def portchannel(): + """Show PortChannel information""" + run_command("teamshow", pager=True) + # # 'lldp' group #### From 06619a6b74ccc05c90e4c278735e870ffdd2b77b Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 22 Feb 2017 18:41:41 +0000 Subject: [PATCH 10/13] Rename 'model' to 'platform' and 'submodel' to 'hwsku' --- scripts/decode-syseeprom | 12 ++++++------ scripts/sfputil | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/decode-syseeprom b/scripts/decode-syseeprom index 38811be5c1..4ca4ee67f5 100755 --- a/scripts/decode-syseeprom +++ b/scripts/decode-syseeprom @@ -29,7 +29,7 @@ PLATFORM_KEY = 'platform' PLATFORM_ROOT = '/usr/share/sonic/device' cache_root = '/var/cache/ssw/decode-syseeprom' -# Returns platform model (platform string) and submodel (HW SKU) +# Returns platform and HW SKU def get_platform(): try: proc = subprocess.Popen([SONIC_CFGGEN, '-v', PLATFORM_KEY], @@ -38,7 +38,7 @@ def get_platform(): stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() - model = stdout.rstrip('\n') + platform = stdout.rstrip('\n') proc = subprocess.Popen([SONIC_CFGGEN, '-m', MINIGRAPH_FILE, '-v', HWSKU_KEY], stdout=subprocess.PIPE, @@ -46,11 +46,11 @@ def get_platform(): stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() - submodel = stdout.rstrip('\n') + hwsku = stdout.rstrip('\n') except OSError, e: raise OSError("Cannot detect platform") - return (model, submodel) + return (platform, hwsku) def main(): @@ -58,9 +58,9 @@ def main(): raise RuntimeError("must be root to run") # Get platform details - (model, submodel) = get_platform() + (platform, hwsku) = get_platform() - platform_path = '/'.join([PLATFORM_ROOT, model, submodel]) + platform_path = '/'.join([PLATFORM_ROOT, platform, hwsku]) # # Currently we only support board eeprom decode. diff --git a/scripts/sfputil b/scripts/sfputil index 0b1e883452..1f0858b998 100755 --- a/scripts/sfputil +++ b/scripts/sfputil @@ -532,7 +532,7 @@ def sfp_dom_data_check(ports_sfp_data): #=========== Functions to load platform specific classes ==================== -# Returns platform model (platform string) and submodel (HW SKU) +# Returns platform and HW SKU def get_platform(): try: proc = subprocess.Popen([SONIC_CFGGEN, '-v', PLATFORM_KEY], @@ -541,7 +541,7 @@ def get_platform(): stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() - model = stdout.rstrip('\n') + platform = stdout.rstrip('\n') proc = subprocess.Popen([SONIC_CFGGEN, '-m', MINIGRAPH_FILE, '-v', HWSKU_KEY], stdout=subprocess.PIPE, @@ -549,11 +549,11 @@ def get_platform(): stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() - submodel = stdout.rstrip('\n') + hwsku = stdout.rstrip('\n') except OSError, e: raise OSError("Cannot detect platform") - return (model, submodel) + return (platform, hwsku) # Loads platform specific sfputil module from source @@ -563,10 +563,10 @@ def load_platform_sfputil(): module_name = 'sfputil' # Get platform details - (model, submodel) = get_platform() + (platform, hwsku) = get_platform() # Load platform module from source - platform_path = '/'.join([PLATFORM_ROOT, model, submodel]) + platform_path = '/'.join([PLATFORM_ROOT, platform, hwsku]) # First check for the presence of the new 'port_config.ini' file porttabfile = '/'.join([platform_path, 'port_config.ini']) From 05b0c7d259f77751d5f0cd252f8aa7e971718cd6 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 22 Feb 2017 18:48:23 +0000 Subject: [PATCH 11/13] Define paths to executables at top of file --- scripts/portstat | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/portstat b/scripts/portstat index a6c5e7244d..13395af9ac 100755 --- a/scripts/portstat +++ b/scripts/portstat @@ -19,6 +19,10 @@ import sys from collections import namedtuple, OrderedDict from tabulate import tabulate +BCMCMD_PATH = "/usr/bin/bcmcmd" +NETSTAT_PATH = "/bin/netstat" +CAT_PATH = "/bin/cat" + PORT_RATE = 40 NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\ @@ -309,7 +313,7 @@ Examples: sys.exit(0) try: - bcmcmd_output = subprocess.Popen((['/usr/bin/bcmcmd', + bcmcmd_output = subprocess.Popen(([BCMCMD_PATH, 'show counters changed same nz']), stdout=subprocess.PIPE, shell=False).communicate()[0] @@ -320,7 +324,7 @@ Examples: bcm_dict = parse_bcmcmd_output(bcmcmd_output) try: - netstat_out = subprocess.Popen((['/bin/netstat', '-i']), + netstat_out = subprocess.Popen(([NETSTAT_PATH, '-i']), stdout=subprocess.PIPE, shell=False).communicate()[0] except EnvironmentError as e: @@ -332,7 +336,7 @@ Examples: # Since netstat -i returns some stats as 32-bits, get full 64-bit # stats from /prov/net/dev and display only the 64-bit stats. try: - proc_out = subprocess.Popen((['/bin/cat', '/proc/net/dev']), + proc_out = subprocess.Popen(([CAT_PATH, '/proc/net/dev']), stdout=subprocess.PIPE, shell=False).communicate()[0] except EnvironmentError as e: From 7314da86d5862b09b635feeaf1deaa6ca76ee1ee Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 22 Feb 2017 18:54:06 +0000 Subject: [PATCH 12/13] Remove 'ssw' directory; all device-specific files now reside in sonic-buildimage --- ssw/ACS-MSN2700/bin/eeprom.py | 33 --------- ssw/ACS-MSN2700/bin/sfputil.py | 28 -------- ssw/ACS-S6000/bin/eeprom.py | 124 --------------------------------- ssw/ACS-S6000/bin/sfputil.py | 27 ------- 4 files changed, 212 deletions(-) delete mode 100644 ssw/ACS-MSN2700/bin/eeprom.py delete mode 100644 ssw/ACS-MSN2700/bin/sfputil.py delete mode 100644 ssw/ACS-S6000/bin/eeprom.py delete mode 100644 ssw/ACS-S6000/bin/sfputil.py diff --git a/ssw/ACS-MSN2700/bin/eeprom.py b/ssw/ACS-MSN2700/bin/eeprom.py deleted file mode 100644 index a9e22e3e69..0000000000 --- a/ssw/ACS-MSN2700/bin/eeprom.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python - -############################################################################# -# Mellanox -# -# Platform and model specific eeprom subclass, inherits from the base class, -# and provides the followings: -# - the eeprom format definition -# - specific encoder/decoder if there is special need -############################################################################# - -try: - import exceptions - import binascii - import time - import optparse - import warnings - import os - import sys - import eeprom_base - import eeprom_tlvinfo - import subprocess -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - -class board(eeprom_tlvinfo.TlvInfoDecoder): - - _TLV_INFO_MAX_LEN = 256 - - def __init__(self, name, path, cpld_root, ro): - self.eeprom_path = "/bsp/eeprom/sys_eeprom" - super(board, self).__init__(self.eeprom_path, 0, '', True) - diff --git a/ssw/ACS-MSN2700/bin/sfputil.py b/ssw/ACS-MSN2700/bin/sfputil.py deleted file mode 100644 index bfe2086db7..0000000000 --- a/ssw/ACS-MSN2700/bin/sfputil.py +++ /dev/null @@ -1,28 +0,0 @@ -#! /usr/bin/python - -try: - from sfputilbase import sfputilbase -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - - -class sfputil(sfputilbase): - """Platform specific sfputil class""" - - port_start = 0 - port_end = 31 - ports_in_block = 32 - - eeprom_offset = 1 - - port_to_eeprom_mapping = {} - - _qsfp_ports = range(0, ports_in_block + 1) - - def __init__(self, port_num): - # Override port_to_eeprom_mapping for class initialization - eeprom_path = '/bsp/qsfp/qsfp{0}' - for x in range(0, self.port_end + 1): - self.port_to_eeprom_mapping[x] = eeprom_path.format(x + self.eeprom_offset) - sfputilbase.__init__(self, port_num) - diff --git a/ssw/ACS-S6000/bin/eeprom.py b/ssw/ACS-S6000/bin/eeprom.py deleted file mode 100644 index 2d2b991db7..0000000000 --- a/ssw/ACS-S6000/bin/eeprom.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python - -############################################################################# -# Dell S6000 -# -# Platform and model specific eeprom subclass, inherits from the base class, -# and provides the followings: -# - the eeprom format definition -# - specific encoder/decoder if there is special need -############################################################################# - -try: - import exceptions - import binascii - import time - import optparse - import warnings - import os - import sys - import eeprom_base - import eeprom_tlvinfo - import subprocess -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - - -class board(eeprom_tlvinfo.TlvInfoDecoder): - _TLV_INFO_MAX_LEN = 128 - _TLV_HDR_ENABLED = 0 - - _TLV_BLOCK_NUMBER = 3 - _TLV_BLOCK_HDR_STRING = "\x3a\x29" - - _TLV_CODE_MFG = 0x20 - _TLV_CODE_SW = 0x1f - _TLV_CODE_MAC = 0x21 - - def __init__(self, name, path, cpld_root, ro): - self.eeprom_path = "/sys/class/i2c-adapter/i2c-10/10-0053/eeprom" - super(board, self).__init__(self.eeprom_path, 0, '', True) - - def decode_eeprom(self, e): - tlv_block_index = 0 - tlv_index = self.eeprom_start - tlv_end = self._TLV_INFO_MAX_LEN - - print "TLV Name Len Value" - print "-------------------- --- -----" - while tlv_block_index < self._TLV_BLOCK_NUMBER: - if not self.is_valid_block(e[tlv_index:]): - print "Invalid TLV field starting at EEPROM offset %d" % (tlv_index,) - return - print self.decoder(None, e[tlv_index:tlv_index + ord(e[tlv_index+2])]) - if not self.is_valid_block_checksum(e[tlv_index:tlv_index + ord(e[tlv_index+2])]): - print "(*** checksum invalid)" - tlv_index += ord(e[tlv_index+2]) - tlv_block_index += 1 - - def is_valid_block(self, e): - return (len(e) >= 8 and ord(e[2]) <= len(e) and \ - e[0:2] == self._TLV_BLOCK_HDR_STRING) - - def is_valid_block_checksum(self, e): - crc = self.compute_dell_crc(e[:-2]) - tlv_crc = ord(e[-1]) << 8 | ord(e[-2]) - return crc == tlv_crc - - def decoder(self, s, t): - ret = "" - if ord(t[4]) == self._TLV_CODE_MFG: - name = "PPID" - value = t[6:8] + "-" + t[8:14] + "-" + t[14:19] + "-" + \ - t[19:22] + "-" + t[22:26] - ret += "%-20s %3d %s\n" % (name, 20, value) - name = "DPN Rev" - ret += "%-20s %3d %s\n" % (name, 3, t[26:29]) - name = "Service Tag" - ret += "%-20s %3d %s\n" % (name, 7, t[29:36]) - name = "Part Number" - ret += "%-20s %3d %s\n" % (name, 10, t[36:46]) - name = "Part Number Rev" - ret += "%-20s %3d %s\n" % (name, 3, t[46:49]) - name = "Mfg Test Results" - ret += "%-20s %3d %s" % (name, 2, t[49:51]) - if ord(t[4]) == self._TLV_CODE_SW: - name = "Card ID" - ret += "%-20s %3d 0x%s\n" % (name, 2, t[6:8].encode('hex')) - name = "Module ID" - ret += "%-20s %3d %s" % (name, 2, ord(t[8:9])) - if ord(t[4]) == self._TLV_CODE_MAC: - name = "Base MAC Address" - value = ":".join([binascii.b2a_hex(T) for T in t[6:12]]).upper() - ret += "%-20s %3d %s" % (name, 12, value) - return ret - - def is_checksum_valid(self, e): - # Checksum is already calculated before - return (True, 0) - - def get_tlv_index(self, e, code): - tlv_index = 0 - while tlv_index < len(e): - if not self.is_valid_block(e[tlv_index:]): - return (False, 0) - if ord(e[tlv_index+4]) == code: - if not self.is_valid_block_checksum(e[tlv_index:tlv_index + ord(e[tlv_index+2])]): - print "(*** checksum invalid)" - return (True, tlv_index) - tlv_index += ord(e[tlv_index+2]) - return (Flase, 0) - - def base_mac_addr(self, e): - (is_valid, t) = self.get_tlv_index(e, self._TLV_CODE_MAC) - if not is_valid: - return "Bad base MAC address" - return ":".join([binascii.b2a_hex(T) for T in e[t:][6:12]]).upper() - - def serial_number_str(self, e): - ''' Return Service Tag ''' - (is_valid, t) = self.get_tlv_index(e, self._TLV_CODE_MFG) - if not is_valid: - return "Bad service tag" - t = e[t:] - return t[29:36] diff --git a/ssw/ACS-S6000/bin/sfputil.py b/ssw/ACS-S6000/bin/sfputil.py deleted file mode 100644 index 7b2e6fd345..0000000000 --- a/ssw/ACS-S6000/bin/sfputil.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python - -try: - from sfputilbase import sfputilbase -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - - -class sfputil(sfputilbase): - """Platform specific sfputil class""" - - port_start = 0 - port_end = 31 - ports_in_block = 32 - - eeprom_offset = 20 - - port_to_eeprom_mapping = {} - - _qsfp_ports = range(0, ports_in_block + 1) - - def __init__(self, port_num): - # Override port_to_eeprom_mapping for class initialization - eeprom_path = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom' - for x in range(0, self.port_end + 1): - self.port_to_eeprom_mapping[x] = eeprom_path.format(x + self.eeprom_offset) - sfputilbase.__init__(self, port_num) From b56584c7549880797950627d324ec18bb79675a6 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 23 Feb 2017 22:12:27 +0000 Subject: [PATCH 13/13] Reference eeprom.py and sfputil.py at new /plugins/ path --- scripts/decode-syseeprom | 23 +++++++---------------- scripts/sfputil | 15 ++++++++------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/scripts/decode-syseeprom b/scripts/decode-syseeprom index 4ca4ee67f5..15c1b93e9e 100755 --- a/scripts/decode-syseeprom +++ b/scripts/decode-syseeprom @@ -22,11 +22,10 @@ except ImportError, e: SONIC_CFGGEN = '/usr/bin/sonic-cfggen' -MINIGRAPH_FILE = '/etc/sonic/minigraph.xml' -HWSKU_KEY = 'minigraph_hwsku' PLATFORM_KEY = 'platform' PLATFORM_ROOT = '/usr/share/sonic/device' + cache_root = '/var/cache/ssw/decode-syseeprom' # Returns platform and HW SKU @@ -39,28 +38,20 @@ def get_platform(): stdout = proc.communicate()[0] proc.wait() platform = stdout.rstrip('\n') - - proc = subprocess.Popen([SONIC_CFGGEN, '-m', MINIGRAPH_FILE, '-v', HWSKU_KEY], - stdout=subprocess.PIPE, - shell=False, - stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - hwsku = stdout.rstrip('\n') except OSError, e: raise OSError("Cannot detect platform") - return (platform, hwsku) + return platform def main(): if not os.geteuid() == 0: raise RuntimeError("must be root to run") - # Get platform details - (platform, hwsku) = get_platform() + # Get platform name + platform = get_platform() - platform_path = '/'.join([PLATFORM_ROOT, platform, hwsku]) + platform_path = '/'.join([PLATFORM_ROOT, platform]) # # Currently we only support board eeprom decode. @@ -71,9 +62,9 @@ def main(): # load the target class file and instantiate the object # try: - m = imp.load_source('eeprom','/'.join([platform_path, 'bin/eeprom.py'])) + m = imp.load_source('eeprom','/'.join([platform_path, 'plugins', 'eeprom.py'])) except IOError: - raise IOError("cannot load module: " + '/'.join([platform_path, 'bin/eeprom.py'])) + raise IOError("cannot load module: " + '/'.join([platform_path, 'plugins', 'eeprom.py'])) class_ = getattr(m, 'board') t = class_('board', '','','') diff --git a/scripts/sfputil b/scripts/sfputil index 1f0858b998..8a350adaf8 100755 --- a/scripts/sfputil +++ b/scripts/sfputil @@ -533,7 +533,7 @@ def sfp_dom_data_check(ports_sfp_data): #=========== Functions to load platform specific classes ==================== # Returns platform and HW SKU -def get_platform(): +def get_platform_and_hwsku(): try: proc = subprocess.Popen([SONIC_CFGGEN, '-v', PLATFORM_KEY], stdout=subprocess.PIPE, @@ -562,21 +562,22 @@ def load_platform_sfputil(): global porttabfile module_name = 'sfputil' - # Get platform details - (platform, hwsku) = get_platform() + # Get platform and hwsku + (platform, hwsku) = get_platform_and_hwsku() # Load platform module from source - platform_path = '/'.join([PLATFORM_ROOT, platform, hwsku]) + platform_path = '/'.join([PLATFORM_ROOT, platform]) + hwsku_path = '/'.join([platform_path, hwsku]) # First check for the presence of the new 'port_config.ini' file - porttabfile = '/'.join([platform_path, 'port_config.ini']) + porttabfile = '/'.join([hwsku_path, 'port_config.ini']) if not os.path.isfile(porttabfile): # port_config.ini doesn't exist. Try loading the older 'portmap.ini' file - porttabfile = '/'.join([platform_path, 'portmap.ini']) + porttabfile = '/'.join([hwsku_path, 'portmap.ini']) try: module_full_name = module_name - module_file = '/'.join([platform_path, 'bin', module_full_name + '.py']) + module_file = '/'.join([platform_path, 'plugins', module_full_name + '.py']) module = imp.load_source(module_name, module_file) except IOError, e: print 'Error loading platform module ' + module_name + str(e)