9
9
The loop interval is PSU_INFO_UPDATE_PERIOD_SECS in seconds.
10
10
"""
11
11
12
- import os
13
12
import signal
14
13
import sys
15
14
import threading
16
15
from datetime import datetime
17
16
17
+ from sonic_platform .psu import Psu
18
18
from sonic_py_common import daemon_base , logger
19
-
20
- # If unit testing is occurring, mock swsscommon and module_base
21
- if os .getenv ("PSUD_UNIT_TESTING" ) == "1" :
22
- from tests .mock_platform import MockPsu as Psu
23
- from tests import mock_swsscommon as swsscommon
24
- else :
25
- from sonic_platform .psu import Psu
26
- from swsscommon import swsscommon
19
+ from swsscommon import swsscommon
27
20
28
21
29
22
#
32
25
33
26
# TODO: Once we no longer support Python 2, we can eliminate this and get the
34
27
# name using the 'name' field (e.g., `signal.SIGINT.name`) starting with Python 3.5
35
- SIGNALS_TO_NAMES_DICT = dict ((getattr (signal , n ), n ) \
36
- for n in dir (signal ) if n .startswith ('SIG' ) and '_' not in n )
28
+ SIGNALS_TO_NAMES_DICT = dict ((getattr (signal , n ), n )
29
+ for n in dir (signal ) if n .startswith ('SIG' ) and '_' not in n )
37
30
38
31
SYSLOG_IDENTIFIER = "psud"
39
32
@@ -85,8 +78,11 @@ PSUUTIL_LOAD_ERROR = 1
85
78
platform_psuutil = None
86
79
platform_chassis = None
87
80
81
+ exit_code = 0
88
82
89
83
# temporary wrappers that are compliable with both new platform api and old-style plugin mode
84
+
85
+
90
86
def _wrapper_get_num_psus ():
91
87
if platform_chassis is not None :
92
88
try :
@@ -131,7 +127,7 @@ def psu_db_update(psu_tbl, psu_num):
131
127
psu_tbl .set (get_psu_key (psu_index ), fvs )
132
128
133
129
134
- # try get information from platform API and return a default value if caught NotImplementedError
130
+ # try get information from platform API and return a default value if we catch NotImplementedError
135
131
def try_get (callback , default = None ):
136
132
"""
137
133
Handy function to invoke the callback and catch NotImplementedError
@@ -257,11 +253,10 @@ class PsuChassisInfo(logger.Logger):
257
253
self .master_status_good = master_status_good
258
254
259
255
# Update the PSU master status LED
260
- try :
261
- color = Psu .STATUS_LED_COLOR_GREEN if master_status_good else Psu .STATUS_LED_COLOR_RED
262
- Psu .set_status_master_led (color )
263
- except NotImplementedError :
264
- self .log_warning ("set_status_master_led() not implemented" )
256
+ # set_status_master_led() is a class method implemented in PsuBase
257
+ # so we do not need to catch NotImplementedError here
258
+ color = Psu .STATUS_LED_COLOR_GREEN if master_status_good else Psu .STATUS_LED_COLOR_RED
259
+ Psu .set_status_master_led (color )
265
260
266
261
log_on_status_changed (self , self .master_status_good ,
267
262
'PSU supplied power warning cleared: supplied power is back to normal.' ,
@@ -351,32 +346,21 @@ class DaemonPsud(daemon_base.DaemonBase):
351
346
def __init__ (self , log_identifier ):
352
347
super (DaemonPsud , self ).__init__ (log_identifier )
353
348
354
- self .stop = threading .Event ()
349
+ # Set minimum logging level to INFO
350
+ self .set_min_log_priority_info ()
351
+
352
+ self .stop_event = threading .Event ()
353
+ self .num_psus = 0
355
354
self .psu_status_dict = {}
355
+ self .chassis_tbl = None
356
356
self .fan_tbl = None
357
+ self .psu_tbl = None
357
358
self .psu_chassis_info = None
358
359
self .first_run = True
359
360
360
- # Signal handler
361
- def signal_handler (self , sig , frame ):
362
- if sig == signal .SIGHUP :
363
- self .log_info ("Caught SIGHUP - ignoring..." )
364
- elif sig == signal .SIGINT :
365
- self .log_info ("Caught SIGINT - exiting..." )
366
- self .stop .set ()
367
- elif sig == signal .SIGTERM :
368
- self .log_info ("Caught SIGTERM - exiting..." )
369
- self .stop .set ()
370
- else :
371
- self .log_warning ("Caught unhandled signal '{}'" .format (SIGNALS_TO_NAMES_DICT [sig ]))
372
-
373
- # Run daemon
374
- def run (self ):
375
361
global platform_psuutil
376
362
global platform_chassis
377
363
378
- self .log_info ("Starting up..." )
379
-
380
364
# Load new platform api class
381
365
try :
382
366
import sonic_platform .platform
@@ -394,52 +378,70 @@ class DaemonPsud(daemon_base.DaemonBase):
394
378
395
379
# Connect to STATE_DB and create psu/chassis info tables
396
380
state_db = daemon_base .db_connect ("STATE_DB" )
397
- chassis_tbl = swsscommon .Table (state_db , CHASSIS_INFO_TABLE )
398
- psu_tbl = swsscommon .Table (state_db , PSU_INFO_TABLE )
381
+ self . chassis_tbl = swsscommon .Table (state_db , CHASSIS_INFO_TABLE )
382
+ self . psu_tbl = swsscommon .Table (state_db , PSU_INFO_TABLE )
399
383
self .fan_tbl = swsscommon .Table (state_db , FAN_INFO_TABLE )
400
384
self .phy_entity_tbl = swsscommon .Table (state_db , PHYSICAL_ENTITY_INFO_TABLE )
401
385
402
386
# Post psu number info to STATE_DB
403
- psu_num = _wrapper_get_num_psus ()
404
- fvs = swsscommon .FieldValuePairs ([(CHASSIS_INFO_PSU_NUM_FIELD , str (psu_num ))])
405
- chassis_tbl .set (CHASSIS_INFO_KEY , fvs )
387
+ self . num_psus = _wrapper_get_num_psus ()
388
+ fvs = swsscommon .FieldValuePairs ([(CHASSIS_INFO_PSU_NUM_FIELD , str (self . num_psus ))])
389
+ self . chassis_tbl .set (CHASSIS_INFO_KEY , fvs )
406
390
407
- # Start main loop
408
- self .log_info ("Start daemon main loop" )
391
+ def __del__ (self ):
392
+ # Delete all the information from DB and then exit
393
+ for psu_index in range (1 , self .num_psus + 1 ):
394
+ self .psu_tbl ._del (get_psu_key (psu_index ))
409
395
410
- while not self .stop .wait (PSU_INFO_UPDATE_PERIOD_SECS ):
411
- self ._update_psu_entity_info ()
412
- psu_db_update (psu_tbl , psu_num )
413
- self .update_psu_data (psu_tbl )
414
- self ._update_led_color (psu_tbl )
396
+ self .chassis_tbl ._del (CHASSIS_INFO_KEY )
397
+ self .chassis_tbl ._del (CHASSIS_INFO_POWER_KEY_TEMPLATE .format (1 ))
415
398
416
- if platform_chassis and platform_chassis .is_modular_chassis ():
417
- self .update_psu_chassis_info (chassis_tbl )
399
+ # Override signal handler from DaemonBase
400
+ def signal_handler (self , sig , frame ):
401
+ FATAL_SIGNALS = [signal .SIGINT , signal .SIGTERM ]
402
+ NONFATAL_SIGNALS = [signal .SIGHUP ]
418
403
419
- self . first_run = False
404
+ global exit_code
420
405
421
- self .log_info ("Stop daemon main loop" )
406
+ if sig in FATAL_SIGNALS :
407
+ self .log_info ("Caught signal '{}' - exiting..." .format (SIGNALS_TO_NAMES_DICT [sig ]))
408
+ exit_code = 128 + sig # Make sure we exit with a non-zero code so that supervisor will try to restart us
409
+ self .stop_event .set ()
410
+ elif sig in NONFATAL_SIGNALS :
411
+ self .log_info ("Caught signal '{}' - ignoring..." .format (SIGNALS_TO_NAMES_DICT [sig ]))
412
+ else :
413
+ self .log_warning ("Caught unhandled signal '{}' - ignoring..." .format (SIGNALS_TO_NAMES_DICT [sig ]))
422
414
423
- # Delete all the information from DB and then exit
424
- for psu_index in range (1 , psu_num + 1 ):
425
- psu_tbl ._del (get_psu_key (psu_index ))
415
+ # Main daemon logic
416
+ def run (self ):
417
+ if self .stop_event .wait (PSU_INFO_UPDATE_PERIOD_SECS ):
418
+ # We received a fatal signal
419
+ return False
426
420
427
- chassis_tbl ._del (CHASSIS_INFO_KEY )
428
- chassis_tbl ._del (CHASSIS_INFO_POWER_KEY_TEMPLATE .format (1 ))
421
+ self ._update_psu_entity_info ()
422
+ psu_db_update (self .psu_tbl , self .num_psus )
423
+ self .update_psu_data ()
424
+ self ._update_led_color ()
429
425
430
- self .log_info ("Shutting down..." )
426
+ if platform_chassis and platform_chassis .is_modular_chassis ():
427
+ self .update_psu_chassis_info ()
431
428
432
- def update_psu_data (self , psu_tbl ):
429
+ if self .first_run :
430
+ self .first_run = False
431
+
432
+ return True
433
+
434
+ def update_psu_data (self ):
433
435
if not platform_chassis :
434
436
return
435
437
436
438
for index , psu in enumerate (platform_chassis .get_all_psus ()):
437
439
try :
438
- self ._update_single_psu_data (index + 1 , psu , psu_tbl )
440
+ self ._update_single_psu_data (index + 1 , psu )
439
441
except Exception as e :
440
442
self .log_warning ("Failed to update PSU data - {}" .format (e ))
441
443
442
- def _update_single_psu_data (self , index , psu , psu_tbl ):
444
+ def _update_single_psu_data (self , index , psu ):
443
445
name = get_psu_key (index )
444
446
presence = _wrapper_get_psu_presence (index )
445
447
power_good = False
@@ -517,7 +519,7 @@ class DaemonPsud(daemon_base.DaemonBase):
517
519
(PSU_INFO_POWER_FIELD , str (power )),
518
520
(PSU_INFO_FRU_FIELD , str (is_replaceable )),
519
521
])
520
- psu_tbl .set (name , fvs )
522
+ self . psu_tbl .set (name , fvs )
521
523
522
524
def _update_psu_entity_info (self ):
523
525
if not platform_chassis :
@@ -567,15 +569,15 @@ class DaemonPsud(daemon_base.DaemonBase):
567
569
except NotImplementedError :
568
570
self .log_warning ("set_status_led() not implemented" )
569
571
570
- def _update_led_color (self , psu_tbl ):
572
+ def _update_led_color (self ):
571
573
if not platform_chassis :
572
574
return
573
575
574
576
for index , psu_status in self .psu_status_dict .items ():
575
577
fvs = swsscommon .FieldValuePairs ([
576
578
('led_status' , str (try_get (psu_status .psu .get_status_led , NOT_AVAILABLE )))
577
- ])
578
- psu_tbl .set (get_psu_key (index ), fvs )
579
+ ])
580
+ self . psu_tbl .set (get_psu_key (index ), fvs )
579
581
self ._update_psu_fan_led_status (psu_status .psu , index )
580
582
581
583
def _update_psu_fan_led_status (self , psu , psu_index ):
@@ -588,14 +590,14 @@ class DaemonPsud(daemon_base.DaemonBase):
588
590
])
589
591
self .fan_tbl .set (fan_name , fvs )
590
592
591
- def update_psu_chassis_info (self , chassis_tbl ):
593
+ def update_psu_chassis_info (self ):
592
594
if not platform_chassis :
593
595
return
594
596
595
597
if not self .psu_chassis_info :
596
598
self .psu_chassis_info = PsuChassisInfo (SYSLOG_IDENTIFIER , platform_chassis )
597
599
598
- self .psu_chassis_info .run_power_budget (chassis_tbl )
600
+ self .psu_chassis_info .run_power_budget (self . chassis_tbl )
599
601
self .psu_chassis_info .update_master_status ()
600
602
601
603
@@ -606,8 +608,16 @@ class DaemonPsud(daemon_base.DaemonBase):
606
608
607
609
def main ():
608
610
psud = DaemonPsud (SYSLOG_IDENTIFIER )
609
- psud .run ()
611
+
612
+ psud .log_info ("Starting up..." )
613
+
614
+ while psud .run ():
615
+ pass
616
+
617
+ psud .log_info ("Shutting down..." )
618
+
619
+ return exit_code
610
620
611
621
612
622
if __name__ == '__main__' :
613
- main ()
623
+ sys . exit ( main () )
0 commit comments