#!/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= sockets=1 cores=1 memory=2048 vmids= help () { cat </dev/null; do sleep 1; done } release_lock () { rmdir $tmpdir/lock-$1 } proxmox () { acquire_lock proxmox http \ --form \ --verify no \ --ignore-stdin \ "$@" \ "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 ) ################################################################################ ## Build ISO build_iso () { acquire_lock build printf 'Building ISO for VM %d...\n' $1 nix build \ .#isoInstallers.provisioning.fedi$1 \ --log-format raw --quiet \ --out-link $tmpdir/installer-fedi$1 ln -sf $tmpdir/installer-fedi$1/iso/installer.iso $tmpdir/installer-fedi$1.iso printf 'done building ISO for VM %d.\n' $1 release_lock build } ################################################################################ ## Upload ISO upload_iso () { acquire_lock upload printf 'Uploading ISO for VM %d...\n' $1 proxmox_sync POST $apiurl/nodes/$node/storage/local/upload \ filename@$tmpdir/installer-fedi$1.iso \ content==iso printf 'done uploading ISO for VM %d.\n' $1 release_lock upload } ################################################################################ ## Remove ISO remove_iso () { printf 'Removing ISO for VM %d... unsupported for now. (FIXME)\n' $1 } ################################################################################ ## Create VM create_vm () { printf 'Creating VM %d...\n' $1 proxmox_sync POST $apiurl/nodes/$node/qemu \ \ vmid==$1 \ name=="fedi$1" \ pool==Fediversity \ \ ide2=="local:iso/installer-fedi$1.iso,media=cdrom" \ ostype==l26 \ \ bios==ovmf \ efidisk0=='linstor_storage:1,efitype=4m' \ agent==1 \ \ scsihw==virtio-scsi-single \ scsi0=='linstor_storage:32,discard=on,ssd=on,iothread=on' \ \ sockets==$sockets \ cores==$cores \ cpu==x86-64-v2-AES \ numa==1 \ \ memory==$memory \ \ net0=='virtio,bridge=vnet1306' printf 'done creating VM %d.\n' $1 } ################################################################################ ## Install VM install_vm () ( printf 'Installing VM %d...\n' $1 proxmox_sync POST $apiurl/nodes/$node/qemu/$1/status/start while :; do response=$(proxmox GET $apiurl/nodes/$node/qemu/$1/status/current) status=$(echo "$response" | jq -r .data.status) case $status in running) sleep 1 ;; stopped) break ;; *) printf ' unexpected status: `%s`\n' "$status"; exit 2 ;; esac done printf 'done installing VM %d.\n' $1 ) ################################################################################ ## Start VM start_vm () { printf 'Starting VM %d...\n' $1 proxmox_sync POST $apiurl/nodes/$node/qemu/$1/config \ ide2=='none,media=cdrom' \ net0=='virtio,bridge=vnet1305' proxmox_sync POST $apiurl/nodes/$node/qemu/$1/status/start printf 'done starting VM %d.\n' $1 } ################################################################################ ## Main loop printf 'Provisioning VMs%s with:\n' "$vmids" printf ' sockets: %d\n' $sockets printf ' cores: %d\n' $cores printf ' memory: %d\n' $memory provision_vm () { build_iso $1 upload_iso $1 create_vm $1 install_vm $1 start_vm $1 remove_iso $1 } for vmid in $vmids; do provision_vm $vmid & done wait printf 'done provisioning VMs%s.\n' "$vmids" ################################################################################ ## Cleanup rm -Rf $tmpdir