office --host with the host table and self-check; board --reset; startup commands written down

This commit is contained in:
Sam
2026-11-12 11:33:47 +11:00
parent e02b04196f
commit 7b2cccf2ff
4 changed files with 142 additions and 4 deletions

View File

@@ -24,6 +24,7 @@ producing a second copy of the same project.
import json
import os
import shlex
import socket
import subprocess
import sys
@@ -167,6 +168,41 @@ exit 0
HOSTS = {
"nixos-desktop": "192.168.20.13", ".13": "192.168.20.13", "13": "192.168.20.13",
"sam-4screen-desktop": "192.168.20.27", "sam-4screen-desktop-1": "192.168.20.27",
".27": "192.168.20.27", "27": "192.168.20.27",
"sam-thinkpad": "192.168.20.51", ".51": "192.168.20.51", "51": "192.168.20.51",
}
def local_addresses():
"""The addresses and names that mean this machine."""
names = {socket.gethostname(), socket.gethostname().split(".")[0]}
try:
out = subprocess.run(["ip", "-4", "-o", "addr", "show", "scope", "global"],
capture_output=True, text=True, timeout=10).stdout
for line in out.splitlines():
parts = line.split()
if len(parts) >= 4:
names.add(parts[3].split("/")[0])
except Exception:
pass
return names
def resolve_host(name):
"""A host name, or the address ssh can actually reach for it."""
if not name:
return ""
return HOSTS.get(name, name)
def is_this_machine(name):
addr = resolve_host(name)
return addr in local_addresses()
def run_on_remote(host, folder, opts):
"""Adopt a folder that lives on another machine, from where you are sitting.
@@ -175,7 +211,13 @@ def run_on_remote(host, folder, opts):
over ssh on that machine, and only the last step — showing the session — is
the client's own business.
"""
here = os.path.dirname(os.path.abspath(__file__))
addr = resolve_host(host)
probe = subprocess.run(["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=8", addr, "true"],
capture_output=True, text=True, timeout=30)
if probe.returncode != 0:
raise h.Refused(3, "cannot log in to %s (%s). Set up a key first: ssh-copy-id %s"
% (host, addr, addr))
here = os.path.dirname(os.path.realpath(__file__))
inner = [os.path.join(here, "office"), folder, "--no-switch"]
for flag, value in (("--project", opts["project"]), ("--session", opts["session"]), ("--new", opts["new"])):
if value:
@@ -184,7 +226,7 @@ def run_on_remote(host, folder, opts):
inner.append("--dry")
cmd = " ".join(shlex.quote(a) for a in inner)
h.say("on %s: %s" % (host, cmd))
out = subprocess.run(["ssh", "-o", "StrictHostKeyChecking=accept-new", host, cmd],
out = subprocess.run(["ssh", "-o", "StrictHostKeyChecking=accept-new", addr, cmd],
capture_output=True, text=True, timeout=600)
sys.stdout.write(out.stdout)
if out.returncode != 0:
@@ -201,6 +243,10 @@ def main():
raise h.Refused(2, "no folder at %s" % folder)
host = opts["host"] or pj.this_machine()
if opts["host"] and not is_this_machine(opts["host"]):
return run_on_remote(opts["host"], folder, opts)
if opts["host"]:
h.say("host: %s (this machine)" % opts["host"])
# An adopted project already knows its session. Only a new one needs a
# default, and a default that names a session nobody made is worse than an
@@ -218,7 +264,11 @@ def main():
# the verb for exactly this; asking the person to run `tuios new` first was
# the step everyone forgot.
if opts["remote"]:
return run_on_remote(opts["remote"], folder, opts)
if is_this_machine(opts["remote"]):
h.say("host: %s (this machine)" % opts["remote"])
opts["remote"] = ""
else:
return run_on_remote(opts["remote"], folder, opts)
if opts["dry"]:
h.say("would create a Paperclip project %r for %s" % (opts["new"] or opts["project"], folder))