[device/celestica]: DX010 platform API update (#4608)
- Fix fancontrol.service path - Fix return temp format in thermal API - Improve init time in chassis API - Upgrade sfp API
This commit is contained in:
parent
0ccdd70671
commit
5e5e9ec417
@ -8,20 +8,10 @@
|
|||||||
#
|
#
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import json
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import sys
|
||||||
from sonic_platform_base.chassis_base import ChassisBase
|
from sonic_platform_base.chassis_base import ChassisBase
|
||||||
from sonic_platform.fan import Fan
|
from helper import APIHelper
|
||||||
from sonic_platform.psu import Psu
|
|
||||||
from sonic_platform.component import Component
|
|
||||||
from sonic_platform.thermal import Thermal
|
|
||||||
from sonic_platform.sfp import Sfp
|
|
||||||
from sonic_platform.eeprom import Tlv
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -44,39 +34,54 @@ class Chassis(ChassisBase):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ChassisBase.__init__(self)
|
ChassisBase.__init__(self)
|
||||||
self.config_data = {}
|
self._api_helper = APIHelper()
|
||||||
|
self.sfp_module_initialized = False
|
||||||
|
self.__initialize_eeprom()
|
||||||
|
self.is_host = self._api_helper.is_host()
|
||||||
|
|
||||||
|
if not self.is_host:
|
||||||
|
self.__initialize_fan()
|
||||||
|
self.__initialize_psu()
|
||||||
|
self.__initialize_thermals()
|
||||||
|
else:
|
||||||
|
self.__initialize_components()
|
||||||
|
|
||||||
|
def __initialize_sfp(self):
|
||||||
|
from sonic_platform.sfp import Sfp
|
||||||
|
for index in range(0, NUM_SFP):
|
||||||
|
sfp = Sfp(index)
|
||||||
|
self._sfp_list.append(sfp)
|
||||||
|
self.sfp_module_initialized = True
|
||||||
|
|
||||||
|
def __initialize_psu(self):
|
||||||
|
from sonic_platform.psu import Psu
|
||||||
|
for index in range(0, NUM_PSU):
|
||||||
|
psu = Psu(index)
|
||||||
|
self._psu_list.append(psu)
|
||||||
|
|
||||||
|
def __initialize_fan(self):
|
||||||
|
from sonic_platform.fan import Fan
|
||||||
for fant_index in range(0, NUM_FAN_TRAY):
|
for fant_index in range(0, NUM_FAN_TRAY):
|
||||||
for fan_index in range(0, NUM_FAN):
|
for fan_index in range(0, NUM_FAN):
|
||||||
fan = Fan(fant_index, fan_index)
|
fan = Fan(fant_index, fan_index)
|
||||||
self._fan_list.append(fan)
|
self._fan_list.append(fan)
|
||||||
for index in range(0, NUM_PSU):
|
|
||||||
psu = Psu(index)
|
def __initialize_thermals(self):
|
||||||
self._psu_list.append(psu)
|
from sonic_platform.thermal import Thermal
|
||||||
for index in range(0, NUM_THERMAL):
|
for index in range(0, NUM_THERMAL):
|
||||||
thermal = Thermal(index)
|
thermal = Thermal(index)
|
||||||
self._thermal_list.append(thermal)
|
self._thermal_list.append(thermal)
|
||||||
# sfp index start from 1
|
|
||||||
for index in range(0, NUM_SFP):
|
def __initialize_eeprom(self):
|
||||||
sfp = Sfp(index)
|
from sonic_platform.eeprom import Tlv
|
||||||
self._sfp_list.append(sfp)
|
self._eeprom = Tlv()
|
||||||
|
|
||||||
|
def __initialize_components(self):
|
||||||
|
from sonic_platform.component import Component
|
||||||
for index in range(0, NUM_COMPONENT):
|
for index in range(0, NUM_COMPONENT):
|
||||||
component = Component(index)
|
component = Component(index)
|
||||||
self._component_list.append(component)
|
self._component_list.append(component)
|
||||||
|
|
||||||
self._eeprom = Tlv()
|
|
||||||
|
|
||||||
def __is_host(self):
|
|
||||||
return os.system(HOST_CHK_CMD) == 0
|
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_base_mac(self):
|
def get_base_mac(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the base MAC address for the chassis
|
Retrieves the base MAC address for the chassis
|
||||||
@ -107,7 +112,6 @@ class Chassis(ChassisBase):
|
|||||||
def get_reboot_cause(self):
|
def get_reboot_cause(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the cause of the previous reboot
|
Retrieves the cause of the previous reboot
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A tuple (string, string) where the first element is a string
|
A tuple (string, string) where the first element is a string
|
||||||
containing the cause of the previous reboot. This string must be
|
containing the cause of the previous reboot. This string must be
|
||||||
@ -118,16 +122,14 @@ class Chassis(ChassisBase):
|
|||||||
description = 'None'
|
description = 'None'
|
||||||
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
||||||
|
|
||||||
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.__is_host(
|
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.is_host else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
|
||||||
) else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
|
prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.is_host else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
|
||||||
prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host(
|
|
||||||
) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
|
|
||||||
|
|
||||||
hw_reboot_cause = self._component_list[0].get_register_value(RESET_REGISTER)
|
hw_reboot_cause = self._component_list[0].get_register_value(RESET_REGISTER)
|
||||||
|
|
||||||
sw_reboot_cause = self.__read_txt_file(
|
sw_reboot_cause = self._api_helper.read_txt_file(
|
||||||
reboot_cause_path) or "Unknown"
|
reboot_cause_path) or "Unknown"
|
||||||
prev_sw_reboot_cause = self.__read_txt_file(
|
prev_sw_reboot_cause = self._api_helper.read_txt_file(
|
||||||
prev_reboot_cause_path) or "Unknown"
|
prev_reboot_cause_path) or "Unknown"
|
||||||
|
|
||||||
if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11":
|
if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11":
|
||||||
@ -146,18 +148,32 @@ class Chassis(ChassisBase):
|
|||||||
|
|
||||||
return (reboot_cause, description)
|
return (reboot_cause, description)
|
||||||
|
|
||||||
def get_watchdog(self):
|
##############################################################
|
||||||
"""
|
######################## SFP methods #########################
|
||||||
Retreives hardware watchdog device on this chassis
|
##############################################################
|
||||||
Returns:
|
|
||||||
An object derived from WatchdogBase representing the hardware
|
|
||||||
watchdog device
|
|
||||||
"""
|
|
||||||
if self._watchdog is None:
|
|
||||||
from sonic_platform.watchdog import Watchdog
|
|
||||||
self._watchdog = Watchdog()
|
|
||||||
|
|
||||||
return self._watchdog
|
def get_num_sfps(self):
|
||||||
|
"""
|
||||||
|
Retrieves the number of sfps available on this chassis
|
||||||
|
Returns:
|
||||||
|
An integer, the number of sfps available on this chassis
|
||||||
|
"""
|
||||||
|
if not self.sfp_module_initialized:
|
||||||
|
self.__initialize_sfp()
|
||||||
|
|
||||||
|
return len(self._sfp_list)
|
||||||
|
|
||||||
|
def get_all_sfps(self):
|
||||||
|
"""
|
||||||
|
Retrieves all sfps available on this chassis
|
||||||
|
Returns:
|
||||||
|
A list of objects derived from SfpBase representing all sfps
|
||||||
|
available on this chassis
|
||||||
|
"""
|
||||||
|
if not self.sfp_module_initialized:
|
||||||
|
self.__initialize_sfp()
|
||||||
|
|
||||||
|
return self._sfp_list
|
||||||
|
|
||||||
def get_sfp(self, index):
|
def get_sfp(self, index):
|
||||||
"""
|
"""
|
||||||
@ -171,6 +187,8 @@ class Chassis(ChassisBase):
|
|||||||
An object dervied from SfpBase representing the specified sfp
|
An object dervied from SfpBase representing the specified sfp
|
||||||
"""
|
"""
|
||||||
sfp = None
|
sfp = None
|
||||||
|
if not self.sfp_module_initialized:
|
||||||
|
self.__initialize_sfp()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# The index will start from 1
|
# The index will start from 1
|
||||||
@ -179,3 +197,64 @@ class Chassis(ChassisBase):
|
|||||||
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
|
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
|
||||||
index, len(self._sfp_list)))
|
index, len(self._sfp_list)))
|
||||||
return sfp
|
return sfp
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
####################### Other methods ########################
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
def get_watchdog(self):
|
||||||
|
"""
|
||||||
|
Retreives hardware watchdog device on this chassis
|
||||||
|
Returns:
|
||||||
|
An object derived from WatchdogBase representing the hardware
|
||||||
|
watchdog device
|
||||||
|
"""
|
||||||
|
if self._watchdog is None:
|
||||||
|
from sonic_platform.watchdog import Watchdog
|
||||||
|
self._watchdog = Watchdog()
|
||||||
|
|
||||||
|
return self._watchdog
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
###################### Device methods ########################
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the device
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
return self._api_helper.hwsku
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the PSU
|
||||||
|
Returns:
|
||||||
|
bool: True if PSU is present, False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
return self._eeprom.get_pn()
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
return self.get_serial_number()
|
||||||
|
|
||||||
|
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 True
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
#
|
#
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
import json
|
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
import shlex
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.component_base import ComponentBase
|
from sonic_platform_base.component_base import ComponentBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -29,7 +28,8 @@ CPLD_ADDR_MAPPING = {
|
|||||||
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
||||||
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
|
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
|
||||||
COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"]
|
COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"]
|
||||||
COMPONENT_DES_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "Basic Input/Output System"]
|
COMPONENT_DES_LIST = ["Used for managing the CPU",
|
||||||
|
"Used for managing QSFP+ ports (1-10)", "Used for managing QSFP+ ports (11-20)", "Used for managing QSFP+ ports (22-32)", "Basic Input/Output System"]
|
||||||
|
|
||||||
|
|
||||||
class Component(ComponentBase):
|
class Component(ComponentBase):
|
||||||
@ -40,24 +40,9 @@ class Component(ComponentBase):
|
|||||||
def __init__(self, component_index):
|
def __init__(self, component_index):
|
||||||
ComponentBase.__init__(self)
|
ComponentBase.__init__(self)
|
||||||
self.index = component_index
|
self.index = component_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
self.name = self.get_name()
|
self.name = self.get_name()
|
||||||
|
|
||||||
def __run_command(self, command):
|
|
||||||
# Run bash command and print output to stdout
|
|
||||||
try:
|
|
||||||
process = subprocess.Popen(
|
|
||||||
shlex.split(command), stdout=subprocess.PIPE)
|
|
||||||
while True:
|
|
||||||
output = process.stdout.readline()
|
|
||||||
if output == '' and process.poll() is not None:
|
|
||||||
break
|
|
||||||
rc = process.poll()
|
|
||||||
if rc != 0:
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __get_bios_version(self):
|
def __get_bios_version(self):
|
||||||
# Retrieves the BIOS firmware version
|
# Retrieves the BIOS firmware version
|
||||||
try:
|
try:
|
||||||
|
@ -14,6 +14,7 @@ import os.path
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.fan_base import FanBase
|
from sonic_platform_base.fan_base import FanBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -38,13 +39,16 @@ PSU_I2C_MAPPING = {
|
|||||||
"addr": "5b"
|
"addr": "5b"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
NULL_VAL = "N/A"
|
||||||
|
|
||||||
|
|
||||||
class Fan(FanBase):
|
class Fan(FanBase):
|
||||||
"""Platform-specific Fan class"""
|
"""Platform-specific Fan class"""
|
||||||
|
|
||||||
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
|
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
|
||||||
|
FanBase.__init__(self)
|
||||||
self.fan_index = fan_index
|
self.fan_index = fan_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
self.fan_tray_index = fan_tray_index
|
self.fan_tray_index = fan_tray_index
|
||||||
self.is_psu_fan = is_psu_fan
|
self.is_psu_fan = is_psu_fan
|
||||||
if self.is_psu_fan:
|
if self.is_psu_fan:
|
||||||
@ -75,16 +79,6 @@ class Fan(FanBase):
|
|||||||
{'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4
|
{'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4
|
||||||
{'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5
|
{'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5
|
||||||
]
|
]
|
||||||
FanBase.__init__(self)
|
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def __write_txt_file(self, file_path, value):
|
def __write_txt_file(self, file_path, value):
|
||||||
try:
|
try:
|
||||||
@ -105,7 +99,7 @@ class Fan(FanBase):
|
|||||||
def __get_gpio_base(self):
|
def __get_gpio_base(self):
|
||||||
for r in os.listdir(GPIO_DIR):
|
for r in os.listdir(GPIO_DIR):
|
||||||
label_path = os.path.join(GPIO_DIR, r, "label")
|
label_path = os.path.join(GPIO_DIR, r, "label")
|
||||||
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
|
if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
|
||||||
return int(r[8:], 10)
|
return int(r[8:], 10)
|
||||||
return 216 # Reserve
|
return 216 # Reserve
|
||||||
|
|
||||||
@ -113,7 +107,7 @@ class Fan(FanBase):
|
|||||||
gpio_base = self.dx010_fan_gpio[0]['base']
|
gpio_base = self.dx010_fan_gpio[0]['base']
|
||||||
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
|
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
|
||||||
gpio_file = gpio_dir + "/value"
|
gpio_file = gpio_dir + "/value"
|
||||||
retval = self.__read_txt_file(gpio_file)
|
retval = self._api_helper.read_txt_file(gpio_file)
|
||||||
return retval.rstrip('\r\n')
|
return retval.rstrip('\r\n')
|
||||||
|
|
||||||
def __set_gpio_value(self, pinnum, value=0):
|
def __set_gpio_value(self, pinnum, value=0):
|
||||||
@ -154,7 +148,8 @@ class Fan(FanBase):
|
|||||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||||
self.psu_hwmon_path, fan_speed_sysfs_name)
|
self.psu_hwmon_path, fan_speed_sysfs_name)
|
||||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
fan_speed_rpm = self._api_helper.read_txt_file(
|
||||||
|
fan_speed_sysfs_path) or 0
|
||||||
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
|
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
|
||||||
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
|
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
|
||||||
elif self.get_presence():
|
elif self.get_presence():
|
||||||
@ -164,7 +159,7 @@ class Fan(FanBase):
|
|||||||
sysfs_path = "%s%s/%s" % (
|
sysfs_path = "%s%s/%s" % (
|
||||||
EMC2305_PATH, device, EMC2305_FAN_INPUT)
|
EMC2305_PATH, device, EMC2305_FAN_INPUT)
|
||||||
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
||||||
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
|
raw = self._api_helper.read_txt_file(sysfs_path).strip('\r\n')
|
||||||
pwm = int(raw, 10) if raw else 0
|
pwm = int(raw, 10) if raw else 0
|
||||||
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
|
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
|
||||||
|
|
||||||
@ -183,19 +178,7 @@ class Fan(FanBase):
|
|||||||
0 : when PWM mode is use
|
0 : when PWM mode is use
|
||||||
pwm : when pwm mode is not use
|
pwm : when pwm mode is not use
|
||||||
"""
|
"""
|
||||||
target = 0
|
return 'N/A'
|
||||||
if not self.is_psu_fan:
|
|
||||||
chip = self.emc2305_chip_mapping[self.fan_index]
|
|
||||||
device = chip['device']
|
|
||||||
fan_index = chip['index_map']
|
|
||||||
sysfs_path = "%s%s/%s" % (
|
|
||||||
EMC2305_PATH, device, EMC2305_FAN_TARGET)
|
|
||||||
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
|
||||||
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
|
|
||||||
pwm = int(raw, 10) if raw else 0
|
|
||||||
target = math.ceil(float(pwm) * 100 / EMC2305_MAX_PWM)
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
def get_speed_tolerance(self):
|
def get_speed_tolerance(self):
|
||||||
"""
|
"""
|
||||||
@ -284,11 +267,43 @@ class Fan(FanBase):
|
|||||||
|
|
||||||
def get_presence(self):
|
def get_presence(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the presence of the PSU
|
Retrieves the presence of the FAN
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if PSU is present, False if not
|
bool: True if FAN is present, False if not
|
||||||
"""
|
"""
|
||||||
present_str = self.__get_gpio_value(
|
present_str = self.__get_gpio_value(
|
||||||
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
|
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
|
||||||
|
|
||||||
return int(present_str, 10) == 0 if not self.is_psu_fan else True
|
return int(present_str, 10) == 0 if not self.is_psu_fan else True
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
if self.is_psu_fan:
|
||||||
|
return NULL_VAL
|
||||||
|
|
||||||
|
model = NULL_VAL
|
||||||
|
return model
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
if self.is_psu_fan:
|
||||||
|
return NULL_VAL
|
||||||
|
|
||||||
|
serial = NULL_VAL
|
||||||
|
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
|
||||||
|
121
device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py
Normal file
121
device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
from sonic_daemon_base.daemon_base import DaemonBase
|
||||||
|
from mmap import *
|
||||||
|
|
||||||
|
HOST_CHK_CMD = "docker > /dev/null 2>&1"
|
||||||
|
EMPTY_STRING = ""
|
||||||
|
|
||||||
|
|
||||||
|
class APIHelper():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
(self.platform, self.hwsku) = DaemonBase().get_platform_and_hwsku()
|
||||||
|
|
||||||
|
def is_host(self):
|
||||||
|
return os.system(HOST_CHK_CMD) == 0
|
||||||
|
|
||||||
|
def pci_get_value(self, resource, offset):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
fd = os.open(resource, os.O_RDWR)
|
||||||
|
mm = mmap(fd, 0)
|
||||||
|
mm.seek(int(offset))
|
||||||
|
read_data_stream = mm.read(4)
|
||||||
|
result = struct.unpack('I', read_data_stream)
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def run_command(self, cmd):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def run_interactive_command(self, cmd):
|
||||||
|
try:
|
||||||
|
os.system(cmd)
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def read_txt_file(self, file_path):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as fd:
|
||||||
|
data = fd.read()
|
||||||
|
return data.strip()
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def read_one_line_file(self, file_path):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as fd:
|
||||||
|
data = fd.readline()
|
||||||
|
return data.strip()
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def ipmi_raw(self, netfn, cmd):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd))
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
else:
|
||||||
|
status = False
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def ipmi_fru_id(self, id, key=None):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
cmd = "ipmitool fru print {}".format(str(
|
||||||
|
id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key))
|
||||||
|
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
else:
|
||||||
|
status = False
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def ipmi_set_ss_thres(self, id, threshold_key, value):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
cmd = "ipmitool sensor thresh '{}' {} {}".format(
|
||||||
|
str(id), str(threshold_key), str(value))
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
else:
|
||||||
|
status = False
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
@ -14,6 +14,7 @@ import sonic_platform
|
|||||||
try:
|
try:
|
||||||
from sonic_platform_base.psu_base import PsuBase
|
from sonic_platform_base.psu_base import PsuBase
|
||||||
from sonic_platform.fan import Fan
|
from sonic_platform.fan import Fan
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ class Psu(PsuBase):
|
|||||||
def __init__(self, psu_index):
|
def __init__(self, psu_index):
|
||||||
PsuBase.__init__(self)
|
PsuBase.__init__(self)
|
||||||
self.index = psu_index
|
self.index = psu_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
self.green_led_path = GREEN_LED_PATH.format(self.index+1)
|
self.green_led_path = GREEN_LED_PATH.format(self.index+1)
|
||||||
self.dx010_psu_gpio = [
|
self.dx010_psu_gpio = [
|
||||||
{'base': self.__get_gpio_base()},
|
{'base': self.__get_gpio_base()},
|
||||||
@ -54,27 +56,18 @@ class Psu(PsuBase):
|
|||||||
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
|
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
|
||||||
self._fan_list.append(fan)
|
self._fan_list.append(fan)
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def __search_file_by_contain(self, directory, search_str, file_start):
|
def __search_file_by_contain(self, directory, search_str, file_start):
|
||||||
for dirpath, dirnames, files in os.walk(directory):
|
for dirpath, dirnames, files in os.walk(directory):
|
||||||
for name in files:
|
for name in files:
|
||||||
file_path = os.path.join(dirpath, name)
|
file_path = os.path.join(dirpath, name)
|
||||||
if name.startswith(file_start) and search_str in self.__read_txt_file(file_path):
|
if name.startswith(file_start) and search_str in self._api_helper.read_txt_file(file_path):
|
||||||
return file_path
|
return file_path
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __get_gpio_base(self):
|
def __get_gpio_base(self):
|
||||||
for r in os.listdir(GPIO_DIR):
|
for r in os.listdir(GPIO_DIR):
|
||||||
label_path = os.path.join(GPIO_DIR, r, "label")
|
label_path = os.path.join(GPIO_DIR, r, "label")
|
||||||
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
|
if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
|
||||||
return int(r[8:], 10)
|
return int(r[8:], 10)
|
||||||
return 216 # Reserve
|
return 216 # Reserve
|
||||||
|
|
||||||
@ -82,7 +75,7 @@ class Psu(PsuBase):
|
|||||||
gpio_base = self.dx010_psu_gpio[0]['base']
|
gpio_base = self.dx010_psu_gpio[0]['base']
|
||||||
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
|
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
|
||||||
gpio_file = gpio_dir + "/value"
|
gpio_file = gpio_dir + "/value"
|
||||||
retval = self.__read_txt_file(gpio_file)
|
retval = self._api_helper.read_txt_file(gpio_file)
|
||||||
return retval.rstrip('\r\n')
|
return retval.rstrip('\r\n')
|
||||||
|
|
||||||
def get_voltage(self):
|
def get_voltage(self):
|
||||||
@ -104,7 +97,7 @@ class Psu(PsuBase):
|
|||||||
in_num = filter(str.isdigit, basename)
|
in_num = filter(str.isdigit, basename)
|
||||||
vout_path = os.path.join(
|
vout_path = os.path.join(
|
||||||
dir_name, voltage_name.format(in_num))
|
dir_name, voltage_name.format(in_num))
|
||||||
vout_val = self.__read_txt_file(vout_path)
|
vout_val = self._api_helper.read_txt_file(vout_path)
|
||||||
psu_voltage = float(vout_val) / 1000
|
psu_voltage = float(vout_val) / 1000
|
||||||
|
|
||||||
return psu_voltage
|
return psu_voltage
|
||||||
@ -127,7 +120,7 @@ class Psu(PsuBase):
|
|||||||
cur_num = filter(str.isdigit, basename)
|
cur_num = filter(str.isdigit, basename)
|
||||||
cur_path = os.path.join(
|
cur_path = os.path.join(
|
||||||
dir_name, current_name.format(cur_num))
|
dir_name, current_name.format(cur_num))
|
||||||
cur_val = self.__read_txt_file(cur_path)
|
cur_val = self._api_helper.read_txt_file(cur_path)
|
||||||
psu_current = float(cur_val) / 1000
|
psu_current = float(cur_val) / 1000
|
||||||
|
|
||||||
return psu_current
|
return psu_current
|
||||||
@ -150,7 +143,7 @@ class Psu(PsuBase):
|
|||||||
pw_num = filter(str.isdigit, basename)
|
pw_num = filter(str.isdigit, basename)
|
||||||
pw_path = os.path.join(
|
pw_path = os.path.join(
|
||||||
dir_name, current_name.format(pw_num))
|
dir_name, current_name.format(pw_num))
|
||||||
pw_val = self.__read_txt_file(pw_path)
|
pw_val = self._api_helper.read_txt_file(pw_path)
|
||||||
psu_power = float(pw_val) / 1000000
|
psu_power = float(pw_val) / 1000000
|
||||||
|
|
||||||
return psu_power
|
return psu_power
|
||||||
@ -196,7 +189,7 @@ class Psu(PsuBase):
|
|||||||
Returns:
|
Returns:
|
||||||
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
||||||
"""
|
"""
|
||||||
status = self.__read_txt_file(self.green_led_path)
|
status = self._api_helper.read_txt_file(self.green_led_path)
|
||||||
status_str = {
|
status_str = {
|
||||||
'255': self.STATUS_LED_COLOR_GREEN,
|
'255': self.STATUS_LED_COLOR_GREEN,
|
||||||
'0': self.STATUS_LED_COLOR_OFF
|
'0': self.STATUS_LED_COLOR_OFF
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ import os.path
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.thermal_base import ThermalBase
|
from sonic_platform_base.thermal_base import ThermalBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ class Thermal(ThermalBase):
|
|||||||
|
|
||||||
def __init__(self, thermal_index):
|
def __init__(self, thermal_index):
|
||||||
self.index = thermal_index
|
self.index = thermal_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
|
|
||||||
# Add thermal name
|
# Add thermal name
|
||||||
self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
|
self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
|
||||||
@ -48,19 +50,11 @@ class Thermal(ThermalBase):
|
|||||||
self.ss_key = self.THERMAL_NAME_LIST[self.index]
|
self.ss_key = self.THERMAL_NAME_LIST[self.index]
|
||||||
self.ss_index = 1
|
self.ss_index = 1
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __get_temp(self, temp_file):
|
def __get_temp(self, temp_file):
|
||||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||||
raw_temp = self.__read_txt_file(temp_file_path)
|
raw_temp = self._api_helper.read_txt_file(temp_file_path)
|
||||||
temp = float(raw_temp)/1000
|
temp = float(raw_temp)/1000
|
||||||
return "{:.3f}".format(temp)
|
return float("{:.3f}".format(temp))
|
||||||
|
|
||||||
def __set_threshold(self, file_name, temperature):
|
def __set_threshold(self, file_name, temperature):
|
||||||
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
||||||
|
@ -2,7 +2,7 @@ dx010/scripts/dx010_check_qsfp.sh usr/local/bin
|
|||||||
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
||||||
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
||||||
dx010/scripts/fancontrol.sh etc/init.d
|
dx010/scripts/fancontrol.sh etc/init.d
|
||||||
services/fancontrol/fancontrol.service lib/systemd/system
|
dx010/scripts/fancontrol.service lib/systemd/system
|
||||||
services/fancontrol/fancontrol usr/local/bin
|
services/fancontrol/fancontrol usr/local/bin
|
||||||
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
|
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
|
||||||
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
||||||
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
|
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
|
||||||
haliburton/script/fancontrol.sh etc/init.d
|
haliburton/script/fancontrol.sh etc/init.d
|
||||||
services/fancontrol/fancontrol.service lib/systemd/system
|
haliburton/script/fancontrol.service lib/systemd/system
|
||||||
services/fancontrol/fancontrol usr/local/bin
|
services/fancontrol/fancontrol usr/local/bin
|
||||||
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
|
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
|
||||||
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=fan speed regulator
|
||||||
|
After=platform-modules-dx010.service
|
||||||
|
Before=pmon.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/etc/init.d/fancontrol.sh start
|
||||||
|
ExecStop=-/etc/init.d/fancontrol.sh stop
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
Loading…
Reference in New Issue
Block a user