Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mellanox]: Align platform API: change CPLD version representation #4221

Merged
merged 4 commits into from
Mar 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def initialize_components(self):
# Initialize component list
from sonic_platform.component import ComponentBIOS, ComponentCPLD
self._component_list.append(ComponentBIOS())
self._component_list.append(ComponentCPLD())
self._component_list.extend(ComponentCPLD.get_component_list())


def get_name(self):
Expand Down
148 changes: 92 additions & 56 deletions platform/mellanox/mlnx-platform-api/sonic_platform/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

#components definitions
COMPONENT_BIOS = "BIOS"
COMPONENT_CPLD = "CPLD"
ZERO = '0'
NEWLINE = '\n'

class Component(ComponentBase):
def __init__(self):
self.name = None
self.description = None
self.image_ext_name = None


Expand All @@ -38,20 +38,35 @@ def get_name(self):
return self.name


def _read_generic_file(self, filename, len):
def get_description(self):
"""
Retrieves the description of the component

Returns:
A string containing the description of the component
"""
return self.description


@staticmethod
def _read_generic_file(filename, len, ignore_errors=False):
"""
Read a generic file, returns the contents of the file
"""
result = ''
result = None

try:
with io.open(filename, 'r') as fileobj:
result = fileobj.read(len)
return result
except IOError as e:
raise RuntimeError("Failed to read file {} due to {}".format(filename, repr(e)))
if not ignore_errors:
raise RuntimeError("Failed to read file {} due to {}".format(filename, repr(e)))

return result


def _get_command_result(self, cmdline):
@staticmethod
def _get_command_result(cmdline):
try:
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
Expand Down Expand Up @@ -83,38 +98,33 @@ def _check_file_validity(self, image_path):


class ComponentBIOS(Component):
COMPONENT_NAME = 'BIOS'
COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System'
COMPONENT_FIRMWARE_EXTENSION = '.rom'

# To update BIOS requires the ONIE with version 5.2.0016 or upper
ONIE_VERSION_PARSE_PATTERN = '[0-9]{4}\.[0-9]{2}-([0-9]+)\.([0-9]+)\.([0-9]+)'
ONIE_VERSION_MAJOR_OFFSET = 1
ONIE_VERSION_MINOR_OFFSET = 2
ONIE_VERSION_RELEASE_OFFSET = 3
ONIE_REQUIRED_MAJOR = "5"
ONIE_REQUIRED_MINOR = "2"
ONIE_REQUIRED_RELEASE = "0016"
ONIE_REQUIRED_MAJOR = '5'
ONIE_REQUIRED_MINOR = '2'
ONIE_REQUIRED_RELEASE = '0016'

BIOS_VERSION_PARSE_PATTERN = 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)'
BIOS_PENDING_UPDATE_PATTERN = '([0-9A-Za-z_]*.rom)[\s]*\|[\s]*bios_update'

ONIE_FW_UPDATE_CMD_ADD = "/usr/bin/onie-fw-update.sh add {}"
ONIE_FW_UPDATE_CMD_REMOVE = "/usr/bin/onie-fw-update.sh remove {}"
ONIE_FW_UPDATE_CMD_UPDATE = "/usr/bin/onie-fw-update.sh update"
ONIE_FW_UPDATE_CMD_SHOW = "/usr/bin/onie-fw-update.sh show-pending"
ONIE_FW_UPDATE_CMD_ADD = '/usr/bin/onie-fw-update.sh add {}'
ONIE_FW_UPDATE_CMD_REMOVE = '/usr/bin/onie-fw-update.sh remove {}'
ONIE_FW_UPDATE_CMD_UPDATE = '/usr/bin/onie-fw-update.sh update'
ONIE_FW_UPDATE_CMD_SHOW = '/usr/bin/onie-fw-update.sh show-pending'

BIOS_QUERY_VERSION_COMMAND = 'dmidecode -t 11'

def __init__(self):
self.name = COMPONENT_BIOS
self.image_ext_name = ".rom"


def get_description(self):
"""
Retrieves the description of the component

Returns:
A string containing the description of the component
"""
return "BIOS - Basic Input/Output System"
self.name = self.COMPONENT_NAME
self.description = self.COMPONENT_DESCRIPTION
self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION


def get_firmware_version(self):
Expand Down Expand Up @@ -210,33 +220,39 @@ def install_firmware(self, image_path):
print("ERROR: Installing BIOS failed due to {}".format(repr(e)))
return False

print("INFO: Reboot is required to finish BIOS installation.")
print("INFO: Reboot is required to finish BIOS installation")
return True



class ComponentCPLD(Component):
CPLD_VERSION_FILE_PATTERN = '/var/run/hw-management/system/cpld[0-9]_version'
CPLD_VERSION_MAX_LENGTH = 4
COMPONENT_NAME = 'CPLD{}'
COMPONENT_DESCRIPTION = 'CPLD - Complex Programmable Logic Device'
COMPONENT_FIRMWARE_EXTENSION = '.vme'

CPLD_UPDATE_COMMAND = "cpldupdate --dev {} {}"
CPLD_INSTALL_SUCCESS_FLAG = "PASS!"
CPLD_NUMBER_FILE = '/var/run/hw-management/config/cpld_num'
CPLD_PART_NUMBER_FILE = '/var/run/hw-management/system/cpld{}_pn'
CPLD_VERSION_FILE = '/var/run/hw-management/system/cpld{}_version'
CPLD_VERSION_MINOR_FILE = '/var/run/hw-management/system/cpld{}_version_minor'

MST_DEVICE_PATTERN = "/dev/mst/mt[0-9]*_pciconf0"
CPLD_NUMBER_MAX_LENGTH = 1
CPLD_PART_NUMBER_MAX_LENGTH = 6
CPLD_VERSION_MAX_LENGTH = 2
CPLD_VERSION_MINOR_MAX_LENGTH = 2

def __init__(self):
self.name = COMPONENT_CPLD
self.image_ext_name = ".vme"
CPLD_PART_NUMBER_DEFAULT = ZERO
CPLD_VERSION_MINOR_DEFAULT = ZERO

CPLD_UPDATE_COMMAND = 'cpldupdate --dev {} {}'
CPLD_INSTALL_SUCCESS_FLAG = 'PASS!'

def get_description(self):
"""
Retrieves the description of the component
MST_DEVICE_PATTERN = '/dev/mst/mt[0-9]*_pci_cr0'

Returns:
A string containing the description of the component
"""
return "CPLD - includes all CPLDs in the switch"
def __init__(self, idx):
self.idx = idx
self.name = self.COMPONENT_NAME.format(self.idx)
self.description = self.COMPONENT_DESCRIPTION
self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION


def get_firmware_version(self):
Expand All @@ -246,19 +262,26 @@ def get_firmware_version(self):
Returns:
A string containing the firmware version of the component
"""
cpld_version_file_list = glob(self.CPLD_VERSION_FILE_PATTERN)
cpld_version = ''
if cpld_version_file_list:
cpld_version_file_list.sort()
for version_file in cpld_version_file_list:
version = self._read_generic_file(version_file, self.CPLD_VERSION_MAX_LENGTH)
if cpld_version:
cpld_version += '.'
cpld_version += version.rstrip('\n')
else:
raise RuntimeError("Failed to get CPLD version files by matching {}".format(self.CPLD_VERSION_FILE_PATTERN))

return cpld_version
part_number_file = self.CPLD_PART_NUMBER_FILE.format(self.idx)
version_file = self.CPLD_VERSION_FILE.format(self.idx)
version_minor_file = self.CPLD_VERSION_MINOR_FILE.format(self.idx)

part_number = self._read_generic_file(part_number_file, self.CPLD_PART_NUMBER_MAX_LENGTH, True)
version = self._read_generic_file(version_file, self.CPLD_VERSION_MAX_LENGTH)
version_minor = self._read_generic_file(version_minor_file, self.CPLD_VERSION_MINOR_MAX_LENGTH, True)

if part_number is None:
part_number = self.CPLD_PART_NUMBER_DEFAULT

if version_minor is None:
version_minor = self.CPLD_VERSION_MINOR_DEFAULT

part_number = part_number.rstrip(NEWLINE).zfill(self.CPLD_PART_NUMBER_MAX_LENGTH)
version = version.rstrip(NEWLINE).zfill(self.CPLD_VERSION_MAX_LENGTH)
version_minor = version_minor.rstrip(NEWLINE).zfill(self.CPLD_VERSION_MINOR_MAX_LENGTH)

return "CPLD{}_REV{}{}".format(part_number, version, version_minor)


def _get_mst_device(self):
Expand Down Expand Up @@ -331,8 +354,21 @@ def install_firmware(self, image_path):
raise RuntimeError("Failed to execute command {} due to {}".format(cmdline, repr(e)))

if success_flag:
print("INFO: Success. Refresh or power cycle is required to finish CPLD installation.")
print("INFO: Refresh or power cycle is required to finish CPLD installation")
else:
print("ERROR: Failed to install CPLD")

return success_flag


@classmethod
def get_component_list(cls):
component_list = [ ]

cpld_number = cls._read_generic_file(cls.CPLD_NUMBER_FILE, cls.CPLD_NUMBER_MAX_LENGTH)
cpld_number = cpld_number.rstrip(NEWLINE)

for cpld_idx in xrange(1, int(cpld_number) + 1):
component_list.append(cls(cpld_idx))

return component_list