"""A4: ONE whole-box backup of demo-hp 9201 by the product's own trigger (POST /api/guest-backup/trigger), polled through /api/guest-backup/status, with the host root disk sampled. Evidence, not product.""" import json, time, subprocess, os os.environ.setdefault("GUEST", "9201") import walk as w OUT = w.EV + "/A/A4-hp-backup-run.txt" def host(cmd): return subprocess.run(["ssh", "hp", "export LC_ALL=C; " + cmd], capture_output=True, text=True, timeout=120).stdout.strip() lines = [] def say(s): s = time.strftime("%H:%M:%S ") + s print(s, flush=True); lines.append(s); open(OUT, "w").write("\n".join(lines) + "\n") w.login() say("root before: " + host("df -B1 / | tail -1")) c, d = w.ctl("POST", "/api/guest-backup/trigger") say(f"POST /api/guest-backup/trigger -> {c} {json.dumps(d, ensure_ascii=False)[:300]}") peak = 0 t0 = time.time() while time.time() - t0 < 3600: time.sleep(20) c, d = w.ctl("GET", "/api/guest-backup/status") used = int(host("df -B1 / | tail -1 | awk '{print $3}'") or 0) peak = max(peak, used) st = json.dumps(d, ensure_ascii=False)[:400] say(f"status {c}: {st} | root used {used}") dd = (d or {}).get("data") or {} if isinstance(dd, dict) and not dd.get("running", dd.get("active", True)) and time.time() - t0 > 60: break say(f"root peak used bytes: {peak}") say("root after: " + host("df -B1 / | tail -1")) say("local archives: " + host("pvesm list local | grep 9201")) say("host journal: " + host("journalctl -u felhom-agent --since '-70min' --no-pager | grep -iE 'vzdump|backup (done|failed|started)|prune|No space' | tail -15")) w.login() c, d = w.ctl("GET", "/api/stacks") say("apps after: " + str([(s['name'], s.get('state')) for s in (d or {}).get('data') or [] if s.get('deployed')]))