@@ -11,6 +11,7 @@ import sys
1111import threading
1212import time
1313from datetime import datetime
14+ import argparse
1415
1516import sonic_platform
1617from sonic_py_common import daemon_base , logger
@@ -435,6 +436,91 @@ class FanUpdater(logger.Logger):
435436 ])
436437 self .drawer_table .set (drawer_name , fvs )
437438
439+ class LiquidCoolingUpdater (threading .Thread , logger .Logger ):
440+
441+ LIQUID_COOLING_INFO_TABLE_NAME = 'LIQUID_COOLING_INFO'
442+
443+ def __init__ (self , chassis , liquid_cooling_update_interval = 0.5 ):
444+ """
445+ Constructor for LiquidCoolingUpdater
446+ :param chassis: Object representing a platform chassis
447+ """
448+ threading .Thread .__init__ (self )
449+ logger .Logger .__init__ (self )
450+ self .name = "LiquidCoolingUpdater"
451+ self .exc = None
452+ self .task_stopping_event = threading .Event ()
453+ self .chassis = chassis
454+ self .liquid_cooling = self .chassis .get_liquid_cooling ()
455+ self .leaking_sensors = []
456+ self .interval = liquid_cooling_update_interval
457+
458+ state_db = daemon_base .db_connect ("STATE_DB" )
459+ self .table = swsscommon .Table (state_db , LiquidCoolingUpdater .LIQUID_COOLING_INFO_TABLE_NAME )
460+
461+ def __del__ (self ):
462+ if self .table :
463+ table_keys = self .table .getKeys ()
464+ for tk in table_keys :
465+ self .table ._del (tk )
466+
467+ def _refresh_leak_status (self ):
468+ for index , sensor in enumerate (self .liquid_cooling .leakage_sensors , start = 1 ):
469+ sensor_name = try_get (sensor .get_name , 'leakage{}' .format (index ))
470+ sensor_leak_status = sensor .is_leak ()
471+ status_msg = "N/A"
472+
473+ if sensor_leak_status is True :
474+ status_msg = "Yes"
475+ if sensor_name not in self .leaking_sensors :
476+ self .leaking_sensors .append (sensor_name )
477+ self .log_error ('Liquid cooling leakage sensor {} reported leaking' .format (sensor_name ))
478+ elif sensor_leak_status is False :
479+ status_msg = "No"
480+ if sensor_name in self .leaking_sensors :
481+ self .leaking_sensors .remove (sensor_name )
482+ self .log_notice ('Liquid cooling leakage sensor {} recovered from leaking' .format (sensor_name ))
483+
484+ fvs = swsscommon .FieldValuePairs ([('leak_status' , status_msg )])
485+ self .table .set (sensor_name , fvs )
486+
487+ def update (self ):
488+ self ._refresh_leak_status ()
489+
490+ def task_worker (self , stopping_event ):
491+ """
492+ Update all liquid cooling information to database
493+ :return:
494+ """
495+ while not stopping_event .is_set ():
496+ self .log_debug ("Start liquid cooling updating" )
497+
498+ self .update ()
499+
500+ self .log_debug ("End liquid cooling updating" )
501+
502+ if self .task_stopping_event .is_set ():
503+ return
504+
505+ time .sleep (self .interval )
506+
507+ def join (self ):
508+ self .task_stopping_event .set ()
509+ super ().join (self )
510+ if self .exc :
511+ raise self .exc
512+
513+ def run (self ):
514+ self .thread_id = threading .current_thread ().ident
515+ if self .task_stopping_event .is_set ():
516+ return
517+ try :
518+ self .task_worker (self .task_stopping_event )
519+ except Exception as e :
520+ logger .log_error ("Exception occured at {} thread due to {}" .format (threading .current_thread ().getName (), repr (e )))
521+ log_exception_traceback ()
522+ self .exc = e
523+ self .task_stopping_event .set ()
438524
439525class TemperatureStatus (logger .Logger ):
440526 TEMPERATURE_DIFF_THRESHOLD = 10
@@ -808,7 +894,7 @@ class ThermalControlDaemon(daemon_base.DaemonBase):
808894
809895 POLICY_FILE = '/usr/share/sonic/platform/thermal_policy.json'
810896
811- def __init__ (self ):
897+ def __init__ (self , enable_liquid_cooling = False , liquid_cooling_update_interval = 0.5 ):
812898 """
813899 Initializer of ThermalControlDaemon
814900 """
@@ -840,6 +926,12 @@ class ThermalControlDaemon(daemon_base.DaemonBase):
840926 except Exception as e :
841927 self .log_error ('Caught exception while initializing thermal manager - {}' .format (repr (e )))
842928
929+ self .liquid_cooling_updater = LiquidCoolingUpdater (self .chassis , liquid_cooling_update_interval ) if enable_liquid_cooling else None
930+
931+ if self .liquid_cooling_updater is not None :
932+ self .liquid_cooling_updater .start ()
933+ self .log_notice ("Started thread for liquid cooling updater" )
934+
843935 def deinit (self ):
844936 """
845937 Deinitializer of ThermalControlDaemon
@@ -852,6 +944,11 @@ class ThermalControlDaemon(daemon_base.DaemonBase):
852944
853945 self .thermal_monitor .task_stop ()
854946
947+ if self .liquid_cooling_updater is not None :
948+ if self .liquid_cooling_updater .is_alive ():
949+ self .liquid_cooling_updater .join ()
950+ self .log_notice ("Joined thread for liquid cooling updater" )
951+
855952 # Override signal handler from DaemonBase
856953 def signal_handler (self , sig , frame ):
857954 """
@@ -912,7 +1009,13 @@ class ThermalControlDaemon(daemon_base.DaemonBase):
9121009# Main =========================================================================
9131010#
9141011def main ():
915- thermal_control = ThermalControlDaemon ()
1012+ parser = argparse .ArgumentParser ()
1013+ parser .add_argument ('--enable_liquid_cooling' , action = 'store_true' )
1014+ parser .add_argument ('--liquid_cooling_update_interval' , type = float )
1015+
1016+ args = parser .parse_args ()
1017+
1018+ thermal_control = ThermalControlDaemon (args .enable_liquid_cooling , args .liquid_cooling_update_interval )
9161019
9171020 thermal_control .log_info ("Starting up..." )
9181021
0 commit comments