sonic-buildimage/device/celestica/x86_64-cel_e1031-r0/sonic_platform/eeprom.py

201 lines
6.1 KiB
Python
Raw Normal View History

#############################################################################
# Celestica Haliburton
#
# 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 os
import sys
import re
[sonic-utilities] Update submodule; Build and install as a Python 3 wheel (#5926) Submodule updates include the following commits: * src/sonic-utilities 9dc58ea...f9eb739 (18): > Remove unnecessary calls to str.encode() now that the package is Python 3; Fix deprecation warning (#1260) > [generate_dump] Ignoring file/directory not found Errors (#1201) > Fixed porstat rate and util issues (#1140) > fix error: interface counters is mismatch after warm-reboot (#1099) > Remove unnecessary calls to str.decode() now that the package is Python 3 (#1255) > [acl-loader] Make list sorting compliant with Python 3 (#1257) > Replace hard-coded fast-reboot with variable. And some typo corrections (#1254) > [configlet][portconfig] Remove calls to dict.has_key() which is not available in Python 3 (#1247) > Remove unnecessary conversions to list() and calls to dict.keys() (#1243) > Clean up LGTM alerts (#1239) > Add 'requests' as install dependency in setup.py (#1240) > Convert to Python 3 (#1128) > Fix mock SonicV2Connector in python3: use decode_responses mode so caller code will be the same as python2 (#1238) > [tests] Do not trim from PATH if we did not append to it; Clean up/fix shebangs in scripts (#1233) > Updates to bgp config and show commands with BGP_INTERNAL_NEIGHBOR table (#1224) > [cli]: NAT show commands newline issue after migrated to Python3 (#1204) > [doc]: Update Command-Reference.md (#1231) > Added 'import sys' in feature.py file (#1232) * src/sonic-py-swsssdk 9d9f0c6...1664be9 (2): > Fix: no need to decode() after redis client scan, so it will work for both python2 and python3 (#96) > FieldValueMap `contains`(`in`) will also work when migrated to libswsscommon(C++ with SWIG wrapper) (#94) - Also fix Python 3-related issues: - Use integer (floor) division in config_samples.py (sonic-config-engine) - Replace print statement with print function in eeprom.py plugin for x86_64-kvm_x86_64-r0 platform - Update all platform plugins to be compatible with both Python 2 and Python 3 - Remove shebangs from plugins files which are not intended to be executable - Replace tabs with spaces in Python plugin files and fix alignment, because Python 3 is more strict - Remove trailing whitespace from plugins files
2020-11-25 12:28:36 -06:00
if sys.version_info.major == 3:
from io import StringIO
else:
from cStringIO import StringIO
from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo
from sonic_platform_base.sonic_eeprom.eeprom_base import EepromDecoder
[sonic-utilities] Update submodule; Build and install as a Python 3 wheel (#5926) Submodule updates include the following commits: * src/sonic-utilities 9dc58ea...f9eb739 (18): > Remove unnecessary calls to str.encode() now that the package is Python 3; Fix deprecation warning (#1260) > [generate_dump] Ignoring file/directory not found Errors (#1201) > Fixed porstat rate and util issues (#1140) > fix error: interface counters is mismatch after warm-reboot (#1099) > Remove unnecessary calls to str.decode() now that the package is Python 3 (#1255) > [acl-loader] Make list sorting compliant with Python 3 (#1257) > Replace hard-coded fast-reboot with variable. And some typo corrections (#1254) > [configlet][portconfig] Remove calls to dict.has_key() which is not available in Python 3 (#1247) > Remove unnecessary conversions to list() and calls to dict.keys() (#1243) > Clean up LGTM alerts (#1239) > Add 'requests' as install dependency in setup.py (#1240) > Convert to Python 3 (#1128) > Fix mock SonicV2Connector in python3: use decode_responses mode so caller code will be the same as python2 (#1238) > [tests] Do not trim from PATH if we did not append to it; Clean up/fix shebangs in scripts (#1233) > Updates to bgp config and show commands with BGP_INTERNAL_NEIGHBOR table (#1224) > [cli]: NAT show commands newline issue after migrated to Python3 (#1204) > [doc]: Update Command-Reference.md (#1231) > Added 'import sys' in feature.py file (#1232) * src/sonic-py-swsssdk 9d9f0c6...1664be9 (2): > Fix: no need to decode() after redis client scan, so it will work for both python2 and python3 (#96) > FieldValueMap `contains`(`in`) will also work when migrated to libswsscommon(C++ with SWIG wrapper) (#94) - Also fix Python 3-related issues: - Use integer (floor) division in config_samples.py (sonic-config-engine) - Replace print statement with print function in eeprom.py plugin for x86_64-kvm_x86_64-r0 platform - Update all platform plugins to be compatible with both Python 2 and Python 3 - Remove shebangs from plugins files which are not intended to be executable - Replace tabs with spaces in Python plugin files and fix alignment, because Python 3 is more strict - Remove trailing whitespace from plugins files
2020-11-25 12:28:36 -06:00
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CACHE_ROOT = '/var/cache/sonic/decode-syseeprom'
CACHE_FILE = 'syseeprom_cache'
NULL = 'N/A'
class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
EEPROM_DECODE_HEADLINES = 6
def __init__(self):
self._eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom"
self._eeprom = None
super(Tlv, self).__init__(self._eeprom_path, 0, '', True)
def __parse_output(self, decode_output):
decode_output.replace('\0', '')
lines = decode_output.split('\n')
lines = lines[self.EEPROM_DECODE_HEADLINES:]
_eeprom_info_dict = dict()
for line in lines:
try:
match = re.search(
'(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line)
if match is not None:
idx = match.group(1)
value = match.group(3).rstrip('\0')
_eeprom_info_dict[idx] = value
except BaseException:
pass
return _eeprom_info_dict
def _load_eeprom(self):
original_stdout = sys.stdout
sys.stdout = StringIO()
try:
self.read_eeprom_db()
except BaseException:
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
return self.__parse_output(decode_output)
status = self.check_status()
if 'ok' not in status:
return False
if not os.path.exists(CACHE_ROOT):
try:
os.makedirs(CACHE_ROOT)
except BaseException:
pass
#
# only the eeprom classes that inherit from eeprom_base
# support caching. Others will work normally
#
try:
self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE))
except BaseException:
pass
e = self.read_eeprom()
if e is None:
return 0
try:
self.update_cache(e)
except BaseException:
pass
self.decode_eeprom(e)
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
(is_valid, valid_crc) = self.is_checksum_valid(e)
if not is_valid:
return False
return self.__parse_output(decode_output)
def _valid_tlv(self, eeprom_data):
tlvinfo_type_codes_list = [
self._TLV_CODE_PRODUCT_NAME,
self._TLV_CODE_PART_NUMBER,
self._TLV_CODE_SERIAL_NUMBER,
self._TLV_CODE_MAC_BASE,
self._TLV_CODE_MANUF_DATE,
self._TLV_CODE_DEVICE_VERSION,
self._TLV_CODE_LABEL_REVISION,
self._TLV_CODE_PLATFORM_NAME,
self._TLV_CODE_ONIE_VERSION,
self._TLV_CODE_MAC_SIZE,
self._TLV_CODE_MANUF_NAME,
self._TLV_CODE_MANUF_COUNTRY,
self._TLV_CODE_VENDOR_NAME,
self._TLV_CODE_DIAG_VERSION,
self._TLV_CODE_SERVICE_TAG,
self._TLV_CODE_VENDOR_EXT,
self._TLV_CODE_CRC_32
]
for code in tlvinfo_type_codes_list:
code_str = "0x{:X}".format(code)
eeprom_data[code_str] = eeprom_data.get(code_str, NULL)
return eeprom_data
def get_eeprom(self):
self._eeprom = self._load_eeprom() if not self._eeprom else self._eeprom
return self._valid_tlv(self._eeprom)
def get_pn(self):
return self.get_eeprom()['0x22']
def get_serial(self):
return self.get_eeprom()['0x23']
def get_mac(self):
return self.get_eeprom()['0x24']
class DeviceEEPROM(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self, eeprom_path, device_format, start_offset):
# Decode device eeprom as per specified format
self.format = device_format
self.start_offset = start_offset
EepromDecoder.__init__(self, eeprom_path, self.format,
self.start_offset, '', True)
self._load_device_eeprom()
def _load_device_eeprom(self):
"""
Reads the Fan/PSU EEPROM and interprets as per the specified format
"""
self.serial_number = 'NA'
self.model_str = 'NA'
# device eeproms use proprietary format
try:
# Read Fan/PSU EEPROM as per the specified format.
self.eeprom_data = EepromDecoder.read_eeprom(self)
except Exception as e:
return
if self.eeprom_data[0] == 255:
return
(valid, data) = self._get_eeprom_field("Model")
if valid:
self.model_str = data.decode()
try:
(valid, data) = self._get_eeprom_field("Serial Number")
if valid:
self.serial_number = data.decode()
except Exception as e:
return
def _get_eeprom_field(self, field_name, decode=False):
"""
For a field name specified in the EEPROM format, returns the
presence of the field and the value for the same.
"""
field_start = 0
for field in self.format:
field_end = field_start + field[2]
if field[0] == field_name:
if decode:
return (True, self.eeprom_data[field_start:field_end].decode('ascii'))
else:
return (True, self.eeprom_data[field_start:field_end])
field_start = field_end
return (False, None)