#!/usr/bin/env bash set -euC ################################################################################ ## Constants ## 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 mkdir $tmpdir ################################################################################ ## Parse arguments api_url= username= password= vm_names= debug=false help () { cat <` and `nixosConfigurations.` to get the informations that it needs. Options: --api-url STR Base URL of the Proxmox API (required) --username STR Username, with provider (eg. niols@pve; required) --password STR Password (required) --debug Run this script in debug mode (default: $debug) -h|-?|--help Show this help and exit Options can also be provided by adding assignments to a '.proxmox' file in the current working directory. For instance, it could contain: api_url=https://192.168.51.81:8006/api2/json username=mireille@pve debug=true Command line options take precedence over options found in the '.proxmox' file. EOF } # shellcheck disable=SC2059 die () { printf '\033[31m'; printf "$@"; printf '\033[0m\n'; exit 2; } # shellcheck disable=SC2059 die_with_help () { printf '\033[31m'; printf "$@"; printf '\033[0m\n\n'; help; exit 2; } # shellcheck disable=SC2059 debug () { if $debug; then printf >&2 '\033[37m'; printf >&2 "$@"; printf >&2 '\033[0m\n'; fi } if [ -f .proxmox ]; then . "$PWD"/.proxmox fi while [ $# -gt 0 ]; do argument=$1 shift case $argument in --api-url|--api_url) readonly api_url="$1"; shift ;; --username) readonly username="$1"; shift ;; --password) readonly password="$1"; shift ;; --debug) debug=true ;; -h|-\?|--help) help; exit 0 ;; -*) die_with_help "Unknown argument: '%s'." "$argument" ;; *) vm_names="$vm_names $argument" ;; esac done if [ -z "$vm_names" ]; then die_with_help "Required: at least one VM name." fi if [ -z "$api_url" ] || [ -z "$username" ] || [ -z "$password" ]; then die_with_help "Required: '--api-url', '--username' and '--password'." fi ## FIXME: When we figure out how to use other nodes than node051. # if [ -z "$node" ]; then # printf 'Picking random node...' # proxmox GET "$api_url/nodes" # node=$(from_response .data[].node | sort -R | head -n 1) # printf " done. Picked '%s'.\n" "$node" # fi # readonly node readonly debug ################################################################################ ## Getting started printf 'Authenticating...' response=$( http \ --verify no \ POST "$api_url/access/ticket" \ "username=$username" \ "password=$password" ) ticket=$(echo "$response" | jq -r .data.ticket) readonly ticket csrf_token=$(echo "$response" | jq -r .data.CSRFPreventionToken) readonly csrf_token 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 debug 'request %s' "$*" response=$( http \ --form \ --verify no \ --ignore-stdin \ "$@" \ "Cookie:PVEAuthCookie=$ticket" \ "CSRFPreventionToken:$csrf_token" ) debug 'response to request %s:\n %s' "$*" "$response" release_lock proxmox echo "$response" } ## 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 "$api_url/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 ) ################################################################################ ## Grab VM option ## ## Takes the name of the VM and an option and grabs `vmOptions..