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 index 2414f0d751..ce49efdded 100644 --- a/ThirdPartyLicenses.txt +++ b/ThirdPartyLicenses.txt @@ -4,13 +4,13 @@ This Microsoft Open Source project incorporates material from the project(s) lis (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 +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 diff --git a/bin/sfputil b/bin/sfputil deleted file mode 100755 index a7235b9386..0000000000 --- a/bin/sfputil +++ /dev/null @@ -1,746 +0,0 @@ -#! /usr/bin/python -#-------------------------------------------------------------------------- -# -# Copyright 2012 Cumulus Networks, inc all rights reserved -# -#-------------------------------------------------------------------------- -try: - 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") - - -version = '1.0' - -usage_help=""" -Usage: sfputil [--help] [-p|--port ] [-d|--dom] [-o|--oneline] - [-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 - -""" - - -csfputil = None -sfp_dom_data_cache_dir = '/var/cache/ssw/sfputil' -sfp_dom_data_cache_file = sfp_dom_data_cache_dir + '/' + 'sfputil.dat' -porttabfile = None -phytabfile = '/var/lib/cumulus/phytab' -indent = '\t' - -def log_init(): - syslog.openlog('sfputil') - -def log_syslog(logmsg): - syslog.syslog(syslog.LOG_INFO, logmsg) - -def inc_indent(): - global indent - indent += '\t' - -def dec_indent(): - 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' - -# Returns, -# 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 - - 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)] - -def print_valid_values_for_port_cmdoption(): - 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) - - 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' : {}}}}}""" - - 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)) - - 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 - -# 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 - -# 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) - - -# 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 - - -# 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 - - -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) - -def get_port_sfp_object(port_num): - sfp_obj = {} - sfp_obj[port_num] = csfputil(int(port_num)) - - 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 - - for p in range(port_start, port_end + 1): - port_sfp_object_all.update(get_port_sfp_object(p)) - - 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 - -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 - -def print_port_sfp_data_raw_all(sfp_obj_all): - 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) - - 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 - - -# 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) - - - -# 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) - - 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]) - - - -# 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 - - -# 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() - - # 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) - - 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) - - - - # 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 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") - - 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' - - - # Get platform details - model = get_platform() - - #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: - csfputil = getattr(module, 'sfputil') - except AttributeError, e: - print 'Error finding sfputil class: ' + str(e) - return -1 - - 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) 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/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 $@ 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 80% rename from bin/decode-syseeprom rename to scripts/decode-syseeprom index 675f0c54ff..15c1b93e9e 100755 --- a/bin/decode-syseeprom +++ b/scripts/decode-syseeprom @@ -1,4 +1,4 @@ -#! /usr/bin/python +#!/usr/bin/env python ############################################################################# # @@ -15,34 +15,43 @@ 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' +PLATFORM_KEY = 'platform' + +PLATFORM_ROOT = '/usr/share/sonic/device' + cache_root = '/var/cache/ssw/decode-syseeprom' +# Returns platform and 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() + platform = stdout.rstrip('\n') + except OSError, e: + raise OSError("Cannot detect platform") + + return platform + 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 name + platform = get_platform() - platform = cmdout.rstrip('\n') - platform_path = '/'.join([platform_root, platform]) + platform_path = '/'.join([PLATFORM_ROOT, platform]) # # Currently we only support board eeprom decode. @@ -53,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', '','','') @@ -121,15 +130,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) 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 95% rename from bin/portstat rename to scripts/portstat index e24650e2a7..13395af9ac 100755 --- a/bin/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,\ @@ -66,7 +70,6 @@ filter_bucket_dict = { 'RFCR': 1, 'RJBR': 1, 'RDBGC0': 2, - 'RDBGC2': 2, 'DROP_PKT_ING': 2, 'ROVR': 3, 'TPKT': 4, @@ -310,7 +313,7 @@ Examples: sys.exit(0) try: - bcmcmd_output = subprocess.Popen((['/usr/sbin/bcmcmd', + bcmcmd_output = subprocess.Popen(([BCMCMD_PATH, 'show counters changed same nz']), stdout=subprocess.PIPE, shell=False).communicate()[0] @@ -321,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: @@ -333,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: @@ -365,9 +368,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]])) diff --git a/scripts/sfputil b/scripts/sfputil new file mode 100755 index 0000000000..8a350adaf8 --- /dev/null +++ b/scripts/sfputil @@ -0,0 +1,762 @@ +#! /usr/bin/python +#-------------------------------------------------------------------------- +# +# Copyright 2012 Cumulus Networks, inc all rights reserved +# +#-------------------------------------------------------------------------- +try: + 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") + + +VERSION = '1.0' + +USAGE_HELP=""" +Usage: sfputil [--help] [-p|--port ] [-d|--dom] [-o|--oneline] + [-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 + +""" + + +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' +porttabfile = None +phytabfile = '/var/lib/cumulus/phytab' +indent = '\t' + + +def log_init(): + syslog.openlog('sfputil') + +def log_syslog(logmsg): + syslog.syslog(syslog.LOG_INFO, logmsg) + +def inc_indent(): + global indent + indent += '\t' + +def dec_indent(): + 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' + +# Returns, +# 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 + + 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)] + +def print_valid_values_for_port_cmdoption(): + 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) + + 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' : {}}}}}""" + + 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)) + + 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 + +# 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 + +# 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) + + +# 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: + continue + if type(elem_val) == types.DictType: + if iter != 0: + print ',', + print_dict_commaseparated(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_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_commaseparated(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) + +def get_port_sfp_object(port_num): + sfp_obj = {} + sfp_obj[port_num] = csfputil(int(port_num)) + + 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 + + for p in range(port_start, port_end + 1): + port_sfp_object_all.update(get_port_sfp_object(p)) + + 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 + +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 + +def print_port_sfp_data_raw_all(sfp_obj_all): + 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) + + 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 + + +# 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) + + + +# 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) + + 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]) + + +# 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 + + +# 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() + + # 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) + + 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) + + + + # 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 + + +#=========== Functions to load platform specific classes ==================== + +# Returns platform and HW SKU +def get_platform_and_hwsku(): + try: + proc = subprocess.Popen([SONIC_CFGGEN, '-v', PLATFORM_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + 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) + + +# Loads platform specific sfputil module from source +def load_platform_sfputil(): + global csfputil + global porttabfile + module_name = 'sfputil' + + # Get platform and hwsku + (platform, hwsku) = get_platform_and_hwsku() + + # Load platform module from source + 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([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([hwsku_path, 'portmap.ini']) + + try: + module_full_name = module_name + 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) + return None + + try: + csfputil = getattr(module, 'sfputil') + except AttributeError, e: + print 'Error finding sfputil class: ' + str(e) + return -1 + + return 0 + + +#========== Main =========================================================== + +# main +def 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: + global porttabfile + 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__': + main() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000..8d856d358b --- /dev/null +++ b/setup.py @@ -0,0 +1,43 @@ +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=['sonic_cli', 'sonic_eeprom', 'sonic_sfp'], + package_data={ + 'sonic_cli': ['aliases.ini'] + }, + scripts=[ + 'scripts/boot_part', + 'scripts/coredump-compress', + 'scripts/decode-syseeprom', + 'scripts/generate_dump', + 'scripts/portstat', + 'scripts/sfputil', + ], + entry_points={ + 'console_scripts': [ + 'show = sonic_cli.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/debian/copyright b/sonic_cli/__init__.py similarity index 100% rename from debian/copyright rename to sonic_cli/__init__.py diff --git a/sonic_cli/aliases.ini b/sonic_cli/aliases.ini new file mode 100644 index 0000000000..409231559c --- /dev/null +++ b/sonic_cli/aliases.ini @@ -0,0 +1,5 @@ +[aliases] +running-configuration=runningconfiguration +running-config=runningconfiguration +startup-configuration=startupconfiguration +startup-config=startupconfiguration diff --git a/sonic_cli/main.py b/sonic_cli/main.py new file mode 100644 index 0000000000..6d14b22cc6 --- /dev/null +++ b/sonic_cli/main.py @@ -0,0 +1,459 @@ +#! /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) + +# 'portchannel' subcommand +@interfaces.command() +def portchannel(): + """Show PortChannel information""" + run_command("teamshow", 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/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 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) 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