This change introduces PDDF which is described here: https://github.com/Azure/SONiC/pull/536 Most of the platform bring up effort goes in developing the platform device drivers, SONiC platform APIs and validating them. Typically each platform vendor writes their own drivers and platform APIs which is very tailor made to that platform. This involves writing code, building, installing it on the target platform devices and testing. Many of the details of the platform are hard coded into these drivers, from the HW spec. They go through this cycle repetitively till everything works fine, and is validated before upstreaming the code. PDDF aims to make this platform driver and platform APIs development process much simpler by providing a data driven development framework. This is enabled by: JSON descriptor files for platform data Generic data-driven drivers for various devices Generic SONiC platform APIs Vendor specific extensions for customisation and extensibility Signed-off-by: Fuzail Khan <fuzail.khan@broadcom.com>
203 lines
5.3 KiB
Python
Executable File
203 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
|
|
# Sample pddf_fanutil file
|
|
# All the supported FAN SysFS aattributes are
|
|
#- fan<idx>_present
|
|
#- fan<idx>_direction
|
|
#- fan<idx>_input
|
|
#- fan<idx>_pwm
|
|
#- fan<idx>_fault
|
|
# where idx is in the range [1-12]
|
|
#
|
|
|
|
|
|
import os.path
|
|
import sys
|
|
sys.path.append('/usr/share/sonic/platform/plugins')
|
|
import pddfparse
|
|
import json
|
|
|
|
try:
|
|
from sonic_fan.fan_base import FanBase
|
|
except ImportError as e:
|
|
raise ImportError (str(e) + "- required module not found")
|
|
|
|
class FanUtil(FanBase):
|
|
"""PDDF generic FAN util class"""
|
|
|
|
def __init__(self):
|
|
FanBase.__init__(self)
|
|
global pddf_obj
|
|
global plugin_data
|
|
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
|
plugin_data = json.load(pd)
|
|
|
|
pddf_obj = pddfparse.PddfParse()
|
|
self.platform = pddf_obj.get_platform()
|
|
|
|
self.num_fans = (self.platform['num_fantrays'] * self.platform['num_fans_pertray'] )
|
|
|
|
def get_num_fans(self):
|
|
return self.num_fans
|
|
|
|
def get_presence(self, idx):
|
|
# 1 based fan index
|
|
if idx<1 or idx>self.num_fans:
|
|
print "Invalid fan index %d\n"%idx
|
|
return False
|
|
|
|
attr_name = "fan"+ str(idx) +"_present"
|
|
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr_name)
|
|
if not output:
|
|
return False
|
|
|
|
mode = output['mode']
|
|
presence = output['status'].rstrip()
|
|
|
|
vmap = plugin_data['FAN']['present'][mode]['valmap']
|
|
|
|
if presence in vmap:
|
|
status = vmap[presence]
|
|
else:
|
|
status = False
|
|
|
|
return status
|
|
|
|
def get_status(self, idx):
|
|
# 1 based fan index
|
|
if idx<1 or idx>self.num_fans:
|
|
print "Invalid fan index %d\n"%idx
|
|
return False
|
|
|
|
speed = self.get_speed(idx)
|
|
status = True if (speed != 0) else False
|
|
return status
|
|
|
|
def get_direction(self, idx):
|
|
# 1 based fan index
|
|
if idx<1 or idx>self.num_fans:
|
|
print "Invalid fan index %d\n"%idx
|
|
return None
|
|
|
|
attr = "fan" + str(idx) + "_direction"
|
|
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
|
if not output:
|
|
return None
|
|
|
|
mode = output['mode']
|
|
val = output['status']
|
|
|
|
val = val.rstrip()
|
|
vmap = plugin_data['FAN']['direction'][mode]['valmap']
|
|
|
|
|
|
if val in vmap:
|
|
direction = vmap[val]
|
|
else:
|
|
direction = val
|
|
|
|
return direction
|
|
|
|
def get_directions(self):
|
|
num_fan = self.get_num_fan();
|
|
|
|
for i in range(1, num_fan+1):
|
|
attr = "fan" + str(i) + "_direction"
|
|
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
|
if not output:
|
|
return None
|
|
|
|
mode = output['mode']
|
|
val = output['status']
|
|
|
|
val = val.rstrip()
|
|
vmap = plugin_data['FAN']['direction'][mode]['valmap']
|
|
|
|
direction = vmap[str(val)]
|
|
|
|
print "FAN-%d direction is %s"%(i, direction)
|
|
|
|
return 0
|
|
|
|
def get_speed(self, idx):
|
|
# 1 based fan index
|
|
if idx<1 or idx>self.num_fans:
|
|
print "Invalid fan index %d\n"%idx
|
|
return 0
|
|
|
|
attr = "fan" + str(idx) + "_input"
|
|
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
|
if not output:
|
|
return 0
|
|
|
|
#mode = output['mode']
|
|
val = output['status'].rstrip()
|
|
|
|
if val.isalpha():
|
|
return 0
|
|
else:
|
|
rpm_speed = int(float(val))
|
|
|
|
return rpm_speed
|
|
|
|
def get_speeds(self):
|
|
num_fan = self.get_num_fan();
|
|
ret = "FAN_INDEX\t\tRPM\n"
|
|
|
|
for i in range(1, num_fan+1):
|
|
attr1 = "fan" + str(i) + "_input"
|
|
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr1)
|
|
if not output:
|
|
return ""
|
|
|
|
#mode = output['mode']
|
|
val = output['status'].rstrip()
|
|
|
|
if val.isalpha():
|
|
frpm = 0
|
|
else:
|
|
frpm = int(val)
|
|
|
|
ret += "FAN-%d\t\t\t%d\n"%(i, frpm)
|
|
|
|
return ret
|
|
|
|
def set_speed(self, val):
|
|
if val<0 or val>100:
|
|
print "Error: Invalid speed %d. Please provide a valid speed percentage"%val
|
|
return False
|
|
|
|
num_fan = self.num_fans
|
|
if 'duty_cycle_to_pwm' not in plugin_data['FAN']:
|
|
print "Setting fan speed is not allowed !"
|
|
return False
|
|
else:
|
|
duty_cycle_to_pwm = eval(plugin_data['FAN']['duty_cycle_to_pwm'])
|
|
pwm = duty_cycle_to_pwm(val)
|
|
print "New Speed: %d%% - PWM value to be set is %d\n"%(val,pwm)
|
|
|
|
for i in range(1, num_fan+1):
|
|
attr = "fan" + str(i) + "_pwm"
|
|
node = pddf_obj.get_path("FAN-CTRL", attr)
|
|
if node is None:
|
|
return False
|
|
try:
|
|
with open(node, 'w') as f:
|
|
f.write(str(pwm))
|
|
except IOError:
|
|
return False
|
|
|
|
return True
|
|
|
|
def dump_sysfs(self):
|
|
return pddf_obj.cli_dump_dsysfs('fan')
|
|
|
|
def get_change_event(self):
|
|
"""
|
|
TODO: This function need to be implemented
|
|
when decide to support monitoring FAN(fand)
|
|
on this platform.
|
|
"""
|
|
raise NotImplementedError
|