Beispiel #1
0
    def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
        FanBase.__init__(self)
        self.fan_index = fan_index
        self._api_helper = APIHelper()
        self.fan_tray_index = fan_tray_index
        self.is_psu_fan = is_psu_fan
        if self.is_psu_fan:
            self.psu_index = psu_index
            self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]["num"]
            self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]["addr"]
            self.psu_hwmon_path = PSU_HWMON_PATH.format(
                self.psu_i2c_num, self.psu_i2c_addr)

        # dx010 fan attributes
        # Two EMC2305s located at i2c-13-4d and i2c-13-2e
        # to control a dual-fan module.
        self.emc2305_chip_mapping = [
            {
                'device': "13-002e",
                'index_map': [2, 1, 4, 5, 3]
            },
            {
                'device': "13-004d",
                'index_map': [2, 4, 5, 3, 1]
            }
        ]
        self.dx010_fan_gpio = [
            {'base': self.__get_gpio_base()},
            {'prs': 11, 'dir': 16, 'color': {'red': 31, 'green': 32}},  # 1
            {'prs': 10, 'dir': 15, 'color': {'red': 29, 'green': 30}},  # 2
            {'prs': 13, 'dir': 18, 'color': {'red': 35, 'green': 36}},  # 3
            {'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}},  # 4
            {'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}},  # 5
        ]
Beispiel #2
0
 def __init__(self, psu_index):
     PsuBase.__init__(self)
     self.index = psu_index
     for fan_index in range(0, PSU_NUM_FAN[self.index]):
         fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
         self._fan_list.append(fan)
     self._api_helper = APIHelper()
Beispiel #3
0
 def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
     self.fan_index = fan_index
     self.fan_tray_index = fan_tray_index
     self.is_psu_fan = is_psu_fan
     if self.is_psu_fan:
         self.psu_index = psu_index
     self._api_helper = APIHelper()
     self.index = self.fan_tray_index * 2 + self.fan_index
 def __init__(self, thermal_index, airflow):
     self.index = thermal_index
     self._api_helper = APIHelper()
     self._airflow = airflow
     self._thermal_info = THERMAL_INFO[self.index]
     self._hwmon_path = "{}/{}".format(I2C_ADAPTER_PATH,
                                       self._thermal_info["i2c_path"])
     self.name = self.get_name()
     self.postion = self._thermal_info["postion"]
     self.ss_index = 1
    def __init__(self):
        self.config_data = {}
        ChassisBase.__init__(self)
        self._eeprom = Tlv()
        self._api_helper = APIHelper()

        for fant_index in range(0, NUM_FAN_TRAY):
            for fan_index in range(0, NUM_FAN):
                fan = Fan(fant_index, fan_index)
                self._fan_list.append(fan)
Beispiel #6
0
    def __init__(self):
        # Init helper
        self._api_helper = APIHelper()

        # Init cpld reg path
        self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE)
        self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE)

        # Set default value
        self._disable()
        self.armed = False
        self.timeout = self._gettimeout()
    def __init__(self):
        ChassisBase.__init__(self)
        self._api_helper = APIHelper()
        self.sfp_module_initialized = False
        self.__initialize_eeprom()
        self.is_host = self._api_helper.is_host()

        if not self.is_host:
            self.__initialize_fan()
            self.__initialize_psu()
            self.__initialize_thermals()
        else:
            self.__initialize_components()
Beispiel #8
0
 def __init__(self, psu_index):
     PsuBase.__init__(self)
     self.index = psu_index
     self._api_helper = APIHelper()
     self.green_led_path = GREEN_LED_PATH.format(self.index + 1)
     self.dx010_psu_gpio = [{
         'base': self.__get_gpio_base()
     }, {
         'prs': 27,
         'status': 22
     }, {
         'prs': 28,
         'status': 25
     }]
     self.i2c_num = PSU_I2C_MAPPING[self.index]["num"]
     self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"]
     self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr)
     for fan_index in range(0, PSU_NUM_FAN[self.index]):
         fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
         self._fan_list.append(fan)
Beispiel #9
0
 def __init__(self, thermal_index):
     ThermalBase.__init__(self)
     self._api_helper = APIHelper()
     self.index = thermal_index
     self.THERMAL_LIST = [
         ('TEMP_FAN_U52', 'Fan Tray Middle Temperature Sensor', '0x00'),
         ('TEMP_FAN_U17', 'Fan Tray Right Temperature Sensor', '0x01'),
         ('TEMP_SW_U52', 'Switchboard Left Inlet Temperature Sensor',
          '0x02'),
         ('TEMP_SW_U16', 'Switchboard Right Inlet Temperature Sensor',
          '0x03'),
         ('TEMP_BB_U3', 'Baseboard Temperature Sensor', '0x04'),
         ('TEMP_CPU', 'CPU Internal Temperature Sensor', '0x05'),
         ('TEMP_SW_Internal', 'ASIC Internal Temperature Sensor', '0x61'),
         ('SW_U04_Temp', 'IR3595 Chip Left Temperature Sensor', '0x4F'),
         ('SW_U14_Temp', 'IR3595 Chip Right Temperature Sensor', '0x56'),
         ('SW_U4403_Temp', 'IR3584 Chip Temperature Sensor', '0x5D'),
     ]
     self.sensor_id = self.THERMAL_LIST[self.index][0]
     self.sensor_des = self.THERMAL_LIST[self.index][1]
     self.sensor_reading_addr = self.THERMAL_LIST[self.index][2]
Beispiel #10
0
    def __init__(self, thermal_index):
        self.index = thermal_index
        self._api_helper = APIHelper()

        # Add thermal name
        self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
        self.THERMAL_NAME_LIST.append("Front-panel temp sensor 2")
        self.THERMAL_NAME_LIST.append("ASIC temp sensor")
        self.THERMAL_NAME_LIST.append("Rear-panel temp sensor 1")
        self.THERMAL_NAME_LIST.append("Rear-panel temp sensor 2")

        # Set hwmon path
        i2c_path = {
            0: "i2c-5/5-0048/hwmon/hwmon1",  # u4 system-inlet
            1: "i2c-6/6-0049/hwmon/hwmon2",  # u2 system-inlet
            2: "i2c-7/7-004a/hwmon/hwmon3",  # u44 bmc56960-on-board
            3: "i2c-14/14-0048/hwmon/hwmon4",  # u9200 cpu-on-board
            4: "i2c-15/15-004e/hwmon/hwmon5"  # u9201 system-outlet
        }.get(self.index, None)

        self.hwmon_path = "{}/{}".format(self.I2C_ADAPTER_PATH, i2c_path)
        self.ss_key = self.THERMAL_NAME_LIST[self.index]
        self.ss_index = 1
Beispiel #11
0
    def __init__(self):
        self.config_data = {}
        ChassisBase.__init__(self)
        self._eeprom = Tlv()
        self._api_helper = APIHelper()

        for fant_index in range(0, NUM_FAN_TRAY):
            for fan_index in range(0, NUM_FAN):
                fan = Fan(fant_index, fan_index)
                self._fan_list.append(fan)

        for index in range(0, NUM_SFP):
            sfp = Sfp(index)
            self._sfp_list.append(sfp)

        for index in range(0, NUM_PSU):
            psu = Psu(index)
            self._psu_list.append(psu)
        for index in range(0, NUM_COMPONENT):
            component = Component(index)
            self._component_list.append(component)
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)
Beispiel #12
0
class Thermal(ThermalBase):
    """Platform-specific Thermal class"""

    THERMAL_NAME_LIST = []
    I2C_ADAPTER_PATH = "/sys/class/i2c-adapter"
    SS_CONFIG_PATH = "/usr/share/sonic/device/x86_64-cel_seastone-r0/sensors.conf"

    def __init__(self, thermal_index):
        self.index = thermal_index
        self._api_helper = APIHelper()

        # Add thermal name
        self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
        self.THERMAL_NAME_LIST.append("Front-panel temp sensor 2")
        self.THERMAL_NAME_LIST.append("ASIC temp sensor")
        self.THERMAL_NAME_LIST.append("Rear-panel temp sensor 1")
        self.THERMAL_NAME_LIST.append("Rear-panel temp sensor 2")

        # Set hwmon path
        i2c_path = {
            0: "i2c-5/5-0048/hwmon/hwmon1",  # u4 system-inlet
            1: "i2c-6/6-0049/hwmon/hwmon2",  # u2 system-inlet
            2: "i2c-7/7-004a/hwmon/hwmon3",  # u44 bmc56960-on-board
            3: "i2c-14/14-0048/hwmon/hwmon4",  # u9200 cpu-on-board
            4: "i2c-15/15-004e/hwmon/hwmon5"  # u9201 system-outlet
        }.get(self.index, None)

        self.hwmon_path = "{}/{}".format(self.I2C_ADAPTER_PATH, i2c_path)
        self.ss_key = self.THERMAL_NAME_LIST[self.index]
        self.ss_index = 1

    def __get_temp(self, temp_file):
        temp_file_path = os.path.join(self.hwmon_path, temp_file)
        raw_temp = self._api_helper.read_txt_file(temp_file_path)
        temp = float(raw_temp) / 1000
        return float("{:.3f}".format(temp))

    def __set_threshold(self, file_name, temperature):
        temp_file_path = os.path.join(self.hwmon_path, file_name)
        try:
            with open(temp_file_path, 'w') as fd:
                fd.write(str(temperature))
            return True
        except IOError:
            return False

    def get_temperature(self):
        """
        Retrieves current temperature reading from thermal
        Returns:
            A float number of current temperature in Celsius up to nearest thousandth
            of one degree Celsius, e.g. 30.125
        """
        temp_file = "temp{}_input".format(self.ss_index)
        return self.__get_temp(temp_file)

    def get_high_threshold(self):
        """
        Retrieves the high threshold temperature of thermal
        Returns:
            A float number, the high threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        temp_file = "temp{}_max".format(self.ss_index)
        return self.__get_temp(temp_file)

    def set_high_threshold(self, temperature):
        """
        Sets the high threshold temperature of thermal
        Args :
            temperature: A float number up to nearest thousandth of one degree Celsius,
            e.g. 30.125
        Returns:
            A boolean, True if threshold is set successfully, False if not
        """
        temp_file = "temp{}_max".format(self.ss_index)
        is_set = self.__set_threshold(temp_file, int(temperature * 1000))
        file_set = False
        if is_set:
            try:
                with open(self.SS_CONFIG_PATH, 'r+') as f:
                    content = f.readlines()
                    f.seek(0)
                    ss_found = False
                    for idx, val in enumerate(content):
                        if self.ss_key in val:
                            ss_found = True
                        elif ss_found and temp_file in val:
                            content[idx] = "    set {} {}\n".format(
                                temp_file, temperature)
                            f.writelines(content)
                            file_set = True
                            break
            except IOError:
                file_set = False

        return is_set & file_set

    def get_name(self):
        """
        Retrieves the name of the thermal device
            Returns:
            string: The name of the thermal device
        """
        return self.THERMAL_NAME_LIST[self.index]

    def get_presence(self):
        """
        Retrieves the presence of the PSU
        Returns:
            bool: True if PSU is present, False if not
        """
        temp_file = "temp{}_input".format(self.ss_index)
        temp_file_path = os.path.join(self.hwmon_path, temp_file)
        return os.path.isfile(temp_file_path)

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        if not self.get_presence():
            return False

        fault_file = "temp{}_fault".format(self.ss_index)
        fault_file_path = os.path.join(self.hwmon_path, fault_file)
        if not os.path.isfile(fault_file_path):
            return True

        raw_txt = self.__read_txt_file(fault_file_path)
        return int(raw_txt) == 0
Beispiel #13
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""
    def __init__(self):
        self.config_data = {}
        ChassisBase.__init__(self)
        self._eeprom = Tlv()
        self._api_helper = APIHelper()

        for fant_index in range(0, NUM_FAN_TRAY):
            for fan_index in range(0, NUM_FAN):
                fan = Fan(fant_index, fan_index)
                self._fan_list.append(fan)

        for index in range(0, NUM_SFP):
            sfp = Sfp(index)
            self._sfp_list.append(sfp)

        for index in range(0, NUM_PSU):
            psu = Psu(index)
            self._psu_list.append(psu)
        for index in range(0, NUM_COMPONENT):
            component = Component(index)
            self._component_list.append(component)
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

    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._eeprom.get_mac()

    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._eeprom.get_serial()

    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._eeprom.get_eeprom()

    def get_reboot_cause(self):
        """
        Retrieves the cause of the previous reboot

        Returns:
            A tuple (string, string) where the first element is a string
            containing the cause of the previous reboot. This string must be
            one of the predefined strings in this class. If the first string
            is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
            to pass a description of the reboot cause.
        """

        status, raw_cause = self._api_helper.ipmi_raw(IPMI_OEM_NETFN,
                                                      IPMI_GET_REBOOT_CAUSE)
        hx_cause = raw_cause.split()[0] if status and len(
            raw_cause.split()) > 0 else 00
        reboot_cause = {
            "00": self.REBOOT_CAUSE_HARDWARE_OTHER,
            "11": self.REBOOT_CAUSE_POWER_LOSS,
            "22": self.REBOOT_CAUSE_NON_HARDWARE,
            "33": self.REBOOT_CAUSE_HARDWARE_OTHER,
            "44": self.REBOOT_CAUSE_NON_HARDWARE,
            "55": self.REBOOT_CAUSE_NON_HARDWARE,
            "66": self.REBOOT_CAUSE_WATCHDOG,
            "77": self.REBOOT_CAUSE_NON_HARDWARE
        }.get(hx_cause, self.REBOOT_CAUSE_HARDWARE_OTHER)

        description = {
            "00": "Unknown reason",
            "11": "The last reset is Power on reset",
            "22": "The last reset is soft-set CPU warm reset",
            "33": "The last reset is soft-set CPU cold reset",
            "44": "The last reset is CPU warm reset",
            "55": "The last reset is CPU cold reset",
            "66": "The last reset is watchdog reset",
            "77": "The last reset is power cycle reset"
        }.get(hx_cause, "Unknown reason")

        return (reboot_cause, description)
Beispiel #14
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""
    def __init__(self):
        ChassisBase.__init__(self)
        self._api_helper = APIHelper()
        self.sfp_module_initialized = False
        self.__initialize_eeprom()
        self.is_host = self._api_helper.is_host()

        if not self.is_host:
            self.__initialize_fan()
            self.__initialize_psu()
            self.__initialize_thermals()
        else:
            self.__initialize_components()

    def __initialize_sfp(self):
        from sonic_platform.sfp import Sfp
        for index in range(0, NUM_SFP):
            sfp = Sfp(index)
            self._sfp_list.append(sfp)
        self.sfp_module_initialized = True

    def __initialize_psu(self):
        from sonic_platform.psu import Psu
        for index in range(0, NUM_PSU):
            psu = Psu(index)
            self._psu_list.append(psu)

    def __initialize_fan(self):
        from sonic_platform.fan import Fan
        for fant_index in range(0, NUM_FAN_TRAY):
            for fan_index in range(0, NUM_FAN):
                fan = Fan(fant_index, fan_index)
                self._fan_list.append(fan)

    def __initialize_thermals(self):
        from sonic_platform.thermal import Thermal
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

    def __initialize_eeprom(self):
        from sonic_platform.eeprom import Tlv
        self._eeprom = Tlv()

    def __initialize_components(self):
        from sonic_platform.component import Component
        for index in range(0, NUM_COMPONENT):
            component = Component(index)
            self._component_list.append(component)

    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._eeprom.get_mac()

    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._eeprom.get_serial()

    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._eeprom.get_eeprom()

    def get_reboot_cause(self):
        """
        Retrieves the cause of the previous reboot
        Returns:
            A tuple (string, string) where the first element is a string
            containing the cause of the previous reboot. This string must be
            one of the predefined strings in this class. If the first string
            is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
            to pass a description of the reboot cause.
        """
        description = 'None'
        reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER

        reboot_cause_path = (
            HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
        ) if self.is_host else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
        prev_reboot_cause_path = (
            HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
        ) if self.is_host else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE

        hw_reboot_cause = self._component_list[0].get_register_value(
            RESET_REGISTER)

        sw_reboot_cause = self._api_helper.read_txt_file(
            reboot_cause_path) or "Unknown"
        prev_sw_reboot_cause = self._api_helper.read_txt_file(
            prev_reboot_cause_path) or "Unknown"

        if sw_reboot_cause == "Unknown" and (
                prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause
                == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11":
            reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
        elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11":
            reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
            description = sw_reboot_cause
        elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11":
            reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
            description = prev_sw_reboot_cause
        elif hw_reboot_cause == "0x22":
            reboot_cause = self.REBOOT_CAUSE_WATCHDOG,
        else:
            reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
            description = 'Unknown reason'

        return (reboot_cause, description)

    ##############################################################
    ######################## SFP methods #########################
    ##############################################################

    def get_num_sfps(self):
        """
        Retrieves the number of sfps available on this chassis
        Returns:
            An integer, the number of sfps available on this chassis
        """
        if not self.sfp_module_initialized:
            self.__initialize_sfp()

        return len(self._sfp_list)

    def get_all_sfps(self):
        """
        Retrieves all sfps available on this chassis
        Returns:
            A list of objects derived from SfpBase representing all sfps
            available on this chassis
        """
        if not self.sfp_module_initialized:
            self.__initialize_sfp()

        return self._sfp_list

    def get_sfp(self, index):
        """
        Retrieves sfp represented by (1-based) index <index>
        Args:
            index: An integer, the index (1-based) of the sfp to retrieve.
            The index should be the sequence of a physical port in a chassis,
            starting from 1.
            For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
        Returns:
            An object dervied from SfpBase representing the specified sfp
        """
        sfp = None
        if not self.sfp_module_initialized:
            self.__initialize_sfp()

        try:
            # The index will start from 1
            sfp = self._sfp_list[index - 1]
        except IndexError:
            sys.stderr.write("SFP index {} out of range (1-{})\n".format(
                index, len(self._sfp_list)))
        return sfp

    ##############################################################
    ####################### Other methods ########################
    ##############################################################

    def get_watchdog(self):
        """
        Retreives hardware watchdog device on this chassis
        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device
        """
        if self._watchdog is None:
            from sonic_platform.watchdog import Watchdog
            self._watchdog = Watchdog()

        return self._watchdog

    ##############################################################
    ###################### Device methods ########################
    ##############################################################

    def get_name(self):
        """
        Retrieves the name of the device
            Returns:
            string: The name of the device
        """
        return self._api_helper.hwsku

    def get_presence(self):
        """
        Retrieves the presence of the PSU
        Returns:
            bool: True if PSU is present, False if not
        """
        return True

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device
        Returns:
            string: Model/part number of device
        """
        return self._eeprom.get_pn()

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        return self.get_serial_number()

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        return True
Beispiel #15
0
class Fan(FanBase):
    """Platform-specific Fan class"""

    def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
        FanBase.__init__(self)
        self.fan_index = fan_index
        self._api_helper = APIHelper()
        self.fan_tray_index = fan_tray_index
        self.is_psu_fan = is_psu_fan
        if self.is_psu_fan:
            self.psu_index = psu_index
            self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]["num"]
            self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]["addr"]
            self.psu_hwmon_path = PSU_HWMON_PATH.format(
                self.psu_i2c_num, self.psu_i2c_addr)

        # dx010 fan attributes
        # Two EMC2305s located at i2c-13-4d and i2c-13-2e
        # to control a dual-fan module.
        self.emc2305_chip_mapping = [
            {
                'device': "13-002e",
                'index_map': [2, 1, 4, 5, 3]
            },
            {
                'device': "13-004d",
                'index_map': [2, 4, 5, 3, 1]
            }
        ]
        self.dx010_fan_gpio = [
            {'base': self.__get_gpio_base()},
            {'prs': 11, 'dir': 16, 'color': {'red': 31, 'green': 32}},  # 1
            {'prs': 10, 'dir': 15, 'color': {'red': 29, 'green': 30}},  # 2
            {'prs': 13, 'dir': 18, 'color': {'red': 35, 'green': 36}},  # 3
            {'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}},  # 4
            {'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}},  # 5
        ]

    def __write_txt_file(self, file_path, value):
        try:
            with open(file_path, 'w') as fd:
                fd.write(str(value))
        except:
            return False
        return True

    def __search_file_by_name(self, directory, file_name):
        for dirpath, dirnames, files in os.walk(directory):
            for name in files:
                file_path = os.path.join(dirpath, name)
                if name in file_name:
                    return file_path
        return None

    def __get_gpio_base(self):
        for r in os.listdir(GPIO_DIR):
            label_path = os.path.join(GPIO_DIR, r, "label")
            if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
                return int(r[8:], 10)
        return 216  # Reserve

    def __get_gpio_value(self, pinnum):
        gpio_base = self.dx010_fan_gpio[0]['base']
        gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
        gpio_file = gpio_dir + "/value"
        retval = self._api_helper.read_txt_file(gpio_file)
        return retval.rstrip('\r\n')

    def __set_gpio_value(self, pinnum, value=0):
        gpio_base = self.dx010_fan_gpio[0]['base']
        gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
        gpio_file = gpio_dir + "/value"
        return self.__write_txt_file(gpio_file, value)

    def get_direction(self):
        """
        Retrieves the direction of fan
        Returns:
            A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
            depending on fan direction
        """
        direction = self.FAN_DIRECTION_EXHAUST
        if not self.is_psu_fan:
            raw = self.__get_gpio_value(
                self.dx010_fan_gpio[self.fan_tray_index+1]['dir'])

            direction = self.FAN_DIRECTION_INTAKE if int(
                raw, 10) == 0 else self.FAN_DIRECTION_EXHAUST

        return direction

    def get_speed(self):
        """
        Retrieves the speed of fan as a percentage of full speed
        Returns:
            An integer, the percentage of full fan speed, in the range 0 (off)
                 to 100 (full speed)

        Note:
            speed = pwm_in/255*100
        """
        speed = 0
        if self.is_psu_fan:
            fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
            fan_speed_sysfs_path = self.__search_file_by_name(
                self.psu_hwmon_path, fan_speed_sysfs_name)
            fan_speed_rpm = self._api_helper.read_txt_file(
                fan_speed_sysfs_path) or 0
            fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
            speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
        elif self.get_presence():
            chip = self.emc2305_chip_mapping[self.fan_index]
            device = chip['device']
            fan_index = chip['index_map']
            sysfs_path = "%s%s/%s" % (
                EMC2305_PATH, device, EMC2305_FAN_INPUT)
            sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
            raw = self._api_helper.read_txt_file(sysfs_path).strip('\r\n')
            pwm = int(raw, 10) if raw else 0
            speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))

        return int(speed)

    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)

        Note:
            speed_pc = pwm_target/255*100

            0   : when PWM mode is use
            pwm : when pwm mode is not use
        """
        return 'N/A'

    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
        """
        return 10

    def set_speed(self, speed):
        """
        Sets the fan speed
        Args:
            speed: An integer, the percentage of full fan speed to set fan to,
                   in the range 0 (off) to 100 (full speed)
        Returns:
            A boolean, True if speed is set successfully, False if not

        Note:
            Depends on pwm or target mode is selected:
            1) pwm = speed_pc * 255             <-- Currently use this mode.
            2) target_pwm = speed_pc * 100 / 255
             2.1) set pwm{}_enable to 3

        """
        pwm = speed * 255 / 100
        if not self.is_psu_fan and self.get_presence():
            chip = self.emc2305_chip_mapping[self.fan_index]
            device = chip['device']
            fan_index = chip['index_map']
            sysfs_path = "%s%s/%s" % (
                EMC2305_PATH, device, EMC2305_FAN_PWM)
            sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
            return self.__write_txt_file(sysfs_path, int(pwm))

        return False

    def set_status_led(self, color):
        """
        Sets the state of the fan module status LED
        Args:
            color: A string representing the color with which to set the
                   fan module status LED
        Returns:
            bool: True if status LED state is set successfully, False if not
        """
        set_status_led = False
        if not self.is_psu_fan:
            s1, s2 = False, False
            try:
                if color == self.STATUS_LED_COLOR_GREEN:
                    s1 = self.__set_gpio_value(
                        self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 1)
                    s2 = self.__set_gpio_value(
                        self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 0)

                elif color == self.STATUS_LED_COLOR_RED:
                    s1 = self.__set_gpio_value(
                        self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 0)
                    s2 = self.__set_gpio_value(
                        self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 1)

                elif color == self.STATUS_LED_COLOR_OFF:
                    s1 = self.__set_gpio_value(
                        self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 1)
                    s2 = self.__set_gpio_value(
                        self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 1)
                set_status_led = s1 and s2
                return set_status_led
            except IOError:
                return False

        return set_status_led

    def get_name(self):
        """
        Retrieves the name of the device
            Returns:
            string: The name of the device
        """
        fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] if not self.is_psu_fan else "PSU-{} FAN-{}".format(
            self.psu_index+1, self.fan_index+1)

        return fan_name

    def get_presence(self):
        """
        Retrieves the presence of the FAN
        Returns:
            bool: True if FAN is present, False if not
        """
        present_str = self.__get_gpio_value(
            self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])

        return int(present_str, 10) == 0 if not self.is_psu_fan else True

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device
        Returns:
            string: Model/part number of device
        """
        if self.is_psu_fan:
            return NULL_VAL

        model = NULL_VAL
        return model

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        if self.is_psu_fan:
            return NULL_VAL

        serial = NULL_VAL
        return serial

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        status = 1
        if self.is_psu_fan:
            fan_fault_sysfs_name = "fan1_fault"
            fan_fault_sysfs_path = self.__search_file_by_name(
                self.psu_hwmon_path, fan_fault_sysfs_name)
            status = self._api_helper.read_one_line_file(fan_fault_sysfs_path)

        elif self.get_presence():
            chip = self.emc2305_chip_mapping[self.fan_index]
            device = chip['device']
            fan_index = chip['index_map']
            sysfs_path = "%s%s/%s" % (
                EMC2305_PATH, device, 'fan{}_fault')
            sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
            status = self._api_helper.read_one_line_file(sysfs_path)

        return False if int(status) != 0 else True
class Fan(FanBase):
    """Platform-specific Fan class"""
    def __init__(self,
                 fan_tray_index,
                 fan_index=0,
                 is_psu_fan=False,
                 psu_index=0):
        self.fan_index = fan_index
        self.fan_tray_index = fan_tray_index
        self.is_psu_fan = is_psu_fan
        if self.is_psu_fan:
            self.psu_index = psu_index
        self._api_helper = APIHelper()
        self.index = self.fan_tray_index * 2 + self.fan_index

    def get_direction(self):
        """
        Retrieves the direction of fan
        Returns:
            A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
            depending on fan direction
        """
        direction = self.FAN_DIRECTION_EXHAUST
        status, raw_flow = self._api_helper.ipmi_raw(
            IPMI_OEM_NETFN, IPMI_AIR_FLOW_CMD.format(hex(self.fan_tray_index)))
        if status and raw_flow == "01":
            direction = self.FAN_DIRECTION_INTAKE

        return direction

    def get_speed(self):
        """
        Retrieves the speed of fan as a percentage of full speed
        Returns:
            An integer, the percentage of full fan speed, in the range 0 (off)
                 to 100 (full speed)

        Note:
            M = 150
            Max F2B = 24700 RPM 
            Max B2F = 29700 RPM
        """
        # ipmitool raw 0x3a 0x03 0x01 0x01 {register}
        # register = 22 32 42 52 62 72 82

        max_rpm = MAX_OUTLET if self.fan_index % 2 == 0 else MAX_INLET
        fan1_ss_start = FAN1_FRONT_SS_ID if self.fan_index % 2 == 0 else FAN1_REAR_SS_ID

        ss_id = hex(int(fan1_ss_start, 16) + self.fan_tray_index)
        status, raw_ss_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN, IPMI_FAN_SPEED_CMD.format(ss_id))

        ss_read = raw_ss_read.split()[0]
        rpm_speed = int(ss_read, 16) * 150
        speed = int(float(rpm_speed) / max_rpm * 100)

        return speed

    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)

        Note:
            speed_pc = pwm_target/255*100

            0   : when PWM mode is use
            pwm : when pwm mode is not use
        """
        target = 0
        return target

    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
        """
        return SPEED_TOLERANCE

    def set_speed(self, speed):
        """
        Sets the fan speed
        Args:
            speed: An integer, the percentage of full fan speed to set fan to,
                   in the range 0 (off) to 100 (full speed)
        Returns:
            A boolean, True if speed is set successfully, False if not
        Notes:
            pwm setting mode must set as Manual
            manual: ipmitool raw 0x3a 0x06 0x01 0x0
            auto: ipmitool raw 0x3a 0x06 0x01 0x1
        """
        # ipmitool raw 0x3a 0x03 0x01 0x02 {register} {pwm_speed}
        # register = 22 32 42 52 62 72 82

        speed_hex = hex(int(float(speed) / 100 * 255))
        fan_register_hex = hex(FAN_PWM_REGISTER_START +
                               (self.fan_tray_index * FAN_PWM_REGISTER_STEP))

        set_speed_cmd = IPMI_SET_PWM.format(fan_register_hex, speed_hex)
        status, set_speed_res = self._api_helper.ipmi_raw(
            IPMI_OEM_NETFN, set_speed_cmd)

        set_speed = False if not status else True

        return set_speed

    def set_status_led(self, color):
        """
        Sets the state of the fan module status LED
        Args:
            color: A string representing the color with which to set the
                   fan module status LED
        Returns:
            bool: True if status LED state is set successfully, False if not

        Note:
           LED setting mode must set as Manual
           manual: ipmitool raw 0x3A 0x09 0x02 0x00
           auto: ipmitool raw 0x3A 0x09 0x02 0x01
        """
        led_cmd = {
            self.STATUS_LED_COLOR_GREEN: FAN_LED_GREEN_CMD,
            self.STATUS_LED_COLOR_RED: FAN_LED_RED_CMD,
            self.STATUS_LED_COLOR_OFF: FAN_LED_OFF_CMD
        }.get(color)

        fan_selector = hex(int(FAN1_LED_CMD, 16) + self.fan_tray_index)
        status, set_led = self._api_helper.ipmi_raw(
            IPMI_OEM_NETFN, IPMI_SET_FAN_LED_CMD.format(fan_selector, led_cmd))
        set_status_led = False if not status else True

        return set_status_led

    def get_status_led(self):
        """
        Gets the state of the fan status LED
        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings above

        Note:
            STATUS_LED_COLOR_GREEN = "green"
            STATUS_LED_COLOR_AMBER = "amber"
            STATUS_LED_COLOR_RED = "red"
            STATUS_LED_COLOR_OFF = "off"
        """
        fan_selector = hex(int(FAN1_LED_CMD, 16) + self.fan_tray_index)
        status, hx_color = self._api_helper.ipmi_raw(
            IPMI_OEM_NETFN, IPMI_GET_FAN_LED_CMD.format(fan_selector))

        status_led = {
            "00": self.STATUS_LED_COLOR_OFF,
            "01": self.STATUS_LED_COLOR_GREEN,
            "02": self.STATUS_LED_COLOR_RED,
        }.get(hx_color, self.STATUS_LED_COLOR_OFF)

        return status_led

    def get_name(self):
        """
        Retrieves the name of the device
            Returns:
            string: The name of the device
        """
        fan_name = FAN_NAME_LIST[
            self.fan_tray_index * 2 +
            self.fan_index] if not self.is_psu_fan else "PSU-{} FAN-{}".format(
                self.psu_index + 1, self.fan_index + 1)

        return fan_name

    def get_presence(self):
        """
        Retrieves the presence of the FAN
        Returns:
            bool: True if FAN is present, False if not
        """
        presence = False
        status, raw_present = self._api_helper.ipmi_raw(
            IPMI_OEM_NETFN, IPMI_FAN_PRESENT_CMD.format(hex(self.index)))
        if status and raw_present == "00":
            presence = True

        return presence

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device
        Returns:
            string: Model/part number of device
        """
        model = "Unknown"
        ipmi_fru_idx = self.fan_tray_index + FAN1_FRU_ID
        status, raw_model = self._api_helper.ipmi_fru_id(
            ipmi_fru_idx, IPMI_FRU_MODEL_KEY)

        fru_pn_list = raw_model.split()
        if len(fru_pn_list) > 4:
            model = fru_pn_list[4]

        return model

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        serial = "Unknown"
        ipmi_fru_idx = self.fan_tray_index + FAN1_FRU_ID
        status, raw_model = self._api_helper.ipmi_fru_id(
            ipmi_fru_idx, IPMI_FRU_SERIAL_KEY)

        fru_sr_list = raw_model.split()
        if len(fru_sr_list) > 3:
            serial = fru_sr_list[3]

        return serial

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        return self.get_presence() and self.get_speed() > 0
Beispiel #17
0
class Watchdog(WatchdogBase):

    def __init__(self):
        # Init helper
        self._api_helper = APIHelper()

        # Init cpld reg path
        self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE)
        self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE)

        # Set default value
        self._disable()
        self.armed = False
        self.timeout = self._gettimeout()

    def _enable(self):
        """
        Turn on the watchdog timer
        """
        # echo 0x141 0x1 > /sys/devices/platform/dx010_cpld/setreg
        enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD)
        return self._api_helper.write_txt_file(self.setreg_path, enable_val)

    def _disable(self):
        """
        Turn off the watchdog timer
        """
        # echo 0x141 0x0 > /sys/devices/platform/dx010_cpld/setreg
        disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD)
        return self._api_helper.write_txt_file(self.setreg_path, disable_val)

    def _keepalive(self):
        """
        Keep alive watchdog timer
        """
        # echo 0x145 0x1 > /sys/devices/platform/dx010_cpld/setreg
        enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD)
        return self._api_helper.write_txt_file(self.setreg_path, enable_val)

    def _get_level_hex(self, sub_hex):
        sub_hex_str = sub_hex.replace("x", "0")
        return hex(int(sub_hex_str, 16))

    def _seconds_to_lmh_hex(self, seconds):
        ms = seconds*1000  # calculate timeout in ms format
        hex_str = hex(ms)
        l = self._get_level_hex(hex_str[-2:])
        m = self._get_level_hex(hex_str[-4:-2])
        h = self._get_level_hex(hex_str[-6:-4])
        return (l, m, h)

    def _settimeout(self, seconds):
        """
        Set watchdog timer timeout
        @param seconds - timeout in seconds
        @return is the actual set timeout
        """
        # max = 0xffffff = 16777.215 seconds

        (l, m, h) = self._seconds_to_lmh_hex(seconds)
        set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h)
        set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m)
        set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l)

        self._api_helper.write_txt_file(self.setreg_path, set_h_val)
        self._api_helper.write_txt_file(self.setreg_path, set_m_val)
        self._api_helper.write_txt_file(self.setreg_path, set_l_val)

        return seconds

    def _gettimeout(self):
        """
        Get watchdog timeout
        @return watchdog timeout
        """

        h_bit = self._api_helper.get_cpld_reg_value(
            self.getreg_path, WDT_TIMER_H_BIT_REG)
        m_bit = self._api_helper.get_cpld_reg_value(
            self.getreg_path, WDT_TIMER_M_BIT_REG)
        l_bit = self._api_helper.get_cpld_reg_value(
            self.getreg_path, WDT_TIMER_L_BIT_REG)

        hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:])
        ms = int(hex_time, 16)
        return int(float(ms)/1000)

    #################################################################

    def arm(self, seconds):
        """
        Arm the hardware watchdog with a timeout of <seconds> seconds.
        If the watchdog is currently armed, calling this function will
        simply reset the timer to the provided value. If the underlying
        hardware does not support the value provided in <seconds>, this
        method should arm the watchdog with the *next greater* available
        value.
        Returns:
            An integer specifying the *actual* number of seconds the watchdog
            was armed with. On failure returns -1.
        """

        ret = WDT_COMMON_ERROR
        if seconds < 0:
            return ret
        if seconds > 16778:
            return ret

        try:
            if self.timeout != seconds:
                self.timeout = self._settimeout(seconds)

            if self.armed:
                self._keepalive()
            else:
                self._enable()
                self.armed = True

            ret = self.timeout
            self.arm_timestamp = time.time()
        except IOError as e:
            pass

        return ret

    def disarm(self):
        """
        Disarm the hardware watchdog
        Returns:
            A boolean, True if watchdog is disarmed successfully, False if not
        """
        disarmed = False
        if self.is_armed():
            try:
                self._disable()
                self.armed = False
                disarmed = True
            except IOError:
                pass

        return disarmed

    def is_armed(self):
        """
        Retrieves the armed state of the hardware watchdog.
        Returns:
            A boolean, True if watchdog is armed, False if not
        """

        return self.armed

    def get_remaining_time(self):
        """
        If the watchdog is armed, retrieve the number of seconds remaining on
        the watchdog timer
        Returns:
            An integer specifying the number of seconds remaining on thei
            watchdog timer. If the watchdog is not armed, returns -1.
        """

        return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR
Beispiel #18
0
class Component(ComponentBase):
    """Platform-specific Component class"""

    DEVICE_TYPE = "component"

    def __init__(self, component_index):
        ComponentBase.__init__(self)
        self.index = component_index
        self.name = self.get_name()
        self._api_helper = APIHelper()

    def __get_bmc_ver(self):
        bmc_ver = "Unknown"
        status, raw_bmc_data = self._api_helper.run_command(BMC_VER_CMD)
        if status:
            bmc_ver_data = raw_bmc_data.split(":")
            bmc_ver = bmc_ver_data[-1].strip(
            ) if len(bmc_ver_data) > 1 else bmc_ver
        return bmc_ver

    def __get_fpga_ver(self):
        fpga_ver = "Unknown"
        status, reg_val = self._api_helper.pci_get_value(
            MEM_PCI_RESOURCE, FPGA_VER_MEM_OFFSET)
        if status:
            major = reg_val[0] >> 16
            minor = int(bin(reg_val[0])[16:32], 2)
            fpga_ver = '{}.{}'.format(major, minor)
        return fpga_ver

    def get_name(self):
        """
        Retrieves the name of the component
         Returns:
            A string containing the name of the component
        """
        return COMPONENT_LIST[self.index][0]

    def get_description(self):
        """
        Retrieves the description of the component
            Returns:
            A string containing the description of the component
        """
        return COMPONENT_LIST[self.index][1]

    def get_firmware_version(self):
        """
        Retrieves the firmware version of module
        Returns:
            string: The firmware versions of the module
        """
        fw_version = {
            "BIOS": self._api_helper.read_txt_file(BIOS_VER_PATH),
            "BMC": self.__get_bmc_ver(),
            "FPGA": self.__get_fpga_ver(),
            "SWITCH_CPLD": self._api_helper.read_txt_file(SW_CPLD_VER_PATH),
            "BASE_CPLD": self._api_helper.read_txt_file(BASE_CPLD_VER_PATH),
        }.get(self.name, "Unknown")

        return fw_version

    def install_firmware(self, image_path):
        """
        Install firmware to module
        Args:
            image_path: A string, path to firmware image
        Returns:
            A boolean, True if install successfully, False if not
        """
        install_command = {
            "BMC":
            CFUFLASH_FW_UPGRADE_CMD.format(BMC_UPGRADE_OPT, image_path),
            "BIOS":
            CFUFLASH_FW_UPGRADE_CMD.format(BIOS__UPGRADE_OPT, image_path),
            "SWITCH_CPLD":
            CFUFLASH_FW_UPGRADE_CMD.format(CPLD_UPGRADE_OPT, image_path),
            "BASE_CPLD":
            CFUFLASH_FW_UPGRADE_CMD.format(CPLD_UPGRADE_OPT, image_path)
        }.get(self.name, None)

        if not os.path.isfile(image_path) or install_command is None:
            return False

        # print(install_command)
        status = self._api_helper.run_interactive_command(install_command)
        return status
Beispiel #19
0
class Psu(PsuBase):
    """Platform-specific Psu class"""
    def __init__(self, psu_index):
        PsuBase.__init__(self)
        self.index = psu_index
        self._api_helper = APIHelper()
        self.green_led_path = GREEN_LED_PATH.format(self.index + 1)
        self.dx010_psu_gpio = [{
            'base': self.__get_gpio_base()
        }, {
            'prs': 27,
            'status': 22
        }, {
            'prs': 28,
            'status': 25
        }]
        self.i2c_num = PSU_I2C_MAPPING[self.index]["num"]
        self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"]
        self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr)
        for fan_index in range(0, PSU_NUM_FAN[self.index]):
            fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
            self._fan_list.append(fan)

    def __search_file_by_contain(self, directory, search_str, file_start):
        for dirpath, dirnames, files in os.walk(directory):
            for name in files:
                file_path = os.path.join(dirpath, name)
                if name.startswith(
                        file_start
                ) and search_str in self._api_helper.read_txt_file(file_path):
                    return file_path
        return None

    def __get_gpio_base(self):
        for r in os.listdir(GPIO_DIR):
            label_path = os.path.join(GPIO_DIR, r, "label")
            if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(
                    label_path):
                return int(r[8:], 10)
        return 216  # Reserve

    def __get_gpio_value(self, pinnum):
        gpio_base = self.dx010_psu_gpio[0]['base']
        gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base + pinnum)
        gpio_file = gpio_dir + "/value"
        retval = self._api_helper.read_txt_file(gpio_file)
        return retval.rstrip('\r\n')

    def get_voltage(self):
        """
        Retrieves current PSU voltage output
        Returns:
            A float number, the output voltage in volts,
            e.g. 12.1
        """
        psu_voltage = 0.0
        voltage_name = "in{}_input"
        voltage_label = "vout1"

        vout_label_path = self.__search_file_by_contain(
            self.hwmon_path, voltage_label, "in")
        if vout_label_path:
            dir_name = os.path.dirname(vout_label_path)
            basename = os.path.basename(vout_label_path)
            in_num = filter(str.isdigit, basename)
            vout_path = os.path.join(dir_name, voltage_name.format(in_num))
            vout_val = self._api_helper.read_txt_file(vout_path)
            psu_voltage = float(vout_val) / 1000

        return psu_voltage

    def get_current(self):
        """
        Retrieves present electric current supplied by PSU
        Returns:
            A float number, the electric current in amperes, e.g 15.4
        """
        psu_current = 0.0
        current_name = "curr{}_input"
        current_label = "iout1"

        curr_label_path = self.__search_file_by_contain(
            self.hwmon_path, current_label, "cur")
        if curr_label_path:
            dir_name = os.path.dirname(curr_label_path)
            basename = os.path.basename(curr_label_path)
            cur_num = filter(str.isdigit, basename)
            cur_path = os.path.join(dir_name, current_name.format(cur_num))
            cur_val = self._api_helper.read_txt_file(cur_path)
            psu_current = float(cur_val) / 1000

        return psu_current

    def get_power(self):
        """
        Retrieves current energy supplied by PSU
        Returns:
            A float number, the power in watts, e.g. 302.6
        """
        psu_power = 0.0
        current_name = "power{}_input"
        current_label = "pout1"

        pw_label_path = self.__search_file_by_contain(self.hwmon_path,
                                                      current_label, "power")
        if pw_label_path:
            dir_name = os.path.dirname(pw_label_path)
            basename = os.path.basename(pw_label_path)
            pw_num = filter(str.isdigit, basename)
            pw_path = os.path.join(dir_name, current_name.format(pw_num))
            pw_val = self._api_helper.read_txt_file(pw_path)
            psu_power = float(pw_val) / 1000000

        return psu_power

    def get_powergood_status(self):
        """
        Retrieves the powergood status of PSU
        Returns:
            A boolean, True if PSU has stablized its output voltages and passed all
            its internal self-tests, False if not.
        """
        return self.get_status()

    def set_status_led(self, color):
        """
        Sets the state of the PSU status LED
        Args:
            color: A string representing the color with which to set the PSU status LED
                   Note: Only support green and off
        Returns:
            bool: True if status LED state is set successfully, False if not
        """

        set_status_str = {
            self.STATUS_LED_COLOR_GREEN: '1',
            self.STATUS_LED_COLOR_OFF: '0'
        }.get(color, None)

        if not set_status_str:
            return False

        try:
            with open(self.green_led_path, 'w') as file:
                file.write(set_status_str)
        except IOError:
            return False

        return True

    def get_status_led(self):
        """
        Gets the state of the PSU status LED
        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings above
        """
        status = self._api_helper.read_txt_file(self.green_led_path)
        status_str = {
            '255': self.STATUS_LED_COLOR_GREEN,
            '0': self.STATUS_LED_COLOR_OFF
        }.get(status, None)

        return status_str

    def get_name(self):
        """
        Retrieves the name of the device
            Returns:
            string: The name of the device
        """
        return PSU_NAME_LIST[self.index]

    def get_presence(self):
        """
        Retrieves the presence of the PSU
        Returns:
            bool: True if PSU is present, False if not
        """
        raw = self.__get_gpio_value(self.dx010_psu_gpio[self.index + 1]['prs'])
        return int(raw, 10) == 0

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        raw = self.__get_gpio_value(self.dx010_psu_gpio[self.index +
                                                        1]['status'])
        return int(raw, 10) == 1
Beispiel #20
0
 def __init__(self, component_index):
     ComponentBase.__init__(self)
     self.index = component_index
     self.name = self.get_name()
     self._api_helper = APIHelper()
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""

    def __init__(self):
        ChassisBase.__init__(self)
        self._api_helper = APIHelper()
        self.sfp_module_initialized = False
        self.__initialize_eeprom()
        self.is_host = self._api_helper.is_host()

        if not self.is_host:
            self.__initialize_fan()
            self.__initialize_psu()
            self.__initialize_thermals()
        else:
            self.__initialize_components()

    def __initialize_sfp(self):
        from sonic_platform.sfp import Sfp
        for index in range(0, NUM_SFP):
            sfp = Sfp(index)
            self._sfp_list.append(sfp)
        self.sfp_module_initialized = True

    def __initialize_psu(self):
        from sonic_platform.psu import Psu
        for index in range(0, NUM_PSU):
            psu = Psu(index)
            self._psu_list.append(psu)

    def __initialize_fan(self):
        from sonic_platform.fan import Fan
        for fant_index in range(0, NUM_FAN_TRAY):
            for fan_index in range(0, NUM_FAN):
                fan = Fan(fant_index, fan_index)
                self._fan_list.append(fan)

    def __initialize_thermals(self):
        from sonic_platform.thermal import Thermal
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

    def __initialize_eeprom(self):
        from sonic_platform.eeprom import Tlv
        self._eeprom = Tlv()

    def __initialize_components(self):
        from sonic_platform.component import Component
        for index in range(0, NUM_COMPONENT):
            component = Component(index)
            self._component_list.append(component)

    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._eeprom.get_mac()

    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._eeprom.get_eeprom()

    def get_reboot_cause(self):
        """
        Retrieves the cause of the previous reboot
        Returns:
            A tuple (string, string) where the first element is a string
            containing the cause of the previous reboot. This string must be
            one of the predefined strings in this class. If the first string
            is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
            to pass a description of the reboot cause.

            REBOOT_CAUSE_POWER_LOSS = "Power Loss"
            REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU"
            REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC"
            REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other"
            REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed"
            REBOOT_CAUSE_WATCHDOG = "Watchdog"
            REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other"
            REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware"

        """
        reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
        sw_reboot_cause = self._api_helper.read_txt_file(
            reboot_cause_path) or "Unknown"
        hw_reboot_cause = self._api_helper.get_cpld_reg_value(
            GETREG_PATH, RESET_REGISTER)

        prev_reboot_cause = {
            '0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'),
            '0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'),
            '0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'),
            '0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'),
            '0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''),
            '0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''),
            '0x77': (self.REBOOT_CAUSE_WATCHDOG, '')
        }.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason'))

        if sw_reboot_cause != 'Unknown' and hw_reboot_cause == '0x11':
            prev_reboot_cause = (
                self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause)

        return prev_reboot_cause

    ##############################################################
    ######################## SFP methods #########################
    ##############################################################

    def get_num_sfps(self):
        """
        Retrieves the number of sfps available on this chassis
        Returns:
            An integer, the number of sfps available on this chassis
        """
        if not self.sfp_module_initialized:
            self.__initialize_sfp()

        return len(self._sfp_list)

    def get_all_sfps(self):
        """
        Retrieves all sfps available on this chassis
        Returns:
            A list of objects derived from SfpBase representing all sfps
            available on this chassis
        """
        if not self.sfp_module_initialized:
            self.__initialize_sfp()

        return self._sfp_list

    def get_sfp(self, index):
        """
        Retrieves sfp represented by (1-based) index <index>
        Args:
            index: An integer, the index (1-based) of the sfp to retrieve.
            The index should be the sequence of a physical port in a chassis,
            starting from 1.
            For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
        Returns:
            An object dervied from SfpBase representing the specified sfp
        """
        sfp = None
        if not self.sfp_module_initialized:
            self.__initialize_sfp()

        try:
            # The index will start from 1
            sfp = self._sfp_list[index-1]
        except IndexError:
            sys.stderr.write("SFP index {} out of range (1-{})\n".format(
                             index, len(self._sfp_list)))
        return sfp

    ##############################################################
    ####################### Other methods ########################
    ##############################################################

    def get_watchdog(self):
        """
        Retreives hardware watchdog device on this chassis
        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device
        """
        if self._watchdog is None:
            from sonic_platform.watchdog import Watchdog
            self._watchdog = Watchdog()

        return self._watchdog

    ##############################################################
    ###################### Device methods ########################
    ##############################################################

    def get_name(self):
        """
        Retrieves the name of the device
            Returns:
            string: The name of the device
        """
        return self._api_helper.hwsku

    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 device
        Returns:
            string: Model/part number of device
        """
        return self._eeprom.get_pn()

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        return self._eeprom.get_serial()

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        return True
Beispiel #22
0
class Thermal(ThermalBase):
    """Platform-specific Thermal class"""
    def __init__(self, thermal_index):
        ThermalBase.__init__(self)
        self._api_helper = APIHelper()
        self.index = thermal_index
        self.THERMAL_LIST = [
            ('TEMP_FAN_U52', 'Fan Tray Middle Temperature Sensor', '0x00'),
            ('TEMP_FAN_U17', 'Fan Tray Right Temperature Sensor', '0x01'),
            ('TEMP_SW_U52', 'Switchboard Left Inlet Temperature Sensor',
             '0x02'),
            ('TEMP_SW_U16', 'Switchboard Right Inlet Temperature Sensor',
             '0x03'),
            ('TEMP_BB_U3', 'Baseboard Temperature Sensor', '0x04'),
            ('TEMP_CPU', 'CPU Internal Temperature Sensor', '0x05'),
            ('TEMP_SW_Internal', 'ASIC Internal Temperature Sensor', '0x61'),
            ('SW_U04_Temp', 'IR3595 Chip Left Temperature Sensor', '0x4F'),
            ('SW_U14_Temp', 'IR3595 Chip Right Temperature Sensor', '0x56'),
            ('SW_U4403_Temp', 'IR3584 Chip Temperature Sensor', '0x5D'),
        ]
        self.sensor_id = self.THERMAL_LIST[self.index][0]
        self.sensor_des = self.THERMAL_LIST[self.index][1]
        self.sensor_reading_addr = self.THERMAL_LIST[self.index][2]

    def __set_threshold(self, key, value):
        print(key, value)

    def get_temperature(self):
        """
        Retrieves current temperature reading from thermal
        Returns:
            A float number of current temperature in Celsius up to nearest thousandth
            of one degree Celsius, e.g. 30.125 
        """
        temperature = 0.0
        status, raw_ss_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN,
            IPMI_SS_READ_CMD.format(self.sensor_reading_addr))
        if status and len(raw_ss_read.split()) > 0:
            ss_read = raw_ss_read.split()[0]
            temperature = float(int(ss_read, 16))
        return temperature

    def get_high_threshold(self):
        """
        Retrieves the high threshold temperature of thermal
        Returns:
            A float number, the high threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        high_threshold = 0.0
        status, raw_up_thres_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN,
            IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr))
        if status and len(raw_up_thres_read.split()) > 6:
            ss_read = raw_up_thres_read.split()[4]
            high_threshold = float(int(ss_read, 16))
        return high_threshold

    def get_low_threshold(self):
        """
        Retrieves the low threshold temperature of thermal
        Returns:
            A float number, the low threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        return DEFUALT_LOWER_TRESHOLD

    def set_high_threshold(self, temperature):
        """
        Sets the high threshold temperature of thermal
        Args : 
            temperature: A float number up to nearest thousandth of one degree Celsius, 
            e.g. 30.125
        Returns:
            A boolean, True if threshold is set successfully, False if not
        """
        status, ret_txt = self._api_helper.ipmi_set_ss_thres(
            self.sensor_id, HIGH_TRESHOLD_SET_KEY, temperature)
        return status

    def set_low_threshold(self, temperature):
        """
        Sets the low threshold temperature of thermal
        Args : 
            temperature: A float number up to nearest thousandth of one degree Celsius,
            e.g. 30.125
        Returns:
            A boolean, True if threshold is set successfully, False if not
        """
        return False

    def get_name(self):
        """
        Retrieves the name of the thermal device
            Returns:
            string: The name of the thermal device
        """
        return self.THERMAL_LIST[self.index][0]

    def get_presence(self):
        """
        Retrieves the presence of the device
        Returns:
            bool: True if device is present, False if not
        """
        return True if self.get_temperature() > 0 else False

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device
        Returns:
            string: Model/part number of device
        """
        return self.sensor_des

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        return "Unknown"

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        return self.get_presence()
class Thermal(ThermalBase):
    """Platform-specific Thermal class"""

    SS_CONFIG_PATH = "/usr/share/sonic/device/x86_64-cel_seastone-r0/sensors.conf"

    def __init__(self, thermal_index, airflow):
        self.index = thermal_index
        self._api_helper = APIHelper()
        self._airflow = airflow
        self._thermal_info = THERMAL_INFO[self.index]
        self._hwmon_path = "{}/{}".format(I2C_ADAPTER_PATH,
                                          self._thermal_info["i2c_path"])
        self.name = self.get_name()
        self.postion = self._thermal_info["postion"]
        self.ss_index = 1

    def __get_temp(self, temp_file):
        temp_file_path = os.path.join(self._hwmon_path, temp_file)
        raw_temp = self._api_helper.read_txt_file(temp_file_path)
        temp = float(raw_temp) / 1000
        return float("{:.3f}".format(temp))

    def __set_threshold(self, file_name, temperature):
        temp_file_path = os.path.join(self._hwmon_path, file_name)
        try:
            with open(temp_file_path, 'w') as fd:
                fd.write(str(temperature))
            return True
        except IOError:
            return False

    def get_temperature(self):
        """
        Retrieves current temperature reading from thermal
        Returns:
            A float number of current temperature in Celsius up to nearest thousandth
            of one degree Celsius, e.g. 30.125
        """
        temp_file = "temp{}_input".format(self.ss_index)
        return self.__get_temp(temp_file)

    def get_high_threshold(self):
        """
        Retrieves the high threshold temperature of thermal
        Returns:
            A float number, the high threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        max_crit_key = '{}_max'.format(self._airflow)
        return self._thermal_info.get(max_crit_key, None)

    def get_low_threshold(self):
        """
        Retrieves the low threshold temperature of thermal
        Returns:
            A float number, the low threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        return 0.0

    def set_high_threshold(self, temperature):
        """
        Sets the high threshold temperature of thermal
        Args :
            temperature: A float number up to nearest thousandth of one degree Celsius,
            e.g. 30.125
        Returns:
            A boolean, True if threshold is set successfully, False if not
        """
        temp_file = "temp{}_max".format(self.ss_index)
        is_set = self.__set_threshold(temp_file, int(temperature * 1000))
        file_set = False
        if is_set:
            try:
                with open(self.SS_CONFIG_PATH, 'r+') as f:
                    content = f.readlines()
                    f.seek(0)
                    ss_found = False
                    for idx, val in enumerate(content):
                        if self.name in val:
                            ss_found = True
                        elif ss_found and temp_file in val:
                            content[idx] = "    set {} {}\n".format(
                                temp_file, temperature)
                            f.writelines(content)
                            file_set = True
                            break
            except IOError:
                file_set = False

        return is_set & file_set

    def set_low_threshold(self, temperature):
        """
        Sets the low threshold temperature of thermal
        Args : 
            temperature: A float number up to nearest thousandth of one degree Celsius,
            e.g. 30.125
        Returns:
            A boolean, True if threshold is set successfully, False if not
        """
        return False

    def get_high_critical_threshold(self):
        """
        Retrieves the high critical threshold temperature of thermal
        Returns:
            A float number, the high critical threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        max_crit_key = '{}_max_crit'.format(self._airflow)
        return self._thermal_info.get(max_crit_key, None)

    def get_low_critical_threshold(self):
        """
        Retrieves the low critical threshold temperature of thermal
        Returns:
            A float number, the low critical threshold temperature of thermal in Celsius
            up to nearest thousandth of one degree Celsius, e.g. 30.125
        """
        return 0.0

    def get_name(self):
        """
        Retrieves the name of the thermal device
            Returns:
            string: The name of the thermal device
        """
        return self._thermal_info["name"]

    def get_presence(self):
        """
        Retrieves the presence of the PSU
        Returns:
            bool: True if PSU is present, False if not
        """
        temp_file = "temp{}_input".format(self.ss_index)
        temp_file_path = os.path.join(self._hwmon_path, temp_file)
        return os.path.isfile(temp_file_path)

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device
        Returns:
            string: Model/part number of device
        """
        return NULL_VAL

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        return NULL_VAL

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        if not self.get_presence():
            return False

        fault_file = "temp{}_fault".format(self.ss_index)
        fault_file_path = os.path.join(self._hwmon_path, fault_file)
        if not os.path.isfile(fault_file_path):
            return True

        raw_txt = self.__read_txt_file(fault_file_path)
        return int(raw_txt) == 0
Beispiel #24
0
class Psu(PsuBase):
    """Platform-specific Psu class"""
    def __init__(self, psu_index):
        PsuBase.__init__(self)
        self.index = psu_index
        for fan_index in range(0, PSU_NUM_FAN[self.index]):
            fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
            self._fan_list.append(fan)
        self._api_helper = APIHelper()

    def find_value(self, in_string):
        result = re.search("^.+ ([0-9a-f]{2}) .+$", in_string)
        return result.group(1) if result else result

    def get_voltage(self):
        """
        Retrieves current PSU voltage output
        Returns:
            A float number, the output voltage in volts,
            e.g. 12.1
        """
        psu_voltage = 0.0
        psu_vout_key = globals()['PSU{}_VOUT_SS_ID'.format(self.index + 1)]
        status, raw_ss_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_vout_key))
        ss_read = raw_ss_read.split()[SS_READ_OFFSET]
        # Formula: Rx1x10^-1
        psu_voltage = int(ss_read, 16) * math.pow(10, -1)

        return psu_voltage

    def get_current(self):
        """
        Retrieves present electric current supplied by PSU
        Returns:
            A float number, the electric current in amperes, e.g 15.4
        """
        psu_current = 0.0
        psu_cout_key = globals()['PSU{}_COUT_SS_ID'.format(self.index + 1)]
        status, raw_ss_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_cout_key))
        ss_read = raw_ss_read.split()[SS_READ_OFFSET]
        # Formula: Rx5x10^-1
        psu_current = int(ss_read, 16) * 5 * math.pow(10, -1)

        return psu_current

    def get_power(self):
        """
        Retrieves current energy supplied by PSU
        Returns:
            A float number, the power in watts, e.g. 302.6
        """
        psu_power = 0.0
        psu_pout_key = globals()['PSU{}_POUT_SS_ID'.format(self.index + 1)]
        status, raw_ss_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pout_key))
        ss_read = raw_ss_read.split()[SS_READ_OFFSET]
        # Formula: Rx6x10^0
        psu_power = int(ss_read, 16) * 6
        return psu_power

    def get_powergood_status(self):
        """
        Retrieves the powergood status of PSU
        Returns:
            A boolean, True if PSU has stablized its output voltages and passed all
            its internal self-tests, False if not.
        """
        return self.get_status()

    def set_status_led(self, color):
        """
        Sets the state of the PSU status LED
        Args:
            color: A string representing the color with which to set the PSU status LED
                   Note: Only support green and off
        Returns:
            bool: True if status LED state is set successfully, False if not
        Note
            Set manual
            ipmitool raw 0x3a 0x09 0x2 0x0
        """
        led_cmd = {
            self.STATUS_LED_COLOR_GREEN: PSU_LED_GREEN_CMD,
            self.STATUS_LED_COLOR_AMBER: PSU_LED_AMBER_CMD,
            self.STATUS_LED_COLOR_OFF: PSU_LED_OFF_CMD
        }.get(color)

        status, set_led = self._api_helper.ipmi_raw(
            IPMI_OEM_NETFN, IPMI_SET_PSU_LED_CMD.format(led_cmd))
        set_status_led = False if not status else True

        return set_status_led

    def get_status_led(self):
        """
        Gets the state of the PSU status LED
        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings above
        """
        status, hx_color = self._api_helper.ipmi_raw(IPMI_OEM_NETFN,
                                                     IPMI_GET_PSU_LED_CMD)

        status_led = {
            "00": self.STATUS_LED_COLOR_OFF,
            "01": self.STATUS_LED_COLOR_GREEN,
            "02": self.STATUS_LED_COLOR_AMBER,
        }.get(hx_color, self.STATUS_LED_COLOR_OFF)

        return status_led

    def get_name(self):
        """
        Retrieves the name of the device
            Returns:
            string: The name of the device
        """
        return PSU_NAME_LIST[self.index]

    def get_presence(self):
        """
        Retrieves the presence of the PSU
        Returns:
            bool: True if PSU is present, False if not
        """
        psu_presence = False
        psu_pstatus_key = globals()['PSU{}_STATUS_REG'.format(self.index + 1)]
        status, raw_status_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pstatus_key))
        status_byte = self.find_value(raw_status_read)

        if status:
            presence_int = (int(status_byte, 16) >> 0) & 1
            psu_presence = True if presence_int else False

        return psu_presence

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device
        Returns:
            string: Model/part number of device
        """
        model = "Unknown"
        ipmi_fru_idx = self.index + PSU1_FRU_ID
        status, raw_model = self._api_helper.ipmi_fru_id(
            ipmi_fru_idx, IPMI_FRU_MODEL_KEY)

        fru_pn_list = raw_model.split()
        if len(fru_pn_list) > 4:
            model = fru_pn_list[4]

        return model

    def get_serial(self):
        """
        Retrieves the serial number of the device
        Returns:
            string: Serial number of device
        """
        serial = "Unknown"
        ipmi_fru_idx = self.index + PSU1_FRU_ID
        status, raw_model = self._api_helper.ipmi_fru_id(
            ipmi_fru_idx, IPMI_FRU_SERIAL_KEY)

        fru_sr_list = raw_model.split()
        if len(fru_sr_list) > 3:
            serial = fru_sr_list[3]

        return serial

    def get_status(self):
        """
        Retrieves the operational status of the device
        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        psu_status = False
        psu_pstatus_key = globals()['PSU{}_STATUS_REG'.format(self.index + 1)]
        status, raw_status_read = self._api_helper.ipmi_raw(
            IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pstatus_key))
        status_byte = self.find_value(raw_status_read)

        if status:
            failure_detected = (int(status_byte, 16) >> 1) & 1
            input_lost = (int(status_byte, 16) >> 3) & 1
            psu_status = False if (input_lost or failure_detected) else True

        return psu_status