Skip to content

Commit d4bf78c

Browse files
authored
Add new platform management API. Currently with support for chassis, PSUs, fans and watchdog (#13)
1 parent 0d1622a commit d4bf78c

9 files changed

+633
-0
lines changed

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
packages=[
1414
'sonic_eeprom',
1515
'sonic_led',
16+
'sonic_platform_base',
1617
'sonic_psu',
1718
'sonic_sfp',
1819
],

sonic_platform_base/__init__.py

Whitespace-only changes.

sonic_platform_base/chassis_base.py

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#
2+
# chassis_base.py
3+
#
4+
# Base class for implementing a platform-specific class with which
5+
# to interact with a chassis device in SONiC.
6+
#
7+
8+
import sys
9+
from . import device_base
10+
11+
12+
class ChassisBase(device_base.DeviceBase):
13+
"""
14+
Base class for interfacing with a platform chassis
15+
"""
16+
17+
# Possible reboot causes
18+
REBOOT_CAUSE_POWER_LOSS = "power_loss"
19+
REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "thermal_overload_cpu"
20+
REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "thermal_overload_asic"
21+
REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "thermal_overload_other"
22+
REBOOT_CAUSE_INSUFFICIENT_FAN = "insufficient_fan"
23+
REBOOT_CAUSE_WATCHDOG = "watchdog"
24+
REBOOT_CAUSE_HARDWARE_OTHER = "hardware_other"
25+
REBOOT_CAUSE_NON_HARDWARE = "non_hardware"
26+
27+
# List of ModuleBase-derived objects representing all modules
28+
# available on the chassis (for use with modular chassis)
29+
_module_list = []
30+
31+
# List of FanBase-derived objects representing all fans
32+
# available on the chassis
33+
_fan_list = []
34+
35+
# List of PsuBase-derived objects representing all power supply units
36+
# available on the chassis
37+
_psu_list = []
38+
39+
# Object derived from WatchdogBase for interacting with hardware watchdog
40+
_watchdog = None
41+
42+
def get_base_mac(self):
43+
"""
44+
Retrieves the base MAC address for the chassis
45+
46+
Returns:
47+
A string containing the MAC address in the format
48+
'XX:XX:XX:XX:XX:XX'
49+
"""
50+
raise NotImplementedError
51+
52+
def get_reboot_cause(self):
53+
"""
54+
Retrieves the cause of the previous reboot
55+
56+
Returns:
57+
A tuple (string, string) where the first element is a string
58+
containing the cause of the previous reboot. This string must be
59+
one of the predefined strings in this class. If the first string
60+
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
61+
to pass a description of the reboot cause.
62+
"""
63+
raise NotImplementedError
64+
65+
def get_component_versions(self):
66+
"""
67+
Retrieves platform-specific hardware/firmware versions for chassis
68+
componenets such as BIOS, CPLD, FPGA, etc.
69+
70+
Returns:
71+
A string containing platform-specific component versions
72+
"""
73+
raise NotImplementedError
74+
75+
##############################################
76+
# Module methods
77+
##############################################
78+
79+
def get_num_modules(self):
80+
"""
81+
Retrieves the number of modules available on this chassis
82+
83+
Returns:
84+
An integer, the number of modules available on this chassis
85+
"""
86+
return len(self._module_list)
87+
88+
def get_all_modules(self):
89+
"""
90+
Retrieves all modules available on this chassis
91+
92+
Returns:
93+
A list of objects derived from ModuleBase representing all
94+
modules available on this chassis
95+
"""
96+
return self._module_list
97+
98+
def get_module(self, index):
99+
"""
100+
Retrieves module represented by (0-based) index <index>
101+
102+
Args:
103+
index: An integer, the index (0-based) of the module to
104+
retrieve
105+
106+
Returns:
107+
An object dervied from ModuleBase representing the specified
108+
module
109+
"""
110+
module = None
111+
112+
try:
113+
module = self._module_list[index]
114+
except IndexError:
115+
sys.stderr.write("Module index {} out of range (0-{})\n".format(
116+
index, len(self._module_list)-1))
117+
118+
return module
119+
120+
##############################################
121+
# Fan methods
122+
##############################################
123+
124+
def get_num_fans(self):
125+
"""
126+
Retrieves the number of fans available on this chassis
127+
128+
Returns:
129+
An integer, the number of fan modules available on this chassis
130+
"""
131+
return len(self._fan_list)
132+
133+
def get_all_fans(self):
134+
"""
135+
Retrieves all fan modules available on this chassis
136+
137+
Returns:
138+
A list of objects derived from FanBase representing all fan
139+
modules available on this chassis
140+
"""
141+
return self._fan_list
142+
143+
def get_fan(self, index):
144+
"""
145+
Retrieves fan module represented by (0-based) index <index>
146+
147+
Args:
148+
index: An integer, the index (0-based) of the fan module to
149+
retrieve
150+
151+
Returns:
152+
An object dervied from FanBase representing the specified fan
153+
module
154+
"""
155+
fan = None
156+
157+
try:
158+
fan = self._fan_list[index]
159+
except IndexError:
160+
sys.stderr.write("Fan index {} out of range (0-{})\n".format(
161+
index, len(self._fan_list)-1))
162+
163+
return fan
164+
165+
##############################################
166+
# PSU methods
167+
##############################################
168+
169+
def get_num_psus(self):
170+
"""
171+
Retrieves the number of power supply units available on this chassis
172+
173+
Returns:
174+
An integer, the number of power supply units available on this
175+
chassis
176+
"""
177+
return len(self._psu_list)
178+
179+
def get_all_psus(self):
180+
"""
181+
Retrieves all power supply units available on this chassis
182+
183+
Returns:
184+
A list of objects derived from PsuBase representing all power
185+
supply units available on this chassis
186+
"""
187+
return self._psu_list
188+
189+
def get_psu(self, index):
190+
"""
191+
Retrieves power supply unit represented by (0-based) index <index>
192+
193+
Args:
194+
index: An integer, the index (0-based) of the power supply unit to
195+
retrieve
196+
197+
Returns:
198+
An object dervied from PsuBase representing the specified power
199+
supply unit
200+
"""
201+
psu = None
202+
203+
try:
204+
psu = self._psu_list[index]
205+
except IndexError:
206+
sys.stderr.write("PSU index {} out of range (0-{})\n".format(
207+
index, len(self._psu_list)-1))
208+
209+
return psu
210+
211+
##############################################
212+
# Other methods
213+
##############################################
214+
215+
def get_watchdog(self):
216+
"""
217+
Retreives hardware watchdog device on this chassis
218+
219+
Returns:
220+
An object derived from WatchdogBase representing the hardware
221+
watchdog device
222+
"""
223+
return _watchdog

sonic_platform_base/device_base.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#
2+
# device_base.py
3+
#
4+
# Abstract base class for interfacing with a generic type of platform
5+
# peripheral device in SONiC
6+
#
7+
8+
class DeviceBase(object):
9+
"""
10+
Abstract base class for interfacing with a generic type of platform
11+
peripheral device
12+
"""
13+
14+
def get_presence(self):
15+
"""
16+
Retrieves the presence of the device
17+
18+
Returns:
19+
bool: True if device is present, False if not
20+
"""
21+
raise NotImplementedError
22+
23+
def get_model(self):
24+
"""
25+
Retrieves the model number (or part number) of the device
26+
27+
Returns:
28+
string: Model/part number of device
29+
"""
30+
raise NotImplementedError
31+
32+
def get_serial(self):
33+
"""
34+
Retrieves the serial number of the device
35+
36+
Returns:
37+
string: Serial number of device
38+
"""
39+
raise NotImplementedError
40+
41+
def get_status(self):
42+
"""
43+
Retrieves the operational status of the device
44+
45+
Returns:
46+
A boolean value, True if device is operating properly, False if not
47+
"""
48+
raise NotImplementedError
49+
50+
def get_change_event(self, timeout=0):
51+
"""
52+
Returns a dictionary containing all devices which have experienced a
53+
change
54+
55+
Args:
56+
timeout: Timeout in milliseconds (optional). If timeout == 0,
57+
this method will block until a change is detected.
58+
59+
Returns:
60+
(bool, dict):
61+
- True if call successful, False if not;
62+
- Dict where key is device ID and value is device event,
63+
status='1' represents device inserted,
64+
status='0' represents device removed. Ex. {'0': '1', '1': '0'}
65+
"""
66+
raise NotImplementedError

sonic_platform_base/fan_base.py

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#
2+
# fan_base.py
3+
#
4+
# Abstract base class for implementing a platform-specific class with which
5+
# to interact with a fan module in SONiC
6+
#
7+
8+
from . import device_base
9+
10+
11+
class FanBase(device_base.DeviceBase):
12+
"""
13+
Abstract base class for interfacing with a fan module
14+
"""
15+
16+
# Possible fan directions (relative to port-side of device)
17+
FAN_DIRECTION_INTAKE = "intake"
18+
FAN_DIRECTION_EXHAUST = "exhaust"
19+
20+
# Possible fan status LED colors
21+
STATUS_LED_COLOR_GREEN = "green"
22+
STATUS_LED_COLOR_RED = "red"
23+
STATUS_LED_COLOR_OFF = "off"
24+
25+
def get_direction(self):
26+
"""
27+
Retrieves the direction of fan
28+
29+
Returns:
30+
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
31+
depending on fan direction
32+
"""
33+
raise NotImplementedError
34+
35+
def get_speed(self):
36+
"""
37+
Retrieves the speed of fan as a percentage of full speed
38+
39+
Returns:
40+
An integer, the percentage of full fan speed, in the range 0 (off)
41+
to 100 (full speed)
42+
"""
43+
raise NotImplementedError
44+
45+
def get_target_speed(self):
46+
"""
47+
Retrieves the target (expected) speed of the fan
48+
49+
Returns:
50+
An integer, the percentage of full fan speed, in the range 0 (off)
51+
to 100 (full speed)
52+
"""
53+
raise NotImplementedError
54+
55+
def get_speed_tolerance(self):
56+
"""
57+
Retrieves the speed tolerance of the fan
58+
59+
Returns:
60+
An integer, the percentage of variance from target speed which is
61+
considered tolerable
62+
"""
63+
raise NotImplementedError
64+
65+
def set_speed(self, speed):
66+
"""
67+
Sets the fan speed
68+
69+
Args:
70+
speed: An integer, the percentage of full fan speed to set fan to,
71+
in the range 0 (off) to 100 (full speed)
72+
73+
Returns:
74+
A boolean, True if speed is set successfully, False if not
75+
"""
76+
raise NotImplementedError
77+
78+
def set_status_led(self, color):
79+
"""
80+
Sets the state of the fan module status LED
81+
82+
Args:
83+
color: A string representing the color with which to set the
84+
fan module status LED
85+
86+
Returns:
87+
bool: True if status LED state is set successfully, False if not
88+
"""
89+
raise NotImplementedError

0 commit comments

Comments
 (0)