[pddf]: Adding support for fan_drawer class in PDDF common platform APIs (#10213)
Why I did it fan_drawer support was missing in PDDF common platform APIs. This resulted in 'thermalctld' not working and 'show platform fan' and 'show platfomr temperature' commands not working. _thermal_list array inside PSU class was not initialized. Made changes to attach the PSU related thermal sensors in the PSU instance. How I did it Added a common class pddf_fan_drawer.py. This class uses the PDDF JSON to fetch the platform specific data. A platform which uses PDDF would follow the below hierarchy. fan_drawer_base.py ---> pddf_fan_drawer.py ---> fan_drawer.py How to verify it Run the 'show platform fan' and 'show platform temperature' commands and check the o/p. o/p on AS7326: root@sonic:/home/admin# show platform fan s Drawer LED FAN Speed Direction Presence Status Timestamp -------- ----- ---------- ------- ----------- ---------- -------- ----------------- Fantray1 green Fantray1_1 38% EXHAUST Present OK 20220311 04:15:03 Fantray1 green Fantray1_2 38% EXHAUST Present OK 20220311 04:15:03 Fantray2 green Fantray2_1 38% EXHAUST Present OK 20220311 04:15:03 Fantray2 green Fantray2_2 38% EXHAUST Present OK 20220311 04:15:03 Fantray3 green Fantray3_1 38% EXHAUST Present OK 20220311 04:15:03 Fantray3 green Fantray3_2 38% EXHAUST Present OK 20220311 04:15:03 Fantray4 green Fantray4_1 38% EXHAUST Present OK 20220311 04:15:03 Fantray4 green Fantray4_2 38% EXHAUST Present OK 20220311 04:15:03 Fantray5 green Fantray5_1 38% EXHAUST Present OK 20220311 04:15:03 Fantray5 green Fantray5_2 38% EXHAUST Present OK 20220311 04:15:03 Fantray6 green Fantray6_1 38% EXHAUST Present OK 20220311 04:15:03 Fantray6 green Fantray6_2 38% EXHAUST Present OK 20220311 04:15:03 N/A off PSU1_FAN1 0% Present Not OK 20220311 04:15:05 N/A green PSU2_FAN1 34% EXHAUST Present OK 20220311 04:15:05 hroot@sonic:/home/admin# show platform temperature Sensor Temperature High TH Low TH Crit High TH Crit Low TH Warning Timestamp ---------- ------------- --------- -------- -------------- ------------- --------- ----------------- PSU1_TEMP1 0 N/A N/A N/A N/A False 20220311 04:15:05 PSU2_TEMP1 37 N/A N/A N/A N/A False 20220311 04:15:05 TEMP1 37 80.0 N/A N/A N/A False 20220311 04:15:05 TEMP2 27 80.0 N/A N/A N/A False 20220311 04:15:05 TEMP3 28.5 80.0 N/A N/A N/A False 20220311 04:15:05 TEMP4 30.5 80.0 N/A N/A N/A False 20220311 04:15:05 root@sonic:/home/admin# root@sonic:/home/admin# root@sonic:/home/admin# o/p on AS7726: root@as7726-32x-2:~# show platform fan Drawer LED FAN Speed Direction Presence Status Timestamp -------- ----- ---------- ------- ----------- ---------- -------- ----------------- Fantray1 green Fantray1_1 38% EXHAUST Present OK 20220311 08:13:04 Fantray1 green Fantray1_2 38% EXHAUST Present OK 20220311 08:13:04 Fantray2 green Fantray2_1 38% EXHAUST Present OK 20220311 08:13:04 Fantray2 green Fantray2_2 38% EXHAUST Present OK 20220311 08:13:04 Fantray3 green Fantray3_1 38% EXHAUST Present OK 20220311 08:13:04 Fantray3 green Fantray3_2 38% EXHAUST Present OK 20220311 08:13:04 Fantray4 green Fantray4_1 38% EXHAUST Present OK 20220311 08:13:04 Fantray4 green Fantray4_2 38% EXHAUST Present OK 20220311 08:13:04 Fantray5 green Fantray5_1 38% EXHAUST Present OK 20220311 08:13:04 Fantray5 green Fantray5_2 38% EXHAUST Present OK 20220311 08:13:04 Fantray6 green Fantray6_1 38% EXHAUST Present OK 20220311 08:13:04 Fantray6 green Fantray6_2 38% EXHAUST Present OK 20220311 08:13:04 N/A green PSU1_FAN1 23% EXHAUST Present OK 20220311 08:13:04 N/A green PSU2_FAN1 22% EXHAUST Present OK 20220311 08:13:04 root@as7726-32x-2:~# show platform temp Sensor Temperature High TH Low TH Crit High TH Crit Low TH Warning Timestamp ---------- ------------- --------- -------- -------------- ------------- --------- ----------------- PSU1_TEMP1 28 N/A N/A N/A N/A False 20220311 08:13:04 PSU2_TEMP1 25 N/A N/A N/A N/A False 20220311 08:13:04 TEMP1 23.5 80.0 N/A N/A N/A False 20220311 08:13:04 TEMP2 27 80.0 N/A N/A N/A False 20220311 08:13:04 TEMP3 24 80.0 N/A N/A N/A False 20220311 08:13:04 TEMP4 27 80.0 N/A N/A N/A False 20220311 08:13:04 TEMP5 24 80.0 N/A N/A N/A False 20220311 08:13:04
This commit is contained in:
parent
ad6200029f
commit
d3f2da8679
@ -10,7 +10,7 @@ try:
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.sfp import Sfp
|
||||
from sonic_platform.psu import Psu
|
||||
from sonic_platform.fan import Fan
|
||||
from sonic_platform.fan_drawer import FanDrawer
|
||||
from sonic_platform.thermal import Thermal
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
except ImportError as e:
|
||||
@ -52,9 +52,9 @@ class PddfChassis(ChassisBase):
|
||||
|
||||
# FANs
|
||||
for i in range(self.platform_inventory['num_fantrays']):
|
||||
for j in range(self.platform_inventory['num_fans_pertray']):
|
||||
fan = Fan(i, j, self.pddf_obj, self.plugin_data)
|
||||
self._fan_list.append(fan)
|
||||
fandrawer = FanDrawer(i, self.pddf_obj, self.plugin_data)
|
||||
self._fan_drawer_list.append(fandrawer)
|
||||
self._fan_list.extend(fandrawer._fan_list)
|
||||
|
||||
# PSUs
|
||||
for i in range(self.platform_inventory['num_psus']):
|
||||
|
@ -153,7 +153,7 @@ class PddfFan(FanBase):
|
||||
speed = int(output['status'])
|
||||
|
||||
max_speed = int(self.plugin_data['PSU']['PSU_FAN_MAX_SPEED'])
|
||||
speed_percentage = (speed*100)/max_speed
|
||||
speed_percentage = round((speed*100)/max_speed)
|
||||
return speed_percentage
|
||||
else:
|
||||
# TODO This calculation should change based on MAX FAN SPEED
|
||||
|
110
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan_drawer.py
Executable file
110
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan_drawer.py
Executable file
@ -0,0 +1,110 @@
|
||||
#############################################################################
|
||||
# PDDF
|
||||
#
|
||||
# PDDF fan_drawer base class inherited from the common base class fan_drawer.py
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||
from sonic_platform.fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class PddfFanDrawer(FanDrawerBase):
|
||||
"""PDDF generic Fan Drawer class"""
|
||||
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None):
|
||||
FanDrawerBase.__init__(self)
|
||||
if not pddf_data or not pddf_plugin_data:
|
||||
raise ValueError('PDDF JSON data error')
|
||||
|
||||
self.pddf_obj = pddf_data
|
||||
self.plugin_data = pddf_plugin_data
|
||||
self.platform = self.pddf_obj.get_platform()
|
||||
|
||||
if tray_idx < 0 or tray_idx >= self.platform['num_fantrays']:
|
||||
print("Invalid fantray index %d\n" % tray_idx)
|
||||
return
|
||||
|
||||
self.fantray_index = tray_idx+1
|
||||
for j in range(self.platform['num_fans_pertray']):
|
||||
# Fan index is 0-based for the init call
|
||||
self._fan_list.append(Fan(tray_idx, j, self.pddf_obj, self.plugin_data))
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the fan drawer name
|
||||
Returns: String containing fan-drawer name
|
||||
"""
|
||||
return "Fantray{0}".format(self.fantray_index)
|
||||
|
||||
def get_presence(self):
|
||||
status = False
|
||||
# Usually if a tray is removed, all the fans inside it are absent
|
||||
if self._fan_list:
|
||||
status = self._fan_list[0].get_presence()
|
||||
|
||||
return status
|
||||
|
||||
def get_status(self):
|
||||
status = False
|
||||
# if all the fans are working fine, then tray status should be okay
|
||||
if self._fan_list:
|
||||
status = all(fan.get_status() == True for fan in self._fan_list)
|
||||
|
||||
return status
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
# Usually Fantrays are replaceable
|
||||
return True
|
||||
|
||||
def get_position_in_parent(self):
|
||||
"""
|
||||
Retrieves 1-based relative physical position in parent device.
|
||||
Returns:
|
||||
integer: The 1-based relative physical position in parent
|
||||
device or -1 if cannot determine the position
|
||||
"""
|
||||
return self.fantray_index
|
||||
|
||||
def get_status_led(self):
|
||||
led_device_name = "FANTRAY{}".format(self.fantray_index) + "_LED"
|
||||
|
||||
if led_device_name not in self.pddf_obj.data.keys():
|
||||
# Implement a generic status_led color scheme
|
||||
if self.get_status():
|
||||
return self.STATUS_LED_COLOR_GREEN
|
||||
else:
|
||||
return self.STATUS_LED_COLOR_OFF
|
||||
|
||||
device_name = self.pddf_obj.data[led_device_name]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', str(self.fantray_index-1), self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path())
|
||||
color = self.pddf_obj.get_led_color()
|
||||
return (color)
|
||||
|
||||
def set_status_led(self, color):
|
||||
result = False
|
||||
led_device_name = "FANTRAY{}".format(self.fantray_index) + "_LED"
|
||||
result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color)
|
||||
if result == False:
|
||||
print(msg)
|
||||
return (False)
|
||||
|
||||
device_name = self.pddf_obj.data[led_device_name]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', str(self.fantray_index-1), self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path())
|
||||
return (True)
|
@ -20,6 +20,7 @@
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_platform.fan import Fan
|
||||
from sonic_platform.thermal import Thermal
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
@ -45,6 +46,11 @@ class PddfPsu(PsuBase):
|
||||
psu_fan = Fan(0, psu_fan_idx, pddf_data, pddf_plugin_data, True, self.psu_index)
|
||||
self._fan_list.append(psu_fan)
|
||||
|
||||
self.num_psu_thermals = 1 # Fixing it 1 for now
|
||||
for psu_thermal_idx in range(self.num_psu_thermals):
|
||||
psu_thermal = Thermal(psu_thermal_idx, pddf_data, pddf_plugin_data, True, self.psu_index)
|
||||
self._thermal_list.append(psu_thermal)
|
||||
|
||||
def get_num_fans(self):
|
||||
"""
|
||||
Retrieves the number of fan modules available on this PSU
|
||||
|
@ -22,7 +22,7 @@ class PddfThermal(ThermalBase):
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
|
||||
def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0):
|
||||
if not pddf_data or not pddf_plugin_data:
|
||||
raise ValueError('PDDF JSON data error')
|
||||
|
||||
@ -35,78 +35,129 @@ class PddfThermal(ThermalBase):
|
||||
self.thermal_obj_name = "TEMP{}".format(self.thermal_index)
|
||||
self.thermal_obj = self.pddf_obj.data[self.thermal_obj_name]
|
||||
|
||||
self.is_psu_thermal = is_psu_thermal
|
||||
if self.is_psu_thermal:
|
||||
self.thermals_psu_index = psu_index
|
||||
|
||||
def get_name(self):
|
||||
if 'dev_attr' in self.thermal_obj.keys():
|
||||
if 'display_name' in self.thermal_obj['dev_attr']:
|
||||
return str(self.thermal_obj['dev_attr']['display_name'])
|
||||
# In case of errors
|
||||
return (self.thermal_obj_name)
|
||||
if self.is_psu_thermal:
|
||||
return "PSU{}_TEMP{}".format(self.thermals_psu_index, self.thermal_index)
|
||||
else:
|
||||
if 'dev_attr' in self.thermal_obj.keys():
|
||||
if 'display_name' in self.thermal_obj['dev_attr']:
|
||||
return str(self.thermal_obj['dev_attr']['display_name'])
|
||||
# In case of errors
|
||||
return (self.thermal_obj_name)
|
||||
|
||||
def get_presence(self):
|
||||
if self.is_psu_thermal:
|
||||
# Temp sensor on the PSU
|
||||
device = "PSU{}".format(self.thermals_psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_present")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
status = output['status']
|
||||
|
||||
vmap = self.plugin_data['PSU']['psu_present'][mode]['valmap']
|
||||
|
||||
if status.rstrip('\n') in vmap:
|
||||
return vmap[status.rstrip('\n')]
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
# Temp sensor on the board
|
||||
return True
|
||||
|
||||
def get_temperature(self):
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_input")
|
||||
if not output:
|
||||
return None
|
||||
if self.is_psu_thermal:
|
||||
device = "PSU{}".format(self.thermals_psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_temp1_input")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
temp1 = output['status']
|
||||
# temperature returned is in milli celcius
|
||||
return float(temp1)/1000
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_input")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
|
||||
def get_high_threshold(self):
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_threshold")
|
||||
if not output:
|
||||
return None
|
||||
if not self.is_psu_thermal:
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def get_low_threshold(self):
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_threshold")
|
||||
if not output:
|
||||
return None
|
||||
if not self.is_psu_thermal:
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
raise NotImplementedError
|
||||
|
||||
def set_high_threshold(self, temperature):
|
||||
node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_high_threshold")
|
||||
if node is None:
|
||||
print("ERROR %s does not exist" % node)
|
||||
return None
|
||||
if not self.is_psu_thermal:
|
||||
node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_high_threshold")
|
||||
if node is None:
|
||||
print("ERROR %s does not exist" % node)
|
||||
return None
|
||||
|
||||
cmd = "echo '%d' > %s" % (temperature * 1000, node)
|
||||
os.system(cmd)
|
||||
cmd = "echo '%d' > %s" % (temperature * 1000, node)
|
||||
os.system(cmd)
|
||||
|
||||
return (True)
|
||||
return (True)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
def set_low_threshold(self, temperature):
|
||||
node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_low_threshold")
|
||||
if node is None:
|
||||
print("ERROR %s does not exist" % node)
|
||||
return None
|
||||
cmd = "echo '%d' > %s" % (temperature * 1000, node)
|
||||
os.system(cmd)
|
||||
if not self.is_psu_thermal:
|
||||
node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_low_threshold")
|
||||
if node is None:
|
||||
print("ERROR %s does not exist" % node)
|
||||
return None
|
||||
cmd = "echo '%d' > %s" % (temperature * 1000, node)
|
||||
os.system(cmd)
|
||||
|
||||
return (True)
|
||||
return (True)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
def get_high_critical_threshold(self):
|
||||
"""
|
||||
@ -116,19 +167,22 @@ class PddfThermal(ThermalBase):
|
||||
A float number, the high critical threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_crit_threshold")
|
||||
if not output:
|
||||
return None
|
||||
if not self.is_psu_thermal:
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_crit_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
raise NotImplementedError
|
||||
|
||||
def get_low_critical_threshold(self):
|
||||
"""
|
||||
@ -138,22 +192,24 @@ class PddfThermal(ThermalBase):
|
||||
A float number, the low critical threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_crit_threshold")
|
||||
if not output:
|
||||
return None
|
||||
if not self.is_psu_thermal:
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_crit_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
if output['mode'] == 'bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
raise NotImplementedError
|
||||
|
||||
# Helper Functions
|
||||
|
||||
def get_temp_label(self):
|
||||
if 'bmc' in self.pddf_obj.data[self.thermal_obj_name].keys():
|
||||
return None
|
||||
|
Loading…
Reference in New Issue
Block a user