NA sees every campus; SSH from the admin laptop to every machine
Campuses set up from NA's install line tell NA where they are and learn nothing back (no campus ever shows another). NA alone reads each campus's key states every two seconds and keeps two pages in its Companion (added at the end, 98 and 99, since every other page is in use): CAMPUSES, a key per campus (its ALL key, purple when it stops answering), and CAMPUS, the tapped campus's status page drawn live in the same places, view only. Tried on NA with a test campus pointing at NA itself, then removed. tools/fleet.py: an Apple Remote Desktop command that turns on Remote Login, adds the laptop's key and reports each Mac to NA, and the laptop SSH shortcuts made from those reports (tried on NA Translation). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+34
-1
@@ -40,7 +40,7 @@ from settings import builders
|
||||
from settings import scripts
|
||||
from settings import outlet as outlets
|
||||
from settings import keyguide, probes
|
||||
from settings import campus, discover
|
||||
from settings import campus, campuses, discover
|
||||
|
||||
log = logging.getLogger("status-settings")
|
||||
UI = os.path.join(HERE, "ui")
|
||||
@@ -696,6 +696,15 @@ class Handler(http.server.BaseHTTPRequestHandler):
|
||||
return self.send(200, campus.join_mac(site.load(), self.base_url()), "text/plain; charset=utf-8")
|
||||
if path == "/join.ps1":
|
||||
return self.send(200, campus.join_windows(site.load(), self.base_url()), "text/plain; charset=utf-8")
|
||||
if path == "/api/state":
|
||||
return self.send(200, campuses.state_now(site))
|
||||
if path == "/api/campuses":
|
||||
# The hub's own view (its settings page). A campus only ever lists itself.
|
||||
data = campuses.load(site.data_dir)
|
||||
return self.send(200, {"list": data.get("list") or {}, "pages": data.get("pages") or {} if not data.get("home") else {},
|
||||
"error": data.get("error"), "hub": not data.get("home")})
|
||||
if path == "/api/fleet":
|
||||
return self.send(200, {"machines": list((site.read_json("fleet.json", {}) or {}).values())})
|
||||
if path == "/api/discover":
|
||||
cfg = site.load()
|
||||
base = self.base_url()
|
||||
@@ -873,6 +882,29 @@ class Handler(http.server.BaseHTTPRequestHandler):
|
||||
log.info("joined: %s (%s, %s) from %s", entry["name"], entry["os"], entry["user"], self.client_address[0])
|
||||
site.discover_poke.set()
|
||||
return self.send(200, {"ok": True})
|
||||
if path == "/api/campus/hello":
|
||||
# Another campus says where its settings page is (the hub keeps the list for everyone).
|
||||
cid = str(body.get("id") or "")
|
||||
url = str(body.get("url") or "")
|
||||
if not re.fullmatch(r"[a-z0-9]{1,8}", cid) or not re.fullmatch(r"http://\d{1,3}(\.\d{1,3}){3}:\d{2,5}", url) \
|
||||
or not allowed_client(url[7:].split(":")[0]):
|
||||
return self.send(400, {"error": "an id like ws and an address like http://10.5.1.1:8020"})
|
||||
data = campuses.load(site.data_dir)
|
||||
data.setdefault("list", {})[cid] = {"id": cid, "name": str(body.get("name") or cid)[:40], "url": url}
|
||||
campuses.save(site.data_dir, data)
|
||||
return self.send(200, {"ok": True})
|
||||
if path == "/api/fleet/hello":
|
||||
# A machine anywhere (any campus) says it now takes the admin laptop's key: kept for the
|
||||
# laptop's SSH shortcuts (tools/fleet.py). Nothing here acts on it.
|
||||
try:
|
||||
entry = discover.clean_hello(body, self.client_address[0])
|
||||
except (ValueError, TypeError) as e:
|
||||
return self.send(400, {"error": str(e)})
|
||||
fleet = site.read_json("fleet.json", {}) or {}
|
||||
fleet["%s|%s" % (entry["name"], (entry["ips"] or ["?"])[0])] = entry
|
||||
sp.write_json(os.path.join(site.data_dir, "fleet.json"), fleet)
|
||||
log.info("fleet: %s (%s, %s) from %s", entry["name"], entry["os"], entry["user"], self.client_address[0])
|
||||
return self.send(200, {"ok": True})
|
||||
if path == "/api/editing/check":
|
||||
return self.send(200, site.check_code(self.client_address[0], str(body.get("code", ""))))
|
||||
if path == "/api/machines/probe":
|
||||
@@ -1444,6 +1476,7 @@ def main(argv=None):
|
||||
stop = threading.Event()
|
||||
threading.Thread(target=rebind_loop, args=(site, servers, port, stop), daemon=True).start()
|
||||
threading.Thread(target=campus.loop, args=(site, stop, site.discover_poke), name="auto-setup", daemon=True).start()
|
||||
threading.Thread(target=campuses.loop, args=(site, stop), name="campuses", daemon=True).start()
|
||||
try:
|
||||
while True:
|
||||
time.sleep(3600)
|
||||
|
||||
Reference in New Issue
Block a user