#!/usr/bin/env python3 """Check the latest backup date. Usage: checkBackup print latest backup date for one container checkBackup -a check all containers returned by activeContainers; status is OK if the latest backup is at most 2 days old, NOK if older or missing """ import subprocess import sys from datetime import date, datetime from pathlib import Path BACKUP_ROOT = Path("/BACKUP") MAX_AGE_DAYS = 2 ACTIVE_CONTAINERS = Path(__file__).resolve().parent / "activeContainers" def check_backup(uuid): """Return (ok, message) for the given UUID.""" directory = BACKUP_ROOT / uuid if not directory.is_dir(): return False, f"ERROR: directory not found for UUID {uuid}" latest_date = None latest_file = None for zip_file in directory.rglob("*.zip"): date_part = zip_file.name.split("_")[0] if len(date_part) != 8 or not date_part.isdigit(): continue if latest_date is None or date_part > latest_date: latest_date = date_part latest_file = zip_file if latest_date is None: return False, "NO BACKUPS" if latest_file.stat().st_size < 1000: return True, "01-01-2000" # Format as yyyy-mm-dd return True, f"{latest_date[:4]}-{latest_date[4:6]}-{latest_date[6:8]}" def is_recent(ok, message): """True if the backup date in message is at most MAX_AGE_DAYS old.""" if not ok: return False try: backup_date = datetime.strptime(message, "%Y-%m-%d").date() except ValueError: # e.g. the "01-01-2000" placeholder for too-small backup files return False return (date.today() - backup_date).days <= MAX_AGE_DAYS def active_uuids(): """UUIDs printed by activeContainers (skips header and separator lines).""" result = subprocess.run( [str(ACTIVE_CONTAINERS)], capture_output=True, text=True ) if result.returncode != 0: print( f"ERROR: activeContainers failed: {result.stderr.strip()}", file=sys.stderr, ) sys.exit(1) lines = result.stdout.splitlines() uuids = [] for line in lines[2:]: # line 0 = header, line 1 = "----" separator fields = line.split() if fields: uuids.append(fields[0]) return uuids def main(): if len(sys.argv) < 2: print("Usage: checkBackup | -a") sys.exit(1) if sys.argv[1] == "-a": rows = [("uuid", "latest", "status")] failed = False for uuid in active_uuids(): ok, message = check_backup(uuid) recent = is_recent(ok, message) rows.append((uuid, message, "OK" if recent else "NOK")) failed = failed or not recent widths = [max(len(row[i]) for row in rows) for i in range(2)] for uuid, message, status in rows: print(f"{uuid:<{widths[0]}} {message:<{widths[1]}} {status}") sys.exit(1 if failed else 0) ok, message = check_backup(sys.argv[1]) print(message) sys.exit(0 if ok else 1) if __name__ == "__main__": main()