gates / gates (push) Successful in 13m17s
Every catalog app installed, used, backed up, removed keeping data, reinstalled, restored and removed with data on a fresh box from the public ISO (demo-hp VM 9360, Tester4), endpoint-level. Worst: a reinstall's capture rewrites the kept unit so its restore breaks the app (R-1269, P2), the restore still reports success (R-1270, P2), and „use my kept data" loaded another box's future-dated database (R-1271, P2). Drill catalog fixes for the morning list (n8n usage data; OpenGist 256M, proven by a cgroup probe). VM 9360 and LXC 9361 destroyed; hub host Tester4-aa9466 left for the operator. REPORT-catalog-sweep-2026-10-24.md.
61 lines
2.7 KiB
Python
61 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""putback.py — D22 (the put-back covers every restore) on the sweep box, the 10-21 night's method
|
|
(`audits/night-2026-10-21/P3-restore/`): install, seed one item through the front door, „Mentés most", then the FAULT —
|
|
the recovery unit's largest volume archive truncated to half (a damaged backup, the only hand-made change) — then the
|
|
household's „Visszaállítás" of that unit. Expected: the restore reports failure, the LIVE data and definition are put
|
|
back, the app runs, and the item reads back. Then remove with data.
|
|
|
|
usage: SC=… SWEEP_EV=… DRIVE_ROOT=… python3 putback.py <app> (evidence: <SWEEP_EV>/_putback/<app>/)
|
|
"""
|
|
import json, os, sys, time
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
import sweep as sw # noqa: E402
|
|
|
|
w, fxm = sw.w, sw.fxm
|
|
|
|
|
|
def main(app):
|
|
d = os.path.join(sw.EV, "_putback", app)
|
|
os.makedirs(d, exist_ok=True)
|
|
log = open(os.path.join(d, "walk.log"), "a")
|
|
|
|
def say(*a):
|
|
line = time.strftime("%H:%M:%SZ", time.gmtime()) + " " + " ".join(str(x) for x in a)
|
|
print(line, flush=True)
|
|
log.write(sw.scrub(line) + "\n")
|
|
log.flush()
|
|
|
|
w.say = say
|
|
fx = fxm.FIXTURES[app]
|
|
sub = getattr(fx, "sub", app)
|
|
rec = {"app": app}
|
|
w.login()
|
|
try:
|
|
rec["install"] = w.deploy(app, sub) and w.wait_app(sub, "/", tries=90, delay=5)
|
|
tok = fx.seed(w, sub, say)
|
|
rec["seed"] = bool(tok)
|
|
sw.backup_now(rec, say)
|
|
units = sw.g(f"ls -la --time-style=+%T /mnt/sys_drive/felhom-data/backups/primary/{app}/volume-dumps/ 2>&1")
|
|
say(" unit before the fault:\n" + units)
|
|
big = sw.g(f"ls -S /mnt/sys_drive/felhom-data/backups/primary/{app}/volume-dumps/*.tar 2>/dev/null | head -1").strip()
|
|
size = sw.g(f"stat -c %s {big}").strip()
|
|
sw.g(f"truncate -s $(( {size} / 2 )) {big}")
|
|
after = sw.g(f"stat -c %s {big}").strip()
|
|
say(f" THE FAULT: {big} {size} -> {after}")
|
|
rec["fault"] = {"file": big, "from": size, "to": after}
|
|
sw.restore_unit(app, rec, say)
|
|
rec["state_after"] = w.stack(app).get("state")
|
|
rec["item_after"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
|
|
rec["controller_log"] = sw.g("docker logs --since 10m felhom-controller 2>&1 | grep -iE 'put back|R-893|restore failed|put-back' | tail -5")
|
|
say(" controller: " + rec["controller_log"].strip()[:600])
|
|
finally:
|
|
sw.remove(app, keep=False, say=say)
|
|
rec["after_remove"] = sw.leftovers(app, sub)
|
|
json.dump(rec, open(os.path.join(d, "record.json"), "w"), ensure_ascii=False, indent=1)
|
|
say(" == putback " + json.dumps({k: rec.get(k) for k in ("seed", "state_after", "item_after")}))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv[1])
|