@@ -224,6 +224,70 @@ def get_params(self) -> Tuple:
224224 return (self .path ,)
225225
226226
227+ @register
228+ class MonitorNUT (Monitor ):
229+ """Check a NUT UPS"""
230+
231+ monitor_type = "nut"
232+
233+ def __init__ (self , name : str , config_options : dict ) -> None :
234+ super ().__init__ (name , config_options )
235+ self .ups = cast (
236+ str , self .get_config_option ("ups" , required = True , allow_empty = False )
237+ )
238+
239+ def run_test (self ) -> bool :
240+ info = {}
241+ try :
242+ _output = subprocess .check_output (["upsc" , self .ups ]) # nosec
243+ output = _output .decode ("utf-8" ) # type: str
244+ except subprocess .CalledProcessError as error :
245+ output = error .output
246+ except OSError as error :
247+ return self .record_fail (f"Could not run upsc: { error } " )
248+ except Exception as error :
249+ return self .record_fail (f"Error while getting UPS info: { error } " )
250+
251+ for line in output .splitlines ():
252+ if line .find (":" ) > - 1 :
253+ bits = line .split (":" )
254+ info [bits [0 ].strip ()] = bits [1 ].strip ()
255+
256+ try :
257+ ups_status = cast (str , info ["ups.status" ])
258+ except KeyError :
259+ return self .record_fail ("Could not get UPS status" )
260+
261+ status_tokens = ups_status .split ()
262+ ok = True
263+ message : list [str ] = []
264+ if "OB" in status_tokens :
265+ message .append ("UPS is on battery" )
266+ ok = False
267+ if "OL" in status_tokens :
268+ message .append ("online" )
269+ if "RB" in status_tokens :
270+ message .append ("battery needs replacing!" )
271+ ok = False
272+ if "ups.load" in info :
273+ message .append (f"load: { info ['ups.load' ]} %" )
274+ if "battery.charge" in info :
275+ message .append (f"charge: { info ['battery.charge' ]} " )
276+ if "battery.runtime" in info :
277+ message .append (f"runtime: { info ['battery.runtime' ]} " )
278+
279+ message_str = "; " .join (message )
280+ if ok :
281+ return self .record_success (message_str )
282+ return self .record_fail (message_str )
283+
284+ def describe (self ) -> str :
285+ return f"Monitoring UPS { self .ups } to make sure it's online"
286+
287+ def get_params (self ) -> Tuple :
288+ return (self .ups ,)
289+
290+
227291@register
228292class MonitorPortAudit (Monitor ):
229293 """Check a host doesn't have outstanding security issues."""
0 commit comments