Every campus matches NA, tailored: Restart page, Companion-Mac programs, NA's auto-fix hours, nightly backups, restart from NA
- Auto-setup: programs on the Companion Mac itself (ProPresenter at Woonsocket) get a local process check and local start/restart fixes; every campus gets a Restart page (keys arrive as computers join); NA's auto-fix hours (Tue, Wed, Sun); a program found after its Companion connection joins that key instead of making a second one. settings.campus rebuild remakes a campus from what is found now, keeping its name, PIN and pages; upgrade-companion brings Companion to 5.0.7 from NA's copy (/campus/companion.zip), as Woonsocket was; setup stops with that advice on an older one. - NA's CAMPUSES page has a RESTART key per campus; the CAMPUS page shows that campus's Restart page and a hold there restarts it at that campus. - Backups: backup/backup-campuses.sh, nightly 04:30 on NA (installed everywhere, acts on the hub), into Drive > Waters Creative > Apps > Status Panel Backups/<campus>, 30 kept, alert email via the checklist's alert.js. Campuses report the account to back up with. sites/ws/config.json in the repo. - Woonsocket rebuilt: 9 keys (PROP with ProPresenter on its Mac), Restart page 20 (SUPERRACK, VISTA, ABLETON, PROP), auto-fix on NA's hours; all OK. Both campuses backed up to Drive by the job. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+41
-5
@@ -86,8 +86,11 @@ SHARED_FIXES = {
|
||||
}
|
||||
|
||||
STATUS_ROWS, COLS = 4, 8
|
||||
# North Attleboro's auto-fix hours, for every campus: Tuesday and Wednesday rehearsals, Sunday services.
|
||||
DEFAULT_AUTO_FIX = {"after_seconds": 20, "max_tries": 2, "retry_seconds": 90, "pause_after_network_seconds": 60,
|
||||
"restart_connections": True, "windows": [{"days": ["sun"], "start": "05:00", "end": "14:00"}]}
|
||||
"restart_connections": True, "windows": [{"days": ["tue"], "start": "14:00", "end": "22:00"},
|
||||
{"days": ["wed"], "start": "09:00", "end": "21:00"},
|
||||
{"days": ["sun"], "start": "05:00", "end": "14:00"}]}
|
||||
|
||||
|
||||
# --- small helpers ---------------------------------------------------------------------
|
||||
@@ -218,6 +221,27 @@ def items(inv, nets):
|
||||
apps_at[(a["app"], c.get("ip"))] = item
|
||||
for ip in c.get("ips") or []:
|
||||
apps_at.setdefault((a["app"], ip), item)
|
||||
# Programs on this Mac itself (the Companion Mac): a local process check and local start/restart fixes.
|
||||
ing = inv.get("ingest") or {}
|
||||
for a in MAC_APPS:
|
||||
exe = (ing.get("exes") or {}).get(a["process"])
|
||||
app_path = (ing.get("paths") or {}).get(a["process"])
|
||||
if not exe or not app_path:
|
||||
continue
|
||||
fid = slug("%s_ingest" % a["app"])
|
||||
pretty = a["label"].title() if a["app"] not in ("propresenter", "ableton") else {"propresenter": "ProPresenter", "ableton": "Ableton"}[a["app"]]
|
||||
start = {"template": "mac_start", "params": {"host": "ingest", "process": a["process"], "app": app_path},
|
||||
"label": "start %s on this Mac if it is not running" % pretty, "short": a["label"]}
|
||||
again = {"template": "mac_restart", "params": {"host": "ingest", "process": a["process"], "app": app_path, "wait_seconds": 10, "force": True},
|
||||
"label": "restart %s on this Mac (closes it first)" % pretty, "short": a["label"]}
|
||||
item = {"ident": "app:ingest|%s" % a["process"], "group": a.get("group") or ("VIDEO" if a["app"] == "arena" else "STREAM" if a["app"] == "obs" else "SHOW"),
|
||||
"label": a["label"], "checks": [{"type": "process", "match": exe, "name": a["label"], "fix": fid}],
|
||||
"fixes": {fid: start, "restart_" + fid: again}, "restart": [{"label": a["label"], "fix": "restart_" + fid}] if a.get("restart") else [],
|
||||
"also": [], "fold": a.get("fold")}
|
||||
out.append(item)
|
||||
for ip in [(ing.get("wired") or {}).get("ip")] + list(ing.get("ips") or []) + ["127.0.0.1"]:
|
||||
if ip:
|
||||
apps_at.setdefault((a["app"], ip), item)
|
||||
# Companion connections.
|
||||
counts = {}
|
||||
for conn in inv.get("connections") or []:
|
||||
@@ -343,7 +367,7 @@ def layout(cfg, new_tiles, restart_items):
|
||||
"""Put the keys on the Status page: everything fits, so no group keys; otherwise group keys along
|
||||
the top row and the members after them (a member with no room left shows inside its group only)."""
|
||||
fixed = {tuple(t["pos"]) for t in cfg["tiles"] if t.get("pos")}
|
||||
if restart_items:
|
||||
if cfg.get("restart_page"):
|
||||
fixed.add(tuple(cfg["restart_page"]["jump_pos"]))
|
||||
cells = free_cells(fixed)
|
||||
groups = [g for g in GROUPS if any(t["_group"] == g for t in new_tiles)]
|
||||
@@ -386,10 +410,10 @@ def place_new(cfg, tile):
|
||||
|
||||
|
||||
def restart_layout(cfg, restart_items):
|
||||
if not restart_items:
|
||||
cfg.pop("restart_page", None)
|
||||
"""The Restart page always exists (a campus set up before its computers joined gets their keys later)."""
|
||||
rp = cfg.get("restart_page")
|
||||
if not rp:
|
||||
return
|
||||
rp = cfg["restart_page"]
|
||||
taken = {tuple(rp["back_pos"])} | {tuple(k["pos"]) for k in rp.get("keys", [])}
|
||||
cells = free_cells(taken)
|
||||
ids = {k["id"] for k in rp.get("keys", [])}
|
||||
@@ -474,6 +498,18 @@ def extend(cfg, inv, seen):
|
||||
continue
|
||||
if any(c.get("params", {}).get("host") not in cfg["hosts"] for c in it["checks"] if c.get("template")):
|
||||
continue
|
||||
# A program whose Companion connection already has a key (Woonsocket's PROP got a second key):
|
||||
# its own checks join that key.
|
||||
home = next((t for t in cfg["tiles"] if any(("conn:" + c.get("conn", "")) in it["also"] for c in t.get("checks", []) if c.get("conn"))), None)
|
||||
if home is not None:
|
||||
for fid, f in it["fixes"].items():
|
||||
cfg["fixes"].setdefault(fid, f)
|
||||
home["checks"] += [c for c in it["checks"] if not c.get("conn")]
|
||||
if it["restart"] and cfg.get("restart_page"):
|
||||
restart_layout(cfg, it["restart"])
|
||||
added.append("%s checks on the %s key" % (key_text(it["label"]), home["label"]))
|
||||
now_seen += [it["ident"]] + it["also"]
|
||||
continue
|
||||
tid = slug(it["label"], taken)
|
||||
taken.add(tid)
|
||||
for fid, f in it["fixes"].items():
|
||||
|
||||
Reference in New Issue
Block a user