sonic-buildimage/platform/mellanox/mlnx-platform-api/sonic_platform/component.py

149 lines
4.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python
#############################################################################
# Mellanox
#
# implementation of new platform api
#############################################################################
try:
from sonic_platform_base.component_base import ComponentBase
from glob import glob
import subprocess
import io
import re
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
#components definitions
COMPONENT_BIOS = "BIOS"
COMPONENT_CPLD = "CPLD"
BIOS_QUERY_VERSION_COMMAND = 'dmidecode -t 11'
CPLD_VERSION_FILE_PATTERN = '/var/run/hw-management/system/cpld[0-9]_version'
CPLD_VERSION_MAX_LENGTH = 4
class Component(ComponentBase):
def get_name(self):
"""
Retrieves the name of the component
Returns:
A string containing the name of the component
"""
return self.name
def _read_generic_file(self, filename, len):
"""
Read a generic file, returns the contents of the file
"""
result = ''
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)))
def _get_command_result(self, cmdline):
try:
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
proc.wait()
result = stdout.rstrip('\n')
except OSError as e:
raise RuntimeError("Failed to execute command {} due to {}".format(cmdline, repr(e)))
return result
class ComponentBIOS(Component):
BIOS_VERSION_PARSE_PATTERN = 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)'
def __init__(self):
self.name = COMPONENT_BIOS
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"
def get_firmware_version(self):
"""
Retrieves the firmware version of the component
Returns:
A string containing the firmware version of the component
BIOS version is retrieved via command 'dmidecode -t 11'
which should return result in the following convention
# dmidecode 3.0
Getting SMBIOS data from sysfs.
SMBIOS 2.7 present.
Handle 0x0022, DMI type 11, 5 bytes
OEM Strings
String 1:*0ABZS017_02.02.002*
String 2: To Be Filled By O.E.M.
By using regular expression 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)'
we can extrace the version string which is marked with * in the above context
"""
bios_ver_str = self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
try:
m = re.search(self.BIOS_VERSION_PARSE_PATTERN, bios_ver_str)
result = m.group(1)
except AttributeError as e:
raise RuntimeError("Failed to parse BIOS version by {} from {} due to {}".format(
self.BIOS_VERSION_PARSE_PATTERN, bios_ver_str, repr(e)))
return result
class ComponentCPLD(Component):
def __init__(self):
self.name = COMPONENT_CPLD
def get_description(self):
"""
Retrieves the description of the component
Returns:
A string containing the description of the component
"""
return "CPLD - includes all CPLDs in the switch"
def get_firmware_version(self):
"""
Retrieves the firmware version of the component
Returns:
A string containing the firmware version of the component
"""
cpld_version_file_list = glob(CPLD_VERSION_FILE_PATTERN)
cpld_version = ''
if cpld_version_file_list is not None and cpld_version_file_list:
cpld_version_file_list.sort()
for version_file in cpld_version_file_list:
version = self._read_generic_file(version_file, CPLD_VERSION_MAX_LENGTH)
if not cpld_version == '':
cpld_version += '.'
cpld_version += version.rstrip('\n')
else:
raise RuntimeError("Failed to get CPLD version files by matching {}".format(CPLD_VERSION_FILE_PATTERN))
return cpld_version