[BFN] Updated syseeprom platform plugin to use onie-eeprom (#10556)

* Align system eeprom info with ONIE

* revert linked sonic_platform implementation

* refactor into one class

* refactor after review
This commit is contained in:
Dmytro Lytvynenko 2022-09-30 01:13:46 +03:00 committed by GitHub
parent d9c9c70fb5
commit d08fcc971c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 333 additions and 85 deletions

View File

@ -13,8 +13,8 @@ try:
from sonic_platform.psu import psu_list_get
from sonic_platform.fan_drawer import fan_drawer_list_get
from sonic_platform.thermal import thermal_list_get
from eeprom import Eeprom
from platform_utils import file_create
from sonic_platform.platform_utils import file_create
from sonic_platform.eeprom import Eeprom
from sonic_platform.platform_thrift_client import pltfm_mgr_ready
from sonic_platform.platform_thrift_client import thrift_try
@ -40,7 +40,10 @@ class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)
self.__eeprom = None
self._eeprom = Eeprom()
self.__tlv_bin_eeprom = self._eeprom.get_raw_data()
self.__tlv_dict_eeprom = self._eeprom.get_data()
self.__fan_drawers = None
self.__fan_list = None
self.__thermals = None
@ -57,16 +60,6 @@ class Chassis(ChassisBase):
file_create(config_dict['handlers']['file']['filename'], '646')
logging.config.dictConfig(config_dict)
@property
def _eeprom(self):
if self.__eeprom is None:
self.__eeprom = Eeprom()
return self.__eeprom
@_eeprom.setter
def _eeprom(self, value):
pass
@property
def _fan_drawer_list(self):
if self.__fan_drawers is None:
@ -152,7 +145,7 @@ class Chassis(ChassisBase):
Returns:
string: The name of the chassis
"""
return self._eeprom.modelstr()
return self._eeprom.modelstr(self.__tlv_bin_eeprom)
def get_presence(self):
"""
@ -168,7 +161,7 @@ class Chassis(ChassisBase):
Returns:
string: Model/part number of chassis
"""
return self._eeprom.part_number_str()
return self._eeprom.part_number_str(self.__tlv_bin_eeprom)
def get_serial(self):
"""
@ -176,7 +169,7 @@ class Chassis(ChassisBase):
Returns:
string: Serial number of chassis
"""
return self._eeprom.serial_number_str()
return self._eeprom.serial_number_str(self.__tlv_bin_eeprom)
def get_revision(self):
"""
@ -184,7 +177,8 @@ class Chassis(ChassisBase):
Returns:
string: Revision number of chassis
"""
return self._eeprom.revision_str()
return self.__tlv_dict_eeprom.get(
"0x{:X}".format(Eeprom._TLV_CODE_LABEL_REVISION), 'N/A')
def get_sfp(self, index):
"""
@ -225,7 +219,7 @@ class Chassis(ChassisBase):
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.base_mac_addr()
return self._eeprom.base_mac_addr(self.__tlv_bin_eeprom)
def get_system_eeprom_info(self):
"""
@ -236,7 +230,7 @@ class Chassis(ChassisBase):
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
return self._eeprom.system_eeprom_info()
return self.__tlv_dict_eeprom
def __get_transceiver_change_event(self, timeout=0):
forever = False

View File

@ -2,7 +2,8 @@ try:
import os
import sys
import datetime
import re
import logging
import logging.config
sys.path.append(os.path.dirname(__file__))
@ -13,13 +14,15 @@ try:
from sonic_platform_base.sonic_eeprom import eeprom_base
from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo
from platform_utils import file_create
from platform_thrift_client import thrift_try
from sonic_py_common import device_info
from sonic_platform.platform_thrift_client import thrift_try
from sonic_platform.platform_utils import file_create
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
_platform_eeprom_map = {
"prod_name" : ("Product Name", "0x21", 12),
"odm_pcba_part_num" : ("Part Number", "0x22", 13),
@ -44,25 +47,55 @@ class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
file_create(_EEPROM_SYMLINK, '646')
file_create(_EEPROM_STATUS, '646')
with open(_EEPROM_STATUS, 'w') as f:
f.write("initializing..")
super(Eeprom, self).__init__(_EEPROM_SYMLINK, 0, _EEPROM_STATUS, True)
self.eeprom_path = _EEPROM_SYMLINK
super(Eeprom, self).__init__(self.eeprom_path, 0, _EEPROM_STATUS, True)
def sys_eeprom_get(client):
return client.pltfm_mgr.pltfm_mgr_sys_eeprom_get()
self._eeprom_bin = bytearray()
self.report_status("initializing..")
try:
platform_eeprom = thrift_try(sys_eeprom_get)
except Exception:
raise RuntimeError("eeprom.py: Initialization failed")
try:
if device_info.get_platform() in ["x86_64-accton_as9516_32d-r0",
"x86_64-accton_as9516bf_32d-r0"]:
def tlv_eeprom_get(client):
return client.pltfm_mgr.pltfm_mgr_tlv_eeprom_get()
try:
self._eeprom_bin = bytearray.fromhex(
thrift_try(tlv_eeprom_get, 1).raw_content_hex)
except TApplicationException as e:
raise RuntimeError("api is not supported")
except Exception as e:
self._eeprom_bin = bytearray.fromhex(
thrift_try(tlv_eeprom_get).raw_content_hex)
else:
raise RuntimeError("platform is not supported")
self.__eeprom_init(platform_eeprom)
except RuntimeError as e:
logging.warning("Tlv eeprom fetching failed: %s, using OpenBMC" % (str(e)))
def __eeprom_init(self, platform_eeprom):
with open(_EEPROM_STATUS, 'w') as f:
f.write("ok")
def sys_eeprom_get(client):
return client.pltfm_mgr.pltfm_mgr_sys_eeprom_get()
eeprom_params = self.platfrom_eeprom_to_params(thrift_try(sys_eeprom_get))
stdout_stream = sys.stdout
sys.stdout = open(os.devnull, 'w')
self._eeprom_bin = self.set_eeprom(self._eeprom_bin, [eeprom_params])
sys.stdout.close()
sys.stdout = stdout_stream
try:
self.write_eeprom(self._eeprom_bin)
self.report_status("ok")
except IOError as e:
logging.error("Failed to write eeprom: %s" % (str(e)))
except Exception as e:
logging.error("eeprom.py: Initialization failed: %s" % (str(e)))
raise RuntimeError("eeprom.py: Initialization failed: %s" % (str(e)))
self._system_eeprom_info = dict()
visitor = EepromContentVisitor(self._system_eeprom_info)
self.visit_eeprom(self._eeprom_bin, visitor)
@staticmethod
def platfrom_eeprom_to_params(platform_eeprom):
eeprom_params = ""
for attr, val in platform_eeprom.__dict__.items():
if val is None:
@ -86,57 +119,41 @@ class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
if len(eeprom_params) > 0:
eeprom_params += ","
eeprom_params += "{0:s}={1:s}".format(elem[1], value)
return eeprom_params
orig_stdout = sys.stdout
sys.stdout = StringIO()
def get_data(self):
return self._system_eeprom_info
def get_raw_data(self):
return self._eeprom_bin
def report_status(self, status):
status_file = None
try:
eeprom_data = eeprom_tlvinfo.TlvInfoDecoder.set_eeprom(self, "", [eeprom_params])
status_file = open(_EEPROM_STATUS, "w")
status_file.write(status)
except IOError as e:
logging.error("Failed to report state: %s" % (str(e)))
finally:
decode_output = sys.stdout.getvalue()
sys.stdout = orig_stdout
if status_file is not None:
status_file.close()
eeprom_base.EepromDecoder.write_eeprom(self, eeprom_data)
self.__eeprom_tlv_dict = self.__parse_output(decode_output)
class EepromContentVisitor(eeprom_tlvinfo.EepromDefaultVisitor):
def __init__(self, content_dict):
self.content_dict = content_dict
def __parse_output(self, decode_output):
EEPROM_DECODE_HEADLINES = 6
lines = decode_output.replace('\0', '').split('\n')
lines = lines[EEPROM_DECODE_HEADLINES:]
res = dict()
for line in lines:
try:
# match whitespace-separated tag hex, length and value (value is mathced with its whitespaces)
match = re.search('(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+[\s]*[\S]*)', line)
if match is not None:
code = match.group(1)
value = match.group(3).rstrip('\0')
res[code] = value
except Exception:
pass
return res
def __tlv_get(self, code):
return self.__eeprom_tlv_dict.get("0x{:X}".format(code), 'N/A')
def system_eeprom_info(self):
return self.__eeprom_tlv_dict
def serial_number_str(self):
return self.__tlv_get(self._TLV_CODE_SERIAL_NUMBER)
def serial_str(self):
return self.serial_number_str()
def base_mac_addr(self):
return self.__tlv_get(self._TLV_CODE_MAC_BASE)
def part_number_str(self):
return self.__tlv_get(self._TLV_CODE_PART_NUMBER)
def modelstr(self):
return self.__tlv_get(self._TLV_CODE_PRODUCT_NAME)
def revision_str(self):
return self.__tlv_get(self._TLV_CODE_LABEL_REVISION)
def visit_tlv(self, name, code, length, value):
if code != Eeprom._TLV_CODE_VENDOR_EXT:
self.content_dict["0x{:X}".format(code)] = value.rstrip('\0')
else:
if value:
value = value.rstrip('\0')
if value:
code = "0x{:X}".format(code)
if code not in self.content_dict:
self.content_dict[code] = [value]
else:
self.content_dict[code].append(value)
def set_error(self, error):
logging.error("EepromContentVisitor error: %s" % (str(error)))

View File

@ -33,6 +33,9 @@ class Iface(object):
def pltfm_mgr_sys_eeprom_get(self):
pass
def pltfm_mgr_tlv_eeprom_get(self):
pass
def pltfm_mgr_pwr_supply_present_get(self, ps_num):
"""
Parameters:
@ -403,6 +406,34 @@ class Client(Iface):
raise result.ouch
raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_sys_eeprom_get failed: unknown result")
def pltfm_mgr_tlv_eeprom_get(self):
self.send_pltfm_mgr_tlv_eeprom_get()
return self.recv_pltfm_mgr_tlv_eeprom_get()
def send_pltfm_mgr_tlv_eeprom_get(self):
self._oprot.writeMessageBegin('pltfm_mgr_tlv_eeprom_get', TMessageType.CALL, self._seqid)
args = pltfm_mgr_tlv_eeprom_get_args()
args.write(self._oprot)
self._oprot.writeMessageEnd()
self._oprot.trans.flush()
def recv_pltfm_mgr_tlv_eeprom_get(self):
iprot = self._iprot
(fname, mtype, rseqid) = iprot.readMessageBegin()
if mtype == TMessageType.EXCEPTION:
x = TApplicationException()
x.read(iprot)
iprot.readMessageEnd()
raise x
result = pltfm_mgr_tlv_eeprom_get_result()
result.read(iprot)
iprot.readMessageEnd()
if result.success is not None:
return result.success
if result.ouch is not None:
raise result.ouch
raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_tlv_eeprom_get failed: unknown result")
def pltfm_mgr_pwr_supply_present_get(self, ps_num):
"""
Parameters:
@ -1579,6 +1610,7 @@ class Processor(Iface, TProcessor):
self._processMap["pltfm_mgr_dummy"] = Processor.process_pltfm_mgr_dummy
self._processMap["pltfm_mgr_sys_tmp_get"] = Processor.process_pltfm_mgr_sys_tmp_get
self._processMap["pltfm_mgr_sys_eeprom_get"] = Processor.process_pltfm_mgr_sys_eeprom_get
self._processMap["pltfm_mgr_tlv_eeprom_get"] = Processor.process_pltfm_mgr_tlv_eeprom_get
self._processMap["pltfm_mgr_pwr_supply_present_get"] = Processor.process_pltfm_mgr_pwr_supply_present_get
self._processMap["pltfm_mgr_pwr_supply_info_get"] = Processor.process_pltfm_mgr_pwr_supply_info_get
self._processMap["pltfm_mgr_pwr_rail_info_get"] = Processor.process_pltfm_mgr_pwr_rail_info_get
@ -1710,6 +1742,32 @@ class Processor(Iface, TProcessor):
oprot.writeMessageEnd()
oprot.trans.flush()
def process_pltfm_mgr_tlv_eeprom_get(self, seqid, iprot, oprot):
args = pltfm_mgr_tlv_eeprom_get_args()
args.read(iprot)
iprot.readMessageEnd()
result = pltfm_mgr_tlv_eeprom_get_result()
try:
result.success = self._handler.pltfm_mgr_tlv_eeprom_get()
msg_type = TMessageType.REPLY
except TTransport.TTransportException:
raise
except InvalidPltfmMgrOperation as ouch:
msg_type = TMessageType.REPLY
result.ouch = ouch
except TApplicationException as ex:
logging.exception('TApplication exception in handler')
msg_type = TMessageType.EXCEPTION
result = ex
except Exception:
logging.exception('Unexpected exception in handler')
msg_type = TMessageType.EXCEPTION
result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
oprot.writeMessageBegin("pltfm_mgr_tlv_eeprom_get", msg_type, seqid)
result.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
def process_pltfm_mgr_pwr_supply_present_get(self, seqid, iprot, oprot):
args = pltfm_mgr_pwr_supply_present_get_args()
args.read(iprot)
@ -2954,6 +3012,123 @@ pltfm_mgr_sys_eeprom_get_result.thrift_spec = (
)
class pltfm_mgr_tlv_eeprom_get_args(object):
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_tlv_eeprom_get_args')
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
all_structs.append(pltfm_mgr_tlv_eeprom_get_args)
pltfm_mgr_tlv_eeprom_get_args.thrift_spec = (
)
class pltfm_mgr_tlv_eeprom_get_result(object):
"""
Attributes:
- success
- ouch
"""
def __init__(self, success=None, ouch=None,):
self.success = success
self.ouch = ouch
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 0:
if ftype == TType.STRUCT:
self.success = pltfm_mgr_tlv_sys_eeprom_t()
self.success.read(iprot)
else:
iprot.skip(ftype)
elif fid == 1:
if ftype == TType.STRUCT:
self.ouch = InvalidPltfmMgrOperation.read(iprot)
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_tlv_eeprom_get_result')
if self.success is not None:
oprot.writeFieldBegin('success', TType.STRUCT, 0)
self.success.write(oprot)
oprot.writeFieldEnd()
if self.ouch is not None:
oprot.writeFieldBegin('ouch', TType.STRUCT, 1)
self.ouch.write(oprot)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
all_structs.append(pltfm_mgr_tlv_eeprom_get_result)
pltfm_mgr_tlv_eeprom_get_result.thrift_spec = (
(0, TType.STRUCT, 'success', [pltfm_mgr_tlv_sys_eeprom_t, None], None, ), # 0
(1, TType.STRUCT, 'ouch', [InvalidPltfmMgrOperation, None], None, ), # 1
)
class pltfm_mgr_pwr_supply_present_get_args(object):
"""
Attributes:

View File

@ -460,6 +460,63 @@ class pltfm_mgr_eeprom_t(object):
return not (self == other)
class pltfm_mgr_tlv_sys_eeprom_t(object):
"""
Attributes:
- raw_content_hex
"""
def __init__(self, raw_content_hex=None,):
self.raw_content_hex = raw_content_hex
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 1:
if ftype == TType.STRING:
self.raw_content_hex = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_tlv_sys_eeprom_t')
if self.raw_content_hex is not None:
oprot.writeFieldBegin('raw_content_hex', TType.STRING, 1)
oprot.writeString(self.raw_content_hex.encode('utf-8') if sys.version_info[0] == 2 else self.raw_content_hex)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class pltfm_mgr_pwr_supply_info_t(object):
"""
Attributes:
@ -1380,6 +1437,11 @@ pltfm_mgr_eeprom_t.thrift_spec = (
(21, TType.STRING, 'location', 'UTF8', None, ), # 21
(22, TType.I16, 'crc8', None, None, ), # 22
)
all_structs.append(pltfm_mgr_tlv_sys_eeprom_t)
pltfm_mgr_tlv_sys_eeprom_t.thrift_spec = (
None, # 0
(1, TType.STRING, 'raw_content_hex', 'UTF8', None, ), # 1
)
all_structs.append(pltfm_mgr_pwr_supply_info_t)
pltfm_mgr_pwr_supply_info_t.thrift_spec = (
None, # 0