106 lines
2.9 KiB
Bash
Executable File
106 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# pct-run — Run commands inside Proxmox CTs by CT ID only. No IPs needed.
|
|
# Usage: pct-run <CT_ID> [command...]
|
|
# If no command given, opens a shell.
|
|
#
|
|
# Source of truth: Proxmox pct config on each node.
|
|
# No hardcoded IPs. No prose contract drift.
|
|
|
|
set -euo pipefail
|
|
|
|
# ── CT ID → PVE Node mapping (maintained HERE, not in prose contracts) ──
|
|
declare -A CT_NODES=(
|
|
# amdpve (192.168.68.15)
|
|
[111]=amdpve # tdunna
|
|
[112]=amdpve # tanko
|
|
[113]=amdpve # baggy
|
|
[115]=amdpve # scottdenya
|
|
# minipve (192.168.68.12)
|
|
[102]=minipve # adguard (was acerpve)
|
|
[104]=minipve # authentik
|
|
[110]=minipve # gitea
|
|
[116]=minipve # syslog-api
|
|
[119]=minipve # infisical-vault
|
|
# storepve (192.168.68.6)
|
|
[106]=storepve # ra-h-os
|
|
[107]=storepve # proxmox-backup
|
|
[108]=storepve # media
|
|
[117]=storepve # zulip
|
|
[118]=storepve # jdownloader
|
|
# acerpve (192.168.68.9) — no CTs (bare metal GPU .8)
|
|
# hwepve (192.168.68.4)
|
|
[100]=hwepve # abiba (was amdpve)
|
|
[105]=hwepve # kagentz (was amdpve)
|
|
[114]=hwepve # mumuni (was minipve)
|
|
# ocupve (192.168.68.5) — no CTs (bare metal GPU .110)
|
|
#
|
|
# REMOVED CTs (migrated to bare metal, decommissioned, or VMs):
|
|
# 101 llm-gpu → bare metal 192.168.68.8 (RTX 3090)
|
|
# 103 ocu-llm → bare metal 192.168.68.110 (RTX 5070)
|
|
# 109 docker-vm → KVM VM 192.168.68.7 (use direct SSH)
|
|
)
|
|
|
|
# Each node must be root-accessible via SSH hostname
|
|
# (Ensure ~/.ssh/config or /etc/hosts has these resolvable)
|
|
|
|
# ── PVE node → IP (needed only because SSH needs an address) ──
|
|
declare -A NODE_IPS=(
|
|
[amdpve]=192.168.68.15
|
|
[minipve]=192.168.68.12
|
|
[storepve]=192.168.68.6
|
|
[acerpve]=192.168.68.9
|
|
[ocupve]=192.168.68.5
|
|
[hwepve]=192.168.68.4
|
|
)
|
|
|
|
resolve_node() {
|
|
local ct_id="$1"
|
|
local node="${CT_NODES[$ct_id]:-}"
|
|
if [[ -z "$node" ]]; then
|
|
echo "ERROR: CT $ct_id not found in mapping" >&2
|
|
exit 1
|
|
fi
|
|
echo "$node"
|
|
}
|
|
|
|
node_ip() {
|
|
local node="$1"
|
|
local ip="${NODE_IPS[$node]:-}"
|
|
if [[ -z "$ip" ]]; then
|
|
echo "ERROR: Node $node not found in IP mapping" >&2
|
|
exit 1
|
|
fi
|
|
echo "$ip"
|
|
}
|
|
|
|
main() {
|
|
if [[ $# -lt 1 ]]; then
|
|
echo "Usage: pct-run <CT_ID> [command...]" >&2
|
|
echo " pct-run 112 cat /etc/hostname" >&2
|
|
echo " pct-run 114 systemctl status hermes-gateway" >&2
|
|
echo ""
|
|
echo "Known CTs:" >&2
|
|
for ct in $(echo "${!CT_NODES[@]}" | tr ' ' '\n' | sort -n); do
|
|
echo " CT $ct → ${CT_NODES[$ct]}" >&2
|
|
done
|
|
exit 1
|
|
fi
|
|
|
|
local ct_id="$1"
|
|
shift
|
|
local node
|
|
node=$(resolve_node "$ct_id")
|
|
local ip
|
|
ip=$(node_ip "$node")
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
# Interactive shell
|
|
exec ssh -t "root@${ip}" "pct enter ${ct_id}"
|
|
else
|
|
# One-shot command
|
|
ssh "root@${ip}" "pct exec ${ct_id} -- $*"
|
|
fi
|
|
}
|
|
|
|
main "$@"
|