Prime, 2026-10-09: "vh gets albok-everything". playbooks/nh3-albok-vh-viewer.yaml joins vh to albok-read, albok-personal and albok-feedback on nh3-albok and authorizes his four Macs' public keys for vh; verified at a fresh login that every wing's .browse/ lists and reads. The withdrawal harness gains a macOS driver (run-mac.sh: every mountable FUSE backend, a read-only smoke of the real wings, results copied back), env overrides for a non-container client, and summarize.py. Sanity-checked as vh from the Linux container before staging.
54 lines
2.0 KiB
Python
Executable File
54 lines
2.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Build a replica of an albok browse view on the share host (nh3-albok).
|
|
|
|
Run ON the server as infra-ops, no sudo:
|
|
ssh infra-ops@10.100.50.44 python3 - < setup-replica.py > manifest.json
|
|
|
|
Why a replica and not the live view: the test renames `.browse/` away. On a live
|
|
wing that rename races albok-service's own link()/unlink() calls, and a failed
|
|
mandatory unlink withholds the wing (BROWSE_WITHHELD marker + a failed write
|
|
transaction). The replica has the same shape as the real view
|
|
(`<wing>/.browse/<locator>` -> relative symlink `../../<id[:2]>/<id>/<blob>`), sits
|
|
on the same filesystem (root ext4), and is served by the same sftp-server, which
|
|
is what the withdrawal property depends on.
|
|
|
|
Content is deterministic per object, so the client can verify bytes without
|
|
fetching a reference copy.
|
|
"""
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import sys
|
|
import uuid
|
|
|
|
# Optional argv[1] places the replica elsewhere (python3 - <root> < setup-replica.py).
|
|
ROOT = sys.argv[1] if len(sys.argv) > 1 else "/home/infra-ops/albok-browse-test/wing"
|
|
COUNT = 60
|
|
SIZE = 1 << 20 # 1 MiB: larger than FUSE readahead, so a late read must reach the server
|
|
|
|
|
|
def content(i: int, oid: str) -> bytes:
|
|
line = f"replica object {i} {oid}\n".encode()
|
|
return (line * (SIZE // len(line) + 1))[:SIZE]
|
|
|
|
|
|
os.makedirs(ROOT, exist_ok=False) # refuse to run over an existing replica
|
|
link_dir = os.path.join(ROOT, ".browse", "stash")
|
|
os.makedirs(link_dir)
|
|
objs = []
|
|
for i in range(COUNT):
|
|
oid = uuid.uuid4().hex
|
|
obj_dir = os.path.join(ROOT, oid[:2], oid)
|
|
os.makedirs(obj_dir)
|
|
name = f"doc{i:02d}.md"
|
|
blob = os.path.join(obj_dir, name)
|
|
data = content(i, oid)
|
|
with open(blob, "wb") as f:
|
|
f.write(data)
|
|
os.chmod(blob, 0o640)
|
|
os.symlink(os.path.relpath(blob, link_dir), os.path.join(link_dir, name))
|
|
objs.append({"i": i, "id": oid, "name": name, "size": SIZE,
|
|
"sha256": hashlib.sha256(data).hexdigest()})
|
|
|
|
print(json.dumps({"root": ROOT, "size": SIZE, "objects": objs}))
|