mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-06-11 19:07:01 +00:00
98 lines
3.6 KiB
Bash
98 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
|
# ==========================================================
|
|
# ProxMenux backup manifest collector — vms_lxcs_at_backup
|
|
# ==========================================================
|
|
# Enumerates VMs (qm list) and LXCs (pct list) on this PVE node.
|
|
# Read-only; emits the metadata only — actual VM/LXC data is
|
|
# the responsibility of vzdump / PBS, not this manifest.
|
|
# Schema: scripts/backup_restore/schema/manifest.schema.json
|
|
# ==========================================================
|
|
set -euo pipefail
|
|
|
|
vms='[]'
|
|
lxcs='[]'
|
|
|
|
# ── VMs (qm list) ──
|
|
# Output:
|
|
# VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID
|
|
# 100 Alpine-Linux-3-21 stopped 4096 0.00 0
|
|
# Header line starts with VMID; we skip it.
|
|
if command -v qm >/dev/null 2>&1; then
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
# Skip the header
|
|
[[ "$line" =~ ^[[:space:]]*VMID[[:space:]] ]] && continue
|
|
# Parse positionally. NAME can contain spaces, but `qm list` pads/columns
|
|
# them, so we use fixed positions: VMID at col 1, STATUS as the 3rd
|
|
# whitespace-delimited token from the END (mem, bootdisk, pid are after).
|
|
vmid="$(printf '%s' "$line" | awk '{print $1}')"
|
|
[[ "$vmid" =~ ^[0-9]+$ ]] || continue
|
|
# Strip trailing PID + BOOTDISK + MEM(MB) + STATUS to extract the NAME.
|
|
# rev → cut → rev technique:
|
|
trailing="$(printf '%s' "$line" | awk '{printf "%s %s %s %s", $(NF-3), $(NF-2), $(NF-1), $NF}')"
|
|
status="$(printf '%s' "$trailing" | awk '{print $1}')"
|
|
memory_mb="$(printf '%s' "$trailing" | awk '{print $2}')"
|
|
bootdisk_gb="$(printf '%s' "$trailing" | awk '{print $3}')"
|
|
# Name: drop first column (vmid) and last 4 columns
|
|
name="$(printf '%s' "$line" | awk '{$1=""; for(i=NF-3;i<=NF;i++) $i=""; sub(/^[[:space:]]+/,""); sub(/[[:space:]]+$/,""); print}')"
|
|
case "$status" in
|
|
running|stopped|paused) ;;
|
|
*) status="stopped" ;;
|
|
esac
|
|
|
|
vms="$(jq --argjson acc "$vms" \
|
|
--argjson vmid "$vmid" \
|
|
--arg name "$name" \
|
|
--argjson memory_mb "${memory_mb:-0}" \
|
|
--argjson bootdisk_gb "${bootdisk_gb:-0}" \
|
|
--arg status "$status" \
|
|
-n '
|
|
$acc + [{
|
|
vmid: $vmid,
|
|
name: $name,
|
|
memory_mb: $memory_mb,
|
|
bootdisk_gb: $bootdisk_gb,
|
|
status: $status,
|
|
config_file: ("configs/qemu-server/" + ($vmid|tostring) + ".conf")
|
|
}]
|
|
')"
|
|
done < <(qm list 2>/dev/null || true)
|
|
fi
|
|
|
|
# ── LXCs (pct list) ──
|
|
# Output:
|
|
# VMID Status Lock Name
|
|
# 101 running alpine
|
|
# Header line starts with VMID; we skip it.
|
|
if command -v pct >/dev/null 2>&1; then
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
[[ "$line" =~ ^[[:space:]]*VMID[[:space:]] ]] && continue
|
|
vmid="$(printf '%s' "$line" | awk '{print $1}')"
|
|
[[ "$vmid" =~ ^[0-9]+$ ]] || continue
|
|
status="$(printf '%s' "$line" | awk '{print $2}')"
|
|
# Lock column is sparse; name is always last positional non-empty token
|
|
name="$(printf '%s' "$line" | awk '{print $NF}')"
|
|
case "$status" in
|
|
running|stopped) ;;
|
|
*) status="stopped" ;;
|
|
esac
|
|
|
|
lxcs="$(jq --argjson acc "$lxcs" \
|
|
--argjson vmid "$vmid" \
|
|
--arg name "$name" \
|
|
--arg status "$status" \
|
|
-n '
|
|
$acc + [{
|
|
vmid: $vmid,
|
|
name: $name,
|
|
status: $status,
|
|
config_file: ("configs/lxc/" + ($vmid|tostring) + ".conf")
|
|
}]
|
|
')"
|
|
done < <(pct list 2>/dev/null || true)
|
|
fi
|
|
|
|
jq -n --argjson vms "$vms" --argjson lxcs "$lxcs" \
|
|
'{ vms: $vms, lxcs: $lxcs }'
|