diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py index a625a796ef..5db6f86a5a 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py @@ -9,18 +9,35 @@ try: import os + import subprocess + import re 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" reset_reason_dict = {} reset_reason_dict[0xe] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE @@ -45,9 +62,20 @@ class Chassis(ChassisBase): sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, index) self._sfp_list.append(sfp_node) - 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 @@ -62,11 +90,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. @@ -76,3 +178,42 @@ 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 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py index b39b140c72..3d824ba282 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py @@ -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 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py new file mode 100644 index 0000000000..126f1c2941 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py @@ -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 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py index 53d4eadaec..c69519fb6c 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py @@ -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.psu import Psu @@ -18,9 +20,16 @@ try: except ImportError as e: raise ImportError(str(e) + "- required module not found") + MAX_S6100_FAN = 4 MAX_S6100_PSU = 2 +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" +#components definitions +COMPONENT_BIOS = "BIOS" +SWITCH_CPLD = "CPLD" +SMF_FPGA = "FPGA1" + class Chassis(ChassisBase): """ @@ -89,6 +98,11 @@ class Chassis(ChassisBase): psu = Psu(i) self._psu_list.append(psu) + # Initialize component list + self._component_name_list.append(COMPONENT_BIOS) + self._component_name_list.append(SWITCH_CPLD) + self._component_name_list.append(SMF_FPGA) + self._populate_port_i2c_mapping() # sfp.py will read eeprom contents and retrive the eeprom data. @@ -143,36 +157,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 @@ -188,7 +211,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() @@ -230,3 +254,55 @@ class Chassis(ChassisBase): return (self.reset_reason_dict[reset_reason], None) 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): + 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() + + return None diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py index c822ccdae2..4aa996ad78 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py @@ -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 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py index f912b806d0..364b97b7d0 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py @@ -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 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py index 2327e24a2f..9460beb8c8 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py @@ -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