mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-09-16 14:30:33 -04:00
* Refactor: TrueNAS VM (core / improve functions / performance) * Boot TrueNAS from sata0, the disk it actually installs to The boot order named scsi0, which never exists: the system disk is sata0, and imported passthrough disks start at scsi1 because SCSI_NR is pre-incremented. So the order always fell through to ide2 and the installer came back up after every reboot. * Fix URL in truenas-vm.sh script
208 lines
6.2 KiB
Bash
208 lines
6.2 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Copyright (c) 2021-2026 community-scripts ORG
|
|
# Author: juronja
|
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
# Source: https://www.truenas.com/truenas-community-edition/
|
|
|
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main}"
|
|
source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/pve/vm-core.func")
|
|
load_functions
|
|
|
|
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
|
|
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
|
|
METHOD=""
|
|
APP="TrueNAS"
|
|
APP_TYPE="vm"
|
|
NSAPP="truenas-vm"
|
|
|
|
header_info
|
|
echo -e "\n Loading..."
|
|
|
|
ISO="${TAB}📀${TAB}${CL}"
|
|
DISK="${TAB}💽${TAB}${CL}"
|
|
|
|
set -e
|
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
trap cleanup EXIT
|
|
trap 'post_update_to_api "failed" "130"' SIGINT
|
|
trap 'post_update_to_api "failed" "143"' SIGTERM
|
|
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
|
|
|
|
function truenas_iso_lookup() {
|
|
local BASE_URL="https://download.truenas.com"
|
|
local current_year=$(date +%y)
|
|
local last_year=$(date -d "1 year ago" +%y)
|
|
local year_pattern="${current_year}\.|${last_year}\."
|
|
|
|
declare -A latest_stables
|
|
local pre_releases=()
|
|
|
|
local all_paths=$(
|
|
curl -sL "$BASE_URL" |
|
|
grep -oE 'href="[^"]+\.iso"' |
|
|
sed 's/href="//; s/"$//' |
|
|
grep -vE '(MASTER|ALPHA)' |
|
|
grep -E "$year_pattern"
|
|
)
|
|
|
|
while read -r path; do
|
|
local filename=$(basename "$path")
|
|
local version=$(echo "$filename" | sed -E 's/.*TrueNAS-SCALE-([0-9]{2}\.[0-9]{2}(\.[0-9]+)*(-RC[0-9]|-BETA[0-9])?)\.iso.*/\1/')
|
|
if [[ "$version" =~ (RC|BETA) ]]; then
|
|
pre_releases+=("$path")
|
|
else
|
|
local major_version=$(echo "$version" | cut -d'.' -f1,2)
|
|
local current_stored_path=${latest_stables["$major_version"]:-}
|
|
if [[ -z "$current_stored_path" ]]; then
|
|
latest_stables["$major_version"]="$path"
|
|
else
|
|
local stored_version=$(basename "$current_stored_path" | sed -E 's/.*TrueNAS-SCALE-([0-9]{2}\.[0-9]{2}(\.[0-9]+)*)\.iso.*/\1/')
|
|
if printf '%s\n' "$version" "$stored_version" | sort -V | tail -n 1 | grep -q "$version"; then
|
|
latest_stables["$major_version"]="$path"
|
|
fi
|
|
fi
|
|
fi
|
|
done <<<"$all_paths"
|
|
|
|
for key in "${!latest_stables[@]}"; do
|
|
echo "${latest_stables[$key]#/}"
|
|
done
|
|
|
|
for pre in "${pre_releases[@]}"; do
|
|
echo "${pre#/}"
|
|
done | sort -V
|
|
}
|
|
|
|
TEMP_DIR=$(mktemp -d)
|
|
pushd $TEMP_DIR >/dev/null
|
|
|
|
function default_settings() {
|
|
VMID=$(get_valid_nextid)
|
|
ISO_DEFAULT="latest stable"
|
|
vm_apply_machine_type "q35"
|
|
DISK_SIZE="16"
|
|
DISK_CACHE=""
|
|
HN="truenas"
|
|
CPU_TYPE=" -cpu host"
|
|
CORE_COUNT="2"
|
|
RAM_SIZE="8192"
|
|
BRG="vmbr0"
|
|
MAC="$GEN_MAC"
|
|
VLAN=""
|
|
MTU=""
|
|
START_VM="yes"
|
|
IMPORT_DISKS="no"
|
|
METHOD="default"
|
|
echo -e "${ISO}${BOLD}${DGN}ISO Chosen: ${BGN}${ISO_DEFAULT}${CL}"
|
|
vm_echo_default_settings
|
|
}
|
|
|
|
function advanced_settings() {
|
|
METHOD="advanced"
|
|
vm_prompt_vmid "${VMID:-$(get_valid_nextid)}"
|
|
vm_prompt_machine_type "q35"
|
|
vm_prompt_disk_size "16G" "Set Disk Size in GiB (e.g., 16, 32)"
|
|
vm_prompt_disk_cache "none"
|
|
vm_prompt_hostname "truenas"
|
|
vm_prompt_cpu_model "host"
|
|
vm_prompt_cpu_cores "2"
|
|
vm_prompt_ram "8192"
|
|
vm_prompt_bridge "vmbr0"
|
|
vm_prompt_mac "$GEN_MAC"
|
|
vm_prompt_vlan
|
|
vm_prompt_mtu
|
|
vm_prompt_verbose "no"
|
|
|
|
if vm_dialog yesno "IMPORT ONBOARD DISKS" --defaultno "Would you like to import onboard disks?" 10 58; then
|
|
IMPORT_DISKS="yes"
|
|
else
|
|
IMPORT_DISKS="no"
|
|
fi
|
|
echo -e "${DISK}${BOLD}${DGN}Import onboard disks: ${BGN}${IMPORT_DISKS}${CL}"
|
|
|
|
vm_prompt_start_vm "yes"
|
|
|
|
if vm_confirm_advanced_settings "Ready to create a TrueNAS VM?"; then
|
|
echo -e "${CREATING}${BOLD}${DGN}Creating a TrueNAS VM using the above advanced settings${CL}"
|
|
else
|
|
header_info
|
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
|
advanced_settings
|
|
fi
|
|
}
|
|
|
|
vm_preflight
|
|
vm_start_script "Use Default Settings?" 10 58
|
|
post_to_api_vm
|
|
|
|
vm_select_storage "$HN"
|
|
|
|
if [ -z "${SELECTED_ISO:-}" ]; then
|
|
SELECTED_ISO=$(truenas_iso_lookup | grep -vE 'RC|BETA' | sort -V | tail -n 1)
|
|
|
|
if [ -z "$SELECTED_ISO" ]; then
|
|
msg_error "Could not find a stable ISO for fallback."
|
|
exit 115
|
|
fi
|
|
fi
|
|
|
|
FULL_URL="https://download.truenas.com/${SELECTED_ISO#/}"
|
|
ISO_NAME=$(basename "$FULL_URL")
|
|
CACHE_DIR="/var/lib/vz/template/iso"
|
|
CACHE_FILE="$CACHE_DIR/$ISO_NAME"
|
|
|
|
msg_info "Retrieving the ISO for the TrueNAS Disk Image"
|
|
MIN_ISO_BYTES=$((500 * 1024 * 1024))
|
|
vm_fetch_image "$FULL_URL" "$CACHE_FILE" --cache --min-bytes "$MIN_ISO_BYTES" || exit 115
|
|
|
|
set -o pipefail
|
|
msg_info "Creating TrueNAS VM shell"
|
|
qm create "$VMID"${MACHINE} -bios ovmf -agent enabled=1 -tablet 0 -localtime 1${CPU_TYPE} \
|
|
-cores "$CORE_COUNT" -memory "$RAM_SIZE" -balloon 0 -name "$HN" -tags community-script \
|
|
-net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 \
|
|
-efidisk0 $STORAGE:1,efitype=4m,pre-enrolled-keys=0 -sata0 $STORAGE:$DISK_SIZE,ssd=1 \
|
|
-scsihw virtio-scsi-single -cdrom local:iso/$ISO_NAME -boot order='sata0;ide2' -vga virtio >/dev/null
|
|
msg_ok "Created VM shell"
|
|
|
|
if [ "$IMPORT_DISKS" == "yes" ]; then
|
|
msg_info "Importing onboard disks"
|
|
DISKARRAY=()
|
|
SCSI_NR=0
|
|
|
|
while read -r LSOUTPUT; do
|
|
TRUNCATED="${LSOUTPUT:0:45}"
|
|
if [ ${#LSOUTPUT} -gt 45 ]; then
|
|
TRUNCATED="${TRUNCATED}..."
|
|
fi
|
|
DISKARRAY+=("$LSOUTPUT" "$TRUNCATED" "OFF")
|
|
done < <(ls /dev/disk/by-id | grep -E '^ata-|^nvme-|^usb-' | grep -v 'part')
|
|
|
|
vm_dialog checklist "SELECT DISKS TO IMPORT" --notags --cancel-button "Exit Script" \
|
|
"\nSelect disk IDs to import. (Use Spacebar to select)\n" 20 58 10 "${DISKARRAY[@]}" || exit
|
|
SELECTIONS=$(echo "$VM_DIALOG_RESULT" | tr -d '"')
|
|
|
|
for SELECTION in $SELECTIONS; do
|
|
((++SCSI_NR))
|
|
|
|
ID_SERIAL=$(udevadm info --query=property --value --property=ID_SERIAL_SHORT "/dev/disk/by-id/$SELECTION")
|
|
ID_SERIAL=${ID_SERIAL:0:20}
|
|
|
|
qm set $VMID --scsi$SCSI_NR /dev/disk/by-id/$SELECTION,serial=$ID_SERIAL
|
|
done
|
|
msg_ok "Disks imported successfully"
|
|
fi
|
|
|
|
set_description
|
|
|
|
sleep 3
|
|
|
|
msg_ok "Created a TrueNAS VM ${CL}${BL}(${HN})"
|
|
if [ "$START_VM" == "yes" ]; then
|
|
msg_info "Starting TrueNAS VM"
|
|
$STD qm start $VMID
|
|
msg_ok "Started TrueNAS VM"
|
|
fi
|
|
|
|
msg_ok "Completed Successfully!\n"
|