31 lines
2.2 KiB
Python
31 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""b8.py — the household's restore buttons, endpoint-level (the same POSTs the backups pages send), B8.
|
|
b8.py points STACK — the restore points the page offers
|
|
b8.py unit STACK [SNAPSHOT_ID] — „Visszaállítás" (POST /backup/restore), then the status until done
|
|
Env: CTL_BASE, CTL_DOMAIN, CTL_PW_ENV."""
|
|
import json, os, subprocess, sys, time
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))); import ctl
|
|
def say(*a): print(time.strftime("%H:%M:%SZ", time.gmtime()), *a, flush=True)
|
|
def points(stack):
|
|
c, d = ctl.call("GET", f"/api/backup/snapshots?stack={stack}", timeout=90)
|
|
data = d.get("data") if isinstance(d, dict) else None
|
|
return data if isinstance(data, list) else next((data[k] for k in ("snapshots", "items", "restore_points") if isinstance(data, dict) and isinstance(data.get(k), list)), [])
|
|
def unit(stack, sid=None):
|
|
pts = points(stack); say("points offered:", json.dumps(pts, ensure_ascii=False)[:500])
|
|
sid = sid or (pts[0].get("short_id") or pts[0].get("id"))
|
|
if ctl._SESS is None: ctl.login()
|
|
out = subprocess.run(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", ctl.HOST, "-H", "Cookie: " + ctl._SESS, "-X", "POST",
|
|
"--data-urlencode", "_csrf=" + ctl._CSRF, "--data-urlencode", "stack_name=" + stack,
|
|
"--data-urlencode", "snapshot_id=" + sid, ctl.BASE + "/backup/restore"], capture_output=True, text=True).stdout
|
|
say("POST /backup/restore", sid, "->", out.splitlines()[0] if out else "?", [l for l in out.splitlines() if l.lower().startswith("location")][:1])
|
|
t0, last = time.time(), None
|
|
while time.time() - t0 < 1800:
|
|
c, d = ctl.call("GET", "/api/backup/restore-status", timeout=90); dd = (d.get("data") or {}) if isinstance(d, dict) else {}
|
|
s = json.dumps(dd, ensure_ascii=False)[:700]
|
|
if s != last: say("status:", s); last = s
|
|
if not dd.get("running") and time.time() - t0 > 8: break
|
|
time.sleep(5)
|
|
c, d = ctl.call("GET", f"/api/stacks/{stack}"); say("app state:", (d.get("data") or {}).get("state"))
|
|
if __name__ == "__main__":
|
|
{"points": lambda *a: print(json.dumps(points(*a), ensure_ascii=False, indent=1)), "unit": unit}[sys.argv[1]](*sys.argv[2:])
|