78 lines
3.7 KiB
Python
78 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""kept_hint_probe.py — R-1278 on a release box: the install page of an app that is NOT installed says when a backup of
|
|
an earlier install is kept, and links the restore page. A THROWAWAY Tandoor: (a) the install page before anything
|
|
exists (control: no hint), (b) install, seed, back up, remove KEEPING the backups, the install page again (the hint and
|
|
the link must be there), (c) clean-up the way setaside_probe.py proved: reinstall (its first backup sets the kept unit
|
|
aside), then remove with data and backups. Endpoint-level, the requests the pages send. No secret is printed.
|
|
|
|
usage: SC=<dir with .ctlpw> SWEEP_EV=<evidence dir> TARGET=tester-1 python3 kept_hint_probe.py"""
|
|
import json, os, re, sys, time
|
|
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools"))
|
|
import sweep as sw # noqa: E402
|
|
|
|
w, fxm = sw.w, sw.fxm
|
|
APP = "tandoor"
|
|
|
|
|
|
def install_page():
|
|
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip()
|
|
r = w.sh(["curl", "-skL", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}", "-w", "\n%{http_code}", f"{w.BASE}/stacks/{APP}/deploy"])
|
|
body = r.stdout or ""
|
|
code = body.rsplit("\n", 1)[-1]
|
|
m = re.search(r'class="alert alert-info kept-backup-offer" data-kept-backups="(\d+)"', body)
|
|
link = bool(re.search(r'kept-backup-offer.*?href="/backups/restore"', body, re.S))
|
|
return {"http": code, "hint": bool(m), "kept": int(m.group(1)) if m else 0, "link": link}
|
|
|
|
|
|
def main():
|
|
d = os.path.join(sw.EV, "_kepthint")
|
|
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()
|
|
t_start = int(time.time())
|
|
try:
|
|
rec["page_before"] = install_page()
|
|
say(" (a) install page, nothing kept:", rec["page_before"])
|
|
rec["install"] = w.deploy(APP, sub) and w.wait_app(sub, "/", tries=90, delay=5)
|
|
rec["seed"] = bool(fx.seed(w, sub, say))
|
|
sw.backup_now(rec, say)
|
|
sw.remove(APP, keep=True, say=say)
|
|
time.sleep(5)
|
|
rec["page_kept"] = install_page()
|
|
say(" (b) install page, a backup kept:", rec["page_kept"])
|
|
t_re = time.time()
|
|
rec["reinstall"] = w.deploy(APP, sub, dict(w.GENERATED.get(APP) or {}))
|
|
aside = ""
|
|
for _ in range(60):
|
|
time.sleep(10)
|
|
aside = sw.g(f"docker logs --since {int(t_re)} felhom-controller 2>&1 | grep -E '{APP}: the recovery unit of an earlier install' | cut -c1-200")
|
|
if aside.strip():
|
|
break
|
|
rec["set_aside_line"] = aside.strip()
|
|
say(" (c) clean-up: set aside " + ("seen" if aside.strip() else "NOT seen within 10 min"))
|
|
finally:
|
|
sw.remove(APP, keep=False, say=say)
|
|
rec["after_remove"] = sw.leftovers(APP, sub)
|
|
rec["set_aside_after_remove"] = sw.g(f"ls -1 /mnt/*/felhom-data/backups/set-aside/{APP} 2>&1 | head -3").strip()
|
|
rec["primary_after_remove"] = sw.g(f"ls -d /mnt/*/felhom-data/backups/primary/{APP} 2>&1 | head -3").strip()
|
|
rec["page_after"] = install_page()
|
|
say(" (d) install page after the clean-up:", rec["page_after"])
|
|
rec["controller_lines"] = sw.scrub(sw.g(
|
|
f"docker logs --since {t_start} felhom-controller 2>&1 | grep -E '{APP}' | grep -iE 'set aside|kept|R-1278' | cut -c1-240"))
|
|
json.dump(rec, open(os.path.join(d, "record.json"), "w"), ensure_ascii=False, indent=1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|