diff --git a/bin/import-vhdx.sh b/bin/import-vhdx.sh new file mode 100644 index 0000000..0df5cb1 --- /dev/null +++ b/bin/import-vhdx.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# Usage: import-vhdx-dir.sh +# If VMID is 0 or already taken, the script will pick the first available VMID. + +set -euo pipefail + +# ----------------------- +# Inputs and defaults +# ----------------------- +INPUT_VMID="${1:-0}" +VMNAME="${2:?VM name required}" +BASEDIR="${3:?Base directory required}" +ENR="${4:-}" +STORAGE="ZFS-01" +ISO_STORAGE="tscale04-nfs" +ISO_NAME="virtio-win.iso" + +# ----------------------- +# Helpers +# ----------------------- +get_free_vmid() { + # Get sorted list of used VMIDs + mapfile -t USED < <(qm list | awk 'NR>1{print $1}' | sort -n) + local id=100 + while true; do + local taken=0 + for u in "${USED[@]}"; do + if [[ "$u" == "$id" ]]; then + taken=1 + break + fi + done + if [[ $taken -eq 0 ]]; then + echo "$id" + return 0 + fi + ((id++)) + done +} + +is_vmid_taken() { + local vmid="$1" + qm list | awk 'NR>1{print $1}' | grep -qx "$vmid" +} + +# Determine VMID (auto-pick if 0 or taken) +if [[ "$INPUT_VMID" == "0" || "$(is_vmid_taken "$INPUT_VMID"; echo $?)" -eq 0 ]]; then + VMID="$(get_free_vmid)" + echo ">>> Requested VMID '$INPUT_VMID' is invalid/taken. Using first available VMID: $VMID" +else + VMID="$INPUT_VMID" +fi + +# ----------------------- +# Create VM (TPM/UEFI + SATA) +# ----------------------- +case "$ENR" in + ENR) + echo ">>> Creating VM $VMID ($VMNAME) with TPM KEY not enrolled..." + qm create "$VMID" --name "$VMNAME" --memory 4096 --cores 4 --machine q35 \ + --bios ovmf --efidisk0 ${STORAGE}:1,efitype=4m,pre-enrolled-keys=1 \ + --tpmstate0 ${STORAGE}:1,version=v2.0 + ;; + *) + echo ">>> Creating VM $VMID ($VMNAME) with TPM and UEFI..." + qm create "$VMID" --name "$VMNAME" --memory 4096 --cores 4 --machine q35 \ + --bios ovmf --efidisk0 ${STORAGE}:1,efitype=4m,pre-enrolled-keys=0 \ + --tpmstate0 ${STORAGE}:1,version=v2.0 + ;; +esac + +# ----------------------- +# Find VHDX files, sort by size (largest first), space-safe +# ----------------------- +declare -a VHDX_FILES +while IFS= read -r -d '' line; do + # line format: "\t" + size="${line%%$'\t'*}" + path="${line#*$'\t'}" + VHDX_FILES+=( "$path" ) +done < <(find "$BASEDIR" -type f -iname "*.vhdx" -printf "%s\t%p\0" | sort -z -nr -k1,1) + +if [ ${#VHDX_FILES[@]} -eq 0 ]; then + echo "!!! No VHDX files found in $BASEDIR" + exit 1 +fi + +echo ">>> Found ${#VHDX_FILES[@]} VHDX file(s), sorted by size:" +for f in "${VHDX_FILES[@]}"; do + echo " $f" +done + +# ----------------------- +# Import and attach disks as SATA (largest -> sata0) +# ----------------------- +DISK_INDEX=0 +for VHDX in "${VHDX_FILES[@]}"; do + echo ">>> Importing disk: $VHDX -> $STORAGE" + qm importdisk "$VMID" "$VHDX" "$STORAGE" --format=raw + + # Identify the last unused disk created by import (space-safe parsing) + LASTDISK="$(qm config "$VMID" | awk '/^unused[0-9]+: /{print $2}' | tail -n1)" + + if [[ -z "$LASTDISK" ]]; then + echo "!!! Could not detect imported disk for $VHDX" + exit 1 + fi + + DISK_NAME="sata${DISK_INDEX}" + echo ">>> Attaching '$LASTDISK' as '$DISK_NAME'..." + qm set "$VMID" --${DISK_NAME} "$LASTDISK" + + ((DISK_INDEX++)) +done + +# ----------------------- +# Boot order: sata0 (largest disk) +# ----------------------- +echo ">>> Setting boot order to sata0..." +qm set "$VMID" --boot order=sata0 diff --git a/bin/pve-remove-nag.sh b/bin/pve-remove-nag.sh index 345342f..f4d9bf0 100644 --- a/bin/pve-remove-nag.sh +++ b/bin/pve-remove-nag.sh @@ -1,4 +1,5 @@ #!/bin/sh + WEB_JS=/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js if [ -s "$WEB_JS" ] && ! grep -q NoMoreNagging "$WEB_JS"; then echo "Patching Web UI nag..."