From e29a37a23a641f0851b3792252587cad1dfaa385 Mon Sep 17 00:00:00 2001 From: James Antill Date: Tue, 12 Aug 2025 17:20:21 -0400 Subject: [PATCH] updates-uptimes: Add dynamic uptime for main data. Fix cron (sigh 12h fix). Signed-off-by: James Antill --- .../files/ansible-hosts-updates-uptime.cron | 10 ++-- scripts/updates-uptime-cmd.py | 50 +++++++++++++------ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/roles/batcave/files/ansible-hosts-updates-uptime.cron b/roles/batcave/files/ansible-hosts-updates-uptime.cron index 591977e7a6..4086e7c949 100644 --- a/roles/batcave/files/ansible-hosts-updates-uptime.cron +++ b/roles/batcave/files/ansible-hosts-updates-uptime.cron @@ -1,11 +1,15 @@ #! /bin/sh -PATH="$PATH:/usr/local/bin" +uuc="/usr/local/bin/updates-uptime-cmd.py" + +# Make it work in cron... +source /root/sshagent >>/dev/null +export ANSIBLE_HOST_KEY_CHECKING=False # This runs the playbook generate-updates-uptimes-per-host-file.yml # which needs privs. to connect to "all" our hosts. # Don't output anything, because it's a lot of ansible output and it's # mostly fine if nothing happens (we just lose history). # Timeout is set for 1h but it should be much faster (< 5m). -timeout 1h updates-uptime-cmd.py update-daily 2> /dev/null > /dev/null || true - updates-uptime-cmd.py history-keep 2> /dev/null > /dev/null || true +timeout 1h $uuc update-daily 2> /dev/null > /dev/null || true + $uuc history-keep 2> /dev/null > /dev/null || true diff --git a/scripts/updates-uptime-cmd.py b/scripts/updates-uptime-cmd.py index 446f2d4e26..fcedca3a35 100755 --- a/scripts/updates-uptime-cmd.py +++ b/scripts/updates-uptime-cmd.py @@ -6,8 +6,9 @@ # This is very helpful when doing upgrade+reboot runs, as we can easily see # what has/hasn't been upgraded and/or rebooted. +# Examples: ($0 = updates-uptime-cmd.py) # $0 update = create the file and/or do backups -# $0 diff [x] [y] = see the difference between the current state and backups +# $0 diff [x] [y] = see the difference between the current state and history # $0 uptime [x] = see the current state, can be filtered for uptime >= x # $0 info [x] = see the current state, in long form, can be filtered by name # $0 host [x] = see the current state of a host(s), can be filtered by name @@ -16,14 +17,13 @@ # $0 history-keep = clenaup old history # $0 stats [x] = see stats, can specify a backup -# Examples: -# $0 update ... run it daily or so as root. -# $0 diff ... see what changed. # $0 list '*.stg.*' ... see what staging looks like. # $0 list '*copr*' ... see what copr looks like. # $0 history-keep 4 ... keep four days of history (including today) # $0 uptime 1d ... see what hasn't been rebooted in the last 24 hours. -# $0 uptime 25w ... see what hasn't been rebooted in too damn long +# $0 uptime 25w ... see what hasn't been rebooted in too damn long. +# $0 update-daily-refresh ... daily update, including a new history, and +# refresh the main file (so any old hosts aren't there anymore). import os import sys @@ -53,6 +53,10 @@ conf_align_osinfo_small = True # Allow 9,999,999 updates, or try to work out the correct size. conf_fast_width_history = True +# Dynamically change the uptime of hosts based on the time since we looked +# at their uptime. Only for the main file. Assume they are still up etc. +conf_dynamic_main_uptime = True + # Remove suffix noise in names. conf_suffix_dns_replace = { '.fedoraproject.org' : '..org', @@ -396,10 +400,25 @@ def fname2lines(fname): def bfname2lines(b): return fname2lines(fname + '.' + b) +def _maybe_dynamic_uptime(data): + """ Only call this for the main file data. """ + if not conf_dynamic_main_uptime: + return data + + mtime = os.path.getmtime(fname) + since = int(time.time()) - int(mtime) + data = list(sorted(data)) + for d1 in data: + d1.uptime += since + return data + +def fname_datas(): + return _maybe_dynamic_uptime(lines2datas(fname2lines(fname))) + def fname1(): if cmp_arg: - return bfname2lines(cmp) - return fname2lines(fname) + return lines2datas(bfname2lines(cmp)) + return fname_datas() _max_len_name = 0 _max_len_rpms = 0 # Number of rpm updates via. _ui_int(). @@ -565,7 +584,7 @@ if cmd in ("backups", "hist", "history"): ident = _backup_today_identical() print("History:") last_name = "main" - last_data = list(sorted(lines2datas(fname2lines(fname)))) + last_data = list(sorted(fname_datas())) last_suff = "" # We _could_ open+read+etc each file, just to find out the max updates for @@ -664,7 +683,7 @@ def _cli_match_host(data): if cmd == "stats": _cmp_arg() - data = lines2datas(fname1()) + data = fname1() if cmp_arg: sys.argv.pop(1) data = list(_cli_match_host(data)) @@ -775,10 +794,9 @@ if cmd == "stats": _ui_osinfo(a[2]))) _explain_ui_name() -def _print_info(host, lines): +def _print_info(host, data): hosts = [] - for x in lines: - x = line2data(x) + for x in data: if fnmatch.fnmatch(x.name, host): hosts.append(x) if not hosts: @@ -801,7 +819,7 @@ if cmd in ("host", "info"): if len(sys.argv) >= 2 and sys.argv[1] == "all": for b in backups: print("Backup:", b) - _print_info(host, bfname2lines(b)) + _print_info(host, lines2datas(bfname2lines(b))) sys.argv = [sys.argv[0]] print("Main:") _cmp_arg() @@ -821,7 +839,7 @@ if cmd == "list": host = sys.argv.pop(1) _cmp_arg() - data = lines2datas(fname1()) + data = fname1() data = list(filter_name_datas(data, host)) _max_update(data) _max_update_correct('') @@ -835,7 +853,7 @@ if cmd == "uptime": age = parse_duration(sys.argv.pop(1)) _cmp_arg() - data = lines2datas(fname1()) + data = fname1() data = list(filter_uptime_datas(data, age)) _max_update(data) _max_update_correct('') @@ -860,6 +878,8 @@ if cmd in ("diff", "diff-u"): print("diff %s %s" % (fn1, fn2), file=sys.stderr) data1 = list(sorted(lines2datas(data1))) data2 = list(sorted(lines2datas(data2))) + if fn2 == fname: + data2 = _maybe_dynamic_uptime(data2) hosts = _ui_int(len(data2)) updates = _ui_int(sum(d.rpms for d in data2)) ul = len(updates)