Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for fan_drawer class in PDDF common platform APIs #10213

Merged
merged 1 commit into from
Mar 18, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
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 @@ def __init__(self, pddf_data=None, pddf_plugin_data=None):

# 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']):
Original file line number Diff line number Diff line change
@@ -153,7 +153,7 @@ def get_speed(self):
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
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -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 @@ def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
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
Original file line number Diff line number Diff line change
@@ -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 @@ def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
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 @@ def get_high_critical_threshold(self):
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 @@ def get_low_critical_threshold(self):
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