Files
felhom.eu/documentation/audits/persistence-sweep-2026-10-02/tools/r800_live.py
T

42 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""r800_live.py — R-800 / decision 67 on scratch 9202 (controller 0.288.0, the LIVE catalog: MeTube is published): MeTube
installed through the product, one download through its own API, then what the remove dialog reads
(`GET /api/stacks/metube/hdd-data` — the call the dialog makes), the dialog text on the page in both languages, the
remove (with data: R-442 refuses on 9202 — no host agent; keeping data: the result), and the file still there.
Endpoint-level method (no browser on DooPlex). Secrets never printed. Env: SC, EV."""
import json, os, re, subprocess, sys, time
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
import box_walk as w
import upgrade_fixtures_box as fixtures
MT = fixtures.FIXTURES["metube"]
log = open(f"{w.EV}/B/r800-9202.txt", "a", buffering=1)
def say(*a):
w.say(*a); log.write(" ".join(map(str, a)) + "\n")
w.login()
say(f"##### R-800 on 9202 — controller {w.guest('docker inspect felhom-controller --format {{.Config.Image}}').strip()} | catalog "
+ w.guest("cd /var/lib/docker/volumes/felhom-controller-data/_data/data/catalog-cache && git log --oneline -1").strip()[:70]
+ f" | {time.strftime('%FT%TZ', time.gmtime())}")
say("deploy metube ->", w.deploy("metube", "video"))
t = MT.seed(w, "video", say)
say("the seed reads back:", MT.verify(w, "video", t, say) if t else "NO SEED")
f = w.guest("find /mnt/felhom-drives -path '*userdata*metube*' -name '*.mp4' | head -1").strip()
say("the download on the drive:", f)
code, d = w.ctl("GET", "/api/stacks/metube/hdd-data")
say("the dialog's source GET /api/stacks/metube/hdd-data ->", code, json.dumps(d.get("data"), ensure_ascii=False)[:400])
for lang, q, frag in (("hu", "", "fajljaid ezekben a mapp"), ("en", "?lang=en", "Your files in these folders stay")):
page = w.page(f"/stacks{q}")
ascii_page = page.encode("ascii", "ignore").decode()
pos = frag.replace("fajljaid", "fjljaid") if lang == "hu" else frag
say(f" the stacks page ({lang}) carries the dialog line: {pos in ascii_page} | negative control 'no-such-sentence-xyz': {'no-such-sentence-xyz' in ascii_page}")
w.ctl("POST", "/api/stacks/metube/stop")
for _ in range(24):
time.sleep(5)
if w.stack("metube").get("state") != "running": break
code, d = w.ctl("POST", "/api/stacks/metube/remove", {"remove_hdd_data": True, "remove_backups": True})
say("remove WITH data ->", code, str(d)[:220], "(9202 has no host agent: R-442 refuses, app kept — the with-data result is pinned by TestRemoveStack_R800_UserdataKeptIsNamed)")
code, d = w.ctl("POST", "/api/stacks/metube/remove", {"remove_hdd_data": False, "remove_backups": True})
say("remove KEEPING data ->", code, json.dumps(d.get("data"), ensure_ascii=False)[:500])
say("the file after the remove:", "STILL THERE" if w.guest(f"test -f '{f}' && echo yes").strip() == "yes" else "GONE")
w.guest("rm -rf /mnt/felhom-drives/scratch_hdd/userdata/metube")
say("the harness removed its own test folder /mnt/felhom-drives/scratch_hdd/userdata/metube by hand (scratch box)")