Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[action] [PR:14508] [Mellanox] add PSU fan direction support #15414

Merged
merged 1 commit into from
Jun 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions platform/mellanox/mlnx-platform-api/sonic_platform/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from .led import ComponentFaultyIndicator
from . import utils
from .thermal import Thermal
from .fan_drawer import VirtualDrawer
except ImportError as e:
raise ImportError (str(e) + "- required module not found")

Expand All @@ -45,7 +46,10 @@
FAN_DIR = "/var/run/hw-management/thermal/fan{}_dir"
FAN_DIR_VALUE_EXHAUST = 0
FAN_DIR_VALUE_INTAKE = 1

FAN_DIR_MAPPING = {
FAN_DIR_VALUE_EXHAUST: FanBase.FAN_DIRECTION_EXHAUST,
FAN_DIR_VALUE_INTAKE: FanBase.FAN_DIRECTION_INTAKE,
}

class MlnxFan(FanBase):
def __init__(self, fan_index, position):
Expand Down Expand Up @@ -125,6 +129,20 @@ def is_replaceable(self):
"""
return False

@classmethod
def get_fan_direction(cls, dir_path):
try:
fan_dir = utils.read_int_from_file(dir_path, raise_exception=True)
ret = FAN_DIR_MAPPING.get(fan_dir)
if ret is None:
logger.log_error(f"Got wrong value {fan_dir} for fan direction {dir_path}")
return FanBase.FAN_DIRECTION_NOT_APPLICABLE
else:
return ret
except (ValueError, IOError) as e:
logger.log_error(f"Failed to read fan direction from {dir_path} - {e}")
return FanBase.FAN_DIRECTION_NOT_APPLICABLE


class PsuFan(MlnxFan):
# PSU fan speed vector
Expand All @@ -145,6 +163,7 @@ def __init__(self, fan_index, position, psu):
self.psu_i2c_bus_path = os.path.join(CONFIG_PATH, 'psu{0}_i2c_bus'.format(self.index))
self.psu_i2c_addr_path = os.path.join(CONFIG_PATH, 'psu{0}_i2c_addr'.format(self.index))
self.psu_i2c_command_path = os.path.join(CONFIG_PATH, 'fan_command')
self.psu_fan_dir_path = os.path.join(FAN_PATH, "psu{}_fan_dir".format(self.index))

def get_direction(self):
"""
Expand All @@ -165,7 +184,10 @@ def get_direction(self):
1 stands for forward, in other words intake
0 stands for reverse, in other words exhaust
"""
return self.FAN_DIRECTION_NOT_APPLICABLE
if not os.path.exists(self.psu_fan_dir_path) or not self.get_presence():
return self.FAN_DIRECTION_NOT_APPLICABLE

return MlnxFan.get_fan_direction(self.psu_fan_dir_path)

def get_status(self):
"""
Expand Down Expand Up @@ -263,7 +285,10 @@ def get_direction(self):
1 stands for forward, in other words intake
0 stands for reverse, in other words exhaust
"""
return self.fan_drawer.get_direction()
if not isinstance(self.fan_drawer, VirtualDrawer):
return self.fan_drawer.get_direction()
else:
return MlnxFan.get_fan_direction(FAN_DIR.format(self.index))

def get_status(self):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,8 @@ def get_direction(self):
if not self.get_presence():
return FanBase.FAN_DIRECTION_NOT_APPLICABLE

try:
from .fan import FAN_DIR, FAN_DIR_VALUE_INTAKE, FAN_DIR_VALUE_EXHAUST
fan_dir = utils.read_int_from_file(FAN_DIR.format(self._index), raise_exception=True)
if fan_dir == FAN_DIR_VALUE_INTAKE:
return FanBase.FAN_DIRECTION_INTAKE
elif fan_dir == FAN_DIR_VALUE_EXHAUST:
return FanBase.FAN_DIRECTION_EXHAUST
else:
logger.log_error("Got wrong value {} for fan direction {}".format(fan_dir, self._index))
return FanBase.FAN_DIRECTION_NOT_APPLICABLE
except (ValueError, IOError) as e:
logger.log_error("Failed to read fan direction status to {}".format(repr(e)))
return FanBase.FAN_DIRECTION_NOT_APPLICABLE
from .fan import FAN_DIR, MlnxFan
return MlnxFan.get_fan_direction(FAN_DIR.format(self._index))

def set_status_led(self, color):
"""
Expand Down
11 changes: 9 additions & 2 deletions platform/mellanox/mlnx-platform-api/tests/test_fan_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
sys.path.insert(0, modules_path)

from sonic_platform import utils
from sonic_platform.fan import Fan, PsuFan
from sonic_platform.fan import Fan, PsuFan, FAN_DIR_VALUE_INTAKE, FAN_DIR_VALUE_EXHAUST
from sonic_platform.fan_drawer import RealDrawer, VirtualDrawer
from sonic_platform.psu import Psu

Expand Down Expand Up @@ -107,11 +107,12 @@ def test_system_fan_set_speed(self, mock_write_file):
fan.set_speed(60)
mock_write_file.assert_called_with(fan.fan_speed_set_path, 153, raise_exception=True)

@patch('sonic_platform.utils.read_int_from_file')
@patch('sonic_platform.thermal.Thermal.get_cooling_level')
@patch('sonic_platform.psu.Psu.get_presence')
@patch('sonic_platform.psu.Psu.get_powergood_status')
@patch('os.path.exists')
def test_psu_fan_basic(self, mock_path_exists, mock_powergood, mock_presence, mock_cooling_level):
def test_psu_fan_basic(self, mock_path_exists, mock_powergood, mock_presence, mock_cooling_level, mock_read_int):
mock_path_exists.return_value = False
psu = Psu(0)
fan = PsuFan(0, 1, psu)
Expand All @@ -126,6 +127,12 @@ def test_psu_fan_basic(self, mock_path_exists, mock_powergood, mock_presence, mo
assert fan.get_presence() is True
mock_cooling_level.return_value = 7
assert fan.get_target_speed() == 70
mock_read_int.return_value = FAN_DIR_VALUE_INTAKE
assert fan.get_direction() == Fan.FAN_DIRECTION_INTAKE
mock_read_int.return_value = FAN_DIR_VALUE_EXHAUST
assert fan.get_direction() == Fan.FAN_DIRECTION_EXHAUST
mock_read_int.return_value = -1 # invalid value
assert fan.get_direction() == Fan.FAN_DIRECTION_NOT_APPLICABLE

def test_psu_fan_set_speed(self):
psu = Psu(0)
Expand Down