From 76d68ad1f5364c3b76b12b2b0ccb7e96c081a416 Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox <57339448+Junchao-Mellanox@users.noreply.github.com> Date: Tue, 14 Jul 2020 01:22:39 +0800 Subject: [PATCH] [Mellanox] Add support for set/get system led status (#4829) System health feature needs to set/get system led status - Add a led object in chassis class and initialize it when the API is called on host side - Read/write system led system fs to get/set the status --- .../sonic_platform/chassis.py | 29 +++++ .../mlnx-platform-api/sonic_platform/led.py | 113 +++++++++++++++++- .../sonic_platform/platform.py | 1 + 3 files changed, 142 insertions(+), 1 deletion(-) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index ff4e289005..5a297ed29d 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -56,6 +56,9 @@ port_position_tuple_list = [(0, 0, 31, 32, 1), (0, 0, 15, 16, 1), (0, 48, 55, 56 class Chassis(ChassisBase): """Platform-specific Chassis class""" + # System status LED + _led = None + def __init__(self): super(Chassis, self).__init__() @@ -156,6 +159,10 @@ class Chassis(ChassisBase): self._component_list.append(ComponentBIOS()) self._component_list.extend(ComponentCPLD.get_component_list()) + def initizalize_system_led(self): + from .led import SystemLed + Chassis._led = SystemLed() + def get_name(self): """ @@ -467,3 +474,25 @@ class Chassis(ChassisBase): from .thermal_manager import ThermalManager return ThermalManager + def set_status_led(self, color): + """ + Sets the state of the system LED + + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False if not Chassis._led else Chassis._led.set_status(color) + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + return None if not Chassis._led else Chassis._led.get_status() diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/led.py b/platform/mellanox/mlnx-platform-api/sonic_platform/led.py index ebc2de25a5..1e401ebbaf 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/led.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/led.py @@ -3,12 +3,16 @@ import os class Led(object): STATUS_LED_COLOR_GREEN = 'green' + STATUS_LED_COLOR_GREEN_BLINK = 'green_blink' STATUS_LED_COLOR_RED = 'red' + STATUS_LED_COLOR_RED_BLINK = 'red_blink' STATUS_LED_COLOR_ORANGE = 'orange' + STATUS_LED_COLOR_ORANGE_BLINK = 'orange_blink' STATUS_LED_COLOR_OFF = 'off' LED_ON = '1' LED_OFF = '0' + LED_BLINK = '50' LED_PATH = "/var/run/hw-management/led/" @@ -19,6 +23,11 @@ class Led(object): status = False try: + self._stop_blink(led_cap_list) + blink_pos = color.find('blink') + if blink_pos != -1: + return self._set_status_blink(color, blink_pos, led_cap_list) + if color == Led.STATUS_LED_COLOR_GREEN: with open(self.get_green_led_path(), 'w') as led: led.write(Led.LED_ON) @@ -54,12 +63,53 @@ class Led(object): return status + def _set_status_blink(self, color, blink_pos, led_cap_list): + if color not in led_cap_list: + if color == Led.STATUS_LED_COLOR_RED_BLINK and Led.STATUS_LED_COLOR_ORANGE_BLINK in led_cap_list: + color = Led.STATUS_LED_COLOR_ORANGE_BLINK + elif color == Led.STATUS_LED_COLOR_ORANGE_BLINK and Led.STATUS_LED_COLOR_RED_BLINK in led_cap_list: + color = Led.STATUS_LED_COLOR_RED_BLINK + else: + return False + + if Led.STATUS_LED_COLOR_GREEN_BLINK == color: + self._set_led_blink_status(self.get_green_led_delay_on_path(), self.get_green_led_delay_off_path(), Led.LED_BLINK) + elif Led.STATUS_LED_COLOR_RED_BLINK == color: + self._set_led_blink_status(self.get_red_led_delay_on_path(), self.get_red_led_delay_off_path(), Led.LED_BLINK) + elif Led.STATUS_LED_COLOR_ORANGE_BLINK == color: + self._set_led_blink_status(self.get_orange_led_delay_on_path(), self.get_orange_led_delay_off_path(), Led.LED_BLINK) + else: + return False + + return True + + def _stop_blink(self, led_cap_list): + try: + if Led.STATUS_LED_COLOR_GREEN_BLINK in led_cap_list: + self._set_led_blink_status(self.get_green_led_delay_on_path(), self.get_green_led_delay_off_path(), Led.LED_OFF) + if Led.STATUS_LED_COLOR_RED_BLINK in led_cap_list: + self._set_led_blink_status(self.get_red_led_delay_on_path(), self.get_red_led_delay_off_path(), Led.LED_OFF) + if Led.STATUS_LED_COLOR_ORANGE_BLINK in led_cap_list: + self._set_led_blink_status(self.get_orange_led_delay_on_path(), self.get_orange_led_delay_off_path(), Led.LED_OFF) + except Exception as e: + return + + def _set_led_blink_status(self, delay_on_file, delay_off_file, value): + with open(delay_on_file, 'w') as led: + led.write(value) + with open(delay_off_file, 'w') as led: + led.write(value) + def get_status(self): led_cap_list = self.get_capability() if led_cap_list is None: return Led.STATUS_LED_COLOR_OFF try: + blink_status = self._get_blink_status(led_cap_list) + if blink_status is not None: + return blink_status + with open(self.get_green_led_path(), 'r') as led: if Led.LED_OFF != led.read().rstrip('\n'): return Led.STATUS_LED_COLOR_GREEN @@ -77,12 +127,35 @@ class Led(object): return Led.STATUS_LED_COLOR_OFF + def _get_blink_status(self, led_cap_list): + try: + if Led.STATUS_LED_COLOR_GREEN_BLINK in led_cap_list: + if self._is_led_blinking(self.get_green_led_delay_on_path(), self.get_green_led_delay_off_path()): + return Led.STATUS_LED_COLOR_GREEN_BLINK + if Led.STATUS_LED_COLOR_RED_BLINK in led_cap_list: + if self._is_led_blinking(self.get_red_led_delay_on_path(), self.get_red_led_delay_off_path()): + return Led.STATUS_LED_COLOR_RED_BLINK + if Led.STATUS_LED_COLOR_ORANGE_BLINK in led_cap_list: + if self._is_led_blinking(self.get_orange_led_delay_on_path(), self.get_orange_led_delay_off_path()): + return Led.STATUS_LED_COLOR_ORANGE_BLINK + except Exception as e: + return None + + return None + + def _is_led_blinking(self, delay_on_file, delay_off_file): + with open(delay_on_file, 'r') as led: + delay_on = led.read().rstrip('\n') + with open(delay_off_file, 'r') as led: + delay_off = led.read().rstrip('\n') + return delay_on != Led.LED_OFF and delay_off != Led.LED_OFF + def get_capability(self): cap_list = None try: with open(self.get_led_cap_path(), 'r') as led_cap: caps = led_cap.read() - cap_list = caps.split() + cap_list = set(caps.split()) except (ValueError, IOError): pass @@ -91,12 +164,30 @@ class Led(object): def get_green_led_path(self): pass + def get_green_led_delay_off_path(self): + return '{}_delay_off'.format(self.get_green_led_path()) + + def get_green_led_delay_on_path(self): + return '{}_delay_on'.format(self.get_green_led_path()) + def get_red_led_path(self): pass + def get_red_led_delay_off_path(self): + return '{}_delay_off'.format(self.get_red_led_path()) + + def get_red_led_delay_on_path(self): + return '{}_delay_on'.format(self.get_red_led_path()) + def get_orange_led_path(self): pass + def get_orange_led_delay_off_path(self): + return '{}_delay_off'.format(self.get_orange_led_path()) + + def get_orange_led_delay_on_path(self): + return '{}_delay_on'.format(self.get_orange_led_path()) + def get_led_cap_path(self): pass @@ -159,6 +250,26 @@ class PsuLed(Led): return self._led_cap_path +class SystemLed(Led): + def __init__(self): + self._green_led_path = os.path.join(Led.LED_PATH, "led_status_green") + self._red_led_path = os.path.join(Led.LED_PATH, "led_status_red") + self._orange_led_path = os.path.join(Led.LED_PATH, "led_status_orange") + self._led_cap_path = os.path.join(Led.LED_PATH, "led_status_capability") + + def get_green_led_path(self): + return self._green_led_path + + def get_red_led_path(self): + return self._red_led_path + + def get_orange_led_path(self): + return self._orange_led_path + + def get_led_cap_path(self): + return self._led_cap_path + + class SharedLed(object): LED_PRIORITY = { Led.STATUS_LED_COLOR_RED: 0, diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py index 6d81ca3e7b..6073ce5fae 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py @@ -19,6 +19,7 @@ class Platform(PlatformBase): if self._is_host(): self._chassis = Chassis() self._chassis.initialize_components() + self._chassis.initizalize_system_led() else: self._chassis = Chassis() self._chassis.initialize_psu()