Files
proxmox/scripts/verify/audit-proxmox-operational-template.sh
defiQUG bad8fdc98c
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
scripts: portal login, PMM mesh install, ops template audit, NPM verify, route matrix export
Made-with: Cursor
2026-03-27 18:46:42 -07:00

93 lines
3.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Read-only: compare expected VMIDs from config/proxmox-operational-template.json
# to live Proxmox inventory (pct/qm list) over SSH. No cluster changes.
#
# Usage (from repo root):
# bash scripts/verify/audit-proxmox-operational-template.sh
# SSH_USER=root SSH_OPTS="-o BatchMode=yes" bash scripts/verify/audit-proxmox-operational-template.sh
#
# Env:
# PROXMOX_HOSTS Space-separated IPs (default: sources config/ip-addresses.conf — ML110, R630-01, R630-02)
# SSH_USER default root
# SSH_OPTS extra ssh options (e.g. -i /path/key)
#
# Exit: 0 always (report-only). Prints [MISSING_ON_CLUSTER] / [EXTRA_ON_CLUSTER] when SSH works.
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TEMPLATE_JSON="$PROJECT_ROOT/config/proxmox-operational-template.json"
SSH_USER="${SSH_USER:-root}"
SSH_OPTS="${SSH_OPTS:--o ConnectTimeout=6 -o StrictHostKeyChecking=accept-new}"
cd "$PROJECT_ROOT"
if ! command -v jq &>/dev/null; then
echo "[WARN] jq not installed; install jq to compare VMIDs."
exit 0
fi
if [[ ! -f "$TEMPLATE_JSON" ]]; then
echo "[ERROR] Missing $TEMPLATE_JSON"
exit 1
fi
# shellcheck source=/dev/null
source "$PROJECT_ROOT/config/ip-addresses.conf" 2>/dev/null || true
PROXMOX_HOSTS="${PROXMOX_HOSTS:-${PROXMOX_HOST_ML110:-192.168.11.10} ${PROXMOX_HOST_R630_01:-192.168.11.11} ${PROXMOX_HOST_R630_02:-192.168.11.12}}"
EXPECTED_VMIDS=$(jq -r '.services[] | select(.vmid != null) | .vmid' "$TEMPLATE_JSON" | sort -n | uniq)
echo "=== Proxmox template audit (read-only) ==="
echo "Template: $TEMPLATE_JSON"
echo "Expected VMIDs (non-null): $(echo "$EXPECTED_VMIDS" | wc -l) rows"
echo ""
ALL_LIVE=""
for h in $PROXMOX_HOSTS; do
out=$(ssh $SSH_OPTS "${SSH_USER}@${h}" "pct list 2>/dev/null | awk 'NR>1 {print \$1}'; qm list 2>/dev/null | awk 'NR>1 {print \$1}'" 2>/dev/null || true)
if [[ -z "$out" ]]; then
echo "[SKIP] No inventory from $h (SSH failed or empty)"
continue
fi
echo "--- Live inventory: $h ---"
while IFS= read -r vid; do
[[ -z "${vid:-}" ]] && continue
echo " VMID $vid"
ALL_LIVE+="$vid"$'\n'
done <<< "$out"
done
LIVE_SORTED=$(echo "$ALL_LIVE" | sed '/^$/d' | sort -n | uniq)
if [[ -z "$LIVE_SORTED" ]]; then
echo ""
echo "[INFO] No live VMIDs collected (no SSH to cluster). Run from LAN with keys to Proxmox nodes."
exit 0
fi
echo ""
echo "=== Diff (template expected vs union of live VMIDs) ==="
MISSING=0
while IFS= read -r ev; do
[[ -z "${ev:-}" ]] && continue
if ! echo "$LIVE_SORTED" | grep -qx "$ev"; then
echo "[MISSING_ON_CLUSTER] VMID $ev (in template, not seen on scanned nodes)"
MISSING=$((MISSING + 1))
fi
done <<< "$EXPECTED_VMIDS"
EXTRA=0
while IFS= read -r lv; do
[[ -z "${lv:-}" ]] && continue
if ! echo "$EXPECTED_VMIDS" | grep -qx "$lv"; then
echo "[EXTRA_ON_CLUSTER] VMID $lv (on cluster, not in template services[])"
EXTRA=$((EXTRA + 1))
fi
done <<< "$LIVE_SORTED"
echo ""
echo "Summary: missing_on_template_scan=$MISSING extra_vs_template=$EXTRA"
echo "Note: VMIDs on nodes not scanned (other hosts) appear as MISSING. Expand PROXMOX_HOSTS if needed."