#!/usr/bin/env python3 import argparse import sys import time import traceback from datetime import datetime, timedelta import humanize from checker import nagios from checker.result import quit_check sys.path.insert(0, "/usr/lib/python3/dist-packages") import dbus def check_timer(timer_name): if not timer_name.endswith('.timer'): timer_name = timer_name + '.timer' try: system_bus = dbus.SystemBus() systemd1 = system_bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1') manager = dbus.Interface(systemd1, 'org.freedesktop.systemd1.Manager') timer_unit_path = manager.GetUnit(timer_name) timer_unit = system_bus.get_object('org.freedesktop.systemd1', timer_unit_path) timer_properties = dbus.Interface(timer_unit, 'org.freedesktop.DBus.Properties') active_state = timer_properties.Get('org.freedesktop.systemd1.Unit', 'ActiveState') if active_state == 'active': next_elapse = timer_properties.Get('org.freedesktop.systemd1.Timer', 'NextElapseUSecRealtime') try: local_timezone_offset_seconds = time.localtime().tm_gmtoff local_timezone_offset = timedelta(seconds=local_timezone_offset_seconds) local_datetime = datetime.utcfromtimestamp(int(next_elapse) / 1e6) + local_timezone_offset next_elapse_str = local_datetime.strftime("%m-%d-%Y %H:%M") except ValueError as v_err: if 'is out of range' in repr(v_err): # This occurs whenever the timer resets. # "year 586524 is out of range" print(f'OK - {timer_name} has triggered.') sys.exit(nagios.STATE_OK) current_time = time.time() * 1e6 # convert current time to microseconds remaining_time_sec = int((next_elapse - current_time) / 1e6) # convert remaining time to seconds remaining_time_human = str(humanize.naturaltime(datetime.now() + timedelta(seconds=remaining_time_sec))).strip(' from now') perfdata_dict = { 'remaining_time': { 'value': remaining_time_sec, 'unit': 's', 'min': 0 } } quit_check(f'{timer_name} is active. Trigger time: {next_elapse_str}. Remaining time: {remaining_time_human}.', nagios.STATE_OK, perfdata_dict) else: quit_check(f'{timer_name} is not active.', nagios.STATE_CRIT) except dbus.exceptions.DBusException: quit_check(f'{timer_name} could not be found.', nagios.STATE_UNKNOWN) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-t', '--timer', required=True, help='The name of the timer to check.') parser.add_argument('-l', '--last-ran-delta', help='The associated service should have been triggered at least this many seconds ago.') args = parser.parse_args() try: check_timer(args.timer) except Exception as e: print(f'UNKNOWN - exception "{e}"') traceback.print_exc() sys.exit(nagios.STATE_UNKNOWN)