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
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