@@ -73,6 +73,7 @@ def _wrapper_get_psus_status(psu_index):
73
73
pass
74
74
return platform_psuutil .get_psu_status (psu_index )
75
75
76
+
76
77
#
77
78
# Helper functions =============================================================
78
79
#
@@ -85,6 +86,108 @@ def psu_db_update(psu_tbl, psu_num):
85
86
'true' if _wrapper_get_psus_status (psu_index ) else 'false' )])
86
87
psu_tbl .set (PSU_INFO_KEY_TEMPLATE .format (psu_index ), fvs )
87
88
89
+
90
+ # try get information from platform API and return a default value if caught NotImplementedError
91
+ def try_get (callback , default = None ):
92
+ """
93
+ Handy function to invoke the callback and catch NotImplementedError
94
+ :param callback: Callback to be invoked
95
+ :param default: Default return value if exception occur
96
+ :return: Default return value if exception occur else return value of the callback
97
+ """
98
+ try :
99
+ ret = callback ()
100
+ if ret is None :
101
+ ret = default
102
+ except NotImplementedError :
103
+ ret = default
104
+
105
+ return ret
106
+
107
+ def log_on_status_changed (normal_status , normal_log , abnormal_log ):
108
+ """
109
+ Log when any status changed
110
+ :param normal_status: Expected status.
111
+ :param normal_log: Log string for expected status.
112
+ :param abnormal_log: Log string for unexpected status
113
+ :return:
114
+ """
115
+ if normal_status :
116
+ logger .log_notice (normal_log )
117
+ else :
118
+ logger .log_warning (abnormal_log )
119
+
120
+ #
121
+ # PSU status ===================================================================
122
+ #
123
+
124
+ class PsuStatus (object ):
125
+ update_led_color = True
126
+
127
+ def __init__ (self , psu ):
128
+ self .psu = psu
129
+ self .presence = True
130
+ self .power_good = True
131
+ self .voltage_good = True
132
+ self .temperature_good = True
133
+
134
+ def set_presence (self , presence ):
135
+ """
136
+ Set and cache PSU presence status
137
+ :param presence: PSU presence status
138
+ :return: True if status changed else False
139
+ """
140
+ if presence == self .presence :
141
+ return False
142
+
143
+ self .presence = presence
144
+ return True
145
+
146
+ def set_power_good (self , power_good ):
147
+ """
148
+ Set and cache PSU power good status
149
+ :param power_good: PSU power good status
150
+ :return: True if status changed else False
151
+ """
152
+ if power_good == self .power_good :
153
+ return False
154
+
155
+ self .power_good = power_good
156
+ return True
157
+
158
+ def set_voltage (self , voltage , high_threshold , low_threshold ):
159
+ if not voltage or not high_threshold or not low_threshold :
160
+ if self .voltage_good is not True :
161
+ logger .log_warning ('PSU voltage or high_threshold or low_threshold become unavailable, '
162
+ 'voltage={}, high_threshold={}, low_threshold={}' .format (voltage , high_threshold , low_threshold ))
163
+ self .voltage_good = True
164
+ return False
165
+
166
+ voltage_good = (low_threshold <= voltage <= high_threshold )
167
+ if voltage_good == self .voltage_good :
168
+ return False
169
+
170
+ self .voltage_good = voltage_good
171
+ return True
172
+
173
+ def set_temperature (self , temperature , high_threshold ):
174
+ if not temperature or not high_threshold :
175
+ if self .temperature_good is not True :
176
+ logger .log_warning ('PSU temperature or high_threshold become unavailable, '
177
+ 'temperature={}, high_threshold={}' .format (temperature , high_threshold ))
178
+ self .temperature_good = True
179
+ return False
180
+
181
+ temperature_good = (temperature < high_threshold )
182
+ if temperature_good == self .temperature_good :
183
+ return False
184
+
185
+ self .temperature_good = temperature_good
186
+ return True
187
+
188
+ def is_ok (self ):
189
+ return self .presence and self .power_good and self .voltage_good and self .temperature_good
190
+
88
191
#
89
192
# Daemon =======================================================================
90
193
#
@@ -94,6 +197,7 @@ class DaemonPsud(DaemonBase):
94
197
DaemonBase .__init__ (self )
95
198
96
199
self .stop = threading .Event ()
200
+ self .psu_status_dict = {}
97
201
98
202
# Signal handler
99
203
def signal_handler (self , sig , frame ):
@@ -145,6 +249,8 @@ class DaemonPsud(DaemonBase):
145
249
146
250
while not self .stop .wait (PSU_INFO_UPDATE_PERIOD_SECS ):
147
251
psu_db_update (psu_tbl , psu_num )
252
+ self .update_psu_data ()
253
+ self ._update_led_color (psu_tbl )
148
254
149
255
logger .log_info ("Stop daemon main loop" )
150
256
@@ -156,6 +262,96 @@ class DaemonPsud(DaemonBase):
156
262
157
263
logger .log_info ("Shutting down..." )
158
264
265
+ def update_psu_data (self ):
266
+ if not platform_chassis :
267
+ return
268
+
269
+ for index , psu in enumerate (platform_chassis .get_all_psus ()):
270
+ try :
271
+ self ._update_single_psu_data (index + 1 , psu )
272
+ except Exception as e :
273
+ logger .log_warning ("Failed to update PSU data - {}" .format (e ))
274
+
275
+ def _update_single_psu_data (self , index , psu ):
276
+ name = try_get (psu .get_name )
277
+ if not name :
278
+ name = PSU_INFO_KEY_TEMPLATE .format (index )
279
+ presence = _wrapper_get_psus_presence (index )
280
+ power_good = False
281
+ voltage = None
282
+ voltage_high_threshold = None
283
+ voltage_low_threshold = None
284
+ temperature = None
285
+ temperature_threshold = None
286
+ if presence :
287
+ power_good = _wrapper_get_psus_status (index )
288
+ voltage = try_get (psu .get_voltage )
289
+ voltage_high_threshold = try_get (psu .get_voltage_high_threshold )
290
+ voltage_low_threshold = try_get (psu .get_voltage_low_threshold )
291
+ temperature = try_get (psu .get_temperature )
292
+ temperature_threshold = try_get (psu .get_temperature_high_threshold )
293
+
294
+ if index not in self .psu_status_dict :
295
+ self .psu_status_dict [index ] = PsuStatus (psu )
296
+
297
+ psu_status = self .psu_status_dict [index ]
298
+ set_led = False
299
+ if psu_status .set_presence (presence ):
300
+ set_led = True
301
+ log_on_status_changed (psu_status .presence ,
302
+ 'PSU absence warning cleared: {} is inserted back.' .format (name ),
303
+ 'PSU absence warning: {} is not present.' .format (name )
304
+ )
305
+
306
+ if presence and psu_status .set_power_good (power_good ):
307
+ set_led = True
308
+ log_on_status_changed (psu_status .power_good ,
309
+ 'Power absence warning cleared: {} power is back to normal.' .format (name ),
310
+ 'Power absence warning: {} is out of power.' .format (name )
311
+ )
312
+
313
+ if presence and psu_status .set_voltage (voltage , voltage_high_threshold , voltage_low_threshold ):
314
+ set_led = True
315
+ log_on_status_changed (psu_status .voltage_good ,
316
+ 'PSU voltage warning cleared: {} voltage is back to normal.' .format (name ),
317
+ 'PSU voltage warning: {} voltage out of range, current voltage={}, valid range=[{}, {}].' .format (name , voltage , voltage_high_threshold , voltage_low_threshold )
318
+ )
319
+
320
+ if presence and psu_status .set_temperature (temperature , temperature_threshold ):
321
+ set_led = True
322
+ log_on_status_changed (psu_status .temperature_good ,
323
+ 'PSU temperature warning cleared: {} temperature is back to normal.' .format (name ),
324
+ 'PSU temperature warning: {} temperature too hot, temperature={}, threshold={}.' .format (name , temperature , temperature_threshold )
325
+ )
326
+
327
+ if set_led :
328
+ PsuStatus .update_led_color = True
329
+ self ._set_psu_led (psu , psu_status )
330
+
331
+ def _set_psu_led (self , psu , psu_status ):
332
+ try :
333
+ color = psu .STATUS_LED_COLOR_GREEN if psu_status .is_ok () else psu .STATUS_LED_COLOR_RED
334
+ psu .set_status_led (color )
335
+ except NotImplementedError as e :
336
+ pass
337
+
338
+ def _update_led_color (self , psu_tbl ):
339
+ if not platform_chassis :
340
+ return
341
+
342
+ if PsuStatus .update_led_color :
343
+ for index , psu_status in self .psu_status_dict .items ():
344
+ try :
345
+ fvs = swsscommon .FieldValuePairs ([
346
+ ('led_status' , str (try_get (psu_status .psu .get_status_led )))
347
+ ])
348
+ except Exception as e :
349
+ logger .log_warning ('Failed to get led status for psu {}' .format (index ))
350
+ fvs = swsscommon .FieldValuePairs ([
351
+ ('led_status' , NOT_AVAILABLE )
352
+ ])
353
+ psu_tbl .set (PSU_INFO_KEY_TEMPLATE .format (index ), fvs )
354
+ PsuStatus .update_led_color = False
159
355
#
160
356
# Main =========================================================================
161
357
#
0 commit comments