Files
felhom.eu/documentation/audits/release-2026-10-26/tools/stableprobe.py
T

56 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""stableprobe.py — fix A, the healthy half: a normal unit restore of a healthy throwaway app → the page says success,
the undo copy is there right after, and gone after the 3-minute stable window. The controller's DEBUG lines say why
any sample was not ok. usage: SC=… SWEEP_EV=… TARGET=9202 python3 stableprobe.py <app>"""
import json, os, sys, time
TOOLS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools")
sys.path.insert(0, TOOLS)
import sweep as sw # noqa: E402
w, fxm = sw.w, sw.fxm
def main(app):
d = os.path.join(sw.EV, "stableprobe", 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)
undo = f"/mnt/sys_drive/felhom-data/backups/restore-undo/{app}"
rec = {}
t0 = int(time.time())
w.login()
try:
rec["install"] = w.deploy(app, sub) and w.wait_app(sub, "/", tries=90, delay=5)
tok = fx.seed(w, sub, say)
sw.backup_now(rec, say)
sw.restore_unit(app, rec, say)
say(" restore: " + rec["restore"].get("status", "")[:400])
rec["copy_right_after"] = sw.g(f"ls -1 {undo} 2>&1").strip()
say(" the copy right after: " + rec["copy_right_after"])
for _ in range(36):
time.sleep(10)
if "No such file" in sw.g(f"ls -1 {undo} 2>&1"):
break
rec["copy_after_window"] = sw.g(f"ls -1 {undo} 2>&1").strip()
rec["item"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
say(f" the copy after the window: {rec['copy_after_window']}; item {rec['item']}")
finally:
rec["lines"] = sw.scrub(sw.g(f"docker logs --since {t0} felhom-controller 2>&1 | grep -E 'stable-start sample {app}|{app}: ran stably|{app}.*not start|{app}.*did not run stably|Restore-from-unit completed: {app}' | cut -c1-260 | head -40"))
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)
if __name__ == "__main__":
main(sys.argv[1])