From d2c5f738f776d65d462a250ba100975b2bdaeefa Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 8 Nov 2018 01:48:28 +0000 Subject: [PATCH 1/3] Add design doc for new platform management API --- doc/platform_api/new_platform_api.md | 182 +++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 doc/platform_api/new_platform_api.md diff --git a/doc/platform_api/new_platform_api.md b/doc/platform_api/new_platform_api.md new file mode 100644 index 0000000000..ad22881e31 --- /dev/null +++ b/doc/platform_api/new_platform_api.md @@ -0,0 +1,182 @@ +## New Platform Management API + +### Overview + +Every platform has a unique set of platform peripheral devices +- PSUs +- Fan modules +- SFP transceiver cages +- Environment sensors +- Front-panel LEDs +- etc. + +These devices can vary by manufacturer, model, quantity, interface, ... + +Challenge: Attempt to create a standardized, unified API to interface with all combinations of these devices + +### SONiC Design Principles + +1. Unified, standardized behavior + - Consistent experience among all SONiC devices, regardless of underlying platform + - Easy to understand, implement, test and debug + +2. Kernel modules kept as simple as possible + - Simply expose hardware registers + - No control logic + +3. Peripheral control logic implemented in user-space + - Applications shared among all platforms + - Standardized API defined by SONiC, implemented by vendors + +### Current Solution + +- Individual plugins, one per peripheral device type + - sfputil.py, psuutil.py, eeprom.py, etc. + - SONiC defines base classes, vendors must implement these classes in their plugins + - All Platform-specific plugins live on disk in image, appropriate plugin is loaded at runtime after determining running platform +- Drawbacks + - Lack of structure; Each plugin base class installed as its own Python package + - As we add support for more devices, new plugins are necessary. + - Vendors need to be made aware of new plugins. Not apparent. + - When adding a new abstract method to a base class, one needs to add default implementation to *all* existing implementations + +### New Solution + +- Combine all plugin base classes into an object-oriented hierarchy + - Hierarchy based on physical connection of devices + - Object-orientation allows for definition of a generic "DeviceBase" class + - Attributes shared by all/most devices inherited by all (Presence, Model #, Serial #, etc.) +- Installed as one Python package: "sonic_platform_base" +- Vendors implement entire package: "sonic_platform" + - Appropriate platform-specific package will be installed during first boot, similar to platform drivers +- No longer abstract base classes + - All abstract methods simply raise "NotImplementedError" + - Adding new methods to the base classes will not break existing implementations + - To ensure vendors are made aware of new methods, we will add a build-time or run-time test which will output all unimplemented methods + +### New Platform API Hierarchy + +- Platform + - Chassis + - Base MAC address + - Reboot cause + - Hardware watchdog + - Environment sensors + - Front-panel LEDs + - Status LEDs + - Power supply unit[0 .. p-1] + - Fan[0 .. f-1] + - SFP cage[0 .. s-1] + - Module[0 .. m-1] + - Environment sensors + - Front-panel LEDs + - Status LEDs + - Power supply unit[0 .. p'-1] + - Fan[0 .. f'-1] + - SFP cage[0 .. s'-1] + +### Sample code to print PSU1 presence using old API + +``` +#!/usr/bin/env python + +import imp +import subprocess +import sys + +# Global platform-specific psuutil class instance +platform_psuutil = None + +# Returns platform and HW SKU +def get_platform_and_hwsku(): + try: + proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + platform = stdout.rstrip('\n') + + proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + hwsku = stdout.rstrip('\n') + except OSError, e: + raise OSError("Cannot detect platform") + + return (platform, hwsku) + +# Loads platform specific psuutil module from source +def load_platform_psuutil(): + global platform_psuutil + + # Get platform and hwsku + (platform, hwsku) = get_platform_and_hwsku() + + # Load platform module from source + platform_path = '' + if len(platform) != 0: + platform_path = "/".join([PLATFORM_ROOT_PATH, platform]) + else: + platform_path = PLATFORM_ROOT_PATH_DOCKER + hwsku_path = "/".join([platform_path, hwsku]) + + try: + module_file = "/".join([platform_path, "plugins", PLATFORM_SPECIFIC_MODULE_NAME + ".py"]) + module = imp.load_source(PLATFORM_SPECIFIC_MODULE_NAME, module_file) + except IOError, e: + print("Failed to load platform module '%s': %s" % (PLATFORM_SPECIFIC_MODULE_NAME, str(e)), True) + return -1 + + try: + platform_psuutil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + platform_psuutil = platform_psuutil_class() + except AttributeError, e: + print("Failed to instantiate '%s' class: %s" % (PLATFORM_SPECIFIC_CLASS_NAME, str(e)), True) + return -2 + + return 0 + +# Load platform-specific psuutil class +err = load_platform_psuutil() +if err != 0: + sys.exit(2) + +presence = platform_psuutil.get_psu_presence(1) + +print("PSU 1 presence: {}".format(presence)) + +``` + + +### Sample code to print PSU1 status using new API + +``` +#!/usr/bin/env python + +import sonic_platform + +platform = sonic_platform.platform.Platform() + +chassis = platform.get_chassis() +if not chassis: + print("Error getting chassis!") + sys.exit(1) + +psu1 = chassis.get_psu(1) +if not psu1: + print("Error getting psu1!") + sys.exit(2) + +presence = psu1.get_presence() + +print("PSU 1 presence: {}".format(presence)) +``` + +### Pull Request for New API Framework + +https://github.com/Azure/sonic-platform-common/pull/13 From d2ff3c8747c25038a8b84605af911af95132d357 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Tue, 27 Nov 2018 00:11:38 +0000 Subject: [PATCH 2/3] Add information about plans for new package installation --- doc/platform_api/new_platform_api.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/platform_api/new_platform_api.md b/doc/platform_api/new_platform_api.md index ad22881e31..454c65aed4 100644 --- a/doc/platform_api/new_platform_api.md +++ b/doc/platform_api/new_platform_api.md @@ -53,6 +53,10 @@ Challenge: Attempt to create a standardized, unified API to interface with all c - All abstract methods simply raise "NotImplementedError" - Adding new methods to the base classes will not break existing implementations - To ensure vendors are made aware of new methods, we will add a build-time or run-time test which will output all unimplemented methods +- New "sonic_platform" package will only be installed in Platform Monitor (pmon) Docker container (not in base image). + - Daemons running in pmon container will be responsible for updating Redis State database with current data from platfrom hardware + - Command-line utilities in base image will query State DB to retrieve current platform peripheral metrics + - For more real-time data, such as transceiver optical data, CLI will notify daemons to retrieve data by writing to DB ### New Platform API Hierarchy @@ -67,7 +71,7 @@ Challenge: Attempt to create a standardized, unified API to interface with all c - Power supply unit[0 .. p-1] - Fan[0 .. f-1] - SFP cage[0 .. s-1] - - Module[0 .. m-1] + - Module[0 .. m-1] (Line card, supervisor card, etc.) - Environment sensors - Front-panel LEDs - Status LEDs From 540d890d3acbc9e424dac75f0f671cbb352f0a52 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 20 Jun 2019 00:18:59 +0000 Subject: [PATCH 3/3] Update to reflect current state of new platform API --- doc/platform_api/new_platform_api.md | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/doc/platform_api/new_platform_api.md b/doc/platform_api/new_platform_api.md index 454c65aed4..42000a8000 100644 --- a/doc/platform_api/new_platform_api.md +++ b/doc/platform_api/new_platform_api.md @@ -42,6 +42,8 @@ Challenge: Attempt to create a standardized, unified API to interface with all c ### New Solution +#### Concept + - Combine all plugin base classes into an object-oriented hierarchy - Hierarchy based on physical connection of devices - Object-orientation allows for definition of a generic "DeviceBase" class @@ -53,16 +55,27 @@ Challenge: Attempt to create a standardized, unified API to interface with all c - All abstract methods simply raise "NotImplementedError" - Adding new methods to the base classes will not break existing implementations - To ensure vendors are made aware of new methods, we will add a build-time or run-time test which will output all unimplemented methods -- New "sonic_platform" package will only be installed in Platform Monitor (pmon) Docker container (not in base image). - - Daemons running in pmon container will be responsible for updating Redis State database with current data from platfrom hardware - - Command-line utilities in base image will query State DB to retrieve current platform peripheral metrics - - For more real-time data, such as transceiver optical data, CLI will notify daemons to retrieve data by writing to DB -### New Platform API Hierarchy +#### Implementation + +- Source for new "sonic_platform" package will reside along with vendor's platform module source under the platform/... directory structure +- At build time, vendor ensures sonic_platform source is compiled into a Python wheel file +- Upon first boot after image installation, at the time the appropriate platform modules are installed, the following must also be done: + 1. Install the sonic_platform package in the host system + 2. Copy the sonic_platform Python wheel to the appropriate /usr/share/sonic/device// directory, which gets mounted in the Docker containers +- When the Platform Monitor (PMon) container starts, it will check whether a "sonic_platform" package is installed. If not, it will attempt to install a "sonic_platform\*.whl" file in the mounted directory as mentioned above. +- In the host system, applications will interact with the platform API for things like watchdog and reboot cause +- Daemons running in pmon container will be responsible for updating Redis State database with current metrics/status from platfrom hardware +- Command-line utilities in host image will query State DB to retrieve current platform peripheral metrics +- For more real-time data, such as transceiver optical data, a mechanism can be implemented CLI can notify daemons to retrieve data by writing to DB + +#### New Platform API Hierarchy - Platform - Chassis - Base MAC address + - Serial number + - System EEPROM info - Reboot cause - Hardware watchdog - Environment sensors @@ -181,6 +194,6 @@ presence = psu1.get_presence() print("PSU 1 presence: {}".format(presence)) ``` -### Pull Request for New API Framework +### New Platform API Framework location -https://github.com/Azure/sonic-platform-common/pull/13 +https://github.com/Azure/sonic-platform-common/tree/master/sonic_platform_base