[Mellanox] Implement new platform API for SONiC physical entity mib extension (#5645)
In order to support SONiC physical entity mib extension, a few new platform API are added to sonic-platform-common, this PR is to provide an mellanox platform implementation for those new APIs.
This commit is contained in:
parent
ced11615a4
commit
b595a6eadf
@ -104,7 +104,7 @@ class Chassis(ChassisBase):
|
||||
drawer = drawer_ctor(drawer_index, fan_data)
|
||||
self._fan_drawer_list.append(drawer)
|
||||
for index in range(fan_num_per_drawer):
|
||||
fan = Fan(fan_index, drawer)
|
||||
fan = Fan(fan_index, drawer, index + 1)
|
||||
fan_index += 1
|
||||
drawer._fan_list.append(fan)
|
||||
self._fan_list.append(fan)
|
||||
@ -130,18 +130,19 @@ class Chassis(ChassisBase):
|
||||
|
||||
for index in range(self.PORT_START, self.PORT_END + 1):
|
||||
if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1):
|
||||
sfp_module = SFP(index, 'QSFP', self.sdk_handle)
|
||||
sfp_module = SFP(index, 'QSFP', self.sdk_handle, self.platform_name)
|
||||
else:
|
||||
sfp_module = SFP(index, 'SFP', self.sdk_handle)
|
||||
sfp_module = SFP(index, 'SFP', self.sdk_handle, self.platform_name)
|
||||
|
||||
self._sfp_list.append(sfp_module)
|
||||
|
||||
self.sfp_module_initialized = True
|
||||
|
||||
|
||||
def initialize_thermals(self):
|
||||
from sonic_platform.thermal import initialize_thermals
|
||||
from sonic_platform.thermal import initialize_chassis_thermals
|
||||
# Initialize thermals
|
||||
initialize_thermals(self.platform_name, self._thermal_list, self._psu_list)
|
||||
initialize_chassis_thermals(self.platform_name, self._thermal_list)
|
||||
|
||||
|
||||
def initialize_eeprom(self):
|
||||
@ -514,3 +515,20 @@ class Chassis(ChassisBase):
|
||||
specified.
|
||||
"""
|
||||
return None if not Chassis._led else Chassis._led.get_status()
|
||||
|
||||
def get_position_in_parent(self):
|
||||
"""
|
||||
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
|
||||
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
|
||||
Returns:
|
||||
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
|
||||
"""
|
||||
return -1
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
return False
|
||||
|
@ -37,14 +37,16 @@ class Fan(FanBase):
|
||||
PSU_FAN_SPEED = ['0x3c', '0x3c', '0x3c', '0x3c', '0x3c',
|
||||
'0x3c', '0x3c', '0x46', '0x50', '0x5a', '0x64']
|
||||
|
||||
def __init__(self, fan_index, fan_drawer, psu_fan = False):
|
||||
def __init__(self, fan_index, fan_drawer, position, psu_fan = False, psu=None):
|
||||
super(Fan, self).__init__()
|
||||
|
||||
# API index is starting from 0, Mellanox platform index is starting from 1
|
||||
self.index = fan_index + 1
|
||||
self.fan_drawer = fan_drawer
|
||||
self.position = position
|
||||
|
||||
self.is_psu_fan = psu_fan
|
||||
self.psu = psu
|
||||
if self.fan_drawer:
|
||||
self.led = ComponentFaultyIndicator(self.fan_drawer.get_led())
|
||||
elif self.is_psu_fan:
|
||||
@ -123,13 +125,8 @@ class Fan(FanBase):
|
||||
Returns:
|
||||
bool: True if fan is present, False if not
|
||||
"""
|
||||
status = 0
|
||||
if self.is_psu_fan:
|
||||
if os.path.exists(os.path.join(FAN_PATH, self.fan_presence_path)):
|
||||
status = 1
|
||||
else:
|
||||
status = 0
|
||||
return status == 1
|
||||
return self.psu.get_presence() and self.psu.get_powergood_status() and os.path.exists(os.path.join(FAN_PATH, self.fan_presence_path))
|
||||
else:
|
||||
return self.fan_drawer.get_presence()
|
||||
|
||||
@ -254,6 +251,22 @@ class Fan(FanBase):
|
||||
# The tolerance value is fixed as 50% for all the Mellanox platform
|
||||
return 50
|
||||
|
||||
def get_position_in_parent(self):
|
||||
"""
|
||||
Retrieves 1-based relative physical position in parent device
|
||||
Returns:
|
||||
integer: The 1-based relative physical position in parent device
|
||||
"""
|
||||
return self.position
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def set_cooling_level(cls, level, cur_state):
|
||||
"""
|
||||
@ -288,3 +301,4 @@ class Fan(FanBase):
|
||||
except (ValueError, IOError) as e:
|
||||
raise RuntimeError("Failed to get cooling level - {}".format(e))
|
||||
|
||||
|
@ -84,6 +84,22 @@ class MellanoxFanDrawer(FanDrawerBase):
|
||||
"""
|
||||
return self._led.get_status()
|
||||
|
||||
def get_position_in_parent(self):
|
||||
"""
|
||||
Retrieves 1-based relative physical position in parent device
|
||||
Returns:
|
||||
integer: The 1-based relative physical position in parent device
|
||||
"""
|
||||
return self._index
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
return self._fan_data['hot_swappable']
|
||||
|
||||
|
||||
class RealDrawer(MellanoxFanDrawer):
|
||||
def __init__(self, index, fan_data):
|
||||
|
@ -103,7 +103,7 @@ class Psu(PsuBase):
|
||||
|
||||
# unplugable PSU has no FAN
|
||||
if self.psu_data['hot_swappable']:
|
||||
fan = Fan(psu_index, None, True)
|
||||
fan = Fan(psu_index, None, 1, True, self)
|
||||
self._fan_list.append(fan)
|
||||
|
||||
if self.psu_data['led_num'] == 1:
|
||||
@ -111,6 +111,10 @@ class Psu(PsuBase):
|
||||
else: # 2010/2100
|
||||
self.led = PsuLed(self.index)
|
||||
|
||||
# initialize thermal for PSU
|
||||
from .thermal import initialize_psu_thermals
|
||||
initialize_psu_thermals(platform, self._thermal_list, self.index, self.get_power_available_status)
|
||||
|
||||
|
||||
def get_name(self):
|
||||
return self._name
|
||||
@ -244,6 +248,22 @@ class Psu(PsuBase):
|
||||
else:
|
||||
return True, ""
|
||||
|
||||
def get_position_in_parent(self):
|
||||
"""
|
||||
Retrieves 1-based relative physical position in parent device
|
||||
Returns:
|
||||
integer: The 1-based relative physical position in parent device
|
||||
"""
|
||||
return self.index
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
return self.psu_data['hot_swappable']
|
||||
|
||||
@classmethod
|
||||
def get_shared_led(cls):
|
||||
if not cls.shared_led:
|
||||
|
@ -309,7 +309,8 @@ def deinitialize_sdk_handle(sdk_handle):
|
||||
class SFP(SfpBase):
|
||||
"""Platform-specific SFP class"""
|
||||
|
||||
def __init__(self, sfp_index, sfp_type, sdk_handle):
|
||||
def __init__(self, sfp_index, sfp_type, sdk_handle, platform):
|
||||
SfpBase.__init__(self)
|
||||
self.index = sfp_index + 1
|
||||
self.sfp_eeprom_path = "qsfp{}".format(self.index)
|
||||
self.sfp_status_path = "qsfp{}_status".format(self.index)
|
||||
@ -319,7 +320,12 @@ class SFP(SfpBase):
|
||||
self.sdk_handle = sdk_handle
|
||||
self.sdk_index = sfp_index
|
||||
|
||||
# initialize SFP thermal list
|
||||
from .thermal import initialize_sfp_thermals
|
||||
initialize_sfp_thermals(platform, self._thermal_list, self.index)
|
||||
|
||||
def reinit(self):
|
||||
|
||||
"""
|
||||
Re-initialize this SFP object when a new SFP inserted
|
||||
:return:
|
||||
@ -2034,3 +2040,11 @@ class SFP(SfpBase):
|
||||
False if not
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
return True
|
||||
|
@ -113,12 +113,10 @@ thermal_name = {
|
||||
}
|
||||
|
||||
thermal_device_categories_all = [
|
||||
THERMAL_DEV_CATEGORY_CPU_CORE,
|
||||
THERMAL_DEV_CATEGORY_CPU_PACK,
|
||||
THERMAL_DEV_CATEGORY_MODULE,
|
||||
THERMAL_DEV_CATEGORY_PSU,
|
||||
THERMAL_DEV_CATEGORY_AMBIENT,
|
||||
THERMAL_DEV_CATEGORY_GEARBOX
|
||||
THERMAL_DEV_CATEGORY_CPU_PACK,
|
||||
THERMAL_DEV_CATEGORY_CPU_CORE,
|
||||
THERMAL_DEV_CATEGORY_GEARBOX,
|
||||
]
|
||||
|
||||
thermal_device_categories_singleton = [
|
||||
@ -305,18 +303,34 @@ thermal_profile_list = [
|
||||
}
|
||||
]
|
||||
|
||||
def initialize_psu_thermals(platform, thermal_list, psu_index, dependency):
|
||||
tp_index = platform_dict_thermal[platform]
|
||||
thermal_profile = thermal_profile_list[tp_index]
|
||||
_, count = thermal_profile[THERMAL_DEV_CATEGORY_PSU]
|
||||
if count == 0:
|
||||
return
|
||||
thermal = Thermal(THERMAL_DEV_CATEGORY_PSU, psu_index, True, 1, dependency)
|
||||
thermal_list.append(thermal)
|
||||
|
||||
def initialize_thermals(platform, thermal_list, psu_list):
|
||||
|
||||
def initialize_sfp_thermals(platform, thermal_list, sfp_index):
|
||||
thermal = Thermal(THERMAL_DEV_CATEGORY_MODULE, sfp_index, True, 1)
|
||||
thermal_list.append(thermal)
|
||||
|
||||
|
||||
def initialize_chassis_thermals(platform, thermal_list):
|
||||
# create thermal objects for all categories of sensors
|
||||
tp_index = platform_dict_thermal[platform]
|
||||
thermal_profile = thermal_profile_list[tp_index]
|
||||
Thermal.thermal_profile = thermal_profile
|
||||
position = 1
|
||||
for category in thermal_device_categories_all:
|
||||
if category == THERMAL_DEV_CATEGORY_AMBIENT:
|
||||
count, ambient_list = thermal_profile[category]
|
||||
for ambient in ambient_list:
|
||||
thermal = Thermal(category, ambient, True)
|
||||
thermal_list.append(thermal)
|
||||
thermal = Thermal(category, ambient, True, position)
|
||||
thermal_list.append(thermal),
|
||||
position += 1
|
||||
else:
|
||||
start, count = 0, 0
|
||||
if category in thermal_profile:
|
||||
@ -324,17 +338,14 @@ def initialize_thermals(platform, thermal_list, psu_list):
|
||||
if count == 0:
|
||||
continue
|
||||
if count == 1:
|
||||
thermal = Thermal(category, 0, False)
|
||||
thermal_list.append(thermal)
|
||||
else:
|
||||
if category == THERMAL_DEV_CATEGORY_PSU:
|
||||
for index in range(count):
|
||||
thermal = Thermal(category, start + index, True, psu_list[index].get_power_available_status)
|
||||
thermal = Thermal(category, 0, False, position)
|
||||
thermal_list.append(thermal)
|
||||
position += 1
|
||||
else:
|
||||
for index in range(count):
|
||||
thermal = Thermal(category, start + index, True)
|
||||
thermal = Thermal(category, start + index, True, position)
|
||||
thermal_list.append(thermal)
|
||||
position += 1
|
||||
|
||||
|
||||
|
||||
@ -342,7 +353,7 @@ class Thermal(ThermalBase):
|
||||
thermal_profile = None
|
||||
thermal_algorithm_status = False
|
||||
|
||||
def __init__(self, category, index, has_index, dependency = None):
|
||||
def __init__(self, category, index, has_index, position, dependency = None):
|
||||
"""
|
||||
index should be a string for category ambient and int for other categories
|
||||
"""
|
||||
@ -357,6 +368,7 @@ class Thermal(ThermalBase):
|
||||
self.index = 0
|
||||
|
||||
self.category = category
|
||||
self.position = position
|
||||
self.temperature = self._get_file_from_api(THERMAL_API_GET_TEMPERATURE)
|
||||
self.high_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_THRESHOLD)
|
||||
self.high_critical_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD)
|
||||
@ -480,6 +492,21 @@ class Thermal(ThermalBase):
|
||||
return None
|
||||
return value_float / 1000.0
|
||||
|
||||
def get_position_in_parent(self):
|
||||
"""
|
||||
Retrieves 1-based relative physical position in parent device
|
||||
Returns:
|
||||
integer: The 1-based relative physical position in parent device
|
||||
"""
|
||||
return self.position
|
||||
|
||||
def is_replaceable(self):
|
||||
"""
|
||||
Indicate whether this device is replaceable.
|
||||
Returns:
|
||||
bool: True if it is replaceable.
|
||||
"""
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def _write_generic_file(cls, filename, content):
|
||||
|
@ -16,7 +16,7 @@ from sonic_platform.device_data import DEVICE_DATA
|
||||
|
||||
def test_get_absence_fan_direction():
|
||||
fan_drawer = RealDrawer(0, DEVICE_DATA['x86_64-mlnx_msn2700-r0']['fans'])
|
||||
fan = Fan(0, fan_drawer)
|
||||
fan = Fan(0, fan_drawer, 1)
|
||||
fan_drawer.get_presence = MagicMock(return_value=False)
|
||||
|
||||
assert not fan.is_psu_fan
|
||||
@ -31,8 +31,8 @@ def test_fan_drawer_set_status_led():
|
||||
with pytest.raises(Exception):
|
||||
fan_drawer.set_status_led(None, Fan.STATUS_LED_COLOR_RED)
|
||||
|
||||
fan1 = Fan(0, fan_drawer)
|
||||
fan2 = Fan(1, fan_drawer)
|
||||
fan1 = Fan(0, fan_drawer, 1)
|
||||
fan2 = Fan(1, fan_drawer, 2)
|
||||
fan_list = fan_drawer.get_all_fans()
|
||||
fan_list.append(fan1)
|
||||
fan_list.append(fan2)
|
||||
|
Loading…
Reference in New Issue
Block a user