2022-02-23 11:52:49 +00:00
#!/usr/bin/env bash
2023-02-07 17:15:22 +00:00
2025-01-01 12:37:29 +00:00
# Copyright (c) 2021-2025 tteck
2023-02-07 17:15:22 +00:00
# Author: tteck (tteckster)
2024-12-16 11:41:51 +00:00
# Co-Author: MickLesk
2023-02-07 17:15:22 +00:00
# License: MIT
2024-11-02 07:48:05 +00:00
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
2023-02-07 17:15:22 +00:00
2023-05-15 23:15:26 +00:00
# This sets verbose mode if the global variable is set to "yes"
2024-01-10 00:44:38 +00:00
# if [ "$VERBOSE" == "yes" ]; then set -x; fi
2023-05-15 23:15:26 +00:00
# This function sets color variables for formatting output in the terminal
2024-12-16 11:41:51 +00:00
# Colors
2022-10-30 00:08:41 +00:00
YW = $( echo "\033[33m" )
2024-12-16 11:41:51 +00:00
YWB = $( echo "\033[93m" )
2022-10-30 00:08:41 +00:00
BL = $( echo "\033[36m" )
RD = $( echo "\033[01;31m" )
GN = $( echo "\033[1;92m" )
2024-12-16 11:41:51 +00:00
# Formatting
2022-10-30 00:08:41 +00:00
CL = $( echo "\033[m" )
2024-12-16 11:41:51 +00:00
UL = $( echo "\033[4m" )
BOLD = $( echo "\033[1m" )
2022-04-16 13:52:57 +00:00
BFR = "\\r\\033[K"
2024-04-21 13:12:55 +00:00
HOLD = " "
2024-12-16 11:41:51 +00:00
TAB = " "
# Icons
CM = " ${ TAB } ✔️ ${ TAB } ${ CL } "
CROSS = " ${ TAB } ✖️ ${ TAB } ${ CL } "
INFO = " ${ TAB } 💡 ${ TAB } ${ CL } "
2023-05-15 23:15:26 +00:00
# This sets error handling options and defines the error_handler function to handle errors
2023-02-03 16:41:12 +00:00
set -Eeuo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
2023-05-15 23:15:26 +00:00
# This function handles errors
2023-02-03 16:41:12 +00:00
function error_handler( ) {
2024-01-21 09:31:14 +00:00
if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
2024-01-06 22:15:45 +00:00
printf "\e[?25h"
2023-02-03 16:41:12 +00:00
local exit_code = " $? "
local line_number = " $1 "
local command = " $2 "
local error_message = " ${ RD } [ERROR] ${ CL } in line ${ RD } $line_number ${ CL } : exit code ${ RD } $exit_code ${ CL } : while executing command ${ YW } $command ${ CL } "
2023-05-06 21:19:12 +00:00
echo -e " \n $error_message \n "
2025-02-05 15:29:07 +00:00
exit 200
2023-02-03 16:41:12 +00:00
}
2023-05-15 23:15:26 +00:00
2024-01-06 22:15:45 +00:00
# This function displays a spinner.
function spinner( ) {
2024-12-16 11:41:51 +00:00
local frames = ( '⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏' )
local spin_i = 0
local interval = 0.1
printf "\e[?25l"
local color = " ${ YWB } "
while true; do
printf " \r ${ color } %s ${ CL } " " ${ frames [spin_i] } "
spin_i = $(( ( spin_i + 1 ) % ${# frames [@] } ))
sleep " $interval "
done
2024-01-06 22:15:45 +00:00
}
# This function displays an informational message with a yellow color.
2022-04-25 14:20:22 +00:00
function msg_info( ) {
2022-10-30 00:08:41 +00:00
local msg = " $1 "
2024-12-16 11:41:51 +00:00
echo -ne " ${ TAB } ${ YW } ${ HOLD } ${ msg } ${ HOLD } "
2024-01-06 22:15:45 +00:00
spinner &
SPINNER_PID = $!
2022-02-23 11:52:49 +00:00
}
2022-04-25 14:20:22 +00:00
2024-01-06 22:15:45 +00:00
# This function displays a success message with a green color.
2022-04-25 14:20:22 +00:00
function msg_ok( ) {
2024-01-21 09:31:14 +00:00
if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
2024-01-06 22:15:45 +00:00
printf "\e[?25h"
2022-10-30 00:08:41 +00:00
local msg = " $1 "
2024-12-16 11:41:51 +00:00
echo -e " ${ BFR } ${ CM } ${ GN } ${ msg } ${ CL } "
2022-02-23 11:52:49 +00:00
}
2023-05-15 23:15:26 +00:00
2024-01-06 22:15:45 +00:00
# This function displays a error message with a red color.
2022-10-25 07:43:46 +00:00
function msg_error( ) {
2024-01-21 09:31:14 +00:00
if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
2024-01-06 22:15:45 +00:00
printf "\e[?25h"
2022-10-30 00:08:41 +00:00
local msg = " $1 "
2024-12-16 11:41:51 +00:00
echo -e " ${ BFR } ${ CROSS } ${ RD } ${ msg } ${ CL } "
2022-10-25 07:43:46 +00:00
}
2023-05-15 23:15:26 +00:00
# This checks for the presence of valid Container Storage and Template Storage locations
2022-10-25 07:43:46 +00:00
msg_info "Validating Storage"
2022-10-25 08:43:15 +00:00
VALIDCT = $( pvesm status -content rootdir | awk 'NR>1' )
2022-10-30 00:08:41 +00:00
if [ -z " $VALIDCT " ] ; then
msg_error "Unable to detect a valid Container Storage location."
exit 1
fi
2022-10-25 08:43:15 +00:00
VALIDTMP = $( pvesm status -content vztmpl | awk 'NR>1' )
2022-10-30 00:08:41 +00:00
if [ -z " $VALIDTMP " ] ; then
msg_error "Unable to detect a valid Template Storage location."
exit 1
fi
2022-10-25 08:43:15 +00:00
2023-05-15 23:15:26 +00:00
# This function is used to select the storage class and determine the corresponding storage content type and label.
2022-02-23 11:52:49 +00:00
function select_storage( ) {
local CLASS = $1
local CONTENT
local CONTENT_LABEL
case $CLASS in
2022-10-30 00:08:41 +00:00
container)
CONTENT = 'rootdir'
CONTENT_LABEL = 'Container'
; ;
template)
CONTENT = 'vztmpl'
CONTENT_LABEL = 'Container template'
; ;
2025-02-05 15:29:07 +00:00
*) false || { msg_error "Invalid storage class." ; exit 201; } ;
2022-02-23 11:52:49 +00:00
esac
2023-05-15 23:15:26 +00:00
# This Queries all storage locations
2022-02-23 11:52:49 +00:00
local -a MENU
while read -r line; do
local TAG = $( echo $line | awk '{print $1}' )
local TYPE = $( echo $line | awk '{printf "%-10s", $2}' )
local FREE = $( echo $line | numfmt --field 4-6 --from-unit= K --to= iec --format %.2f | awk '{printf( "%9sB", $6)}' )
2024-12-16 11:41:51 +00:00
local ITEM = " Type: $TYPE Free: $FREE "
2022-02-23 11:52:49 +00:00
local OFFSET = 2
if [ [ $(( ${# ITEM } + $OFFSET )) -gt ${ MSG_MAX_LENGTH :- } ] ] ; then
local MSG_MAX_LENGTH = $(( ${# ITEM } + $OFFSET ))
fi
2022-10-30 00:08:41 +00:00
MENU += ( " $TAG " " $ITEM " "OFF" )
2022-02-23 11:52:49 +00:00
done < <( pvesm status -content $CONTENT | awk 'NR>1' )
2023-05-15 23:15:26 +00:00
# Select storage location
2023-08-19 10:22:12 +00:00
if [ $(( ${# MENU [@] } / 3 )) -eq 1 ] ; then
2022-02-23 11:52:49 +00:00
printf ${ MENU [0] }
2022-10-30 00:08:41 +00:00
else
2022-02-23 11:52:49 +00:00
local STORAGE
2022-10-30 00:08:41 +00:00
while [ -z " ${ STORAGE : +x } " ] ; do
2023-09-09 09:13:17 +00:00
STORAGE = $( whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
2023-08-19 10:22:12 +00:00
" Which storage pool you would like to use for the ${ CONTENT_LABEL ,, } ?\nTo make a selection, use the Spacebar.\n " \
16 $(( $MSG_MAX_LENGTH + 23 )) 6 \
2025-02-05 15:29:07 +00:00
" ${ MENU [@] } " 3>& 1 1>& 2 2>& 3) || { msg_error "Menu aborted." ; exit 202; }
2024-12-16 11:41:51 +00:00
if [ $? -ne 0 ] ; then
echo -e " ${ CROSS } ${ RD } Menu aborted by user. ${ CL } "
exit 0
fi
2022-02-23 11:52:49 +00:00
done
2024-12-16 11:41:51 +00:00
printf "%s" " $STORAGE "
2022-02-23 11:52:49 +00:00
fi
}
2023-05-15 23:15:26 +00:00
# Test if required variables are set
2025-02-05 15:29:07 +00:00
[ [ " ${ CTID :- } " ] ] || { msg_error "You need to set 'CTID' variable." ; exit 203; }
[ [ " ${ PCT_OSTYPE :- } " ] ] || { msg_error "You need to set 'PCT_OSTYPE' variable." ; exit 204; }
2022-02-23 11:52:49 +00:00
2023-05-15 23:15:26 +00:00
# Test if ID is valid
2025-02-05 15:29:07 +00:00
[ " $CTID " -ge "100" ] || { msg_error "ID cannot be less than 100." ; exit 205; }
2022-02-23 11:52:49 +00:00
2023-05-15 23:15:26 +00:00
# Test if ID is in use
2022-02-23 11:52:49 +00:00
if pct status $CTID & >/dev/null; then
2022-05-21 11:11:10 +00:00
echo -e " ID ' $CTID ' is already in use. "
2022-02-23 11:52:49 +00:00
unset CTID
2025-02-05 15:29:07 +00:00
msg_error "Cannot use ID that is already in use."
exit 206
2022-02-23 11:52:49 +00:00
fi
2023-05-15 23:15:26 +00:00
# Get template storage
2022-02-23 11:52:49 +00:00
TEMPLATE_STORAGE = $( select_storage template) || exit
2022-04-25 14:27:30 +00:00
msg_ok " Using ${ BL } $TEMPLATE_STORAGE ${ CL } ${ GN } for Template Storage. "
2022-02-23 11:52:49 +00:00
2023-05-15 23:15:26 +00:00
# Get container storage
2022-02-23 11:52:49 +00:00
CONTAINER_STORAGE = $( select_storage container) || exit
2022-04-25 14:27:30 +00:00
msg_ok " Using ${ BL } $CONTAINER_STORAGE ${ CL } ${ GN } for Container Storage. "
2022-02-23 11:52:49 +00:00
2023-05-15 23:15:26 +00:00
# Update LXC template list
2022-04-16 13:52:57 +00:00
msg_info "Updating LXC Template List"
2022-02-23 11:52:49 +00:00
pveam update >/dev/null
2022-04-16 15:57:11 +00:00
msg_ok "Updated LXC Template List"
2022-02-23 11:52:49 +00:00
2023-05-15 23:15:26 +00:00
# Get LXC template string
2022-02-23 11:52:49 +00:00
TEMPLATE_SEARCH = ${ PCT_OSTYPE } -${ PCT_OSVERSION :- }
mapfile -t TEMPLATES < <( pveam available -section system | sed -n " s/.*\( $TEMPLATE_SEARCH .*\)/\1/p " | sort -t - -k 2 -V)
2025-02-05 15:29:07 +00:00
[ ${# TEMPLATES [@] } -gt 0 ] || { msg_error " Unable to find a template when searching for ' $TEMPLATE_SEARCH '. " ; exit 207; }
2022-02-23 11:52:49 +00:00
TEMPLATE = " ${ TEMPLATES [-1] } "
2023-05-15 23:15:26 +00:00
# Download LXC template if needed
2022-02-23 11:52:49 +00:00
if ! pveam list $TEMPLATE_STORAGE | grep -q $TEMPLATE ; then
2022-04-16 13:52:57 +00:00
msg_info "Downloading LXC Template"
2023-02-03 15:53:08 +00:00
pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null ||
2025-02-05 15:29:07 +00:00
msg_error "A problem occured while downloading the LXC template."
exit 208
2022-04-20 18:27:25 +00:00
msg_ok "Downloaded LXC Template"
2022-02-23 11:52:49 +00:00
fi
2023-05-15 23:15:26 +00:00
# Combine all options
2022-02-23 11:52:49 +00:00
DEFAULT_PCT_OPTIONS = (
-arch $( dpkg --print-architecture) )
2022-10-30 00:08:41 +00:00
PCT_OPTIONS = ( ${ PCT_OPTIONS [@] :- ${ DEFAULT_PCT_OPTIONS [@] } } )
[ [ " ${ PCT_OPTIONS [@] } " = ~ " -rootfs " ] ] || PCT_OPTIONS += ( -rootfs $CONTAINER_STORAGE :${ PCT_DISK_SIZE :- 8 } )
2022-02-23 11:52:49 +00:00
2023-05-15 23:15:26 +00:00
# Create container
2022-04-16 14:05:03 +00:00
msg_info "Creating LXC Container"
2025-02-05 15:45:47 +00:00
pct create $CTID ${ TEMPLATE_STORAGE } :vztmpl/${ TEMPLATE } ${ PCT_OPTIONS [@] } >/dev/null || { msg_error "A problem occured while trying to create container." ; exit 200; }
2022-04-16 15:46:18 +00:00
msg_ok " LXC Container ${ BL } $CTID ${ CL } ${ GN } was successfully created. "
2025-02-05 15:29:07 +00:00