Merge pull request #3381 from ArunSaravananBalachandran/platform2.0

DellEMC : Platform2.0 API Implementation for Chassis [S6000, S6100, Z9100], Fan [S6000]
This commit is contained in:
Sujin Kang 2019-09-16 12:25:01 -07:00 committed by GitHub
commit a62ab7890e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 691 additions and 62 deletions

View File

@ -11,18 +11,34 @@ try:
import os import os
import time import time
import datetime import datetime
import subprocess
from sonic_platform_base.chassis_base import ChassisBase from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp from sonic_platform.sfp import Sfp
from sonic_platform.eeprom import Eeprom
from sonic_platform.fan import Fan
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
MAX_S6000_FAN = 3
BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version"
#components definitions
COMPONENT_BIOS = "BIOS"
COMPONENT_CPLD1 = "CPLD1"
COMPONENT_CPLD2 = "CPLD2"
COMPONENT_CPLD3 = "CPLD3"
CPLD1_VERSION = 'system_cpld_ver'
CPLD2_VERSION = 'master_cpld_ver'
CPLD3_VERSION = 'slave_cpld_ver'
class Chassis(ChassisBase): class Chassis(ChassisBase):
""" """
DELLEMC Platform-specific Chassis class DELLEMC Platform-specific Chassis class
""" """
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0"
MAILBOX_DIR = "/sys/devices/platform/dell-s6000-cpld.0"
sfp_control = "" sfp_control = ""
PORT_START = 0 PORT_START = 0
@ -54,9 +70,20 @@ class Chassis(ChassisBase):
# Get Transceiver status # Get Transceiver status
self.modprs_register = self._get_transceiver_status() self.modprs_register = self._get_transceiver_status()
def get_register(self, reg_name): self.sys_eeprom = Eeprom()
for i in range(MAX_S6000_FAN):
fan = Fan(i)
self._fan_list.append(fan)
# Initialize component list
self._component_name_list.append(COMPONENT_BIOS)
self._component_name_list.append(COMPONENT_CPLD1)
self._component_name_list.append(COMPONENT_CPLD2)
self._component_name_list.append(COMPONENT_CPLD3)
def _get_cpld_register(self, reg_name):
rv = 'ERR' rv = 'ERR'
mb_reg_file = self.MAILBOX_DIR+'/'+reg_name mb_reg_file = self.CPLD_DIR+'/'+reg_name
if (not os.path.isfile(mb_reg_file)): if (not os.path.isfile(mb_reg_file)):
return rv return rv
@ -71,11 +98,85 @@ class Chassis(ChassisBase):
rv = rv.lstrip(" ") rv = rv.lstrip(" ")
return rv return rv
def get_name(self):
"""
Retrieves the name of the chassis
Returns:
string: The name of the chassis
"""
return self.sys_eeprom.modelstr()
def get_presence(self):
"""
Retrieves the presence of the chassis
Returns:
bool: True if chassis is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the chassis
Returns:
string: Model/part number of chassis
"""
return self.sys_eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the chassis (Service tag)
Returns:
string: Serial number of chassis
"""
return self.sys_eeprom.serial_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self.sys_eeprom.base_mac_addr()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this
chassis.
"""
return self.sys_eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the
chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their
corresponding values.
"""
return self.sys_eeprom.system_eeprom_info()
def get_reboot_cause(self): def get_reboot_cause(self):
""" """
Retrieves the cause of the previous reboot Retrieves the cause of the previous reboot
""" """
reset_reason = int(self.get_register('last_reboot_reason'), base=16) reset_reason = int(self._get_cpld_register('last_reboot_reason'),
base=16)
# In S6000, We track the reboot reason by writing the reason in # In S6000, We track the reboot reason by writing the reason in
# NVRAM. Only Warmboot and Coldboot reason are supported here. # NVRAM. Only Warmboot and Coldboot reason are supported here.
@ -85,6 +186,46 @@ class Chassis(ChassisBase):
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
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:
result = ''
return result
def _get_cpld_version(self,cpld_name):
"""
Cpld Version
"""
cpld_ver = int(self._get_cpld_register(cpld_name),16)
return cpld_ver
def get_firmware_version(self, component_name):
"""
Retrieves platform-specific hardware/firmware versions for
chassis componenets such as BIOS, CPLD, FPGA, etc.
Args:
component_name: A string, the component name.
Returns:
A string containing platform-specific component versions
"""
if component_name in self._component_name_list :
if component_name == COMPONENT_BIOS:
return self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
elif component_name == COMPONENT_CPLD1:
return self._get_cpld_version(CPLD1_VERSION)
elif component_name == COMPONENT_CPLD2:
return self._get_cpld_version(CPLD2_VERSION)
elif component_name == COMPONENT_CPLD3:
return self._get_cpld_version(CPLD3_VERSION)
return None
def _get_transceiver_status(self): def _get_transceiver_status(self):
presence_ctrl = self.sfp_control + 'qsfp_modprs' presence_ctrl = self.sfp_control + 'qsfp_modprs'
try: try:
@ -151,3 +292,4 @@ class Chassis(ChassisBase):
return True, {} return True, {}
return False, {} return False, {}

View File

@ -35,7 +35,8 @@ psu_eeprom_format = [
fan_eeprom_format = [ fan_eeprom_format = [
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7), ('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
('Part Number', 's', 10), ('Part Num Revision', 's', 3), ('Part Number', 's', 10), ('Part Num Revision', 's', 3),
('Mfg Test', 's', 2), ('Number of Fans', 's', 2), ('Fan Type', 's', 1), ('Mfg Test', 's', 2), ('Redundant copy', 's', 82),
('Number of Fans', 's', 1), ('Fan Type', 's', 1),
('Fab Rev', 's', 2) ('Fab Rev', 's', 2)
] ]
@ -86,6 +87,8 @@ class Eeprom(TlvInfoDecoder):
self.base_mac = 'NA' self.base_mac = 'NA'
self.serial_number = 'NA' self.serial_number = 'NA'
self.part_number = 'NA' self.part_number = 'NA'
self.model_str = 'NA'
self.serial = 'NA'
self.eeprom_tlv_dict = dict() self.eeprom_tlv_dict = dict()
else: else:
eeprom = self.eeprom_data eeprom = self.eeprom_data
@ -95,6 +98,8 @@ class Eeprom(TlvInfoDecoder):
self.base_mac = 'NA' self.base_mac = 'NA'
self.serial_number = 'NA' self.serial_number = 'NA'
self.part_number = 'NA' self.part_number = 'NA'
self.model_str = 'NA'
self.serial = 'NA'
return return
total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10])
@ -123,11 +128,15 @@ class Eeprom(TlvInfoDecoder):
tlv_index += ord(eeprom[tlv_index+1]) + 2 tlv_index += ord(eeprom[tlv_index+1]) + 2
self.base_mac = self.eeprom_tlv_dict.get( self.base_mac = self.eeprom_tlv_dict.get(
hex(self._TLV_CODE_MAC_BASE), 'NA') "0x%X" % (self._TLV_CODE_MAC_BASE), 'NA')
self.serial_number = self.eeprom_tlv_dict.get( self.serial_number = self.eeprom_tlv_dict.get(
hex(self._TLV_CODE_SERIAL_NUMBER), 'NA') "0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
self.part_number = self.eeprom_tlv_dict.get( self.part_number = self.eeprom_tlv_dict.get(
hex(self._TLV_CODE_PART_NUMBER), 'NA') "0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA')
self.model_str = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA')
self.serial = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA')
def _load_device_eeprom(self): def _load_device_eeprom(self):
""" """
@ -151,7 +160,7 @@ class Eeprom(TlvInfoDecoder):
if valid: if valid:
self.serial_number += "-" + data self.serial_number += "-" + data
else: else:
seld.serial_number = 'NA' self.serial_number = 'NA'
(valid, data) = self._get_eeprom_field("Part Number") (valid, data) = self._get_eeprom_field("Part Number")
if valid: if valid:
@ -159,6 +168,12 @@ class Eeprom(TlvInfoDecoder):
else: else:
self.part_number = 'NA' self.part_number = 'NA'
(valid, data) = self._get_eeprom_field("Fan Type")
if valid:
self.fan_type = data
else:
self.fan_type = 'NA'
def _get_eeprom_field(self, field_name): def _get_eeprom_field(self, field_name):
""" """
For a field name specified in the EEPROM format, returns the For a field name specified in the EEPROM format, returns the
@ -185,6 +200,12 @@ class Eeprom(TlvInfoDecoder):
""" """
return self.part_number return self.part_number
def airflow_fan_type(self):
"""
Returns the airflow fan type.
"""
return int(self.fan_type.encode('hex'), 16)
# System EEPROM specific methods # System EEPROM specific methods
def base_mac_addr(self): def base_mac_addr(self):
""" """
@ -192,6 +213,18 @@ class Eeprom(TlvInfoDecoder):
""" """
return self.base_mac return self.base_mac
def modelstr(self):
"""
Returns the Model name.
"""
return self.model_str
def serial_str(self):
"""
Returns the servicetag number.
"""
return self.serial
def system_eeprom_info(self): def system_eeprom_info(self):
""" """
Returns a dictionary, where keys are the type code defined in Returns a dictionary, where keys are the type code defined in

View File

@ -0,0 +1,286 @@
#!/usr/bin/env python
########################################################################
# DellEMC S6000
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fans' information which are available in the platform
#
########################################################################
try:
import os
from sonic_platform_base.fan_base import FanBase
from sonic_platform.eeprom import Eeprom
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
MAX_S6000_FAN_SPEED = 19000
class Fan(FanBase):
"""DellEMC Platform-specific Fan class"""
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/"
I2C_DIR = "/sys/class/i2c-adapter/"
def __init__(self, fan_index, psu_fan=False):
# Fan is 1-based in DellEMC platforms
self.index = fan_index + 1
self.is_psu_fan = psu_fan
if not self.is_psu_fan:
self.fan_presence_reg = "fan_prs"
self.fan_led_reg = "fan{}_led".format(fan_index)
self.get_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
"fan{}_input".format(self.index)
self.set_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
"fan{}_target".format(self.index)
self.eeprom = Eeprom(is_fan=True, fan_index=self.index)
self.max_fan_speed = MAX_S6000_FAN_SPEED
self.supported_led_color = ['off', 'green', 'amber']
else:
self.get_fan_speed_reg = self.I2C_DIR + "i2c-1/1-005{}/" +\
"fan1_input".format(10 - self.index)
def _get_cpld_register(self, reg_name):
# On successful read, returns the value read from given
# reg_name and on failure returns 'ERR'
rv = 'ERR'
cpld_reg_file = self.CPLD_DIR + reg_name
if (not os.path.isfile(cpld_reg_file)):
return rv
try:
with open(cpld_reg_file, 'r') as fd:
rv = fd.read()
except:
rv = 'ERR'
rv = rv.rstrip('\r\n')
rv = rv.lstrip(" ")
return rv
def _set_cpld_register(self, reg_name, value):
# On successful write, returns the value will be written on
# reg_name and on failure returns 'ERR'
rv = 'ERR'
cpld_reg_file = self.CPLD_DIR + reg_name
if (not os.path.isfile(cpld_reg_file)):
print "open error"
return rv
try:
with open(cpld_reg_file, 'w') as fd:
rv = fd.write(str(value))
except:
rv = 'ERR'
return rv
def _get_i2c_register(self, reg_file):
# On successful read, returns the value read from given
# reg_name and on failure returns 'ERR'
rv = 'ERR'
if (not os.path.isfile(reg_file)):
return rv
try:
with open(reg_file, 'r') as fd:
rv = fd.read()
except:
rv = 'ERR'
rv = rv.rstrip('\r\n')
rv = rv.lstrip(" ")
return rv
def _set_i2c_register(self, reg_file, value):
# On successful write, the value read will be written on
# reg_name and on failure returns 'ERR'
rv = 'ERR'
if (not os.path.isfile(reg_file)):
return rv
try:
with open(reg_file, 'w') as fd:
rv = fd.write(str(value))
except:
rv = 'ERR'
return rv
def get_name(self):
"""
Retrieves the name of the Fan
Returns:
string: The name of the Fan
"""
if not self.is_psu_fan:
return "Fan{}".format(self.index)
else:
return "PSU{} Fan".format(self.index)
def get_presence(self):
"""
Retrieves the presence of the Fan Unit
Returns:
bool: True if Fan is present, False if not
"""
status = False
fan_presence = self._get_cpld_register(self.fan_presence_reg)
if (fan_presence != 'ERR'):
fan_presence = int(fan_presence,16) & self.index
if fan_presence:
status = True
return status
def get_model(self):
"""
Retrieves the part number of the Fan
Returns:
string: Part number of Fan
"""
return self.eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the Fan
Returns:
string: Serial number of Fan
"""
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
return self.eeprom.serial_number_str()
def get_status(self):
"""
Retrieves the operational status of the Fan
Returns:
bool: True if Fan is operating properly, False if not
"""
status = False
fan_speed = self._get_i2c_register(self.get_fan_speed_reg)
if (fan_speed != 'ERR'):
if (int(fan_speed) > 14000):
status = True
return status
def get_direction(self):
"""
Retrieves the fan airflow direction
Returns:
A string, either FAN_DIRECTION_INTAKE or
FAN_DIRECTION_EXHAUST depending on fan direction
"""
direction = {1: 'FAN_DIRECTION_INTAKE', 2: 'FAN_DIRECTION_EXHAUST'}
fan_direction = self.eeprom.airflow_fan_type()
return direction.get(fan_direction,'NA')
def get_speed(self):
"""
Retrieves the speed of fan
Returns:
int: percentage of the max fan speed
"""
fan_speed = self._get_i2c_register(self.get_fan_speed_reg)
if (fan_speed != 'ERR') and self.get_presence():
speed_in_rpm = int(fan_speed, 10)
speed = (100 * speed_in_rpm)/self.max_fan_speed
else:
speed = 0
return speed
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed
which is considered tolerable
"""
if self.get_presence():
# The tolerance value is fixed as 20% for all the DellEmc platform
tolerance = 20
else:
tolerance = 0
return tolerance
def set_speed(self, speed):
"""
Set fan speed to expected value
Args:
speed: An integer, the percentage of full fan speed to set
fan to, in the range 0 (off) to 100 (full speed)
Returns:
bool: True if set success, False if fail.
"""
fan_set = (speed * self.max_fan_speed)/ 100
rv = self._set_i2c_register(self.set_fan_speed_reg , fan_set)
if (rv != 'ERR'):
return True
else:
return False
def set_status_led(self, color):
"""
Set led to expected color
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if set success, False if fail.
"""
if color not in self.supported_led_color:
return False
if(color == self.STATUS_LED_COLOR_AMBER):
color = 'yellow'
rv = self._set_cpld_register(self.fan_led_reg ,color)
if (rv != 'ERR'):
return True
else:
return False
def get_status_led(self):
"""
Gets the state of the fan status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings.
"""
fan_led = self._get_cpld_register(self.fan_led_reg)
if (fan_led != 'ERR'):
if (fan_led == 'yellow'):
return self.STATUS_LED_COLOR_AMBER
else:
return fan_led
else:
return self.STATUS_LED_COLOR_OFF
def get_target_speed(self):
"""
Retrieves the target (expected) speed of the fan
Returns:
An integer, the percentage of full fan speed, in the range 0
(off) to 100 (full speed)
"""
return 79

View File

@ -15,7 +15,6 @@ try:
import subprocess import subprocess
import glob import glob
import sonic_device_util import sonic_device_util
from commands import getstatusoutput
from sonic_platform_base.platform_base import PlatformBase from sonic_platform_base.platform_base import PlatformBase
from sonic_platform_base.chassis_base import ChassisBase from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp from sonic_platform.sfp import Sfp
@ -32,6 +31,12 @@ MAX_S6100_FAN = 4
MAX_S6100_PSU = 2 MAX_S6100_PSU = 2
MAX_S6100_THERMAL = 10 MAX_S6100_THERMAL = 10
BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version"
#components definitions
COMPONENT_BIOS = "BIOS"
SWITCH_CPLD = "CPLD"
SMF_FPGA = "FPGA1"
class Chassis(ChassisBase): class Chassis(ChassisBase):
""" """
@ -54,8 +59,6 @@ class Chassis(ChassisBase):
power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
_component_name_list = ["BIOS", "CPLD1", "CPLD2", "FPGA"]
def __init__(self): def __init__(self):
ChassisBase.__init__(self) ChassisBase.__init__(self)
@ -77,6 +80,11 @@ class Chassis(ChassisBase):
thermal = Thermal(i) thermal = Thermal(i)
self._thermal_list.append(thermal) self._thermal_list.append(thermal)
# Initialize component list
self._component_name_list.append(COMPONENT_BIOS)
self._component_name_list.append(SWITCH_CPLD)
self._component_name_list.append(SMF_FPGA)
def _get_pmc_register(self, reg_name): def _get_pmc_register(self, reg_name):
# On successful read, returns the value read from given # On successful read, returns the value read from given
# reg_name and on failure returns 'ERR' # reg_name and on failure returns 'ERR'
@ -111,36 +119,45 @@ class Chassis(ChassisBase):
def get_name(self): def get_name(self):
""" """
Retrieves the name of the device Retrieves the name of the chassis
Returns: Returns:
string: The name of the device string: The name of the chassis
""" """
return self.sys_eeprom.modelstr() return self.sys_eeprom.modelstr()
def get_presence(self): def get_presence(self):
""" """
Retrieves the presence of the device Retrieves the presence of the chassis
Returns: Returns:
bool: True if device is present, False if not bool: True if chassis is present, False if not
""" """
return True return True
def get_model(self): def get_model(self):
""" """
Retrieves the model number (or part number) of the device Retrieves the model number (or part number) of the chassis
Returns: Returns:
string: Model/part number of device string: Model/part number of chassis
""" """
return self.sys_eeprom.part_number_str() return self.sys_eeprom.part_number_str()
def get_serial(self): def get_serial(self):
""" """
Retrieves the serial number of the device (Service tag) Retrieves the serial number of the chassis (Service tag)
Returns: Returns:
string: Serial number of device string: Serial number of chassis
""" """
return self.sys_eeprom.serial_str() return self.sys_eeprom.serial_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
def get_base_mac(self): def get_base_mac(self):
""" """
Retrieves the base MAC address for the chassis Retrieves the base MAC address for the chassis
@ -156,7 +173,8 @@ class Chassis(ChassisBase):
Retrieves the hardware serial number for the chassis Retrieves the hardware serial number for the chassis
Returns: Returns:
A string containing the hardware serial number for this chassis. A string containing the hardware serial number for this
chassis.
""" """
return self.sys_eeprom.serial_number_str() return self.sys_eeprom.serial_number_str()
@ -200,35 +218,57 @@ class Chassis(ChassisBase):
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
def get_component_name_list(self): def _get_command_result(self, cmdline):
""" try:
Retrieves chassis components list such as BIOS, CPLD, FPGA, etc. proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
shell=True, stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
proc.wait()
result = stdout.rstrip('\n')
except OSError:
result = ''
Returns: return result
A list containing component name.
""" def _get_cpld_version(self):
return self._component_name_list io_resource = "/dev/port"
CPLD1_VERSION_ADDR = 0x100
fd = os.open(io_resource, os.O_RDONLY)
if (fd < 0):
return 'NA'
if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET)
!= CPLD1_VERSION_ADDR):
return 'NA'
buf = os.read(fd, 1)
cpld_version = ord(buf)
os.close(fd)
return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF)
def _get_fpga_version(self):
fpga_ver = float(self._get_pmc_register('smf_firmware_ver'))
return fpga_ver
def get_firmware_version(self, component_name): def get_firmware_version(self, component_name):
"""
Retrieves platform-specific hardware/firmware versions for
chassis componenets such as BIOS, CPLD, FPGA, etc.
Args:
component_name: A string, the component name.
Returns:
A string containing platform-specific component versions
"""
if component_name in self._component_name_list :
if component_name == COMPONENT_BIOS:
return self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
elif component_name == SWITCH_CPLD:
return self._get_cpld_version()
elif component_name == SMF_FPGA:
return self._get_fpga_version()
version = None return None
if component_name in self._component_name_list:
if component_name == self._component_name_list[0]: # BIOS
status, version = getstatusoutput(
"dmidecode -s system-version")
elif component_name == self._component_name_list[1]: # CPLD1
version = None
elif component_name == self._component_name_list[2]: # CPLD2
version = None
elif component_name == self._component_name_list[3]: # SMF
version = None
return version
def install_component_firmware(self, component_name, image_path): def install_component_firmware(self, component_name, image_path):
@ -250,7 +290,7 @@ class Chassis(ChassisBase):
""" """
if component_name in self._component_name_list: if component_name in self._component_name_list:
if component_name == self._component_name_list[0]: # BIOS if component_name == COMPONENT_BIOS: # BIOS
# current BIOS version # current BIOS version
current_bios_version = self.get_firmware_version("BIOS") current_bios_version = self.get_firmware_version("BIOS")
@ -310,16 +350,14 @@ class Chassis(ChassisBase):
image_path image_path
self.run_command(command) self.run_command(command)
elif component_name == self._component_name_list[1]: # CPLD1 elif component_name == SWITCH_CPLD: # CPLD
return False return False
elif component_name == self._component_name_list[2]: # CPLD2 elif component_name == SMF_FPGA: # SMF
return False
elif component_name == self._component_name_list[3]: # SMF
return False return False
else: else:
print "Invalid component Name:", component_name print "Invalid component Name:", component_name
return True return True

View File

@ -209,6 +209,18 @@ class Fan(FanBase):
status = False status = False
return status return status
def get_status_led(self):
"""
Gets the state of the Fan status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings.
"""
if self.get_status():
return self.STATUS_LED_COLOR_GREEN
else:
return self.STATUS_LED_COLOR_OFF
def get_target_speed(self): def get_target_speed(self):
""" """
Retrieves the target (expected) speed of the fan Retrieves the target (expected) speed of the fan

View File

@ -10,6 +10,8 @@
try: try:
import os import os
import subprocess
import re
from sonic_platform_base.chassis_base import ChassisBase from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp from sonic_platform.sfp import Sfp
from sonic_platform.fan import Fan from sonic_platform.fan import Fan
@ -17,10 +19,20 @@ try:
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
MAX_Z9100_FANTRAY = 5 MAX_Z9100_FANTRAY = 5
MAX_Z9100_FAN = 2 MAX_Z9100_FAN = 2
MAX_Z9100_PSU = 2 MAX_Z9100_PSU = 2
BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version"
#components definitions
COMPONENT_BIOS = "BIOS"
SWITCH_CPLD1 = "CPLD1"
SWITCH_CPLD2 = "CPLD2"
SWITCH_CPLD3 = "CPLD3"
SWITCH_CPLD4 = "CPLD4"
SMF_FPGA = "FPGA1"
class Chassis(ChassisBase): class Chassis(ChassisBase):
""" """
@ -92,6 +104,14 @@ class Chassis(ChassisBase):
fan = Fan(i, j) fan = Fan(i, j)
self._fan_list.append(fan) self._fan_list.append(fan)
# Initialize component list
self._component_name_list.append(COMPONENT_BIOS)
self._component_name_list.append(SWITCH_CPLD1)
self._component_name_list.append(SWITCH_CPLD2)
self._component_name_list.append(SWITCH_CPLD3)
self._component_name_list.append(SWITCH_CPLD4)
self._component_name_list.append(SMF_FPGA)
def _get_pmc_register(self, reg_name): def _get_pmc_register(self, reg_name):
# On successful read, returns the value read from given # On successful read, returns the value read from given
# reg_name and on failure returns 'ERR' # reg_name and on failure returns 'ERR'
@ -113,36 +133,45 @@ class Chassis(ChassisBase):
def get_name(self): def get_name(self):
""" """
Retrieves the name of the device Retrieves the name of the chassis
Returns: Returns:
string: The name of the device string: The name of the chassis
""" """
return self.sys_eeprom.modelstr() return self.sys_eeprom.modelstr()
def get_presence(self): def get_presence(self):
""" """
Retrieves the presence of the device Retrieves the presence of the chassis
Returns: Returns:
bool: True if device is present, False if not bool: True if chassis is present, False if not
""" """
return True return True
def get_model(self): def get_model(self):
""" """
Retrieves the model number (or part number) of the device Retrieves the model number (or part number) of the chassis
Returns: Returns:
string: Model/part number of device string: Model/part number of chassis
""" """
return self.sys_eeprom.part_number_str() return self.sys_eeprom.part_number_str()
def get_serial(self): def get_serial(self):
""" """
Retrieves the serial number of the device (Service tag) Retrieves the serial number of the chassis (Service tag)
Returns: Returns:
string: Serial number of device string: Serial number of chassis
""" """
return self.sys_eeprom.serial_str() return self.sys_eeprom.serial_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
def get_base_mac(self): def get_base_mac(self):
""" """
Retrieves the base MAC address for the chassis Retrieves the base MAC address for the chassis
@ -172,7 +201,6 @@ class Chassis(ChassisBase):
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause. to pass a description of the reboot cause.
""" """
reset_reason = int(self._get_pmc_register('smf_reset_reason')) reset_reason = int(self._get_pmc_register('smf_reset_reason'))
power_reason = int(self._get_pmc_register('smf_poweron_reason')) power_reason = int(self._get_pmc_register('smf_poweron_reason'))
@ -192,3 +220,81 @@ class Chassis(ChassisBase):
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
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:
result = ''
return result
def _get_cpld_version(self,cpld_number):
io_resource = "/dev/port"
CPLD1_VERSION_ADDR = 0x100
if (cpld_number == 1):
fd = os.open(io_resource, os.O_RDONLY)
if (fd < 0):
return 'NA'
if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET)
!= CPLD1_VERSION_ADDR):
return 'NA'
buf = os.read(fd, 1)
cpld_version = ord(buf)
os.close(fd)
return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF)
else:
cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e"
"/iom_cpld_vers").format(12 + cpld_number)
if (not os.path.isfile(cpld_version_file)):
return 'NA'
try:
with open(cpld_version_file, 'r') as fd:
ver_str = fd.read()
except Exception as error:
return 'NA'
if ver_str == "read error":
return 'NA'
else:
ver_str = ver_str.rstrip("\r\n")
cpld_version = int(ver_str.split(":")[1], 16)
return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF)
def _get_fpga_version(self):
fpga_ver = float(self._get_pmc_register('smf_firmware_ver'))
return fpga_ver
def get_firmware_version(self, component_name):
"""
Retrieves platform-specific hardware/firmware versions for chassis
componenets such as BIOS, CPLD, FPGA, etc.
Args:
component_name: A string, the component name.
Returns:
A string containing platform-specific component versions
"""
if component_name in self._component_name_list :
if component_name == COMPONENT_BIOS:
return self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
elif component_name == SWITCH_CPLD1:
return self._get_cpld_version(1)
elif component_name == SWITCH_CPLD2:
return self._get_cpld_version(2)
elif component_name == SWITCH_CPLD3:
return self._get_cpld_version(3)
elif component_name == SWITCH_CPLD4:
return self._get_cpld_version(4)
elif component_name == SMF_FPGA:
return self._get_fpga_version()
return None

View File

@ -208,6 +208,18 @@ class Fan(FanBase):
status = False status = False
return status return status
def get_status_led(self):
"""
Gets the state of the Fan status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings.
"""
if self.get_status():
return self.STATUS_LED_COLOR_GREEN
else:
return self.STATUS_LED_COLOR_OFF
def get_target_speed(self): def get_target_speed(self):
""" """
Retrieves the target (expected) speed of the fan Retrieves the target (expected) speed of the fan