From 939e809e32bc732dc8195d6d7807a220775279e0 Mon Sep 17 00:00:00 2001 From: Wirut Getbamrung Date: Wed, 8 May 2019 17:08:56 +0700 Subject: [PATCH] [device/celestica] Implement PSU APIs based on the new platform API --- .../sonic_platform/__init__.py | 0 .../sonic_platform/chassis.py | 113 +++++++++++++++++ .../x86_64-cel_e1031-r0/sonic_platform/psu.py | 61 ++++++++++ .../sonic_platform/__init__.py | 0 .../sonic_platform/chassis.py | 114 ++++++++++++++++++ .../sonic_platform/psu.py | 78 ++++++++++++ 6 files changed, 366 insertions(+) create mode 100644 device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py create mode 100644 device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py create mode 100644 device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py create mode 100644 device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py create mode 100644 device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py create mode 100644 device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..4dee5ac87784 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys +import re +import os +import subprocess +import json + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MMC_CPLD_ADDR = '0x100' +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +CONFIG_DB_PATH = "/etc/sonic/config_db.json" +SMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/version" +MMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/getreg" +NUM_FAN = 3 +NUM_PSU = 2 + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + self.config_data = {} + for index in range(0, NUM_FAN): + fan = Fan(index) + self._fan_list.append(fan) + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + ChassisBase.__init__(self) + + def __get_register_value(self, path, register): + cmd = "echo {1} > {0}; cat {0}".format(path, register) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err is not '': + return 'None' + else: + return raw_data.strip() + + def __read_config_db(self): + try: + with open(CONFIG_DB_PATH, 'r') as fd: + data = json.load(fd) + return data + except IOError: + raise IOError("Unable to open config_db file !") + + 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' + """ + try: + self.config_data = self.__read_config_db() + base_mac = self.config_data["DEVICE_METADATA"]["localhost"]["mac"] + return str(base_mac) + except KeyError: + raise KeyError("Base MAC not found") + + def get_component_versions(self): + """ + Retrieves platform-specific hardware/firmware versions for chassis + componenets such as BIOS, CPLD, FPGA, etc. + Returns: + A string containing platform-specific component versions + """ + + component_versions = dict() + + # Get BIOS version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + except IOError: + raise IOError("Unable to open version file !") + + # Get CPLD version + cpld_version = dict() + + with open(SMC_CPLD_PATH, 'r') as fd: + smc_cpld_version = fd.read() + smc_cpld_version = 'None' if smc_cpld_version is 'None' else "{}.{}".format( + int(smc_cpld_version[2], 16), int(smc_cpld_version[3], 16)) + + mmc_cpld_version = self.__get_register_value( + MMC_CPLD_PATH, MMC_CPLD_ADDR) + mmc_cpld_version = 'None' if mmc_cpld_version is 'None' else "{}.{}".format( + int(mmc_cpld_version[2], 16), int(mmc_cpld_version[3], 16)) + + cpld_version["SMC"] = smc_cpld_version + cpld_version["MMC"] = mmc_cpld_version + + component_versions["CPLD"] = cpld_version + component_versions["BIOS"] = bios_version.strip() + return str(component_versions) diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..8fd32fd64d86 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path +import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_E1031_SPEED_PATH = "/sys/class/hwmon/hwmon{}/fan1_input" +FAN_MAX_RPM = 11000 + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index + + def get_fan(self): + """ + Retrieves object representing the fan module contained in this PSU + Returns: + An object dervied from FanBase representing the fan module + contained in this PSU + """ + fan_speed_path = FAN_E1031_SPEED_PATH.format( + str(self.index+3)) + try: + with open(fan_speed_path) as fan_speed_file: + fan_speed_rpm = int(fan_speed_file.read()) + except IOError: + fan_speed = 0 + + fan_speed = float(fan_speed_rpm)/FAN_MAX_RPM * 100 + fan = Fan(0) + fan.fan_speed = int(fan_speed) if int(fan_speed) <= 100 else 100 + return fan + + 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 + """ + # Hardware not supported + return False diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..e7c62e372b34 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys +import re +import os +import subprocess +import json + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg" +CONFIG_DB_PATH = "/etc/sonic/config_db.json" +NUM_FAN = 5 +NUM_PSU = 2 +CPLD_ADDR_MAPPING = { + "CPLD1": "0x100", + "CPLD2": "0x200", + "CPLD3": "0x280", + "CPLD4": "0x300", + "CPLD5": "0x380" +} + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + self.config_data = {} + for index in range(0, NUM_FAN): + fan = Fan(index) + self._fan_list.append(fan) + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + ChassisBase.__init__(self) + + def __get_register_value(self, path, register): + cmd = "echo {1} > {0}; cat {0}".format(path, register) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err is not '': + return 'None' + else: + return raw_data.strip() + + def __read_config_db(self): + try: + with open(CONFIG_DB_PATH, 'r') as fd: + data = json.load(fd) + return data + except IOError: + raise IOError("Unable to open config_db file !") + + 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' + """ + try: + self.config_data = self.__read_config_db() + base_mac = self.config_data["DEVICE_METADATA"]["localhost"]["mac"] + return str(base_mac) + except KeyError: + raise KeyError("Base MAC not found") + + def get_component_versions(self): + """ + Retrieves platform-specific hardware/firmware versions for chassis + componenets such as BIOS, CPLD, FPGA, etc. + Returns: + A string containing platform-specific component versions + """ + + component_versions = dict() + + # Get BIOS version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + except IOError: + raise IOError("Unable to open version file !") + + # Get CPLD version + cpld_version = dict() + for cpld_name in CPLD_ADDR_MAPPING: + try: + cpld_addr = CPLD_ADDR_MAPPING[cpld_name] + cpld_version_raw = self.__get_register_value( + GETREG_PATH, cpld_addr) + cpld_version_str = "{}.{}".format(int(cpld_version_raw[2], 16), int( + cpld_version_raw[3], 16)) if cpld_version_raw is not None else 'None' + cpld_version[cpld_name] = cpld_version_str + except Exception, e: + cpld_version[cpld_name] = 'None' + component_versions["CPLD"] = cpld_version + component_versions["BIOS"] = bios_version.strip() + return str(component_versions) diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..c70e45214475 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path +import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_DX010_SPEED_PATH = "/sys/class/hwmon/hwmon{}/fan1_input" +GREEN_LED_PATH = "/sys/devices/platform/leds_dx010/leds/dx010:green:p-{}/brightness" +FAN_MAX_RPM = 11000 + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index + self.green_led_path = GREEN_LED_PATH.format(self.index+1) + + def get_fan(self): + """ + Retrieves object representing the fan module contained in this PSU + Returns: + An object dervied from FanBase representing the fan module + contained in this PSU + """ + + fan_speed_path = FAN_DX010_SPEED_PATH.format( + str(self.index+8)) + try: + with open(fan_speed_path) as fan_speed_file: + fan_speed_rpm = int(fan_speed_file.read()) + except IOError: + fan_speed = 0 + + fan_speed = float(fan_speed_rpm)/FAN_MAX_RPM * 100 + fan = Fan(0) + fan.fan_speed = int(fan_speed) if int(fan_speed) <= 100 else 100 + return fan + + 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 + """ + + set_status_str = { + self.STATUS_LED_COLOR_GREEN: '1', + self.STATUS_LED_COLOR_OFF: '0' + }.get(color, None) + + if not set_status_str: + return False + + try: + with open(self.green_led_path, 'w') as file: + file.write(set_status_str) + except IOError: + return False + + return True