From b4a27e5c2c6e0860567376a94c2a5380943c684c Mon Sep 17 00:00:00 2001 From: Stephen Sun Date: Fri, 12 Jul 2019 12:36:13 +0300 Subject: [PATCH 1/5] backport new platform api to 201811, reboot cause part --- platform/mellanox/mlnx-platform-api.mk | 7 ++ platform/mellanox/mlnx-platform-api/setup.py | 30 ++++++ .../sonic_platform/__init__.py | 0 .../sonic_platform/chassis.py | 97 +++++++++++++++++++ .../sonic_platform/platform.py | 19 ++++ 5 files changed, 153 insertions(+) create mode 100644 platform/mellanox/mlnx-platform-api.mk create mode 100644 platform/mellanox/mlnx-platform-api/setup.py create mode 100644 platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py create mode 100644 platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py create mode 100644 platform/mellanox/mlnx-platform-api/sonic_platform/platform.py diff --git a/platform/mellanox/mlnx-platform-api.mk b/platform/mellanox/mlnx-platform-api.mk new file mode 100644 index 000000000000..98a57d0090ed --- /dev/null +++ b/platform/mellanox/mlnx-platform-api.mk @@ -0,0 +1,7 @@ +# SONIC_PLATFORM_API_PY2 package + +SONIC_PLATFORM_API_PY2 = mlnx_platform_api-1.0-py2-none-any.whl +$(SONIC_PLATFORM_API_PY2)_SRC_PATH = $(PLATFORM_PATH)/mlnx-platform-api +$(SONIC_PLATFORM_API_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2) + diff --git a/platform/mellanox/mlnx-platform-api/setup.py b/platform/mellanox/mlnx-platform-api/setup.py new file mode 100644 index 000000000000..12809c4085ed --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/setup.py @@ -0,0 +1,30 @@ +from setuptools import setup + +setup( + name='mlnx-platform-api', + version='1.0', + description='SONiC platform API implementation on Mellanox platform', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Kevin Wang', + maintainer_email='kevinw@mellanox.com', + packages=[ + 'sonic_platform', + ], + 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 :: 2.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py b/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py new file mode 100644 index 000000000000..6f1c83b080d0 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys + +try: + from sonic_platform_base.chassis_base import ChassisBase +# from sonic_daemon_base.daemon_base import Logger + from os.path import join + import io + import re + import subprocess +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +HWMGMT_SYSTEM_ROOT = '/var/run/hw-management/system/' + +#reboot cause related definitions +REBOOT_CAUSE_ROOT = HWMGMT_SYSTEM_ROOT + +REBOOT_CAUSE_POWER_LOSS_FILE = 'reset_main_pwr_fail' +REBOOT_CAUSE_AUX_POWER_LOSS_FILE = 'reset_aux_pwr_or_ref' +REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC_FILE = 'reset_asic_thermal' +REBOOT_CAUSE_WATCHDOG_FILE = 'reset_hotswap_or_wd' +REBOOT_CAUSE_MLNX_FIRMWARE_RESET = 'reset_fw_reset' + +REBOOT_CAUSE_FILE_LENGTH = 1 + +# Global logger class instance +# SYSLOG_IDENTIFIER = "mlnx-chassis" +# logger = Logger(SYSLOG_IDENTIFIER) + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + super(Chassis, self).__init__() + + def _read_generic_file(self, filename, len): + """ + Read a generic file, returns the contents of the file + """ + result = '' + try: + fileobj = io.open(filename) + result = fileobj.read(len) + fileobj.close() + return result + except: + logger.log_warning("Fail to read file {}, maybe it doesn't exist".format(filename)) + return '' + + def _verify_reboot_cause(self, filename): + ''' + Open and read the reboot cause file in + /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT) + If a reboot cause file doesn't exists, returns '0'. + ''' + return bool(int(self._read_generic_file(join(REBOOT_CAUSE_ROOT, filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n'))) + + 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. + """ + #read reboot causes files in the following order + minor_cause = '' + if self._verify_reboot_cause(REBOOT_CAUSE_POWER_LOSS_FILE): + major_cause = self.REBOOT_CAUSE_POWER_LOSS + elif self._verify_reboot_cause(REBOOT_CAUSE_AUX_POWER_LOSS_FILE): + major_cause = self.REBOOT_CAUSE_POWER_LOSS + elif self._verify_reboot_cause(REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC_FILE): + major_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC + elif self._verify_reboot_cause(REBOOT_CAUSE_WATCHDOG_FILE): + major_cause = self.REBOOT_CAUSE_WATCHDOG + else: + major_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + if self._verify_reboot_cause(REBOOT_CAUSE_MLNX_FIRMWARE_RESET): + minor_cause = "Reset by ASIC firmware" + else: + major_cause = self.REBOOT_CAUSE_NON_HARDWARE + + return major_cause, minor_cause + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py new file mode 100644 index 000000000000..5a081bd27f83 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# implementation of new platform api +############################################################################# + +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): + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() \ No newline at end of file From 4aeefb1a7d7cbced28fb264c181b965b6df7da5c Mon Sep 17 00:00:00 2001 From: Stephen Sun Date: Mon, 15 Jul 2019 01:22:17 +0300 Subject: [PATCH 2/5] install new platform api on host --- files/build_templates/sonic_debian_extension.j2 | 6 ++++++ platform/mellanox/mlnx-platform-api.mk | 1 + platform/mellanox/rules.mk | 1 + 3 files changed, 8 insertions(+) diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 9c6e8a553206..b5d2feeae5d6 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -333,6 +333,12 @@ sudo cp target/files/$ISSU_VERSION_FILE $FILESYSTEM_ROOT/etc/mlnx/issu-version sudo cp target/files/$MLNX_FFB_SCRIPT $FILESYSTEM_ROOT/usr/bin/mlnx-ffb.sh j2 platform/mellanox/mlnx-fw-upgrade.j2 | sudo tee $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh + +# Install mlnx-sonic-platform-common Python 2 package +MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME=$(basename {{mlnx_platform_api_py2_wheel_path}}) +sudo cp {{mlnx_platform_api_py2_wheel_path}} $FILESYSTEM_ROOT/$MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME {% endif %} {%- if SONIC_ROUTING_STACK == "frr" %} diff --git a/platform/mellanox/mlnx-platform-api.mk b/platform/mellanox/mlnx-platform-api.mk index 98a57d0090ed..4b70e59debc1 100644 --- a/platform/mellanox/mlnx-platform-api.mk +++ b/platform/mellanox/mlnx-platform-api.mk @@ -5,3 +5,4 @@ $(SONIC_PLATFORM_API_PY2)_SRC_PATH = $(PLATFORM_PATH)/mlnx-platform-api $(SONIC_PLATFORM_API_PY2)_PYTHON_VERSION = 2 SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2) +export mlnx_platform_api_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2))" diff --git a/platform/mellanox/rules.mk b/platform/mellanox/rules.mk index 1c0072bec3ce..afd52a3459b1 100644 --- a/platform/mellanox/rules.mk +++ b/platform/mellanox/rules.mk @@ -3,6 +3,7 @@ include $(PLATFORM_PATH)/fw.mk include $(PLATFORM_PATH)/mft.mk include $(PLATFORM_PATH)/mlnx-sai.mk include $(PLATFORM_PATH)/hw-management.mk +include $(PLATFORM_PATH)/mlnx-platform-api.mk include $(PLATFORM_PATH)/docker-syncd-mlnx.mk include $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.mk include $(PLATFORM_PATH)/docker-orchagent-mlnx.mk From 30fbcf83d24e0f9d8ba0f085a67dba9a03ba03bc Mon Sep 17 00:00:00 2001 From: Stephen Sun Date: Tue, 16 Jul 2019 11:38:49 +0300 Subject: [PATCH 3/5] 1. remove chassis's dependency on sonic_platform_daemon. 2. add some mellanox-specific hardware reboot causes. 3. fix typo in files/image_config/process-reboot-cause/process-reboot-cause. --- .../process-reboot-cause/process-reboot-cause | 2 +- .../sonic_platform/chassis.py | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/files/image_config/process-reboot-cause/process-reboot-cause b/files/image_config/process-reboot-cause/process-reboot-cause index 0d5ae78137fa..2e152c699ce7 100755 --- a/files/image_config/process-reboot-cause/process-reboot-cause +++ b/files/image_config/process-reboot-cause/process-reboot-cause @@ -70,7 +70,7 @@ def main(): # if there is no sonic_platform package installed, we only provide # software-related reboot causes. try: - import sonic_platform + import sonic_platform.platform # Check if the previous reboot was caused by hardware platform = sonic_platform.platform.Platform() diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index 6f1c83b080d0..bc5e1b5dd677 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -12,11 +12,11 @@ try: from sonic_platform_base.chassis_base import ChassisBase -# from sonic_daemon_base.daemon_base import Logger from os.path import join import io import re import subprocess + import syslog except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -30,12 +30,17 @@ REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC_FILE = 'reset_asic_thermal' REBOOT_CAUSE_WATCHDOG_FILE = 'reset_hotswap_or_wd' REBOOT_CAUSE_MLNX_FIRMWARE_RESET = 'reset_fw_reset' +REBOOT_CAUSE_LONG_PB = 'reset_long_pb' +REBOOT_CAUSE_SHORT_PB = 'reset_short_pb' REBOOT_CAUSE_FILE_LENGTH = 1 -# Global logger class instance -# SYSLOG_IDENTIFIER = "mlnx-chassis" -# logger = Logger(SYSLOG_IDENTIFIER) +# ========================== Syslog wrappers ========================== +def log_warning(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + class Chassis(ChassisBase): """Platform-specific Chassis class""" @@ -54,7 +59,7 @@ def _read_generic_file(self, filename, len): fileobj.close() return result except: - logger.log_warning("Fail to read file {}, maybe it doesn't exist".format(filename)) + log_warning("Fail to read file {}, maybe it doesn't exist".format(filename)) return '' def _verify_reboot_cause(self, filename): @@ -90,6 +95,10 @@ def get_reboot_cause(self): major_cause = self.REBOOT_CAUSE_HARDWARE_OTHER if self._verify_reboot_cause(REBOOT_CAUSE_MLNX_FIRMWARE_RESET): minor_cause = "Reset by ASIC firmware" + elif self._verify_reboot_cause(REBOOT_CAUSE_LONG_PB): + minor_cause = "Reset by long press on power button" + elif self._verify_reboot_cause(REBOOT_CAUSE_SHORT_PB): + minor_cause = "Reset by short press on power button" else: major_cause = self.REBOOT_CAUSE_NON_HARDWARE From 5642953e7d09d8a414611ef91474df553d9f10c0 Mon Sep 17 00:00:00 2001 From: Stephen Sun Date: Tue, 16 Jul 2019 13:42:15 +0300 Subject: [PATCH 4/5] 1. add dependency of sonic_platform for base image 2. handle the case of reboot cause file not found --- files/build_templates/sonic_debian_extension.j2 | 2 +- .../mellanox/mlnx-platform-api/sonic_platform/chassis.py | 6 +++++- slave.mk | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index b5d2feeae5d6..3b40bd87774e 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -334,7 +334,7 @@ sudo cp target/files/$MLNX_FFB_SCRIPT $FILESYSTEM_ROOT/usr/bin/mlnx-ffb.sh j2 platform/mellanox/mlnx-fw-upgrade.j2 | sudo tee $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh -# Install mlnx-sonic-platform-common Python 2 package +# Install mlnx-sonic-platform Python 2 package MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME=$(basename {{mlnx_platform_api_py2_wheel_path}}) sudo cp {{mlnx_platform_api_py2_wheel_path}} $FILESYSTEM_ROOT/$MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $MLNX_PLATFORM_COMMON_PY2_WHEEL_NAME diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index bc5e1b5dd677..e22d06854d09 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -36,6 +36,7 @@ REBOOT_CAUSE_FILE_LENGTH = 1 # ========================== Syslog wrappers ========================== +SYSLOG_IDENTIFIER = "mlnx-chassis" def log_warning(msg, also_print_to_console=False): syslog.openlog(SYSLOG_IDENTIFIER) syslog.syslog(syslog.LOG_WARNING, msg) @@ -68,7 +69,10 @@ def _verify_reboot_cause(self, filename): /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT) If a reboot cause file doesn't exists, returns '0'. ''' - return bool(int(self._read_generic_file(join(REBOOT_CAUSE_ROOT, filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n'))) + try: + return bool(int(self._read_generic_file(join(REBOOT_CAUSE_ROOT, filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n'))) + except: + return False def get_reboot_cause(self): """ diff --git a/slave.mk b/slave.mk index e2e3d2729ef2..bf1ea426cdea 100644 --- a/slave.mk +++ b/slave.mk @@ -558,7 +558,8 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ $$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \ $$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE)) \ $$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2)) \ - $$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2)) + $$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2)) \ + $$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2)) $(HEADER) # Pass initramfs and linux kernel explicitly. They are used for all platforms export initramfs_tools="$(DEBS_PATH)/$(INITRAMFS_TOOLS)" From 02adcccfac4369d28ef5469f00cf5490dd87cf7f Mon Sep 17 00:00:00 2001 From: Stephen Sun Date: Mon, 22 Jul 2019 14:41:20 +0300 Subject: [PATCH 5/5] adjust log message. --- platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index e22d06854d09..73279102691c 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -59,8 +59,8 @@ def _read_generic_file(self, filename, len): result = fileobj.read(len) fileobj.close() return result - except: - log_warning("Fail to read file {}, maybe it doesn't exist".format(filename)) + except Exception as e: + log_warning("Fail to read file {} due to {}".format(filename, repr(e))) return '' def _verify_reboot_cause(self, filename):