From 3ea3a5c8c137969fc758655087607e655b8f404b Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox <57339448+Junchao-Mellanox@users.noreply.github.com> Date: Tue, 25 May 2021 02:36:39 +0800 Subject: [PATCH] [Mellanox] clear fan from chassis._fan_list (#7682) #### Why I did it According to thermalctld hld, each fan must belong to a fan drawer, if the fan drawer does not physically exist, put fan into a virtual fan drawer. This PR is to clear fan from chassis._fan_list #### How I did it 1. Don't put fan to chassis._fan_list 2. Always query fan from fan_drawer --- .../sonic_platform/chassis.py | 1 - .../sonic_platform/thermal_infos.py | 39 ++++++++++--------- .../mlnx-platform-api/tests/mock_platform.py | 16 +++++++- .../tests/test_thermal_policy.py | 29 +++++++------- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index 341a4407fe..1167f56368 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -160,7 +160,6 @@ class Chassis(ChassisBase): fan = Fan(fan_index, drawer, index + 1) fan_index += 1 drawer._fan_list.append(fan) - self._fan_list.append(fan) def initialize_single_sfp(self, index): diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py index e810a56464..df262557c4 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py @@ -24,26 +24,27 @@ class FanInfo(ThermalPolicyInfoBase): :return: """ self._status_changed = False - for fan in chassis.get_all_fans(): - presence = fan.get_presence() - status = fan.get_status() - if presence and fan not in self._presence_fans: - self._presence_fans.add(fan) - self._status_changed = True - if fan in self._absence_fans: - self._absence_fans.remove(fan) - elif not presence and fan not in self._absence_fans: - self._absence_fans.add(fan) - self._status_changed = True - if fan in self._presence_fans: - self._presence_fans.remove(fan) + for fan_drawer in chassis.get_all_fan_drawers(): + for fan in fan_drawer.get_all_fans(): + presence = fan.get_presence() + status = fan.get_status() + if presence and fan not in self._presence_fans: + self._presence_fans.add(fan) + self._status_changed = True + if fan in self._absence_fans: + self._absence_fans.remove(fan) + elif not presence and fan not in self._absence_fans: + self._absence_fans.add(fan) + self._status_changed = True + if fan in self._presence_fans: + self._presence_fans.remove(fan) - if not status and fan not in self._fault_fans: - self._fault_fans.add(fan) - self._status_changed = True - elif status and fan in self._fault_fans: - self._fault_fans.remove(fan) - self._status_changed = True + if not status and fan not in self._fault_fans: + self._fault_fans.add(fan) + self._status_changed = True + elif status and fan in self._fault_fans: + self._fault_fans.remove(fan) + self._status_changed = True def get_absence_fans(self): diff --git a/platform/mellanox/mlnx-platform-api/tests/mock_platform.py b/platform/mellanox/mlnx-platform-api/tests/mock_platform.py index 8edb9d4fb1..1cd8f89d48 100644 --- a/platform/mellanox/mlnx-platform-api/tests/mock_platform.py +++ b/platform/mellanox/mlnx-platform-api/tests/mock_platform.py @@ -36,10 +36,19 @@ class MockPsu: return [] +class MockFanDrawer: + def __init__(self): + self.fan_list = [] + + def get_all_fans(self): + return self.fan_list + + class MockChassis: def __init__(self): self.fan_list = [] self.psu_list = [] + self.fan_drawer_list = [] def get_all_psus(self): return self.psu_list @@ -47,6 +56,9 @@ class MockChassis: def get_all_fans(self): return self.fan_list + def get_all_fan_drawers(self): + return self.fan_drawer_list + def get_thermal_manager(self): from sonic_platform.thermal_manager import ThermalManager return ThermalManager @@ -54,7 +66,9 @@ class MockChassis: def make_fan_absence(self): fan = MockFan() fan.presence = False - self.fan_list.append(fan) + fan_drawer = MockFanDrawer() + self.fan_drawer_list.append(fan_drawer) + fan_drawer.fan_list.append(fan) def make_psu_absence(self): psu = MockPsu() diff --git a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py index 4d69a39c58..e2fb26cf60 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py @@ -3,7 +3,7 @@ import sys import pytest import json from mock import MagicMock -from .mock_platform import MockChassis, MockFan, MockPsu +from .mock_platform import MockChassis, MockFan, MockFanDrawer, MockPsu test_path = os.path.dirname(os.path.abspath(__file__)) modules_path = os.path.dirname(test_path) @@ -49,15 +49,14 @@ def test_fan_info(): assert len(fan_info.get_fault_fans()) == 0 assert fan_info.is_status_changed() - fan_list = chassis.get_all_fans() - fan_list[0].presence = True + chassis.get_all_fan_drawers()[0].get_all_fans()[0].presence = True fan_info.collect(chassis) assert len(fan_info.get_absence_fans()) == 0 assert len(fan_info.get_presence_fans()) == 1 assert len(fan_info.get_fault_fans()) == 0 assert fan_info.is_status_changed() - fan_list[0].status = False + chassis.get_all_fan_drawers()[0].get_all_fans()[0].status = False fan_info.collect(chassis) assert len(fan_info.get_absence_fans()) == 0 assert len(fan_info.get_presence_fans()) == 1 @@ -90,10 +89,10 @@ def test_psu_info(): def test_fan_policy(thermal_manager): chassis = MockChassis() chassis.make_fan_absence() - chassis.fan_list.append(MockFan()) + chassis.get_all_fan_drawers()[0].get_all_fans().append(MockFan()) thermal_manager.run_policy(chassis) - fan_list = chassis.get_all_fans() + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() assert fan_list[1].speed == 100 Thermal.set_thermal_algorithm_status.assert_called_with(False, False) @@ -144,7 +143,7 @@ def test_any_fan_absence_condition(): condition = AnyFanAbsenceCondition() assert condition.is_match({'fan_info': fan_info}) - fan = chassis.get_all_fans()[0] + fan = chassis.get_all_fan_drawers()[0].get_all_fans()[0] fan.presence = True fan_info.collect(chassis) assert not condition.is_match({'fan_info': fan_info}) @@ -154,7 +153,7 @@ def test_all_fan_absence_condition(): chassis = MockChassis() chassis.make_fan_absence() fan = MockFan() - fan_list = chassis.get_all_fans() + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() fan_list.append(fan) fan_info = FanInfo() fan_info.collect(chassis) @@ -172,7 +171,7 @@ def test_all_fan_presence_condition(): chassis = MockChassis() chassis.make_fan_absence() fan = MockFan() - fan_list = chassis.get_all_fans() + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() fan_list.append(fan) fan_info = FanInfo() fan_info.collect(chassis) @@ -187,8 +186,9 @@ def test_all_fan_presence_condition(): def test_any_fan_fault_condition(): chassis = MockChassis() + chassis.get_all_fan_drawers().append(MockFanDrawer()) fan = MockFan() - fan_list = chassis.get_all_fans() + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() fan_list.append(fan) fault_fan = MockFan() fault_fan.status = False @@ -206,8 +206,9 @@ def test_any_fan_fault_condition(): def test_all_fan_good_condition(): chassis = MockChassis() + chassis.get_all_fan_drawers().append(MockFanDrawer()) fan = MockFan() - fan_list = chassis.get_all_fans() + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() fan_list.append(fan) fault_fan = MockFan() fault_fan.status = False @@ -302,7 +303,8 @@ def test_load_set_fan_speed_action(): def test_execute_set_fan_speed_action(): chassis = MockChassis() - fan_list = chassis.get_all_fans() + chassis.get_all_fan_drawers().append(MockFanDrawer()) + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() fan_list.append(MockFan()) fan_list.append(MockFan()) fan_info = FanInfo() @@ -364,7 +366,8 @@ def test_load_check_and_set_speed_action(): def test_execute_check_and_set_fan_speed_action(): chassis = MockChassis() - fan_list = chassis.get_all_fans() + chassis.get_all_fan_drawers().append(MockFanDrawer()) + fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() fan_list.append(MockFan()) fan_list.append(MockFan()) fan_info = FanInfo()