[AS5835-54X] Support system-health and remove extra code (#8137)

Co-authored-by: Jostar Yang <jostar_yang@accton.com.tw>
This commit is contained in:
jostar-yang 2021-07-25 09:35:06 +08:00 committed by GitHub
parent 814865b2c5
commit 4eab1514ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 454 additions and 429 deletions

View File

@ -1,5 +1,5 @@
{ {
"skip_ledd": true, "skip_ledd": true,
"skip_thermalctld": true "skip_pcied": true
} }

View File

@ -1,2 +1,2 @@
__all__ = ['chassis', 'eeprom', 'platform', 'psu', 'sfp', 'thermal', 'fan'] __all__ = [ "platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer" ]
from . import platform from . import platform

View File

@ -29,6 +29,14 @@ PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt" REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
HOST_CHK_CMD = "docker > /dev/null 2>&1" HOST_CHK_CMD = "docker > /dev/null 2>&1"
SYSLED_FNODE= "/sys/class/leds/as5835_54x_led::diag/brightness"
SYSLED_MODES = {
"0" : "STATUS_LED_COLOR_OFF",
"1" : "STATUS_LED_COLOR_GREEN",
"2" : "STATUS_LED_COLOR_AMBER",
"5" : "STATUS_LED_COLOR_GREEN_BLINK"
}
class Chassis(ChassisBase): class Chassis(ChassisBase):
@ -57,11 +65,11 @@ class Chassis(ChassisBase):
self.sfp_module_initialized = True self.sfp_module_initialized = True
def __initialize_fan(self): def __initialize_fan(self):
from sonic_platform.fan import Fan from sonic_platform.fan_drawer import FanDrawer
for fant_index in range(0, NUM_FAN_TRAY): for fant_index in range(NUM_FAN_TRAY):
for fan_index in range(0, NUM_FAN): fandrawer = FanDrawer(fant_index)
fan = Fan(fant_index, fan_index) self._fan_drawer_list.append(fandrawer)
self._fan_list.append(fan) self._fan_list.extend(fandrawer._fan_list)
def __initialize_psu(self): def __initialize_psu(self):
from sonic_platform.psu import Psu from sonic_platform.psu import Psu
@ -212,3 +220,40 @@ 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
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False
def initizalize_system_led(self):
return True
def get_status_led(self):
val = self._api_helper.read_txt_file(SYSLED_FNODE)
return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN"
def set_status_led(self, color):
mode = None
for key, val in SYSLED_MODES.items():
if val == color:
mode = key
break
if mode is None:
return False
else:
return self._api_helper.write_txt_file(SYSLED_FNODE, mode)

View File

@ -126,3 +126,55 @@ class Component(ComponentBase):
A boolean, True if install successfully, False if not A boolean, True if install successfully, False if not
""" """
raise NotImplementedError raise NotImplementedError
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device 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 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return 'N/A'
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
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False

View File

@ -1,131 +0,0 @@
try:
import os
import sys
import re
if sys.version_info[0] >= 3:
from io import StringIO
else:
from cStringIO import StringIO
from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CACHE_ROOT = '/var/cache/sonic/decode-syseeprom'
CACHE_FILE = 'syseeprom_cache'
NULL = 'N/A'
class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
EEPROM_DECODE_HEADLINES = 6
def __init__(self):
self._eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
super(Tlv, self).__init__(self._eeprom_path, 0, '', True)
self._eeprom = self._load_eeprom()
def __parse_output(self, decode_output):
decode_output.replace('\0', '')
lines = decode_output.split('\n')
lines = lines[self.EEPROM_DECODE_HEADLINES:]
_eeprom_info_dict = dict()
for line in lines:
try:
match = re.search(
'(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line)
if match is not None:
idx = match.group(1)
value = match.group(3).rstrip('\0')
_eeprom_info_dict[idx] = value
except Exception:
pass
return _eeprom_info_dict
def _load_eeprom(self):
original_stdout = sys.stdout
sys.stdout = StringIO()
try:
self.read_eeprom_db()
except Exception:
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
return self.__parse_output(decode_output)
status = self.check_status()
if 'ok' not in status:
return False
if not os.path.exists(CACHE_ROOT):
try:
os.makedirs(CACHE_ROOT)
except Exception:
pass
#
# only the eeprom classes that inherit from eeprom_base
# support caching. Others will work normally
#
try:
self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE))
except Exception:
pass
e = self.read_eeprom()
if e is None:
return 0
try:
self.update_cache(e)
except Exception:
pass
self.decode_eeprom(e)
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
(is_valid, valid_crc) = self.is_checksum_valid(e)
if not is_valid:
return False
return self.__parse_output(decode_output)
def _valid_tlv(self, eeprom_data):
tlvinfo_type_codes_list = [
self._TLV_CODE_PRODUCT_NAME,
self._TLV_CODE_PART_NUMBER,
self._TLV_CODE_SERIAL_NUMBER,
self._TLV_CODE_MAC_BASE,
self._TLV_CODE_MANUF_DATE,
self._TLV_CODE_DEVICE_VERSION,
self._TLV_CODE_LABEL_REVISION,
self._TLV_CODE_PLATFORM_NAME,
self._TLV_CODE_ONIE_VERSION,
self._TLV_CODE_MAC_SIZE,
self._TLV_CODE_MANUF_NAME,
self._TLV_CODE_MANUF_COUNTRY,
self._TLV_CODE_VENDOR_NAME,
self._TLV_CODE_DIAG_VERSION,
self._TLV_CODE_SERVICE_TAG,
self._TLV_CODE_VENDOR_EXT,
self._TLV_CODE_CRC_32
]
for code in tlvinfo_type_codes_list:
code_str = "0x{:X}".format(code)
eeprom_data[code_str] = eeprom_data.get(code_str, NULL)
return eeprom_data
def get_eeprom(self):
return self._valid_tlv(self._eeprom)
def get_pn(self):
return self._eeprom.get('0x22', NULL)
def get_serial(self):
return self._eeprom.get('0x23', NULL)
def get_mac(self):
return self._eeprom.get('0x24', NULL)

View File

@ -15,9 +15,10 @@ except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
PSU_FAN_MAX_RPM = 26688 PSU_FAN_MAX_RPM = 26688
CPLD_I2C_PATH = "/sys/bus/i2c/devices/3-0063/fan" SPEED_TOLERANCE = 15
PSU_HWMON_I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/" CPLD_FAN_I2C_PATH = "/sys/bus/i2c/devices/3-0063/fan"
PSU_I2C_MAPPING = { I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: { 0: {
"num": 11, "num": 11,
"addr": "58" "addr": "58"
@ -28,6 +29,20 @@ PSU_I2C_MAPPING = {
}, },
} }
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 11,
"addr": "50"
},
1: {
"num": 12,
"addr": "53"
},
}
FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R",
"FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R", "FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R",
"FAN-5F", "FAN-5R"] "FAN-5F", "FAN-5R"]
@ -42,9 +57,14 @@ class Fan(FanBase):
self.is_psu_fan = is_psu_fan self.is_psu_fan = is_psu_fan
if self.is_psu_fan: if self.is_psu_fan:
self.psu_index = psu_index self.psu_index = psu_index
self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]['num'] self.psu_i2c_num = PSU_HWMON_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]['addr'] self.psu_i2c_addr = PSU_HWMON_I2C_MAPPING[self.psu_index]['addr']
self.psu_hwmon_path = PSU_HWMON_I2C_PATH.format( self.psu_hwmon_path = I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
self.psu_i2c_num = PSU_CPLD_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_CPLD_I2C_MAPPING[self.psu_index]['addr']
self.psu_cpld_path = I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr) self.psu_i2c_num, self.psu_i2c_addr)
FanBase.__init__(self) FanBase.__init__(self)
@ -60,7 +80,7 @@ class Fan(FanBase):
if not self.is_psu_fan: if not self.is_psu_fan:
dir_str = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_direction') dir_str = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_direction')
val=self._api_helper.read_txt_file(dir_str) val=self._api_helper.read_txt_file(dir_str)
if val is not None: if val is not None:
if int(val, 10)==0: if int(val, 10)==0:
@ -103,7 +123,7 @@ class Fan(FanBase):
else: else:
return 0 return 0
elif self.get_presence(): elif self.get_presence():
speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage') speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, '_duty_cycle_percentage')
speed=self._api_helper.read_txt_file(speed_path) speed=self._api_helper.read_txt_file(speed_path)
if speed is None: if speed is None:
return 0 return 0
@ -123,7 +143,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
""" """
return False #Not supported return self.get_speed()
def get_speed_tolerance(self): def get_speed_tolerance(self):
""" """
@ -132,7 +152,7 @@ class Fan(FanBase):
An integer, the percentage of variance from target speed which is An integer, the percentage of variance from target speed which is
considered tolerable considered tolerable
""" """
return False #Not supported return SPEED_TOLERANCE
def set_speed(self, speed): def set_speed(self, speed):
""" """
@ -146,7 +166,7 @@ class Fan(FanBase):
""" """
if not self.is_psu_fan and self.get_presence(): if not self.is_psu_fan and self.get_presence():
speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage') speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, '_duty_cycle_percentage')
return self._api_helper.write_txt_file(speed_path, int(speed)) return self._api_helper.write_txt_file(speed_path, int(speed))
return False return False
@ -195,17 +215,18 @@ class Fan(FanBase):
Returns: Returns:
bool: True if FAN is present, False if not bool: True if FAN is present, False if not
""" """
present_path = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_present')
val=self._api_helper.read_txt_file(present_path)
if not self.is_psu_fan:
if val is not None:
return int(val, 10)==1
else:
return False
if self.is_psu_fan:
present_path="{}{}".format(self.psu_cpld_path, 'psu_present')
else: else:
return True present_path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_present')
val=self._api_helper.read_txt_file(present_path)
if val is not None:
return int(val, 10)==1
else:
return False
def get_status(self): def get_status(self):
""" """
@ -221,7 +242,7 @@ class Fan(FanBase):
else: else:
return False return False
else: else:
path = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_fault') path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_fault')
val=self._api_helper.read_txt_file(path) val=self._api_helper.read_txt_file(path)
if val is not None: if val is not None:
return int(val, 10)==0 return int(val, 10)==0
@ -245,3 +266,25 @@ class Fan(FanBase):
string: Serial number of device string: Serial number of device
""" """
return "N/A" return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fan_tray_index+1) \
if not self.is_psu_fan else (self.psu_index+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True if not self.is_psu_fan else False

View File

@ -0,0 +1,90 @@
########################################################################
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FANS_PER_FANTRAY = 2
class FanDrawer(FanDrawerBase):
"""Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
# FanTray is 0-based in platforms
self.fantrayindex = fantray_index
self.__initialize_fan_drawer()
def __initialize_fan_drawer(self):
from sonic_platform.fan import Fan
for i in range(FANS_PER_FANTRAY):
self._fan_list.append(Fan(self.fantrayindex, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex+1)
def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return self._fan_list[0].get_presence()
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return self._fan_list[0].get_model()
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return self._fan_list[0].get_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._fan_list[0].get_status()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
If the agent cannot determine the parent-relative position
for some reason, or if the associated value of
entPhysicalContainedIn is'0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device
or -1 if cannot determine the position
"""
return (self.fantrayindex+1)
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -51,7 +51,7 @@ class APIHelper():
def read_txt_file(self, file_path): def read_txt_file(self, file_path):
try: try:
with open(file_path, 'r') as fd: with open(file_path, 'r', errors='replace') as fd:
data = fd.read() data = fd.read()
return data.strip() return data.strip()
except IOError: except IOError:

View File

@ -251,3 +251,20 @@ class Psu(PsuBase):
if serial is None: if serial is None:
return "N/A" return "N/A"
return serial return serial
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.index+1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -1253,3 +1253,20 @@ class Sfp(SfpBase):
A boolean value, True if device is operating properly, False if not A boolean value, True if device is operating properly, False if not
""" """
return self.get_presence() and self.get_transceiver_bulk_status() return self.get_presence() and self.get_transceiver_bulk_status()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.port_num
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

View File

@ -15,21 +15,56 @@ try:
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/"
PSU_HWMON_I2C_MAPPING = {
0: {
"num": 11,
"addr": "58"
},
1: {
"num": 12,
"addr": "5b"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 11,
"addr": "50"
},
1: {
"num": 12,
"addr": "53"
},
}
class Thermal(ThermalBase): class Thermal(ThermalBase):
"""Platform-specific Thermal class""" """Platform-specific Thermal class"""
THERMAL_NAME_LIST = [] THERMAL_NAME_LIST = []
PSU_THERMAL_NAME_LIST = []
SYSFS_PATH = "/sys/bus/i2c/devices" SYSFS_PATH = "/sys/bus/i2c/devices"
def __init__(self, thermal_index=0): def __init__(self, thermal_index=0, is_psu=False, psu_index=0):
self.index = thermal_index self.index = thermal_index
self.is_psu = is_psu
self.psu_index = psu_index
if self.is_psu:
psu_i2c_bus = PSU_HWMON_I2C_MAPPING[psu_index]["num"]
psu_i2c_addr = PSU_HWMON_I2C_MAPPING[psu_index]["addr"]
self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus,
psu_i2c_addr)
psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["num"]
psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"]
self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr)
# Add thermal name # Add thermal name
self.THERMAL_NAME_LIST.append("Temp sensor 1") self.THERMAL_NAME_LIST.append("Temp sensor 1")
self.THERMAL_NAME_LIST.append("Temp sensor 2") self.THERMAL_NAME_LIST.append("Temp sensor 2")
self.THERMAL_NAME_LIST.append("Temp sensor 3") self.THERMAL_NAME_LIST.append("Temp sensor 3")
self.THERMAL_NAME_LIST.append("Temp sensor 4") self.PSU_THERMAL_NAME_LIST.append("PSU-1 temp sensor 1")
self.PSU_THERMAL_NAME_LIST.append("PSU-2 temp sensor 1")
# Set hwmon path # Set hwmon path
i2c_path = { i2c_path = {
@ -54,17 +89,20 @@ class Thermal(ThermalBase):
return None return None
def __get_temp(self, temp_file): def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file) if not self.is_psu:
temp_file_path = os.path.join(self.hwmon_path, temp_file)
else:
temp_file_path = temp_file
raw_temp = self.__read_txt_file(temp_file_path) raw_temp = self.__read_txt_file(temp_file_path)
if raw_temp is not None: if raw_temp is not None:
return float(raw_temp)/1000 return float(raw_temp)/1000
else: else:
return 0 return 0
def __set_threshold(self, file_name, temperature): def __set_threshold(self, file_name, temperature):
if self.is_psu:
return True
temp_file_path = os.path.join(self.hwmon_path, file_name) temp_file_path = os.path.join(self.hwmon_path, file_name)
for filename in glob.glob(temp_file_path): for filename in glob.glob(temp_file_path):
try: try:
@ -84,7 +122,11 @@ class Thermal(ThermalBase):
A float number of current temperature in Celsius up to nearest thousandth A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125 of one degree Celsius, e.g. 30.125
""" """
temp_file = "temp{}_input".format(self.ss_index) if not self.is_psu:
temp_file = "temp{}_input".format(self.ss_index)
else:
temp_file = self.psu_hwmon_path + "psu_temp1_input"
return self.__get_temp(temp_file) return self.__get_temp(temp_file)
def get_high_threshold(self): def get_high_threshold(self):
@ -94,6 +136,9 @@ class Thermal(ThermalBase):
A float number, the high threshold temperature of thermal in Celsius A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125 up to nearest thousandth of one degree Celsius, e.g. 30.125
""" """
if self.is_psu:
return 0
temp_file = "temp{}_max".format(self.ss_index) temp_file = "temp{}_max".format(self.ss_index)
return self.__get_temp(temp_file) return self.__get_temp(temp_file)
@ -118,7 +163,10 @@ class Thermal(ThermalBase):
Returns: Returns:
string: The name of the thermal device string: The name of the thermal device
""" """
return self.THERMAL_NAME_LIST[self.index] if self.is_psu:
return self.PSU_THERMAL_NAME_LIST[self.psu_index]
else:
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self): def get_presence(self):
""" """
@ -126,6 +174,9 @@ class Thermal(ThermalBase):
Returns: Returns:
bool: True if Thermal is present, False if not bool: True if Thermal is present, False if not
""" """
if self.is_psu:
val = self.__read_txt_file(self.cpld_path + "psu_present")
return int(val, 10) == 1
temp_file = "temp{}_input".format(self.ss_index) temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file) temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_txt = self.__read_txt_file(temp_file_path) raw_txt = self.__read_txt_file(temp_file_path)
@ -140,6 +191,10 @@ class Thermal(ThermalBase):
Returns: Returns:
A boolean value, True if device is operating properly, False if not A boolean value, True if device is operating properly, False if not
""" """
if self.is_psu:
temp_file = self.psu_hwmon_path + "psu_temp_fault"
return self.get_presence() and (not int(
self.__read_txt_file(temp_file)))
file_str = "temp{}_input".format(self.ss_index) file_str = "temp{}_input".format(self.ss_index)
file_path = os.path.join(self.hwmon_path, file_str) file_path = os.path.join(self.hwmon_path, file_str)
@ -148,3 +203,37 @@ class Thermal(ThermalBase):
return False return False
else: else:
return int(raw_txt) != 0 return int(raw_txt) != 0
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Retrieves whether thermal module is replaceable
Returns:
A boolean value, True if replaceable, False if not
"""
return False

View File

@ -0,0 +1,15 @@
{
"services_to_ignore": [],
"devices_to_ignore": [
"asic",
"psu.temperature"
],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "STATUS_LED_COLOR_AMBER",
"normal": "STATUS_LED_COLOR_GREEN",
"booting": "STATUS_LED_COLOR_GREEN"
}
}

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# #
# Copyright (C) 2019 Accton Networks, Inc. # Copyright (C) 2019 Accton Networks, Inc.
# #
@ -17,7 +17,6 @@
""" """
Usage: %(scriptName)s [options] command object Usage: %(scriptName)s [options] command object
options: options:
-h | --help : this help message -h | --help : this help message
-d | --debug : run with debug mode -d | --debug : run with debug mode
@ -25,16 +24,11 @@ options:
command: command:
install : install drivers and generate related sysfs nodes install : install drivers and generate related sysfs nodes
clean : uninstall drivers and remove related sysfs nodes clean : uninstall drivers and remove related sysfs nodes
show : show all systen status
sff : dump SFP eeprom
set : change board setting with fan|led|sfp
""" """
import subprocess
import commands
import getopt import getopt
import sys import sys
import logging import logging
import re
import time import time
import os import os
@ -47,15 +41,15 @@ verbose = False
DEBUG = False DEBUG = False
args = [] args = []
ALL_DEVICE = {} ALL_DEVICE = {}
DEVICE_NO = {'led':5, 'fan':5,'thermal':4, 'psu':2, 'sfp':54}
FORCE = 0 FORCE = 0
#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) #logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG)
#logging.basicConfig(level=logging.INFO) #logging.basicConfig(level=logging.INFO)
if DEBUG == True: if DEBUG == True:
print sys.argv[0] print(sys.argv[0])
print 'ARGV :', sys.argv[1:] print("ARGV :", sys.argv[1:])
def main(): def main():
@ -71,9 +65,9 @@ def main():
'force', 'force',
]) ])
if DEBUG == True: if DEBUG == True:
print options print(options)
print args print(args)
print len(sys.argv) print(len(sys.argv))
for opt, arg in options: for opt, arg in options:
if opt in ('-h', '--help'): if opt in ('-h', '--help'):
@ -94,22 +88,7 @@ def main():
do_sonic_platform_install() do_sonic_platform_install()
elif arg == 'api_clean': elif arg == 'api_clean':
do_sonic_platform_clean() do_sonic_platform_clean()
elif arg == 'show':
device_traversal()
elif arg == 'sff':
if len(args)!=2:
show_eeprom_help()
elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']:
show_eeprom_help()
else:
show_eeprom(args[1])
return
elif arg == 'set':
if len(args)<3:
show_set_help()
else:
set_device(args[1:])
return
else: else:
show_help() show_help()
@ -117,30 +96,18 @@ def main():
return 0 return 0
def show_help(): def show_help():
print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} print(__doc__ % {'scriptName' : sys.argv[0].split("/")[-1]})
sys.exit(0) sys.exit(0)
def show_set_help():
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
print cmd +" [led|sfp|fan]"
print " use \""+ cmd + " led 0-4 \" to set led color"
print " use \""+ cmd + " fan 0-100\" to set fan duty percetage"
print " use \""+ cmd + " sfp 1-48 {0|1}\" to set sfp# tx_disable"
sys.exit(0)
def show_eeprom_help():
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom"
sys.exit(0)
def my_log(txt): def my_log(txt):
if DEBUG == True: if DEBUG == True:
print "[Debug]"+txt print("[Debug]"+txt)
return return
def log_os_system(cmd, show): def log_os_system(cmd, show):
logging.info('Run :'+cmd) logging.info('Run :'+cmd)
status, output = commands.getstatusoutput(cmd) status, output = subprocess.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status)) my_log (cmd +"with result:" + str(status))
my_log (" output:"+output) my_log (" output:"+output)
if status: if status:
@ -177,6 +144,8 @@ def driver_install():
if ret[0]: if ret[0]:
if FORCE == 0: if FORCE == 0:
return ret[0] return ret[0]
print("Done driver_install")
return 0 return 0
def driver_uninstall(): def driver_uninstall():
@ -194,12 +163,8 @@ def driver_uninstall():
return ret[0] return ret[0]
return 0 return 0
led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::'
hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']}
hwmon_nodes = {'led': ['brightness'] }
hwmon_prefix ={'led': led_prefix}
i2c_prefix = '/sys/bus/i2c/devices/' i2c_prefix = '/sys/bus/i2c/devices/'
'''
i2c_bus = {'fan': ['3-0063'] , i2c_bus = {'fan': ['3-0063'] ,
'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] , 'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] ,
'psu': ['11-0050','12-0053'], 'psu': ['11-0050','12-0053'],
@ -208,7 +173,7 @@ i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] ,
'thermal': ['hwmon/hwmon*/temp1_input'] , 'thermal': ['hwmon/hwmon*/temp1_input'] ,
'psu': ['psu_present ', 'psu_power_good'] , 'psu': ['psu_present ', 'psu_power_good'] ,
'sfp': ['module_present_', 'module_tx_disable_']} 'sfp': ['module_present_', 'module_tx_disable_']}
'''
sfp_map = [42,43,44,45,46,47,48,49,50,51, sfp_map = [42,43,44,45,46,47,48,49,50,51,
52,53,54,55,56,57,58,59,60,61, 52,53,54,55,56,57,58,59,60,61,
62,63,64,65,66,67,68,69,70,71, 62,63,64,65,66,67,68,69,70,71,
@ -303,7 +268,7 @@ def device_install():
status, output = log_os_system(mknod2[i], 1) status, output = log_os_system(mknod2[i], 1)
time.sleep(0.01) time.sleep(0.01)
if status: if status:
print output print(output)
if FORCE == 0: if FORCE == 0:
return status return status
else: else:
@ -314,7 +279,7 @@ def device_install():
status, output = log_os_system(mknod[i], 1) status, output = log_os_system(mknod[i], 1)
if status: if status:
print output print(output)
if FORCE == 0: if FORCE == 0:
return status return status
@ -327,9 +292,11 @@ def device_install():
else: else:
status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
if status: if status:
print output print(output)
if FORCE == 0: if FORCE == 0:
return status return status
print("Done device_install")
return return
def device_uninstall(): def device_uninstall():
@ -339,7 +306,7 @@ def device_uninstall():
target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device"
status, output =log_os_system("echo 0x50 > "+ target, 1) status, output =log_os_system("echo 0x50 > "+ target, 1)
if status: if status:
print output print(output)
if FORCE == 0: if FORCE == 0:
return status return status
@ -356,7 +323,7 @@ def device_uninstall():
temp[-1] = temp[-1].replace('new_device', 'delete_device') temp[-1] = temp[-1].replace('new_device', 'delete_device')
status, output = log_os_system(" ".join(temp), 1) status, output = log_os_system(" ".join(temp), 1)
if status: if status:
print output print(output)
if FORCE == 0: if FORCE == 0:
return status return status
@ -381,10 +348,10 @@ def do_sonic_platform_install():
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_PY3): if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_PY3):
status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG_PY3, 1) status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG_PY3, 1)
if status: if status:
print "Error: Failed to install {}".format(PLATFORM_API2_WHL_FILE_PY3) print("Error: Failed to install {}".format(PLATFORM_API2_WHL_FILE_PY3) )
return status return status
else: else:
print "Successfully installed {} package".format(PLATFORM_API2_WHL_FILE_PY3) print("Successfully installed {} package".format(PLATFORM_API2_WHL_FILE_PY3) )
else: else:
print('{} is not found'.format(PLATFORM_API2_WHL_FILE_PY3)) print('{} is not found'.format(PLATFORM_API2_WHL_FILE_PY3))
else: else:
@ -406,43 +373,43 @@ def do_sonic_platform_clean():
print('{} is uninstalled'.format(PLATFORM_API2_WHL_FILE_PY3)) print('{} is uninstalled'.format(PLATFORM_API2_WHL_FILE_PY3))
def do_install(): def do_install():
print "Checking system...." print("Checking system....")
if driver_check() == False: if driver_check() == False:
print "No driver, installing...." print("No driver, installing....")
status = driver_install() status = driver_install()
if status: if status:
if FORCE == 0: if FORCE == 0:
return status return status
else: else:
print PROJECT_NAME.upper()+" drivers detected...." print(PROJECT_NAME.upper()+" drivers detected....")
if not device_exist(): if not device_exist():
print "No device, installing...." print("No device, installing....")
status = device_install() status = device_install()
if status: if status:
if FORCE == 0: if FORCE == 0:
return status return status
else: else:
print PROJECT_NAME.upper()+" devices detected...." print(PROJECT_NAME.upper()+" devices detected....")
do_sonic_platform_install() do_sonic_platform_install()
return return
def do_uninstall(): def do_uninstall():
print "Checking system...." print("Checking system....")
if not device_exist(): if not device_exist():
print PROJECT_NAME.upper() +" has no device installed...." print(PROJECT_NAME.upper() +" has no device installed....")
else: else:
print "Removing device...." print("Removing device....")
status = device_uninstall() status = device_uninstall()
if status: if status:
if FORCE == 0: if FORCE == 0:
return status return status
if driver_check()== False : if driver_check()== False :
print PROJECT_NAME.upper() +" has no driver installed...." print(PROJECT_NAME.upper() +" has no driver installed....")
else: else:
print "Removing installed driver...." print("Removing installed driver....")
status = driver_uninstall() status = driver_uninstall()
if status: if status:
if FORCE == 0: if FORCE == 0:
@ -452,185 +419,6 @@ def do_uninstall():
return return
def devices_info():
global DEVICE_NO
global ALL_DEVICE
global i2c_bus, hwmon_types
for key in DEVICE_NO:
ALL_DEVICE[key]= {}
for i in range(0,DEVICE_NO[key]):
ALL_DEVICE[key][key+str(i+1)] = []
for key in i2c_bus:
buses = i2c_bus[key]
nodes = i2c_nodes[key]
for i in range(0,len(buses)):
for j in range(0,len(nodes)):
if 'fan' == key:
for k in range(0,DEVICE_NO[key]):
node = key+str(k+1)
path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
elif 'sfp' == key:
for k in range(0,DEVICE_NO[key]):
for lk in cpld_of_module:
if k in cpld_of_module[lk]:
node = key+str(k+1)
path = i2c_prefix + lk + "/"+ nodes[j] + str(k+1)
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
else:
node = key+str(i+1)
path = i2c_prefix+ buses[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
for key in hwmon_types:
itypes = hwmon_types[key]
nodes = hwmon_nodes[key]
for i in range(0,len(itypes)):
for j in range(0,len(nodes)):
node = key+"_"+itypes[i]
path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][ key+str(i+1)].append(path)
#show dict all in the order
if DEBUG == True:
for i in sorted(ALL_DEVICE.keys()):
print(i+": ")
for j in sorted(ALL_DEVICE[i].keys()):
print(" "+j)
for k in (ALL_DEVICE[i][j]):
print(" "+" "+k)
return
def show_eeprom(index):
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0]
node = node.replace(node.split("/")[-1], 'sfp_eeprom')
# check if got hexdump command in current environment
ret, log = log_os_system("which hexdump", 0)
ret, log2 = log_os_system("which busybox hexdump", 0)
if log :
hex_cmd = 'hexdump'
elif log2 :
hex_cmd = ' busybox hexdump'
else:
log = 'Failed : no hexdump cmd!!'
logging.info(log)
print log
return 1
print node + ":"
ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1)
if ret==0:
print log
else:
print "**********device no found**********"
return
def set_device(args):
global DEVICE_NO
global ALL_DEVICE
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
if args[0]=='led':
if int(args[1])>4:
show_set_help()
return
#print ALL_DEVICE['led']
for i in range(0,len(ALL_DEVICE['led'])):
for k in (ALL_DEVICE['led']['led'+str(i+1)]):
ret = log_os_system("echo "+args[1]+" >"+k, 1)
if ret[0]:
return ret[0]
elif args[0]=='fan':
if int(args[1])>100:
show_set_help()
return
#print ALL_DEVICE['fan']
#fan1~5 is all fine, all fan share same setting
node = ALL_DEVICE['fan'] ['fan1'][0]
node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage')
ret = log_os_system("cat "+ node, 1)
if ret[0] == 0:
print ("Previous fan duty: " + log.strip() +"%")
ret = log_os_system("echo "+args[1]+" >"+node, 1)
if ret[0] == 0:
print ("Current fan duty: " + args[1] +"%")
return ret[0]
elif args[0]=='sfp':
if int(args[1])> qsfp_start or int(args[1])==0:
show_set_help()
return
if len(args)<2:
show_set_help()
return
if int(args[2])>1:
show_set_help()
return
#print ALL_DEVICE[args[0]]
for i in range(0,len(ALL_DEVICE[args[0]])):
for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]:
if j.find('tx_disable')!= -1:
ret = log_os_system("echo "+args[2]+" >"+ j, 1)
if ret[0]:
return ret[0]
return
#get digits inside a string.
#Ex: 31 for "sfp31"
def get_value(input):
digit = re.findall('\d+', input)
return int(digit[0])
def device_traversal():
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
for i in sorted(ALL_DEVICE.keys()):
print("============================================")
print(i.upper()+": ")
print("============================================")
for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
print " "+j+":",
for k in (ALL_DEVICE[i][j]):
ret, log = log_os_system("cat "+k, 0)
func = k.split("/")[-1].strip()
func = re.sub(j+'_','',func,1)
func = re.sub(i.lower()+'_','',func,1)
if ret==0:
print func+"="+log+" ",
else:
print func+"="+"X"+" ",
print
print("----------------------------------------------------------------")
print
return
def device_exist(): def device_exist():
ret1 = log_os_system("ls "+i2c_prefix+"*0077", 0) ret1 = log_os_system("ls "+i2c_prefix+"*0077", 0)