forked from sonoble/sonic-buildimage
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new platform management API. Currently with support for chassis, …
…PSUs, fans and watchdog (#13)
- Loading branch information
Showing
9 changed files
with
633 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
packages=[ | ||
'sonic_eeprom', | ||
'sonic_led', | ||
'sonic_platform_base', | ||
'sonic_psu', | ||
'sonic_sfp', | ||
], | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
# | ||
# chassis_base.py | ||
# | ||
# Base class for implementing a platform-specific class with which | ||
# to interact with a chassis device in SONiC. | ||
# | ||
|
||
import sys | ||
from . import device_base | ||
|
||
|
||
class ChassisBase(device_base.DeviceBase): | ||
""" | ||
Base class for interfacing with a platform chassis | ||
""" | ||
|
||
# Possible reboot causes | ||
REBOOT_CAUSE_POWER_LOSS = "power_loss" | ||
REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "thermal_overload_cpu" | ||
REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "thermal_overload_asic" | ||
REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "thermal_overload_other" | ||
REBOOT_CAUSE_INSUFFICIENT_FAN = "insufficient_fan" | ||
REBOOT_CAUSE_WATCHDOG = "watchdog" | ||
REBOOT_CAUSE_HARDWARE_OTHER = "hardware_other" | ||
REBOOT_CAUSE_NON_HARDWARE = "non_hardware" | ||
|
||
# List of ModuleBase-derived objects representing all modules | ||
# available on the chassis (for use with modular chassis) | ||
_module_list = [] | ||
|
||
# List of FanBase-derived objects representing all fans | ||
# available on the chassis | ||
_fan_list = [] | ||
|
||
# List of PsuBase-derived objects representing all power supply units | ||
# available on the chassis | ||
_psu_list = [] | ||
|
||
# Object derived from WatchdogBase for interacting with hardware watchdog | ||
_watchdog = None | ||
|
||
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' | ||
""" | ||
raise NotImplementedError | ||
|
||
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. | ||
""" | ||
raise NotImplementedError | ||
|
||
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 | ||
""" | ||
raise NotImplementedError | ||
|
||
############################################## | ||
# Module methods | ||
############################################## | ||
|
||
def get_num_modules(self): | ||
""" | ||
Retrieves the number of modules available on this chassis | ||
Returns: | ||
An integer, the number of modules available on this chassis | ||
""" | ||
return len(self._module_list) | ||
|
||
def get_all_modules(self): | ||
""" | ||
Retrieves all modules available on this chassis | ||
Returns: | ||
A list of objects derived from ModuleBase representing all | ||
modules available on this chassis | ||
""" | ||
return self._module_list | ||
|
||
def get_module(self, index): | ||
""" | ||
Retrieves module represented by (0-based) index <index> | ||
Args: | ||
index: An integer, the index (0-based) of the module to | ||
retrieve | ||
Returns: | ||
An object dervied from ModuleBase representing the specified | ||
module | ||
""" | ||
module = None | ||
|
||
try: | ||
module = self._module_list[index] | ||
except IndexError: | ||
sys.stderr.write("Module index {} out of range (0-{})\n".format( | ||
index, len(self._module_list)-1)) | ||
|
||
return module | ||
|
||
############################################## | ||
# Fan methods | ||
############################################## | ||
|
||
def get_num_fans(self): | ||
""" | ||
Retrieves the number of fans available on this chassis | ||
Returns: | ||
An integer, the number of fan modules available on this chassis | ||
""" | ||
return len(self._fan_list) | ||
|
||
def get_all_fans(self): | ||
""" | ||
Retrieves all fan modules available on this chassis | ||
Returns: | ||
A list of objects derived from FanBase representing all fan | ||
modules available on this chassis | ||
""" | ||
return self._fan_list | ||
|
||
def get_fan(self, index): | ||
""" | ||
Retrieves fan module represented by (0-based) index <index> | ||
Args: | ||
index: An integer, the index (0-based) of the fan module to | ||
retrieve | ||
Returns: | ||
An object dervied from FanBase representing the specified fan | ||
module | ||
""" | ||
fan = None | ||
|
||
try: | ||
fan = self._fan_list[index] | ||
except IndexError: | ||
sys.stderr.write("Fan index {} out of range (0-{})\n".format( | ||
index, len(self._fan_list)-1)) | ||
|
||
return fan | ||
|
||
############################################## | ||
# PSU methods | ||
############################################## | ||
|
||
def get_num_psus(self): | ||
""" | ||
Retrieves the number of power supply units available on this chassis | ||
Returns: | ||
An integer, the number of power supply units available on this | ||
chassis | ||
""" | ||
return len(self._psu_list) | ||
|
||
def get_all_psus(self): | ||
""" | ||
Retrieves all power supply units available on this chassis | ||
Returns: | ||
A list of objects derived from PsuBase representing all power | ||
supply units available on this chassis | ||
""" | ||
return self._psu_list | ||
|
||
def get_psu(self, index): | ||
""" | ||
Retrieves power supply unit represented by (0-based) index <index> | ||
Args: | ||
index: An integer, the index (0-based) of the power supply unit to | ||
retrieve | ||
Returns: | ||
An object dervied from PsuBase representing the specified power | ||
supply unit | ||
""" | ||
psu = None | ||
|
||
try: | ||
psu = self._psu_list[index] | ||
except IndexError: | ||
sys.stderr.write("PSU index {} out of range (0-{})\n".format( | ||
index, len(self._psu_list)-1)) | ||
|
||
return psu | ||
|
||
############################################## | ||
# Other methods | ||
############################################## | ||
|
||
def get_watchdog(self): | ||
""" | ||
Retreives hardware watchdog device on this chassis | ||
Returns: | ||
An object derived from WatchdogBase representing the hardware | ||
watchdog device | ||
""" | ||
return _watchdog |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# | ||
# device_base.py | ||
# | ||
# Abstract base class for interfacing with a generic type of platform | ||
# peripheral device in SONiC | ||
# | ||
|
||
class DeviceBase(object): | ||
""" | ||
Abstract base class for interfacing with a generic type of platform | ||
peripheral device | ||
""" | ||
|
||
def get_presence(self): | ||
""" | ||
Retrieves the presence of the device | ||
Returns: | ||
bool: True if device is present, False if not | ||
""" | ||
raise NotImplementedError | ||
|
||
def get_model(self): | ||
""" | ||
Retrieves the model number (or part number) of the device | ||
Returns: | ||
string: Model/part number of device | ||
""" | ||
raise NotImplementedError | ||
|
||
def get_serial(self): | ||
""" | ||
Retrieves the serial number of the device | ||
Returns: | ||
string: Serial number of device | ||
""" | ||
raise NotImplementedError | ||
|
||
def get_status(self): | ||
""" | ||
Retrieves the operational status of the device | ||
Returns: | ||
A boolean value, True if device is operating properly, False if not | ||
""" | ||
raise NotImplementedError | ||
|
||
def get_change_event(self, timeout=0): | ||
""" | ||
Returns a dictionary containing all devices which have experienced a | ||
change | ||
Args: | ||
timeout: Timeout in milliseconds (optional). If timeout == 0, | ||
this method will block until a change is detected. | ||
Returns: | ||
(bool, dict): | ||
- True if call successful, False if not; | ||
- Dict where key is device ID and value is device event, | ||
status='1' represents device inserted, | ||
status='0' represents device removed. Ex. {'0': '1', '1': '0'} | ||
""" | ||
raise NotImplementedError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# | ||
# fan_base.py | ||
# | ||
# Abstract base class for implementing a platform-specific class with which | ||
# to interact with a fan module in SONiC | ||
# | ||
|
||
from . import device_base | ||
|
||
|
||
class FanBase(device_base.DeviceBase): | ||
""" | ||
Abstract base class for interfacing with a fan module | ||
""" | ||
|
||
# Possible fan directions (relative to port-side of device) | ||
FAN_DIRECTION_INTAKE = "intake" | ||
FAN_DIRECTION_EXHAUST = "exhaust" | ||
|
||
# Possible fan status LED colors | ||
STATUS_LED_COLOR_GREEN = "green" | ||
STATUS_LED_COLOR_RED = "red" | ||
STATUS_LED_COLOR_OFF = "off" | ||
|
||
def get_direction(self): | ||
""" | ||
Retrieves the direction of fan | ||
Returns: | ||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST | ||
depending on fan direction | ||
""" | ||
raise NotImplementedError | ||
|
||
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) | ||
""" | ||
raise NotImplementedError | ||
|
||
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) | ||
""" | ||
raise NotImplementedError | ||
|
||
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 | ||
""" | ||
raise NotImplementedError | ||
|
||
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 | ||
""" | ||
raise NotImplementedError | ||
|
||
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 | ||
""" | ||
raise NotImplementedError |
Oops, something went wrong.