#!/usr/bin/env sh
set -euC

################################################################################
## Constants

readonly apiurl=https://192.168.51.81:8006/api2/json

## FIXME: There seems to be a problem with file upload where the task is
## registered to `node051` no matter what node we are actually uploading to? For
## now, let us just use `node051` everywhere.
readonly node=node051

readonly tmpdir=/tmp/proxmox-provision-$RANDOM$RANDOM
mkdir $tmpdir

################################################################################
## Parse arguments

username=
password=
vmids=

help () {
  cat <<EOF
Usage: $0 [OPTION...] [ID...]

Authentication options:
  --username STR    Username, with provider (eg. niols@pve)
  --password STR    Password

  If not provided via the command line, username and password will be looked for
  in a '.proxmox' file in the current working directory, the username on the
  first line, and the password on the second.

Others:
  -h|-?|--help      Show this help and exit
EOF
}

die () { printf '\033[31m'; printf "$@"; printf '\033[0m\n'; exit 2; }
die_with_help () { printf '\033[31m'; printf "$@"; printf '\033[0m\n'; help; exit 2; }

while [ $# -gt 0 ]; do
  argument=$1
  shift
  case $argument in
    --username) readonly username=$1; shift ;;
    --password) readonly password=$1; shift ;;

    -h|-\?|--help) help; exit 0 ;;

    -*) die_with_help 'Unknown argument: `%s`.' "$argument" ;;

    *) vmids="$vmids $argument" ;;
  esac
done

if [ -z "$username" ] || [ -z "$password" ]; then
  if [ -f .proxmox ]; then
    { read username; read password; } < .proxmox
  else
    die_with_help 'Required: `--username` and `--password`.\n'
  fi
fi

################################################################################
## Getting started

printf 'Authenticating...'
response=$(
    http \
        --verify no \
        POST $apiurl/access/ticket \
        "username=$username" \
        "password=$password"
    )
readonly ticket=$(echo "$response" | jq -r .data.ticket)
readonly csrfToken=$(echo "$response" | jq -r .data.CSRFPreventionToken)
printf ' done.\n'

acquire_lock () {
  until mkdir $tmpdir/lock-$1 2>/dev/null; do sleep 1; done
}
release_lock () {
  rmdir $tmpdir/lock-$1
}

proxmox () {
  acquire_lock proxmox
  http \
    --verify no \
    --form \
    "$@" \
    "Cookie:PVEAuthCookie=$ticket" \
    "CSRFPreventionToken:$csrfToken"
  release_lock proxmox
}

## Synchronous variant for when the `proxmox` function would just respond an
## UPID in the `data` JSON field.
proxmox_sync () (
  response=$(proxmox "$@")
  upid=$(echo "$response" | jq -r .data)

  while :; do
    response=$(proxmox GET $apiurl/nodes/$node/tasks/$upid/status)
    status=$(echo "$response" | jq -r .data.status)

    case $status in
      running) sleep 1 ;;
      stopped) break ;;
      *) die 'unexpected status: `%s`' "$status" ;;
    esac
  done
)

################################################################################
## Stop VM

stop_vm () {
  printf 'Stopping VM %d...\n' $1

  proxmox_sync POST $apiurl/nodes/$node/qemu/$1/status/stop \
    'overrule-shutdown'==1

  printf 'done stopping VM %d.\n' $1
}

################################################################################
## Delete VM

delete_vm () {
  printf 'Deleting VM %d...\n' $1

  proxmox_sync DELETE $apiurl/nodes/$node/qemu/$1 \
    'destroy-unreferenced-disks'==1 \
    'purge'==1

  printf 'done deleting VM %d.\n' $1
}

################################################################################
## Main loop

printf 'Removing VMs%s...\n' "$vmids"

remove_vm () {
  stop_vm $1
  delete_vm $1
}

for vmid in $vmids; do
  remove_vm $vmid &
done
wait

printf 'done removing VMs%s.\n' "$vmids"

################################################################################
## Cleanup

rm -Rf $tmpdir
