NetVM: fleet control script (netvm-fleet.sh) for operators
This commit is contained in:
@@ -5,4 +5,4 @@ designed choice — record the reason.
|
|||||||
|
|
||||||
| node | netns | warp identity | egress IP | tail IP | shared with / reason |
|
| node | netns | warp identity | egress IP | tail IP | shared with / reason |
|
||||||
|------|-------|---------------|-----------|---------|----------------------|
|
|------|-------|---------------|-----------|---------|----------------------|
|
||||||
| laptop (node zero) | — | — | — | — | orchestrator + first node, not yet provisioned |
|
| tp | warp-tp | — | — | — | laptop; orchestrator + first node; identity pending (netvm-new-identity.sh tp) |
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ Tear down: sudo bin/netvm-node-down.sh <node>.
|
|||||||
- bin/netvm-node-down.sh <node> — tear a node's egress down.
|
- bin/netvm-node-down.sh <node> — tear a node's egress down.
|
||||||
- bin/netvm-topology.sh — print the live topology table.
|
- bin/netvm-topology.sh — print the live topology table.
|
||||||
- `bin/netvm-provision-edge.sh` — prepare an edge device (sudoers allowlist, deps, /etc/netvm); run on the node, once.
|
- `bin/netvm-provision-edge.sh` — prepare an edge device (sudoers allowlist, deps, /etc/netvm); run on the node, once.
|
||||||
|
- `bin/netvm-fleet.sh` — operator fleet control over the tailnet (topology/up/down/ssh per node).
|
||||||
- NODES.md — the registry: node -> netns -> Warp identity -> egress IP.
|
- NODES.md — the registry: node -> netns -> Warp identity -> egress IP.
|
||||||
|
|
||||||
## Verification checklist
|
## Verification checklist
|
||||||
|
|||||||
Executable
+59
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# netvm-fleet.sh — operator fleet control over the tailnet.
|
||||||
|
# Run on any tailnet-connected host (laptop, VM) as the operator user.
|
||||||
|
# netvm-fleet.sh topology # egress per node, fleet-wide
|
||||||
|
# netvm-fleet.sh up <node> # bring a node's egress up
|
||||||
|
# netvm-fleet.sh down <node> # bring it down
|
||||||
|
# netvm-fleet.sh ssh <node> # shell on the node
|
||||||
|
# Node names are tailnet hostnames (see NODES.md).
|
||||||
|
# Prereqs: targets provisioned via netvm-provision-edge.sh; this user's SSH
|
||||||
|
# key accepted on targets. Lifecycle runs through the sudoers allowlist
|
||||||
|
# (sudo -n), so it is audit-logged and never blanket root.
|
||||||
|
set -euo pipefail
|
||||||
|
REPO="${NETVM_REPO:-$HOME/Projects/NetVM}"
|
||||||
|
OPERATOR_USER="${OPERATOR_USER:-$(whoami)}"
|
||||||
|
|
||||||
|
nodes() {
|
||||||
|
awk -F'|' '/^\|/ && $2 !~ /node/ && $2 !~ /---/ { n=$2; gsub(/^ +| +$/, "", n); if (n != "") print n }' "$REPO/NODES.md"
|
||||||
|
}
|
||||||
|
|
||||||
|
tail_ip() {
|
||||||
|
NODE="$1" python3 -c "
|
||||||
|
import json, os, subprocess, sys
|
||||||
|
node = os.environ['NODE']
|
||||||
|
st = json.loads(subprocess.run(['tailscale','status','--json'], capture_output=True, text=True).stdout)
|
||||||
|
cands = list(st.get('Peer', {}).values()) + [st.get('Self', {})]
|
||||||
|
for p in cands:
|
||||||
|
names = {p.get('HostName',''), p.get('DNSName','').split('.')[0]}
|
||||||
|
if node in names and p.get('TailscaleIPs'):
|
||||||
|
print(p['TailscaleIPs'][0]); sys.exit(0)
|
||||||
|
sys.exit(1)
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_on() { # <node> <remote-command...>
|
||||||
|
local node="$1"; shift
|
||||||
|
local ip
|
||||||
|
ip=$(tail_ip "$node") || { echo "unknown tailnet node: $node"; exit 1; }
|
||||||
|
ssh -o BatchMode=yes -o ConnectTimeout=15 "${OPERATOR_USER}@${ip}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd="${1:?usage: netvm-fleet.sh topology|up <node>|down <node>|ssh <node>}"
|
||||||
|
case "$cmd" in
|
||||||
|
topology)
|
||||||
|
for n in $(nodes); do
|
||||||
|
printf '== %s ==\n' "$n"
|
||||||
|
run_on "$n" 'sudo -n $HOME/Projects/NetVM/bin/netvm-topology.sh' 2>&1 || echo "unreachable"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
up|down)
|
||||||
|
node="${2:?usage: netvm-fleet.sh $cmd <node>}"
|
||||||
|
run_on "$node" "sudo -n \$HOME/Projects/NetVM/bin/netvm-node-${cmd}.sh ${node}"
|
||||||
|
;;
|
||||||
|
ssh)
|
||||||
|
node="${2:?usage: netvm-fleet.sh ssh <node>}"
|
||||||
|
ip=$(tail_ip "$node") || { echo "unknown tailnet node: $node"; exit 1; }
|
||||||
|
exec ssh "${OPERATOR_USER}@${ip}"
|
||||||
|
;;
|
||||||
|
*) echo "unknown command: $cmd"; exit 1 ;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user