Some checks failed
Test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
127 lines
3.2 KiB
Bash
Executable File
127 lines
3.2 KiB
Bash
Executable File
#!/bin/bash
|
|
source ~/.bashrc
|
|
# Proxmox VM Helper Functions
|
|
# Shared library for Proxmox VM operations with guest-agent IP discovery
|
|
|
|
set -euo pipefail
|
|
|
|
# Ensure we're on a Proxmox node
|
|
if ! command -v qm >/dev/null 2>&1; then
|
|
echo "[ERROR] qm command not found. Run this on a Proxmox host." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Ensure jq is installed
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
echo "[ERROR] jq command not found. Install with: apt update && apt install -y jq" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# get_vm_ip_from_guest_agent <vmid>
|
|
#
|
|
# Uses qemu-guest-agent to read network interfaces and returns the first
|
|
# non-loopback IPv4 address. Requires:
|
|
# - qemu-guest-agent installed in the guest
|
|
# - Agent enabled in VM config: qm set <vmid> --agent enabled=1
|
|
#
|
|
# Returns: IP address or empty string if not available
|
|
get_vm_ip_from_guest_agent() {
|
|
local vmid="$1"
|
|
|
|
# This will exit non-zero if guest agent is not running or not enabled
|
|
qm guest cmd "$vmid" network-get-interfaces 2>/dev/null \
|
|
| jq -r '
|
|
.[]?."ip-addresses"[]?
|
|
| select(.["ip-address-type"] == "ipv4"
|
|
and ."ip-address" != "127.0.0.1")
|
|
| ."ip-address"
|
|
' \
|
|
| head -n1 || echo ""
|
|
}
|
|
|
|
# Convenience wrapper that logs and optionally fails
|
|
# get_vm_ip_or_warn <vmid> <name>
|
|
#
|
|
# Returns: IP address or empty string
|
|
# Prints: Warning message if IP not available
|
|
get_vm_ip_or_warn() {
|
|
local vmid="$1"
|
|
local name="$2"
|
|
|
|
local ip
|
|
ip="$(get_vm_ip_from_guest_agent "$vmid" || true)"
|
|
|
|
if [[ -z "$ip" ]]; then
|
|
echo "[WARN] No IP from guest agent for VM $vmid ($name)." >&2
|
|
echo " - Ensure qemu-guest-agent is installed in the guest" >&2
|
|
echo " - Ensure 'Agent' is enabled in VM options" >&2
|
|
echo " - VM must be powered on" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "$ip"
|
|
}
|
|
|
|
# get_vm_ip_or_fallback <vmid> <name> <fallback_ip>
|
|
#
|
|
# Tries guest agent first, falls back to provided IP if agent not available
|
|
# Useful for bootstrap scenarios
|
|
get_vm_ip_or_fallback() {
|
|
local vmid="$1"
|
|
local name="$2"
|
|
local fallback_ip="${3:-}"
|
|
|
|
local ip
|
|
ip="$(get_vm_ip_from_guest_agent "$vmid" || true)"
|
|
|
|
if [[ -n "$ip" ]]; then
|
|
echo "$ip"
|
|
return 0
|
|
fi
|
|
|
|
if [[ -n "$fallback_ip" ]]; then
|
|
echo "[INFO] Guest agent not available for VM $vmid ($name), using fallback IP: $fallback_ip" >&2
|
|
echo "$fallback_ip"
|
|
return 0
|
|
fi
|
|
|
|
echo "[ERROR] No IP available for VM $vmid ($name) (no guest agent, no fallback)" >&2
|
|
return 1
|
|
}
|
|
|
|
# ensure_guest_agent_enabled <vmid>
|
|
#
|
|
# Ensures guest agent is enabled in VM config (doesn't install in guest)
|
|
ensure_guest_agent_enabled() {
|
|
local vmid="$1"
|
|
qm set "$vmid" --agent enabled=1 >/dev/null 2>&1 || true
|
|
}
|
|
|
|
# check_vm_status <vmid>
|
|
#
|
|
# Returns VM status (running, stopped, etc.)
|
|
check_vm_status() {
|
|
local vmid="$1"
|
|
qm status "$vmid" 2>/dev/null | awk '{print $2}' || echo "unknown"
|
|
}
|
|
|
|
# wait_for_guest_agent <vmid> <timeout_seconds>
|
|
#
|
|
# Waits for guest agent to become available
|
|
wait_for_guest_agent() {
|
|
local vmid="$1"
|
|
local timeout="${2:-60}"
|
|
local elapsed=0
|
|
|
|
while [ $elapsed -lt $timeout ]; do
|
|
if get_vm_ip_from_guest_agent "$vmid" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
elapsed=$((elapsed + 2))
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|