diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index 1682d4649d3f..77cf27da2d6e 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -104,7 +104,7 @@ def initialize_fan(self): 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 @@ def initialize_sfp(self): 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 @@ def get_status_led(self): 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 diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py index 1808bdd0aeee..686b0f82ddbe 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py @@ -36,14 +36,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: @@ -125,13 +127,8 @@ def get_presence(self): 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() @@ -291,6 +288,22 @@ def get_speed_tolerance(self): # 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): """ @@ -329,3 +342,4 @@ def get_cooling_level(cls): except (ValueError, IOError) as e: raise RuntimeError("Failed to get cooling level - {}".format(e)) + \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py b/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py index bed6c7ab042a..66ee39491735 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py @@ -84,6 +84,22 @@ def get_status_led(self): """ 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): diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py index d26df89f04ce..897555ed8020 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py @@ -103,7 +103,7 @@ def __init__(self, psu_index, platform): # 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 @@ def __init__(self, psu_index, platform): 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 @@ def get_power_available_status(self): 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: diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py index 4814055ca5bc..30942009a38c 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py @@ -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 @@ def __init__(self, sfp_index, sfp_type, sdk_handle): 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 @@ def set_power_override(self, power_override, power_set): False if not """ return NotImplementedError + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py index 4ebe28252481..48b277345b3a 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py @@ -113,12 +113,10 @@ } 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 @@ } ] +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 = Thermal(category, 0, False, position) thermal_list.append(thermal) + position += 1 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) - else: - for index in range(count): - thermal = Thermal(category, start + index, True) - thermal_list.append(thermal) + for index in range(count): + 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 @@ def __init__(self, category, index, has_index, dependency = None): 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 @@ def get_high_critical_threshold(self): 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): diff --git a/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py index 24158997abf7..bb9ee7e125a2 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py @@ -16,7 +16,7 @@ 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)