Skip to content
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
20 changes: 20 additions & 0 deletions sonic-thermalctld/scripts/thermalctld
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ except ImportError as e:

SYSLOG_IDENTIFIER = 'thermalctld'
NOT_AVAILABLE = 'N/A'
INVALID_SLOT = -1

# utility functions

Expand Down Expand Up @@ -462,6 +463,15 @@ class TemperatureUpdater(logger.Logger):
self.temperature_status_dict = {}
state_db = daemon_base.db_connect("STATE_DB")
self.table = swsscommon.Table(state_db, TemperatureUpdater.TEMPER_INFO_TABLE_NAME)
self.chassis_table = None

self.is_chassis_system = chassis.is_modular_chassis()
if self.is_chassis_system:
my_slot = try_get(chassis.get_my_slot, INVALID_SLOT)
if my_slot != INVALID_SLOT:
table_name = TemperatureUpdater.TEMPER_INFO_TABLE_NAME+'_'+str(my_slot)
chassis_state_db = daemon_base.db_connect("CHASSIS_STATE_DB")
self.chassis_table = swsscommon.Table(chassis_state_db, table_name)

def deinit(self):
"""
Expand All @@ -470,6 +480,8 @@ class TemperatureUpdater(logger.Logger):
"""
for name in self.temperature_status_dict.keys():
self.table._del(name)
if self.is_chassis_system and self.chassis_table is not None:
self.chassis_table._del(name)

def _log_on_status_changed(self, normal_status, normal_log, abnormal_log):
"""
Expand Down Expand Up @@ -515,9 +527,13 @@ class TemperatureUpdater(logger.Logger):
low_threshold = NOT_AVAILABLE
high_critical_threshold = NOT_AVAILABLE
low_critical_threshold = NOT_AVAILABLE
maximum_temperature = NOT_AVAILABLE
minimum_temperature = NOT_AVAILABLE
temperature = try_get(thermal.get_temperature)
if temperature != NOT_AVAILABLE:
temperature_status.set_temperature(name, temperature)
minimum_temperature = try_get(thermal.get_minimum_recorded)
maximum_temperature = try_get(thermal.get_maximum_recorded)
high_threshold = try_get(thermal.get_high_threshold)
low_threshold = try_get(thermal.get_low_threshold)
high_critical_threshold = try_get(thermal.get_high_critical_threshold)
Expand All @@ -544,6 +560,8 @@ class TemperatureUpdater(logger.Logger):

fvs = swsscommon.FieldValuePairs(
[('temperature', str(temperature)),
('minimum_temperature', str(minimum_temperature)),
('maximum_temperature', str(maximum_temperature)),
('high_threshold', str(high_threshold)),
('low_threshold', str(low_threshold)),
('warning_status', str(warning)),
Expand All @@ -553,6 +571,8 @@ class TemperatureUpdater(logger.Logger):
])

self.table.set(name, fvs)
if self.is_chassis_system and self.chassis_table is not None:
self.chassis_table.set(name, fvs)


class ThermalMonitor(ProcessTaskBase):
Expand Down
23 changes: 23 additions & 0 deletions sonic-thermalctld/tests/mock_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class MockThermal:
def __init__(self):
self.name = None
self.temperature = 2
self.minimum_temperature = 1
self.maximum_temperature = 5
self.high_threshold = 3
self.low_threshold = 1
self.high_critical_threshold = 4
Expand All @@ -115,6 +117,12 @@ def get_name(self):
def get_temperature(self):
return self.temperature

def get_minimum_recorded(self):
return self.minimum_temperature

def get_maximum_recorded(self):
return self.maximum_temperature

def get_high_threshold(self):
return self.high_threshold

Expand Down Expand Up @@ -154,6 +162,7 @@ def __init__(self):
self.psu_list = []
self.thermal_list = []
self.fan_drawer_list = []
self.is_chassis_system = False

def get_all_fans(self):
return self.fan_list
Expand All @@ -167,6 +176,9 @@ def get_all_thermals(self):
def get_all_fan_drawers(self):
return self.fan_drawer_list

def get_num_thermals(self):
return len(self.thermal_list)

def make_absence_fan(self):
fan = MockFan()
fan.presence = False
Expand Down Expand Up @@ -220,3 +232,14 @@ def make_error_thermal(self):
thermal = MockErrorThermal()
self.thermal_list.append(thermal)

def is_modular_chassis(self):
return self.is_chassis_system

def set_modular_chassis(self, is_true):
self.is_chassis_system = is_true

def set_my_slot(self, my_slot):
self.my_slot = my_slot

def get_my_slot(self):
return self.my_slot
17 changes: 14 additions & 3 deletions sonic-thermalctld/tests/mock_swsscommon.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
STATE_DB = ''

CHASSIS_STATE_DB = ''

class Table:
def __init__(self, db, table_name):
self.table_name = table_name
self.mock_dict = {}

def _del(self, key):
del self.mock_dict[key]
pass

def set(self, key, fvs):
self.mock_dict[key] = fvs.fv_dict
pass

def get(self, key):
if key in self.mock_dict:
return self.mock_dict[key]
return None

def get_size(self):
return (len(self.mock_dict))

class FieldValuePairs:
def __init__(self, fvs):
pass
def __init__(self, fvs):
self.fv_dict = dict(fvs)
pass
56 changes: 56 additions & 0 deletions sonic-thermalctld/tests/test_thermalctld.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
load_source('thermalctld', scripts_path + '/thermalctld')
from thermalctld import *

TEMPER_INFO_TABLE_NAME = 'TEMPERATURE_INFO'

def setup_function():
FanStatus.log_notice = MagicMock()
Expand Down Expand Up @@ -283,3 +284,58 @@ def test_update_thermal_with_exception():
temperature_updater = TemperatureUpdater(SYSLOG_IDENTIFIER, chassis)
temperature_updater.update()
temperature_updater.log_warning.assert_called()

#Modular chassis related tests
def test_updater_thermal_check_modular_chassis():
chassis = MockChassis()
assert chassis.is_modular_chassis() == False

temperature_updater = TemperatureUpdater(SYSLOG_IDENTIFIER, chassis)
assert temperature_updater.chassis_table == None

chassis.set_modular_chassis(True)
chassis.set_my_slot(-1)
temperature_updater = TemperatureUpdater(SYSLOG_IDENTIFIER, chassis)
assert temperature_updater.chassis_table == None

my_slot = 1
chassis.set_my_slot(my_slot)
temperature_updater = TemperatureUpdater(SYSLOG_IDENTIFIER, chassis)
assert temperature_updater.chassis_table != None
assert temperature_updater.chassis_table.table_name == TEMPER_INFO_TABLE_NAME+'_'+str(my_slot)

def test_updater_thermal_check_chassis_table():
chassis = MockChassis()

thermal1 = MockThermal()
chassis.get_all_thermals().append(thermal1)

chassis.set_modular_chassis(True)
chassis.set_my_slot(1)
temperature_updater = TemperatureUpdater(SYSLOG_IDENTIFIER, chassis)

temperature_updater.update()
assert temperature_updater.chassis_table.get_size() == chassis.get_num_thermals()

thermal2 = MockThermal()
chassis.get_all_thermals().append(thermal2)
temperature_updater.update()
assert temperature_updater.chassis_table.get_size() == chassis.get_num_thermals()

temperature_updater.deinit()
assert temperature_updater.chassis_table.get_size() == 0

def test_updater_thermal_check_min_max():
chassis = MockChassis()

thermal = MockThermal()
chassis.get_all_thermals().append(thermal)

chassis.set_modular_chassis(True)
chassis.set_my_slot(1)
temperature_updater = TemperatureUpdater(SYSLOG_IDENTIFIER, chassis)

temperature_updater.update()
slot_dict = temperature_updater.chassis_table.get('Thermal 1')
assert slot_dict['minimum_temperature'] == str(thermal.get_minimum_recorded())
assert slot_dict['maximum_temperature'] == str(thermal.get_maximum_recorded())