[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)
|
drawer = drawer_ctor(drawer_index, fan_data)
|
||||||
self._fan_drawer_list.append(drawer)
|
self._fan_drawer_list.append(drawer)
|
||||||
for index in range(fan_num_per_drawer):
|
for index in range(fan_num_per_drawer):
|
||||||
fan = Fan(fan_index, drawer)
|
fan = Fan(fan_index, drawer, index + 1)
|
||||||
fan_index += 1
|
fan_index += 1
|
||||||
drawer._fan_list.append(fan)
|
drawer._fan_list.append(fan)
|
||||||
self._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):
|
for index in range(self.PORT_START, self.PORT_END + 1):
|
||||||
if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 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:
|
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_list.append(sfp_module)
|
||||||
|
|
||||||
self.sfp_module_initialized = True
|
self.sfp_module_initialized = True
|
||||||
|
|
||||||
|
|
||||||
def initialize_thermals(self):
|
def initialize_thermals(self):
|
||||||
from sonic_platform.thermal import initialize_thermals
|
from sonic_platform.thermal import initialize_chassis_thermals
|
||||||
# Initialize 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):
|
def initialize_eeprom(self):
|
||||||
@ -514,3 +515,20 @@ class Chassis(ChassisBase):
|
|||||||
specified.
|
specified.
|
||||||
"""
|
"""
|
||||||
return None if not Chassis._led else Chassis._led.get_status()
|
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',
|
PSU_FAN_SPEED = ['0x3c', '0x3c', '0x3c', '0x3c', '0x3c',
|
||||||
'0x3c', '0x3c', '0x46', '0x50', '0x5a', '0x64']
|
'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__()
|
super(Fan, self).__init__()
|
||||||
|
|
||||||
# API index is starting from 0, Mellanox platform index is starting from 1
|
# API index is starting from 0, Mellanox platform index is starting from 1
|
||||||
self.index = fan_index + 1
|
self.index = fan_index + 1
|
||||||
self.fan_drawer = fan_drawer
|
self.fan_drawer = fan_drawer
|
||||||
|
self.position = position
|
||||||
|
|
||||||
self.is_psu_fan = psu_fan
|
self.is_psu_fan = psu_fan
|
||||||
|
self.psu = psu
|
||||||
if self.fan_drawer:
|
if self.fan_drawer:
|
||||||
self.led = ComponentFaultyIndicator(self.fan_drawer.get_led())
|
self.led = ComponentFaultyIndicator(self.fan_drawer.get_led())
|
||||||
elif self.is_psu_fan:
|
elif self.is_psu_fan:
|
||||||
@ -123,13 +125,8 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if fan is present, False if not
|
bool: True if fan is present, False if not
|
||||||
"""
|
"""
|
||||||
status = 0
|
|
||||||
if self.is_psu_fan:
|
if self.is_psu_fan:
|
||||||
if os.path.exists(os.path.join(FAN_PATH, self.fan_presence_path)):
|
return self.psu.get_presence() and self.psu.get_powergood_status() and os.path.exists(os.path.join(FAN_PATH, self.fan_presence_path))
|
||||||
status = 1
|
|
||||||
else:
|
|
||||||
status = 0
|
|
||||||
return status == 1
|
|
||||||
else:
|
else:
|
||||||
return self.fan_drawer.get_presence()
|
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
|
# The tolerance value is fixed as 50% for all the Mellanox platform
|
||||||
return 50
|
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
|
@classmethod
|
||||||
def set_cooling_level(cls, level, cur_state):
|
def set_cooling_level(cls, level, cur_state):
|
||||||
"""
|
"""
|
||||||
@ -288,3 +301,4 @@ class Fan(FanBase):
|
|||||||
except (ValueError, IOError) as e:
|
except (ValueError, IOError) as e:
|
||||||
raise RuntimeError("Failed to get cooling level - {}".format(e))
|
raise RuntimeError("Failed to get cooling level - {}".format(e))
|
||||||
|
|
||||||
|
|
@ -84,6 +84,22 @@ class MellanoxFanDrawer(FanDrawerBase):
|
|||||||
"""
|
"""
|
||||||
return self._led.get_status()
|
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):
|
class RealDrawer(MellanoxFanDrawer):
|
||||||
def __init__(self, index, fan_data):
|
def __init__(self, index, fan_data):
|
||||||
|
@ -103,7 +103,7 @@ class Psu(PsuBase):
|
|||||||
|
|
||||||
# unplugable PSU has no FAN
|
# unplugable PSU has no FAN
|
||||||
if self.psu_data['hot_swappable']:
|
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)
|
self._fan_list.append(fan)
|
||||||
|
|
||||||
if self.psu_data['led_num'] == 1:
|
if self.psu_data['led_num'] == 1:
|
||||||
@ -111,6 +111,10 @@ class Psu(PsuBase):
|
|||||||
else: # 2010/2100
|
else: # 2010/2100
|
||||||
self.led = PsuLed(self.index)
|
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):
|
def get_name(self):
|
||||||
return self._name
|
return self._name
|
||||||
@ -244,6 +248,22 @@ class Psu(PsuBase):
|
|||||||
else:
|
else:
|
||||||
return True, ""
|
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
|
@classmethod
|
||||||
def get_shared_led(cls):
|
def get_shared_led(cls):
|
||||||
if not cls.shared_led:
|
if not cls.shared_led:
|
||||||
|
@ -309,7 +309,8 @@ def deinitialize_sdk_handle(sdk_handle):
|
|||||||
class SFP(SfpBase):
|
class SFP(SfpBase):
|
||||||
"""Platform-specific SFP class"""
|
"""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.index = sfp_index + 1
|
||||||
self.sfp_eeprom_path = "qsfp{}".format(self.index)
|
self.sfp_eeprom_path = "qsfp{}".format(self.index)
|
||||||
self.sfp_status_path = "qsfp{}_status".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_handle = sdk_handle
|
||||||
self.sdk_index = sfp_index
|
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):
|
def reinit(self):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Re-initialize this SFP object when a new SFP inserted
|
Re-initialize this SFP object when a new SFP inserted
|
||||||
:return:
|
:return:
|
||||||
@ -2034,3 +2040,11 @@ class SFP(SfpBase):
|
|||||||
False if not
|
False if not
|
||||||
"""
|
"""
|
||||||
return NotImplementedError
|
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_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_AMBIENT,
|
||||||
THERMAL_DEV_CATEGORY_GEARBOX
|
THERMAL_DEV_CATEGORY_CPU_PACK,
|
||||||
|
THERMAL_DEV_CATEGORY_CPU_CORE,
|
||||||
|
THERMAL_DEV_CATEGORY_GEARBOX,
|
||||||
]
|
]
|
||||||
|
|
||||||
thermal_device_categories_singleton = [
|
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
|
# create thermal objects for all categories of sensors
|
||||||
tp_index = platform_dict_thermal[platform]
|
tp_index = platform_dict_thermal[platform]
|
||||||
thermal_profile = thermal_profile_list[tp_index]
|
thermal_profile = thermal_profile_list[tp_index]
|
||||||
Thermal.thermal_profile = thermal_profile
|
Thermal.thermal_profile = thermal_profile
|
||||||
|
position = 1
|
||||||
for category in thermal_device_categories_all:
|
for category in thermal_device_categories_all:
|
||||||
if category == THERMAL_DEV_CATEGORY_AMBIENT:
|
if category == THERMAL_DEV_CATEGORY_AMBIENT:
|
||||||
count, ambient_list = thermal_profile[category]
|
count, ambient_list = thermal_profile[category]
|
||||||
for ambient in ambient_list:
|
for ambient in ambient_list:
|
||||||
thermal = Thermal(category, ambient, True)
|
thermal = Thermal(category, ambient, True, position)
|
||||||
thermal_list.append(thermal)
|
thermal_list.append(thermal),
|
||||||
|
position += 1
|
||||||
else:
|
else:
|
||||||
start, count = 0, 0
|
start, count = 0, 0
|
||||||
if category in thermal_profile:
|
if category in thermal_profile:
|
||||||
@ -324,17 +338,14 @@ def initialize_thermals(platform, thermal_list, psu_list):
|
|||||||
if count == 0:
|
if count == 0:
|
||||||
continue
|
continue
|
||||||
if count == 1:
|
if count == 1:
|
||||||
thermal = Thermal(category, 0, False)
|
thermal = Thermal(category, 0, False, position)
|
||||||
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_list.append(thermal)
|
thermal_list.append(thermal)
|
||||||
|
position += 1
|
||||||
else:
|
else:
|
||||||
for index in range(count):
|
for index in range(count):
|
||||||
thermal = Thermal(category, start + index, True)
|
thermal = Thermal(category, start + index, True, position)
|
||||||
thermal_list.append(thermal)
|
thermal_list.append(thermal)
|
||||||
|
position += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -342,7 +353,7 @@ class Thermal(ThermalBase):
|
|||||||
thermal_profile = None
|
thermal_profile = None
|
||||||
thermal_algorithm_status = False
|
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
|
index should be a string for category ambient and int for other categories
|
||||||
"""
|
"""
|
||||||
@ -357,6 +368,7 @@ class Thermal(ThermalBase):
|
|||||||
self.index = 0
|
self.index = 0
|
||||||
|
|
||||||
self.category = category
|
self.category = category
|
||||||
|
self.position = position
|
||||||
self.temperature = self._get_file_from_api(THERMAL_API_GET_TEMPERATURE)
|
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_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)
|
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 None
|
||||||
return value_float / 1000.0
|
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
|
@classmethod
|
||||||
def _write_generic_file(cls, filename, content):
|
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():
|
def test_get_absence_fan_direction():
|
||||||
fan_drawer = RealDrawer(0, DEVICE_DATA['x86_64-mlnx_msn2700-r0']['fans'])
|
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)
|
fan_drawer.get_presence = MagicMock(return_value=False)
|
||||||
|
|
||||||
assert not fan.is_psu_fan
|
assert not fan.is_psu_fan
|
||||||
@ -31,8 +31,8 @@ def test_fan_drawer_set_status_led():
|
|||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
fan_drawer.set_status_led(None, Fan.STATUS_LED_COLOR_RED)
|
fan_drawer.set_status_led(None, Fan.STATUS_LED_COLOR_RED)
|
||||||
|
|
||||||
fan1 = Fan(0, fan_drawer)
|
fan1 = Fan(0, fan_drawer, 1)
|
||||||
fan2 = Fan(1, fan_drawer)
|
fan2 = Fan(1, fan_drawer, 2)
|
||||||
fan_list = fan_drawer.get_all_fans()
|
fan_list = fan_drawer.get_all_fans()
|
||||||
fan_list.append(fan1)
|
fan_list.append(fan1)
|
||||||
fan_list.append(fan2)
|
fan_list.append(fan2)
|
||||||
|
Loading…
Reference in New Issue
Block a user