[as7312-54x] Support platform API2.0 (#6272)

Add platform 2.0 support for Accton as7312-54x platform
This commit is contained in:
jostar-yang 2021-02-10 02:02:09 +08:00 committed by GitHub
parent cea8c1895e
commit c54a03fade
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 2427 additions and 7 deletions

View File

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

View File

@ -0,0 +1,193 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Chassis information which are available in the platform
#
#############################################################################
import os
try:
from sonic_platform_base.chassis_base import ChassisBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 6
NUM_FAN = 2
NUM_PSU = 2
NUM_THERMAL = 4
PORT_END = 54
NUM_COMPONENT = 4
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
HOST_CHK_CMD = "docker > /dev/null 2>&1"
class Chassis(ChassisBase):
"""Platform-specific Chassis class"""
def __init__(self):
ChassisBase.__init__(self)
self._api_helper = APIHelper()
self._api_helper = APIHelper()
self.is_host = self._api_helper.is_host()
self.config_data = {}
self.__initialize_fan()
self.__initialize_psu()
self.__initialize_thermals()
self.__initialize_components()
self.__initialize_sfp()
self.__initialize_eeprom()
def __initialize_sfp(self):
from sonic_platform.sfp import Sfp
for index in range(0, PORT_END):
sfp = Sfp(index)
self._sfp_list.append(sfp)
self.sfp_module_initialized = True
def __initialize_fan(self):
from sonic_platform.fan import Fan
for fant_index in range(0, NUM_FAN_TRAY):
for fan_index in range(0, NUM_FAN):
fan = Fan(fant_index, fan_index)
self._fan_list.append(fan)
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_thermals(self):
from sonic_platform.thermal import Thermal
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
def __initialize_eeprom(self):
from sonic_platform.eeprom import Tlv
self._eeprom = Tlv()
def __initialize_components(self):
from sonic_platform.component import Component
for index in range(0, NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
def __initialize_watchdog(self):
from sonic_platform.watchdog import Watchdog
self._watchdog = Watchdog()
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_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 Chassis
Returns:
bool: True if Chassis is present, False if not
"""
return True
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_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.get_mac()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.get_serial()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
return self._eeprom.get_eeprom()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
sw_reboot_cause = self._api_helper.read_txt_file(
reboot_cause_path) or "Unknown"
return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause)
def get_sfp(self, index):
"""
Retrieves sfp represented by (1-based) index <index>
Args:
index: An integer, the index (1-based) of the sfp to retrieve.
The index should be the sequence of a physical port in a chassis,
starting from 1.
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
Returns:
An object dervied from SfpBase representing the specified sfp
"""
sfp = None
if not self.sfp_module_initialized:
self.__initialize_sfp()
try:
# The index will start from 1
sfp = self._sfp_list[index-1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
return sfp

View File

@ -0,0 +1,125 @@
#############################################################################
# Celestica
#
# Component contains an implementation of SONiC Platform Base API and
# provides the components firmware management function
#
#############################################################################
import shlex
import subprocess
try:
from sonic_platform_base.component_base import ComponentBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CPLD_ADDR_MAPPING = {
"CPLD1": "4-0060",
"CPLD2": "5-0062",
"CPLD3": "6-0064",
}
SYSFS_PATH = "/sys/bus/i2c/devices/"
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
COMPONENT_LIST= [
("CPLD1", "CPLD 1"),
("CPLD2", "CPLD 2"),
("CPLD3", "CPLD 3"),
("BIOS", "Basic Input/Output System")
]
COMPONENT_DES_LIST = ["CPLD","Basic Input/Output System"]
class Component(ComponentBase):
"""Platform-specific Component class"""
DEVICE_TYPE = "component"
def __init__(self, component_index=0):
self._api_helper=APIHelper()
ComponentBase.__init__(self)
self.index = component_index
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 Exception:
return False
return True
def __get_bios_version(self):
# Retrieves the BIOS firmware version
try:
with open(BIOS_VERSION_PATH, 'r') as fd:
bios_version = fd.read()
return bios_version.strip()
except Exception as e:
return None
def __get_cpld_version(self):
# Retrieves the CPLD firmware version
cpld_version = dict()
for cpld_name in CPLD_ADDR_MAPPING:
try:
cpld_path = "{}{}{}".format(SYSFS_PATH, CPLD_ADDR_MAPPING[cpld_name], '/version')
cpld_version_raw= self._api_helper.read_txt_file(cpld_path)
cpld_version[cpld_name] = "{}".format(int(cpld_version_raw,16))
except Exception as e:
print('Get exception when read cpld')
cpld_version[cpld_name] = 'None'
return cpld_version
def get_name(self):
"""
Retrieves the name of the component
Returns:
A string containing the name of the component
"""
return COMPONENT_LIST[self.index][0]
def get_description(self):
"""
Retrieves the description of the component
Returns:
A string containing the description of the component
"""
return COMPONENT_LIST[self.index][1]
#return "testhwsku"
def get_firmware_version(self):
"""
Retrieves the firmware version of module
Returns:
string: The firmware versions of the module
"""
fw_version = None
if self.name == "BIOS":
fw_version = self.__get_bios_version()
elif "CPLD" in self.name:
cpld_version = self.__get_cpld_version()
fw_version = cpld_version.get(self.name)
return fw_version
def install_firmware(self, image_path):
"""
Install firmware to module
Args:
image_path: A string, path to firmware image
Returns:
A boolean, True if install successfully, False if not
"""
raise NotImplementedError

View File

@ -0,0 +1,102 @@
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'
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 get_eeprom(self):
return self._eeprom
def get_serial(self):
return self._eeprom.get('0x23', "Undefined.")
def get_mac(self):
return self._eeprom.get('0x24', "Undefined.")

View File

@ -0,0 +1,177 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
try:
from sonic_platform_base.fan_base import FanBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PSU_FAN_MAX_RPM = 26688
CPLD_I2C_PATH = "/sys/bus/i2c/devices/2-0066/fan"
PSU_HWMON_I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/"
PSU_I2C_MAPPING = {
0: {
"num": 11,
"addr": "5b"
},
1: {
"num": 10,
"addr": "58"
},
}
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
self._api_helper=APIHelper()
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
self.is_psu_fan = is_psu_fan
if self.is_psu_fan:
self.psu_index = psu_index
self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]['num']
self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]['addr']
self.psu_hwmon_path = PSU_HWMON_I2C_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
FanBase.__init__(self)
def get_direction(self):
"""
Retrieves the direction of fan
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
if not self.is_psu_fan:
dir_str = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index, '_direction')
val=self._api_helper.read_txt_file(dir_str)
if val is not None:
if val==0:#F2B
direction=self.FAN_DIRECTION_EXHAUST
else:
direction=self.FAN_DIRECTION_INTAKE
else:
direction=self.FAN_DIRECTION_EXHAUST
else: #For PSU
dir_str = "{}{}".format(self.psu_hwmon_path,'psu_hwmon_path')
val=self._api_helper.read_txt_file(dir_str)
if val is not None:
if val=='F2B':
direction=self.FAN_DIRECTION_EXHAUST
else:
direction=self.FAN_DIRECTION_INTAKE
else:
direction=self.FAN_DIRECTION_EXHAUST
return direction
def get_speed(self):
"""
Retrieves the speed of fan as a percentage of full speed
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
"""
speed = 0
if self.is_psu_fan:
psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_speed_rpm')
fan_speed_rpm = self._api_helper.read_txt_file(psu_fan_path)
if fan_speed_rpm is not None:
speed = (int(fan_speed_rpm,10))*100/26688
if speed > 100:
speed=100
else:
return 0
elif self.get_presence():
speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage')
speed=self._api_helper.read_txt_file(speed_path)
if speed is None:
return 0
return int(speed)
def get_target_speed(self):
"""
Retrieves the target (expected) speed of the fan
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
return False #Not supported
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return False #Not supported
def set_speed(self, speed):
"""
Sets the fan speed
Args:
speed: An integer, the percentage of full fan speed to set fan to,
in the range 0 (off) to 100 (full speed)
Returns:
A boolean, True if speed is set successfully, False if not
"""
if not self.is_psu_fan and self.get_presence():
speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage')
return self._api_helper.write_txt_file(speed_path, int(speed))
return False
def set_status_led(self, color):
"""
Sets the state of the fan module status LED
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if status LED state is set successfully, False if not
"""
return False #Not supported
def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
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
else:
return True

View File

@ -0,0 +1,117 @@
import os
import struct
import subprocess
from mmap import *
from sonic_py_common import device_info
HOST_CHK_CMD = "docker > /dev/null 2>&1"
EMPTY_STRING = ""
class APIHelper():
def __init__(self):
(self.platform, self.hwsku) = device_info.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 Exception:
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 Exception:
status = False
return status, result
def run_interactive_command(self, cmd):
try:
os.system(cmd)
except Exception:
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 write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except IOError:
return False
return True
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 Exception:
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 Exception:
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 Exception:
status = False
return status, result

View File

@ -0,0 +1,21 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
"""Platform-specific Platform class"""
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,220 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
#import sonic_platform
try:
from sonic_platform_base.psu_base import PsuBase
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
I2C_PATH ="/sys/bus/i2c/devices/{0}-00{1}/"
PSU_NAME_LIST = ["PSU-1", "PSU-2"]
PSU_NUM_FAN = [1, 1]
PSU_HWMON_I2C_MAPPING = {
0: {
"num": 11,
"addr": "5b"
},
1: {
"num": 10,
"addr": "58"
},
}
PSU_CPLD_I2C_MAPPING = {
0: {
"num": 11,
"addr": "53"
},
1: {
"num": 10,
"addr": "50"
},
}
class Psu(PsuBase):
"""Platform-specific Psu class"""
def __init__(self, psu_index=0):
PsuBase.__init__(self)
self.index = psu_index
self._api_helper = APIHelper()
self.i2c_num = PSU_HWMON_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_HWMON_I2C_MAPPING[self.index]["addr"]
self.hwmon_path = I2C_PATH.format(self.i2c_num, self.i2c_addr)
self.i2c_num = PSU_CPLD_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_CPLD_I2C_MAPPING[self.index]["addr"]
self.cpld_path = I2C_PATH.format(self.i2c_num, self.i2c_addr)
self.__initialize_fan()
def __initialize_fan(self):
from sonic_platform.fan import Fan
for fan_index in range(0, PSU_NUM_FAN[self.index]):
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
self._fan_list.append(fan)
def get_voltage(self):
"""
Retrieves current PSU voltage output
Returns:
A float number, the output voltage in volts,
e.g. 12.1
"""
vout_path = "{}{}".format(self.hwmon_path, 'psu_v_out')
vout_val=self._api_helper.read_txt_file(vout_path)
return float(vout_val)/ 1000
def get_current(self):
"""
Retrieves present electric current supplied by PSU
Returns:
A float number, the electric current in amperes, e.g 15.4
"""
iout_path = "{}{}".format(self.hwmon_path, 'psu_i_out')
val=self._api_helper.read_txt_file(iout_path)
if val is not None:
return float(val)/1000
else:
return 0
def get_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts, e.g. 302.6
"""
pout_path = "{}{}".format(self.hwmon_path, 'psu_p_out')
val=self._api_helper.read_txt_file(pout_path)
if val is not None:
return float(val)/1000
else:
return 0
def get_powergood_status(self):
"""
Retrieves the powergood status of PSU
Returns:
A boolean, True if PSU has stablized its output voltages and passed all
its internal self-tests, False if not.
"""
return self.get_status()
def set_status_led(self, color):
"""
Sets the state of the PSU status LED
Args:
color: A string representing the color with which to set the PSU status LED
Note: Only support green and off
Returns:
bool: True if status LED state is set successfully, False if not
"""
return False #Controlled by HW
def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
if self.get_status():
return True
else:
return False
def get_temperature(self):
"""
Retrieves current temperature reading from PSU
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_path = "{}{}".format(self.hwmon_path, 'psu_temp1_input')
val=self._api_helper.read_txt_file(temp_path)
if val is not None:
return float(val)/1000
else:
return 0
def get_temperature_high_threshold(self):
"""
Retrieves the high threshold temperature of PSU
Returns:
A float number, the high threshold temperature of PSU in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
return False #Not supported
def get_voltage_high_threshold(self):
"""
Retrieves the high threshold PSU voltage output
Returns:
A float number, the high threshold output voltage in volts,
e.g. 12.1
"""
vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_max')
vout_val=self._api_helper.read_txt_file(vout_path)
if vout_val is not None:
return float(vout_val)/ 1000
else:
return 0
def get_voltage_low_threshold(self):
"""
Retrieves the low threshold PSU voltage output
Returns:
A float number, the low threshold output voltage in volts,
e.g. 12.1
"""
vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_min')
vout_val=self._api_helper.read_txt_file(vout_path)
if vout_val is not None:
return float(vout_val)/ 1000
else:
return 0
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return PSU_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
presence_path="{}{}".format(self.cpld_path, 'psu_present')
val=self._api_helper.read_txt_file(presence_path)
if val is not None:
return int(val, 10) == 1
else:
return 0
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
power_path="{}{}".format(self.cpld_path, 'psu_power_good')
val=self._api_helper.read_txt_file(power_path)
if val is not None:
return int(val, 10) == 1
else:
return 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
#############################################################################
# Edgecore
#
# Thermal contains an implementation of SONiC Platform Base API and
# provides the thermal device status which are available in the platform
#
#############################################################################
import os
import os.path
import glob
try:
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
SYSFS_PATH = "/sys/bus/i2c/devices"
def __init__(self, thermal_index=0):
self.index = thermal_index
# Add thermal name
self.THERMAL_NAME_LIST.append("Temp sensor 1")
self.THERMAL_NAME_LIST.append("Temp sensor 2")
self.THERMAL_NAME_LIST.append("Temp sensor 3")
self.THERMAL_NAME_LIST.append("Temp sensor 4")
# Set hwmon path
i2c_path = {
0: "3-0048/hwmon/hwmon*/",
1: "3-0049/hwmon/hwmon*/",
2: "3-004a/hwmon/hwmon*/",
3: "3-004b/hwmon/hwmon*/",
}.get(self.index, None)
self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path)
self.ss_key = self.THERMAL_NAME_LIST[self.index]
self.ss_index = 1
def __read_txt_file(self, file_path):
for filename in glob.glob(file_path):
try:
with open(filename, 'r') as fd:
data =fd.readline().rstrip()
return data
except IOError as e:
pass
return None
def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_temp = self.__read_txt_file(temp_file_path)
if raw_temp is not None:
return float(raw_temp)/1000
else:
return 0
def __set_threshold(self, file_name, temperature):
temp_file_path = os.path.join(self.hwmon_path, file_name)
for filename in glob.glob(temp_file_path):
try:
with open(filename, 'w') as fd:
fd.write(str(temperature))
return True
except IOError as e:
print("IOError")
def get_temperature(self):
"""
Retrieves current temperature reading from thermal
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_file = "temp{}_input".format(self.ss_index)
return self.__get_temp(temp_file)
def get_high_threshold(self):
"""
Retrieves the high threshold temperature of thermal
Returns:
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
temp_file = "temp{}_max".format(self.ss_index)
return self.__get_temp(temp_file)
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A float number up to nearest thousandth of one degree Celsius,
e.g. 30.125
Returns:
A boolean, True if threshold is set successfully, False if not
"""
temp_file = "temp{}_max".format(self.ss_index)
temperature = temperature *1000
self.__set_threshold(temp_file, temperature)
return True
def get_name(self):
"""
Retrieves the name of the thermal device
Returns:
string: The name of the thermal device
"""
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the Thermal
Returns:
bool: True if Thermal is present, False if not
"""
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_txt = self.__read_txt_file(temp_file_path)
if raw_txt is not None:
return True
else:
return False
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
file_str = "temp{}_input".format(self.ss_index)
file_path = os.path.join(self.hwmon_path, file_str)
raw_txt = self.__read_txt_file(file_path)
if raw_txt is None:
return False
else:
return int(raw_txt) != 0

View File

@ -0,0 +1,34 @@
from setuptools import setup
DEVICE_NAME = 'accton'
HW_SKU = 'x86_64-accton_as7312_54x-r0'
setup(
name='sonic-platform',
version='1.0',
description='SONiC platform API implementation on Accton Platforms',
license='Apache 2.0',
author='SONiC Team',
author_email='linuxnetdev@microsoft.com',
url='https://github.com/Azure/sonic-buildimage',
maintainer='Jostar Yang',
maintainer_email='jostar_yang@edge-core.com',
packages=[
'sonic_platform',
],
package_dir={
'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)},
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Plugins',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Apache Software License',
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 3.7',
'Topic :: Utilities',
],
keywords='sonic SONiC platform PLATFORM',
)

View File

@ -35,7 +35,7 @@ import sys
import logging
import re
import time
import os
PROJECT_NAME = 'as7312_54x'
version = '0.1.0'
@ -90,6 +90,10 @@ def main():
do_install()
elif arg == 'clean':
do_uninstall()
elif arg == 'api':
do_sonic_platform_install()
elif arg == 'api_clean':
do_sonic_platform_clean()
elif arg == 'show':
device_traversal()
elif arg == 'sff':
@ -358,6 +362,43 @@ def system_ready():
return False
return True
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
PLATFORM_API2_WHL_FILE_PY3 ='sonic_platform-1.0-py3-none-any.whl'
def do_sonic_platform_install():
device_path = "{}{}{}{}".format(PLATFORM_ROOT_PATH, '/x86_64-accton_', PROJECT_NAME, '-r0')
SONIC_PLATFORM_BSP_WHL_PKG_PY3 = "/".join([device_path, PLATFORM_API2_WHL_FILE_PY3])
#Check API2.0 on py whl file
status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0)
if status:
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_PY3):
status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG_PY3, 1)
if status:
print "Error: Failed to install {}".format(PLATFORM_API2_WHL_FILE_PY3)
return status
else:
print "Successfully installed {} package".format(PLATFORM_API2_WHL_FILE_PY3)
else:
print('{} is not found'.format(PLATFORM_API2_WHL_FILE_PY3))
else:
print('{} has installed'.format(PLATFORM_API2_WHL_FILE_PY3))
return
def do_sonic_platform_clean():
status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0)
if status:
print('{} does not install, not need to uninstall'.format(PLATFORM_API2_WHL_FILE_PY3))
else:
status, output = log_os_system("pip3 uninstall sonic-platform -y", 0)
if status:
print('Error: Failed to uninstall {}'.format(PLATFORM_API2_WHL_FILE_PY3))
return status
else:
print('{} is uninstalled'.format(PLATFORM_API2_WHL_FILE_PY3))
return
def do_install():
print 'Checking system....'
@ -377,6 +418,8 @@ def do_install():
return status
else:
print PROJECT_NAME.upper() + ' devices detected....'
do_sonic_platform_install()
return
@ -397,6 +440,9 @@ def do_uninstall():
status = driver_uninstall()
if status and FORCE == 0:
return status
do_sonic_platform_clean()
return None
@ -460,8 +506,8 @@ def devices_info():
def show_eeprom(index):
if system_ready() is False:
print "System's not ready."
print 'Please install first!'
print('Systems not ready.')
print('Please install first!')
return
if len(ALL_DEVICE) == 0:
@ -488,7 +534,7 @@ def show_eeprom(index):
if ret == 0:
print log
else:
print '**********device no found**********'
print( '**********device no found**********')
return
@ -496,8 +542,8 @@ def set_device(args):
global DEVICE_NO
global ALL_DEVICE
if system_ready() is False:
print "System's not ready."
print 'Please install first!'
print('System is not ready.')
print('Please install first!')
return
if not ALL_DEVICE:
@ -565,7 +611,7 @@ def get_value(i):
def device_traversal():
if system_ready() is False:
print "System's not ready."
print "System is not ready."
print 'Please install first!'
return

View File

@ -14,6 +14,7 @@ include /usr/share/dpkg/pkg-info.mk
export INSTALL_MOD_DIR:=extra
PYTHON ?= python2
PYTHON3 ?= python3
PACKAGE_PRE_NAME := sonic-platform-accton
KVERSION ?= $(shell uname -r)
@ -40,6 +41,12 @@ build:
(for mod in $(MODULE_DIRS); do \
make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
$(PYTHON) $${mod}/setup.py build; \
cd $(MOD_SRC_DIR)/$${mod}; \
if [ -f sonic_platform_setup.py ]; then \
$(PYTHON3) sonic_platform_setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}; \
echo "Finished makig whl package for $$mod"; \
fi; \
cd $(MOD_SRC_DIR); \
done)
binary: binary-arch binary-indep

View File

@ -0,0 +1,2 @@
as7312-54x/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-accton_as7312_54x-r0