This commit is contained in:
Павел Родионов
2025-11-28 18:58:15 +07:00
parent 409ec04823
commit b558aaa76d
9 changed files with 1012 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Load the .env file that lives beside the script
set -a # automatically export assignments
source "${SCRIPT_DIR}/.env"
set +a
# ---- login ----
login=$(curl -s -k -d "username=${USERNAME}&password=${PASSWORD}" \
"https://${ADDR}:8006/api2/json/access/ticket")
echo "=== LOGIN RESPONSE ==="
echo "$login"
echo "======================"
# Extract ticket & CSRF
TICKET=$(echo "$login" | grep -o '"ticket":"[^"]*' | cut -d'"' -f4)
CSRF=$(echo "$login" | grep -o '"CSRFPreventionToken":"[^"]*' | cut -d'"' -f4)
echo "Ticket: $TICKET"
echo "CSRF : $CSRF"
echo "-------------------"
# -------------------------------------------------
# Helper: wait for a Proxmox task to finish
# -------------------------------------------------
wait_task() {
local upid="$1"
local timeout=${2:-120} # seconds (default 2min)
local interval=2
local elapsed=0
while (( elapsed < timeout )); do
result=$(curl -s -k \
-b "PVEAuthCookie=${TICKET}" \
-H "CSRFPreventionToken: ${CSRF}" \
"https://${ADDR}:8006/api2/json/nodes/${ADDR}/tasks/${upid}/status")
status=$(echo "$result" | jq -r '.data.status')
exitstatus=$(echo "$result" | jq -r '.data.exitstatus')
if [[ "$status" == "stopped" ]]; then
if [[ "$exitstatus" == "OK" ]]; then
return 0
else
echo "Task $upid finished with error: $exitstatus" >&2
return 1
fi
fi
sleep "$interval"
(( elapsed += interval ))
done
echo "Task $upid timed out after $timeout seconds" >&2
return 1
}
# -------------------------------------------------
force_stop_vm_ssh() {
local vmid=$1
local node=$2 # e.g. pve01
# SSH to the node (assumes keybased auth or passwordless login)
ssh root@"${node}" bash <<EOF
# Remove stale lock if it exists
lock="/var/lock/qemu-server/lock-${vmid}.conf"
if [[ -e "\$lock" ]]; then
pid=\$(fuser -n file "\$lock" 2>/dev/null | awk '{print \$1}')
[[ -n "\$pid" ]] && kill -9 "\$pid"
rm -f "\$lock"
fi
# Stop the VM
qm stop "${vmid}"
# Wait until it reports stopped
while qm status "${vmid}" | grep -q running; do sleep 1; done
EOF
echo "VM $vmid on node $node is now stopped."
}
while true; do
echo "Select an option:"
echo "1) get nodes"
echo "2) get vm"
echo "3) create vm"
echo "4) power vm"
echo "5) delete vm"
echo "6) Exit"
printf "Enter choice [1-6]: "
read choice
case $choice in
1)
# Show only VM IDs and names
curl -s -k -b "PVEAuthCookie=${TICKET}" -H "CSRFPreventionToken: ${CSRF}" \
"https://${ADDR}:8006/api2/json/cluster/resources?type=vm" |
jq '.data[] | {vmid, name, status, node}'
;;
2)
curl -s -k -b "PVEAuthCookie=${TICKET}" -H "CSRFPreventionToken: ${CSRF}" \
"https://${ADDR}:8006/api2/json/cluster/resources?type=vm" | jq .
;;
3)
echo "PrintID:"
read id
echo "PintNAME:"
read name
curl -k -X POST \
-b "PVEAuthCookie=${TICKET}" \
-H "CSRFPreventionToken: ${CSRF}" \
-d "vmid=${id}&name=${name}&memory=2048&net0=virtio,bridge=vmbr0" \
https://${ADDR}:8006/api2/json/nodes/${ADDR}/qemu
;;
4)
echo "PrintID:"
read id
curl -k -X POST \
-b "PVEAuthCookie=${TICKET}" \
-H "CSRFPreventionToken: ${CSRF}" \
https://${ADDR}:8006/api2/json/nodes/${ADDR}/qemu/${id}/status/start
;;
5)
echo "PrintID:"; read id
# -------------------------------------------------
# 1️⃣ Find the node that actually hosts the VM
# -------------------------------------------------
VM_INFO=$(curl -s -k -b "PVEAuthCookie=${TICKET}" \
-H "CSRFPreventionToken: ${CSRF}" \
"https://${ADDR}:8006/api2/json/cluster/resources?type=vm")
VM_NODE=$(echo "$VM_INFO" | jq -r --arg id "$id" \
'.data[] | select(.vmid == ($id|tonumber)) | .node')
if [[ -z "$VM_NODE" ]]; then
echo "Could not locate VM $id"
continue
fi
echo "VM $id is on node $VM_NODE"
# -------------------------------------------------
# 2️⃣ Stop the VM via API and wait for the task
# -------------------------------------------------
stop_resp=$(curl -s -k -X POST \
-b "PVEAuthCookie=${TICKET}" \
-H "CSRFPreventionToken: ${CSRF}" \
"https://${ADDR}:8006/api2/json/nodes/${VM_NODE}/qemu/${id}/status/stop")
stop_upid=$(echo "$stop_resp" | jq -r '.data')
echo "Stop task UPID: $stop_upid"
if ! wait_task "$stop_upid"; then
echo "Failed to stop VM $id aborting delete."
continue
fi
echo "VM $id is now stopped."
# -------------------------------------------------
# 3️⃣ Destroy the VM via API and wait for the task
# -------------------------------------------------
destroy_resp=$(curl -s -k -X POST \
-b "PVEAuthCookie=${TICKET}" \
-H "CSRFPreventionToken: ${CSRF}" \
"https://${ADDR}:8006/api2/json/nodes/${VM_NODE}/qemu/${id}/destroy")
destroy_upid=$(echo "$destroy_resp" | jq -r '.data')
echo "Destroy task UPID: $destroy_upid"
if wait_task "$destroy_upid"; then
echo "VM $id successfully removed."
else
echo "Failed to destroy VM $id."
fi
;;
6)
echo "Goodbye!"; exit 0
;;
*)
echo "Invalid choice, try again."
;;
esac
done