134 lines
4.4 KiB
Bash
134 lines
4.4 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
|
||
|
|
# Fast force remove VMs - optimized for batch processing
|
||
|
|
set -e
|
||
|
|
|
||
|
|
PROXMOX_ENDPOINT="${PROXMOX_ENDPOINT:-https://192.168.11.10:8006}"
|
||
|
|
PROXMOX_NODE="${PROXMOX_NODE:-ml110-01}"
|
||
|
|
PROXMOX_USER="${PROXMOX_USER:-}"
|
||
|
|
PROXMOX_PASS="${PROXMOX_PASS:-}"
|
||
|
|
|
||
|
|
# Generate VM IDs: 103-145 and 211-233
|
||
|
|
ORPHANED_VMS=()
|
||
|
|
for i in {103..145}; do
|
||
|
|
ORPHANED_VMS+=($i)
|
||
|
|
done
|
||
|
|
for i in {211..233}; do
|
||
|
|
ORPHANED_VMS+=($i)
|
||
|
|
done
|
||
|
|
|
||
|
|
if [ -z "$PROXMOX_USER" ] || [ -z "$PROXMOX_PASS" ]; then
|
||
|
|
echo "Error: PROXMOX_USER and PROXMOX_PASS must be set"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "FORCE REMOVING VMs: 103-145 and 211-233"
|
||
|
|
echo "Total VMs: ${#ORPHANED_VMS[@]}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Get authentication
|
||
|
|
TICKET=$(curl -s -k -d "username=${PROXMOX_USER}&password=${PROXMOX_PASS}" \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/access/ticket" | \
|
||
|
|
jq -r '.data.ticket // empty')
|
||
|
|
|
||
|
|
if [ -z "$TICKET" ]; then
|
||
|
|
echo "Error: Failed to authenticate"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
CSRF_TOKEN=$(curl -s -k -d "username=${PROXMOX_USER}&password=${PROXMOX_PASS}" \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/access/ticket" | \
|
||
|
|
jq -r '.data.CSRFPreventionToken // empty')
|
||
|
|
|
||
|
|
SUCCESS_COUNT=0
|
||
|
|
FAILED_COUNT=0
|
||
|
|
NOT_FOUND_COUNT=0
|
||
|
|
PROCESSED=0
|
||
|
|
|
||
|
|
for VMID in "${ORPHANED_VMS[@]}"; do
|
||
|
|
PROCESSED=$((PROCESSED + 1))
|
||
|
|
echo -n "[$PROCESSED/${#ORPHANED_VMS[@]}] VM $VMID: "
|
||
|
|
|
||
|
|
# Quick check if VM exists
|
||
|
|
VM_EXISTS=$(curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/qemu/${VMID}/status/current" 2>/dev/null | \
|
||
|
|
jq -r '.data // empty')
|
||
|
|
|
||
|
|
if [ -z "$VM_EXISTS" ] || [ "$VM_EXISTS" = "null" ]; then
|
||
|
|
echo "not found"
|
||
|
|
NOT_FOUND_COUNT=$((NOT_FOUND_COUNT + 1))
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Quick unlock (single attempt)
|
||
|
|
curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
-H "CSRFPreventionToken: ${CSRF_TOKEN}" \
|
||
|
|
-X POST \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/qemu/${VMID}/unlock" > /dev/null 2>&1
|
||
|
|
|
||
|
|
# Stop if running
|
||
|
|
curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
-H "CSRFPreventionToken: ${CSRF_TOKEN}" \
|
||
|
|
-X POST \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/qemu/${VMID}/status/stop" > /dev/null 2>&1
|
||
|
|
|
||
|
|
sleep 1
|
||
|
|
|
||
|
|
# Delete with purge
|
||
|
|
DELETE_RESULT=$(curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
-H "CSRFPreventionToken: ${CSRF_TOKEN}" \
|
||
|
|
-X DELETE \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/qemu/${VMID}?purge=1&skiplock=1" 2>&1)
|
||
|
|
|
||
|
|
TASK_UPID=$(echo "$DELETE_RESULT" | jq -r '.data // empty' 2>/dev/null)
|
||
|
|
|
||
|
|
if [ -n "$TASK_UPID" ] && [ "$TASK_UPID" != "null" ]; then
|
||
|
|
# Wait for completion (shorter timeout)
|
||
|
|
DELETED=false
|
||
|
|
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
|
||
|
|
sleep 1
|
||
|
|
TASK_STATUS=$(curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/tasks/${TASK_UPID}/status" 2>/dev/null | \
|
||
|
|
jq -r '.data.status // "unknown"')
|
||
|
|
|
||
|
|
if [ "$TASK_STATUS" = "stopped" ]; then
|
||
|
|
EXIT_STATUS=$(curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/tasks/${TASK_UPID}/status" 2>/dev/null | \
|
||
|
|
jq -r '.data.exitstatus // "unknown"')
|
||
|
|
|
||
|
|
if [ "$EXIT_STATUS" = "OK" ] || [ "$EXIT_STATUS" = "0" ]; then
|
||
|
|
sleep 1
|
||
|
|
VM_STILL_EXISTS=$(curl -s -k -b "PVEAuthCookie=${TICKET}" \
|
||
|
|
"${PROXMOX_ENDPOINT}/api2/json/nodes/${PROXMOX_NODE}/qemu/${VMID}/status/current" 2>/dev/null | \
|
||
|
|
jq -r '.data // empty')
|
||
|
|
|
||
|
|
if [ -z "$VM_STILL_EXISTS" ] || [ "$VM_STILL_EXISTS" = "null" ]; then
|
||
|
|
echo "✅"
|
||
|
|
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
|
||
|
|
DELETED=true
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
if [ "$DELETED" = "false" ]; then
|
||
|
|
echo "⚠️"
|
||
|
|
FAILED_COUNT=$((FAILED_COUNT + 1))
|
||
|
|
fi
|
||
|
|
else
|
||
|
|
echo "❌"
|
||
|
|
FAILED_COUNT=$((FAILED_COUNT + 1))
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "========================================="
|
||
|
|
echo "Summary:"
|
||
|
|
echo " Successfully deleted: $SUCCESS_COUNT"
|
||
|
|
echo " Failed: $FAILED_COUNT"
|
||
|
|
echo " Not found: $NOT_FOUND_COUNT"
|
||
|
|
echo " Total: ${#ORPHANED_VMS[@]}"
|
||
|
|
echo ""
|
||
|
|
|