2022-06-15 11:39:41 -05:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#############################################################################
|
|
|
|
# Dell
|
|
|
|
#
|
|
|
|
# Module contains an implementation of SONiC FAN Base API and
|
|
|
|
# provides various info about the FANs which are available in the platform
|
|
|
|
#
|
|
|
|
#############################################################################
|
|
|
|
import logging
|
2023-01-05 18:22:09 -06:00
|
|
|
from sonic_py_common.general import getstatusoutput_noshell
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
try:
|
|
|
|
from sonic_fan.fan_base import FanBase
|
|
|
|
except ImportError as e:
|
|
|
|
raise ImportError (str(e) + "- required module not found")
|
|
|
|
|
|
|
|
class FanUtil(FanBase):
|
|
|
|
"""Platform-specific FANutil class"""
|
|
|
|
FANTRAY_NUM_ON_MAIN_BOARD = 7
|
|
|
|
NUM_FANS_PERTRAY = 2
|
|
|
|
FANTRAY_NUM_START_IDX = 1
|
|
|
|
FRU_FAN_START_IDX = 1
|
2023-01-05 18:22:09 -06:00
|
|
|
IPMI_FAN_PRESENCE = ["ipmitool", "sensor", "get", ""]
|
|
|
|
IPMI_FAN_FRONT_SPEED = ["ipmitool", "sdr", "get", ""]
|
|
|
|
IPMI_FAN_REAR_SPEED = ["ipmitool", "sdr", "get", ""]
|
|
|
|
IPMI_FRU_DATA = ["ipmitool", "fru", "print", ""]
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
def __init__(self, log_level=logging.DEBUG):
|
|
|
|
FanBase.__init__(self)
|
|
|
|
self.num_fans = (self.FANTRAY_NUM_ON_MAIN_BOARD*self.NUM_FANS_PERTRAY)
|
|
|
|
|
|
|
|
def get_fan_status(self,fan_id):
|
|
|
|
try:
|
2023-01-05 18:22:09 -06:00
|
|
|
self.IPMI_FAN_PRESENCE[3] = 'FAN' + str(fan_id) + '_prsnt'
|
|
|
|
ret_status, ipmi_cmd_ret = getstatusoutput_noshell(self.IPMI_FAN_PRESENCE)
|
|
|
|
if ret_status == 0:
|
|
|
|
return(ipmi_cmd_ret.splitlines()[5].strip(' ').strip('[]'))
|
2022-06-15 11:39:41 -05:00
|
|
|
except Exception:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Failed to execute : %s'%(' '.join(self.IPMI_FAN_PRESENCE)))
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
def get_front_fan_speed(self,fan_id):
|
|
|
|
try:
|
2023-01-05 18:22:09 -06:00
|
|
|
self.IPMI_FAN_FRONT_SPEED[3] = 'Fan' + str(fan_id) + '_Front_rpm'
|
|
|
|
ret_status, ipmi_cmd_ret = getstatusoutput_noshell(self.IPMI_FAN_FRONT_SPEED)
|
|
|
|
if ret_status == 0:
|
|
|
|
rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1]
|
|
|
|
return rdata
|
2022-06-15 11:39:41 -05:00
|
|
|
except Exception:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Failed to execute : %s'%(' '.join(self.IPMI_FAN_FRONT_SPEED)))
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
def get_rear_fan_speed(self,fan_id):
|
|
|
|
try:
|
2023-01-05 18:22:09 -06:00
|
|
|
self.IPMI_FAN_REAR_SPEED[3] = 'Fan' + str(fan_id) + '_Rear_rpm'
|
|
|
|
ret_status, ipmi_cmd_ret = getstatusoutput_noshell(self.IPMI_FAN_REAR_SPEED)
|
|
|
|
if ret_status == 0:
|
|
|
|
rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1]
|
|
|
|
return rdata
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
except Exception:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Failed to execute : %s'%(' '.join(self.IPMI_FAN_REAR_SPEED)))
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
|
|
|
|
# Read FAN FRU info
|
|
|
|
def get_fan_direction_from_fru(self,fru_id,reg_name):
|
|
|
|
output = None
|
|
|
|
try:
|
2023-01-05 18:22:09 -06:00
|
|
|
self.IPMI_FRU_DATA[3] = str(fru_id)
|
|
|
|
status, ipmi_fru_list = getstatusoutput_noshell(self.IPMI_FRU_DATA)
|
|
|
|
if status == 0:
|
|
|
|
for item in ipmi_fru_list.split("\n"):
|
|
|
|
if reg_name in item:
|
|
|
|
output = item.strip()
|
|
|
|
if output is None:
|
|
|
|
logging.error('\nFailed to fetch: ' + reg_name + ' sensor ')
|
|
|
|
output = output.split(':')[1].strip(' ')
|
|
|
|
if output == 'F2B' or output == 'B2F':
|
|
|
|
return output
|
2022-06-15 11:39:41 -05:00
|
|
|
except Exception:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Failed to execute:' + ipmi_fru_list)
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
def get_num_fans(self):
|
|
|
|
return self.num_fans
|
|
|
|
|
|
|
|
def get_presence(self, index):
|
|
|
|
if index is None:
|
2023-01-05 18:22:09 -06:00
|
|
|
return False
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Invalid FAN index:%d', index)
|
|
|
|
return False
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + 1
|
|
|
|
|
|
|
|
if (self.get_fan_status(tray_index) == 'Device Present'):
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def get_status(self, index):
|
|
|
|
if index is None:
|
2023-01-05 18:22:09 -06:00
|
|
|
return False
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Invalid FAN index:%d', index)
|
|
|
|
return False
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + 1
|
|
|
|
fantray_front_speed=self.get_front_fan_speed(tray_index)
|
|
|
|
fantray_rear_speed=self.get_rear_fan_speed(tray_index)
|
|
|
|
|
|
|
|
if (fantray_front_speed != '0' and fantray_rear_speed != '0'):
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def get_direction(self, index):
|
|
|
|
if index is None:
|
2023-01-05 18:22:09 -06:00
|
|
|
return None
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Invalid FAN index:%d', index)
|
|
|
|
return None
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
tray_index = ((index-1)/self.NUM_FANS_PERTRAY)
|
|
|
|
fru_id = self.FRU_FAN_START_IDX + tray_index
|
|
|
|
direction = self.get_fan_direction_from_fru(fru_id,'Board Extra')
|
|
|
|
|
|
|
|
if direction == 'B2F':
|
2023-01-05 18:22:09 -06:00
|
|
|
return "INTAKE"
|
2022-06-15 11:39:41 -05:00
|
|
|
elif direction == 'F2B':
|
2023-01-05 18:22:09 -06:00
|
|
|
return "EXHAUST"
|
2022-06-15 11:39:41 -05:00
|
|
|
else:
|
2023-01-05 18:22:09 -06:00
|
|
|
return None
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
|
|
|
|
def get_speed(self, index):
|
|
|
|
if index is None:
|
2023-01-05 18:22:09 -06:00
|
|
|
return 0
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1:
|
2023-01-05 18:22:09 -06:00
|
|
|
logging.error('Invalid FAN index:%d', index)
|
|
|
|
return 0
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + 1
|
|
|
|
|
|
|
|
if (index % 2 != 0):
|
2023-01-05 18:22:09 -06:00
|
|
|
fantray_speed=self.get_front_fan_speed(tray_index)
|
2022-06-15 11:39:41 -05:00
|
|
|
else:
|
2023-01-05 18:22:09 -06:00
|
|
|
fantray_speed=self.get_rear_fan_speed(tray_index)
|
2022-06-15 11:39:41 -05:00
|
|
|
|
|
|
|
if (self.get_presence(index) == True):
|
|
|
|
return int(fantray_speed.strip())
|
|
|
|
else:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def set_speed(self, val):
|
|
|
|
logging.error("Not allowed to set fan speed!")
|
|
|
|
|
|
|
|
return False
|