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:
commit
a62ab7890e
@ -11,18 +11,34 @@ try:
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
import subprocess
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.sfp import Sfp
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
from sonic_platform.fan import Fan
|
||||
except ImportError as e:
|
||||
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):
|
||||
"""
|
||||
DELLEMC Platform-specific Chassis class
|
||||
"""
|
||||
|
||||
MAILBOX_DIR = "/sys/devices/platform/dell-s6000-cpld.0"
|
||||
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0"
|
||||
|
||||
sfp_control = ""
|
||||
PORT_START = 0
|
||||
@ -54,9 +70,20 @@ class Chassis(ChassisBase):
|
||||
# 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'
|
||||
mb_reg_file = self.MAILBOX_DIR+'/'+reg_name
|
||||
mb_reg_file = self.CPLD_DIR+'/'+reg_name
|
||||
|
||||
if (not os.path.isfile(mb_reg_file)):
|
||||
return rv
|
||||
@ -71,11 +98,85 @@ class Chassis(ChassisBase):
|
||||
rv = rv.lstrip(" ")
|
||||
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):
|
||||
"""
|
||||
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
|
||||
# NVRAM. Only Warmboot and Coldboot reason are supported here.
|
||||
@ -85,6 +186,46 @@ class Chassis(ChassisBase):
|
||||
|
||||
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):
|
||||
presence_ctrl = self.sfp_control + 'qsfp_modprs'
|
||||
try:
|
||||
@ -151,3 +292,4 @@ class Chassis(ChassisBase):
|
||||
return True, {}
|
||||
return False, {}
|
||||
|
||||
|
||||
|
@ -35,7 +35,8 @@ psu_eeprom_format = [
|
||||
fan_eeprom_format = [
|
||||
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
|
||||
('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)
|
||||
]
|
||||
|
||||
@ -86,6 +87,8 @@ class Eeprom(TlvInfoDecoder):
|
||||
self.base_mac = 'NA'
|
||||
self.serial_number = 'NA'
|
||||
self.part_number = 'NA'
|
||||
self.model_str = 'NA'
|
||||
self.serial = 'NA'
|
||||
self.eeprom_tlv_dict = dict()
|
||||
else:
|
||||
eeprom = self.eeprom_data
|
||||
@ -95,6 +98,8 @@ class Eeprom(TlvInfoDecoder):
|
||||
self.base_mac = 'NA'
|
||||
self.serial_number = 'NA'
|
||||
self.part_number = 'NA'
|
||||
self.model_str = 'NA'
|
||||
self.serial = 'NA'
|
||||
return
|
||||
|
||||
total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10])
|
||||
@ -123,11 +128,15 @@ class Eeprom(TlvInfoDecoder):
|
||||
tlv_index += ord(eeprom[tlv_index+1]) + 2
|
||||
|
||||
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(
|
||||
hex(self._TLV_CODE_SERIAL_NUMBER), 'NA')
|
||||
"0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
|
||||
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):
|
||||
"""
|
||||
@ -151,7 +160,7 @@ class Eeprom(TlvInfoDecoder):
|
||||
if valid:
|
||||
self.serial_number += "-" + data
|
||||
else:
|
||||
seld.serial_number = 'NA'
|
||||
self.serial_number = 'NA'
|
||||
|
||||
(valid, data) = self._get_eeprom_field("Part Number")
|
||||
if valid:
|
||||
@ -159,6 +168,12 @@ class Eeprom(TlvInfoDecoder):
|
||||
else:
|
||||
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):
|
||||
"""
|
||||
For a field name specified in the EEPROM format, returns the
|
||||
@ -185,6 +200,12 @@ class Eeprom(TlvInfoDecoder):
|
||||
"""
|
||||
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
|
||||
def base_mac_addr(self):
|
||||
"""
|
||||
@ -192,6 +213,18 @@ class Eeprom(TlvInfoDecoder):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Returns a dictionary, where keys are the type code defined in
|
||||
|
@ -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
|
@ -15,7 +15,6 @@ try:
|
||||
import subprocess
|
||||
import glob
|
||||
import sonic_device_util
|
||||
from commands import getstatusoutput
|
||||
from sonic_platform_base.platform_base import PlatformBase
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.sfp import Sfp
|
||||
@ -32,6 +31,12 @@ MAX_S6100_FAN = 4
|
||||
MAX_S6100_PSU = 2
|
||||
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):
|
||||
"""
|
||||
@ -54,8 +59,6 @@ class Chassis(ChassisBase):
|
||||
power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
|
||||
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
||||
|
||||
_component_name_list = ["BIOS", "CPLD1", "CPLD2", "FPGA"]
|
||||
|
||||
def __init__(self):
|
||||
|
||||
ChassisBase.__init__(self)
|
||||
@ -77,6 +80,11 @@ class Chassis(ChassisBase):
|
||||
thermal = Thermal(i)
|
||||
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):
|
||||
# On successful read, returns the value read from given
|
||||
# reg_name and on failure returns 'ERR'
|
||||
@ -111,36 +119,45 @@ class Chassis(ChassisBase):
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Retrieves the name of the chassis
|
||||
Returns:
|
||||
string: The name of the device
|
||||
string: The name of the chassis
|
||||
"""
|
||||
return self.sys_eeprom.modelstr()
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the device
|
||||
Retrieves the presence of the chassis
|
||||
Returns:
|
||||
bool: True if device is present, False if not
|
||||
bool: True if chassis is present, False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
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:
|
||||
string: Model/part number of device
|
||||
string: Model/part number of chassis
|
||||
"""
|
||||
return self.sys_eeprom.part_number_str()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the device (Service tag)
|
||||
Retrieves the serial number of the chassis (Service tag)
|
||||
Returns:
|
||||
string: Serial number of device
|
||||
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
|
||||
@ -156,7 +173,8 @@ class Chassis(ChassisBase):
|
||||
Retrieves the hardware serial number for the chassis
|
||||
|
||||
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()
|
||||
|
||||
@ -200,35 +218,57 @@ class Chassis(ChassisBase):
|
||||
|
||||
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
|
||||
|
||||
def get_component_name_list(self):
|
||||
"""
|
||||
Retrieves chassis components list such as BIOS, CPLD, FPGA, etc.
|
||||
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 = ''
|
||||
|
||||
Returns:
|
||||
A list containing component name.
|
||||
"""
|
||||
return self._component_name_list
|
||||
return result
|
||||
|
||||
def _get_cpld_version(self):
|
||||
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):
|
||||
"""
|
||||
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
|
||||
|
||||
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
|
||||
return None
|
||||
|
||||
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 == self._component_name_list[0]: # BIOS
|
||||
if component_name == COMPONENT_BIOS: # BIOS
|
||||
|
||||
# current BIOS version
|
||||
current_bios_version = self.get_firmware_version("BIOS")
|
||||
@ -310,16 +350,14 @@ class Chassis(ChassisBase):
|
||||
image_path
|
||||
self.run_command(command)
|
||||
|
||||
elif component_name == self._component_name_list[1]: # CPLD1
|
||||
elif component_name == SWITCH_CPLD: # CPLD
|
||||
return False
|
||||
|
||||
elif component_name == self._component_name_list[2]: # CPLD2
|
||||
return False
|
||||
|
||||
elif component_name == self._component_name_list[3]: # SMF
|
||||
elif component_name == SMF_FPGA: # SMF
|
||||
return False
|
||||
else:
|
||||
print "Invalid component Name:", component_name
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -209,6 +209,18 @@ class Fan(FanBase):
|
||||
status = False
|
||||
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):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
try:
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.sfp import Sfp
|
||||
from sonic_platform.fan import Fan
|
||||
@ -17,10 +19,20 @@ try:
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
MAX_Z9100_FANTRAY = 5
|
||||
MAX_Z9100_FAN = 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):
|
||||
"""
|
||||
@ -92,6 +104,14 @@ class Chassis(ChassisBase):
|
||||
fan = Fan(i, j)
|
||||
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):
|
||||
# On successful read, returns the value read from given
|
||||
# reg_name and on failure returns 'ERR'
|
||||
@ -113,36 +133,45 @@ class Chassis(ChassisBase):
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Retrieves the name of the chassis
|
||||
Returns:
|
||||
string: The name of the device
|
||||
string: The name of the chassis
|
||||
"""
|
||||
return self.sys_eeprom.modelstr()
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the device
|
||||
Retrieves the presence of the chassis
|
||||
Returns:
|
||||
bool: True if device is present, False if not
|
||||
bool: True if chassis is present, False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
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:
|
||||
string: Model/part number of device
|
||||
string: Model/part number of chassis
|
||||
"""
|
||||
return self.sys_eeprom.part_number_str()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the device (Service tag)
|
||||
Retrieves the serial number of the chassis (Service tag)
|
||||
Returns:
|
||||
string: Serial number of device
|
||||
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
|
||||
@ -172,7 +201,6 @@ class Chassis(ChassisBase):
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
"""
|
||||
|
||||
reset_reason = int(self._get_pmc_register('smf_reset_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")
|
||||
|
||||
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
|
||||
|
@ -208,6 +208,18 @@ class Fan(FanBase):
|
||||
status = False
|
||||
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):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
|
Loading…
Reference in New Issue
Block a user