Commit 652c3a06 authored by Vitaly Lipatov's avatar Vitaly Lipatov

pve: add pve-list.sh to list VM/CT and templates across cluster

Default mode lists VM/CT with filters --node/--pool/--running/--stopped/ --user and a name pattern. With --templates lists LXC templates (vztmpl) discovered on cluster storages, deduplicated by storage name. Co-Authored-By: 's avatarClaude Opus 4.7 (1M context) <noreply@anthropic.com>
parent bf777a27
#!/bin/sh
# List VM/CT across PVE cluster
# Usage: pve-list.sh [--node NODE] [--pool POOL] [--running] [--stopped] [--user USER] [pattern]
set -e
MYDIR=$(dirname "$0")
. "$MYDIR/functions"
FILTER_NODE=""
FILTER_POOL=""
FILTER_STATUS=""
FILTER_USER=""
MODE_TEMPLATES=""
PATTERN=""
while [ $# -gt 0 ] ; do
case "$1" in
--node) FILTER_NODE="$2" ; shift 2 ;;
--pool) FILTER_POOL="$2" ; shift 2 ;;
--running) FILTER_STATUS="running" ; shift ;;
--stopped) FILTER_STATUS="stopped" ; shift ;;
--user) FILTER_USER="$2" ; shift 2 ;;
--templates) MODE_TEMPLATES=1 ; shift ;;
--help|-h)
echo "Usage: $(basename "$0") [--node NODE] [--pool POOL] [--running] [--stopped] [--user USER] [--templates] [pattern]"
echo ""
echo "List VM/CT across PVE cluster (default), or available LXC templates."
echo ""
echo "Options:"
echo " --node NODE Filter by PVE node (e.g. gefest)"
echo " --pool POOL Filter by resource pool (e.g. Testing)"
echo " --running Show only running VM/CT"
echo " --stopped Show only stopped VM/CT"
echo " --user USER Filter by owner (first part of name before '-')"
echo " --templates List available LXC templates (vztmpl) on storages"
echo " pattern Grep VM/CT name (or template name) by pattern"
exit 0
;;
-*)
fatal "unknown option: $1"
;;
*)
PATTERN="$1" ; shift ;;
esac
done
list_templates() {
local storages_json pairs
storages_json=$(pvesh_cmd "get /cluster/resources --type storage --output-format json") \
|| fatal "cannot get storage resources"
if [ -n "$FILTER_NODE" ] ; then
pairs=$(echo "$storages_json" | jq -r --arg n "$FILTER_NODE" '
[.[] | select((.content // "") | test("vztmpl")) | select(.node == $n)]
| unique_by(.storage) | .[] | "\(.node)\t\(.storage)"')
else
pairs=$(echo "$storages_json" | jq -r '
[.[] | select((.content // "") | test("vztmpl"))]
| unique_by(.storage) | .[] | "\(.node)\t\(.storage)"')
fi
[ -n "$pairs" ] || fatal "no storages with vztmpl content found"
local tmp
tmp=$(mktemp) || fatal "mktemp failed"
# shellcheck disable=SC2064
trap "rm -f '$tmp'" EXIT
echo "$pairs" | while IFS="$(printf '\t')" read -r node storage ; do
pvesh_cmd "get /nodes/$node/storage/$storage/content --content vztmpl --output-format json" 2>/dev/null | \
jq -r --arg s "$storage" '.[] | [$s, ((.size // 0) / 1048576 | floor), .volid] | @tsv' >> "$tmp"
done
if [ -n "$PATTERN" ] ; then
grep -i "$PATTERN" "$tmp" > "$tmp.flt" || true
mv "$tmp.flt" "$tmp"
fi
printf "%-12s %10s %s\n" "STORAGE" "SIZE_MB" "VOLID"
printf "%-12s %10s %s\n" "-------" "-------" "-----"
sort -k1,1 -k3 "$tmp" | while IFS="$(printf '\t')" read -r storage size volid ; do
printf "%-12s %10s %s\n" "$storage" "$size" "$volid"
done
}
if [ -n "$MODE_TEMPLATES" ] ; then
list_templates
exit 0
fi
json=$(get_cluster_resources)
# Build jq filter
jq_filter='.'
if [ -n "$FILTER_NODE" ] ; then
jq_filter="$jq_filter | select(.node == \"$FILTER_NODE\")"
fi
if [ -n "$FILTER_POOL" ] ; then
jq_filter="$jq_filter | select(.pool == \"$FILTER_POOL\")"
fi
if [ -n "$FILTER_STATUS" ] ; then
jq_filter="$jq_filter | select(.status == \"$FILTER_STATUS\")"
fi
if [ -n "$FILTER_USER" ] ; then
jq_filter="$jq_filter | select(.name and (.name | startswith(\"$FILTER_USER-\")))"
fi
if [ -n "$PATTERN" ] ; then
jq_filter="$jq_filter | select(.name and (.name | test(\"$PATTERN\"; \"i\")))"
fi
# Header
printf "%-10s %-5s %6s %-8s %-40s %-15s %6s\n" "NODE" "TYPE" "VMID" "STATUS" "NAME" "POOL" "MEM_MB"
printf "%-10s %-5s %6s %-8s %-40s %-15s %6s\n" "----" "----" "----" "------" "----" "----" "------"
# Output sorted by node, then VMID
echo "$json" | jq -r "[.[] | $jq_filter] | sort_by(.node, .vmid)[] | [.node, .type, .vmid, .status, (.name // \"-\"), (.pool // \"-\"), ((.maxmem // 0) / 1048576 | floor)] | @tsv" | \
while IFS="$(printf '\t')" read -r node type vmid status name pool mem ; do
printf "%-10s %-5s %6s %-8s %-40s %-15s %6s\n" "$node" "$type" "$vmid" "$status" "$name" "$pool" "$mem"
done
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment