@@ -36,7 +36,7 @@ trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
3636
3737# This function handles errors
3838function error_handler() {
39- if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
39+ if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
4040 printf " \e[?25h"
4141 local exit_code=" $? "
4242 local line_number=" $1 "
@@ -51,13 +51,13 @@ function spinner() {
5151 local frames=(' ⠋' ' ⠙' ' ⠹' ' ⠸' ' ⠼' ' ⠴' ' ⠦' ' ⠧' ' ⠇' ' ⠏' )
5252 local spin_i=0
5353 local interval=0.1
54- printf " \e[?25l"
54+ printf " \e[?25l"
5555
5656 local color=" ${YWB} "
5757
5858 while true ; do
5959 printf " \r ${color} %s${CL} " " ${frames[spin_i]} "
60- spin_i=$(( (spin_i + 1 ) % ${# frames[@]} ))
60+ spin_i=$(( (spin_i + 1 ) % ${# frames[@]} ))
6161 sleep " $interval "
6262 done
6363}
@@ -70,17 +70,24 @@ function msg_info() {
7070 SPINNER_PID=$!
7171}
7272
73+ function msg_warn() {
74+ if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
75+ printf " \e[?25h"
76+ local msg=" $1 "
77+ echo -e " ${BFR}${INFO}${YWB}${msg}${CL} "
78+ }
79+
7380# This function displays a success message with a green color.
7481function msg_ok() {
75- if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
82+ if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
7683 printf " \e[?25h"
7784 local msg=" $1 "
7885 echo -e " ${BFR}${CM}${GN}${msg}${CL} "
7986}
8087
8188# This function displays a error message with a red color.
8289function msg_error() {
83- if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
90+ if [ -n " $SPINNER_PID " ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
8491 printf " \e[?25h"
8592 local msg=" $1 "
8693 echo -e " ${BFR}${CROSS}${RD}${msg}${CL} "
@@ -113,9 +120,12 @@ function select_storage() {
113120 CONTENT=' vztmpl'
114121 CONTENT_LABEL=' Container template'
115122 ;;
116- * ) false || { msg_error " Invalid storage class." ; exit 201; };
123+ * ) false || {
124+ msg_error " Invalid storage class."
125+ exit 201
126+ } ;;
117127 esac
118-
128+
119129 # This Queries all storage locations
120130 local -a MENU
121131 while read -r line; do
@@ -129,34 +139,60 @@ function select_storage() {
129139 fi
130140 MENU+=(" $TAG " " $ITEM " " OFF" )
131141 done < <( pvesm status -content $CONTENT | awk ' NR>1' )
132-
142+
133143 # Select storage location
134- if [ $(( ${# MENU[@]} / 3 )) -eq 1 ]; then
144+ if [ $(( ${# MENU[@]} / 3 )) -eq 1 ]; then
135145 printf ${MENU[0]}
136146 else
137147 local STORAGE
138148 while [ -z " ${STORAGE: +x} " ]; do
139149 STORAGE=$( whiptail --backtitle " Proxmox VE Helper Scripts" --title " Storage Pools" --radiolist \
140- " Which storage pool you would like to use for the ${CONTENT_LABEL,,} ?\nTo make a selection, use the Spacebar.\n" \
141- 16 $(( $MSG_MAX_LENGTH + 23 )) 6 \
142- " ${MENU[@]} " 3>&1 1>&2 2>&3 ) || { msg_error " Menu aborted." ; exit 202; }
150+ " Which storage pool you would like to use for the ${CONTENT_LABEL,,} ?\nTo make a selection, use the Spacebar.\n" \
151+ 16 $(( $MSG_MAX_LENGTH + 23 )) 6 \
152+ " ${MENU[@]} " 3>&1 1>&2 2>&3 ) || {
153+ msg_error " Menu aborted."
154+ exit 202
155+ }
143156 if [ $? -ne 0 ]; then
144157 echo -e " ${CROSS}${RD} Menu aborted by user.${CL} "
145- exit 0
158+ exit 0
146159 fi
147160 done
148161 printf " %s" " $STORAGE "
149162 fi
150163}
151164# Test if required variables are set
152- [[ " ${CTID:- } " ]] || { msg_error " You need to set 'CTID' variable." ; exit 203; }
153- [[ " ${PCT_OSTYPE:- } " ]] || { msg_error " You need to set 'PCT_OSTYPE' variable." ; exit 204; }
165+ [[ " ${CTID:- } " ]] || {
166+ msg_error " You need to set 'CTID' variable."
167+ exit 203
168+ }
169+ [[ " ${PCT_OSTYPE:- } " ]] || {
170+ msg_error " You need to set 'PCT_OSTYPE' variable."
171+ exit 204
172+ }
154173
155174# Test if ID is valid
156- [ " $CTID " -ge " 100" ] || { msg_error " ID cannot be less than 100." ; exit 205; }
175+ [ " $CTID " -ge " 100" ] || {
176+ msg_error " ID cannot be less than 100."
177+ exit 205
178+ }
179+
180+ # Check for network connectivity (IPv4 & IPv6)
181+ function check_network() {
182+ local CHECK_URLS=(" 8.8.8.8" " 1.1.1.1" " 9.9.9.9" " 2606:4700:4700::1111" " 2001:4860:4860::8888" " 2620:fe::fe" )
183+
184+ for url in " ${CHECK_URLS[@]} " ; do
185+ if ping -c 1 -W 2 " $url " & > /dev/null; then
186+ return 0 # Success: At least one connection works
187+ fi
188+ done
189+
190+ msg_error " No network connection detected. Check your internet connection."
191+ exit 101
192+ }
157193
158194# Test if ID is in use
159- if pct status $CTID & > /dev/null; then
195+ if qm status " $CTID " & > /dev/null || pct status " $CTID " & > /dev/null; then
160196 echo -e " ID '$CTID ' is already in use."
161197 unset CTID
162198 msg_error " Cannot use ID that is already in use."
@@ -173,46 +209,73 @@ msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
173209
174210# Update LXC template list
175211msg_info " Updating LXC Template List"
212+ check_network
176213pveam update > /dev/null
177214msg_ok " Updated LXC Template List"
178215
179216# Get LXC template string
180217TEMPLATE_SEARCH=${PCT_OSTYPE} -${PCT_OSVERSION:- }
181218mapfile -t TEMPLATES < <( pveam available -section system | sed -n " s/.*\($TEMPLATE_SEARCH .*\)/\1/p" | sort -t - -k 2 -V)
182- [ ${# TEMPLATES[@]} -gt 0 ] || { msg_error " Unable to find a template when searching for '$TEMPLATE_SEARCH '." ; exit 207; }
219+ [ ${# TEMPLATES[@]} -gt 0 ] || {
220+ msg_error " Unable to find a template when searching for '$TEMPLATE_SEARCH '."
221+ exit 207
222+ }
183223TEMPLATE=" ${TEMPLATES[-1]} "
184-
185224TEMPLATE_PATH=" /var/lib/vz/template/cache/$TEMPLATE "
186225# Check if template exists, if corrupt remove and redownload
187- if ! pveam list " $TEMPLATE_STORAGE " | grep -q " $TEMPLATE " ; then
226+ if ! pveam list " $TEMPLATE_STORAGE " | grep -q " $TEMPLATE " || ! zstdcat " $TEMPLATE_PATH " | tar -tf - > /dev/null 2>&1 ; then
227+ msg_warn " Template $TEMPLATE not found in storage or seems to be corrupted. Redownloading."
188228 [[ -f " $TEMPLATE_PATH " ]] && rm -f " $TEMPLATE_PATH "
189- msg_info " Downloading LXC Template"
190- pveam download " $TEMPLATE_STORAGE " " $TEMPLATE " > /dev/null ||
191- { msg_error " A problem occurred while downloading the LXC template." ; exit 208; }
192- msg_ok " Downloaded LXC Template"
229+
230+ # Download with 3 attempts
231+ for attempt in {1..3}; do
232+ msg_info " Attempt $attempt : Downloading LXC template..."
233+
234+ if timeout 120 pveam download " $TEMPLATE_STORAGE " " $TEMPLATE " > /dev/null; then
235+ msg_ok " Template download successful."
236+ break
237+ fi
238+
239+ if [ $attempt -eq 3 ]; then
240+ msg_error " Three failed attempts. Aborting."
241+ exit 208
242+ fi
243+
244+ sleep $(( attempt * 5 ))
245+ done
193246fi
247+ msg_ok " LXC Template is ready to use."
194248
195249# Check and fix subuid/subgid
196- grep -q " root:100000:65536" /etc/subuid || echo " root:100000:65536" >> /etc/subuid
197- grep -q " root:100000:65536" /etc/subgid || echo " root:100000:65536" >> /etc/subgid
250+ grep -q " root:100000:65536" /etc/subuid || echo " root:100000:65536" >> /etc/subuid
251+ grep -q " root:100000:65536" /etc/subgid || echo " root:100000:65536" >> /etc/subgid
198252
199253# Combine all options
200254PCT_OPTIONS=(${PCT_OPTIONS[@]:- ${DEFAULT_PCT_OPTIONS[@]} } )
201255[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs " $CONTAINER_STORAGE :${PCT_DISK_SIZE:- 8} " )
202256
203- # Create container with template integrity check
204257msg_info " Creating LXC Container"
205- if ! pct create " $CTID " " ${TEMPLATE_STORAGE} :vztmpl/${TEMPLATE} " " ${PCT_OPTIONS[@]} " & > /dev/null; then
206- [[ -f " $TEMPLATE_PATH " ]] && rm -f " $TEMPLATE_PATH "
207-
208- msg_ok " Template integrity check completed"
209- pveam download " $TEMPLATE_STORAGE " " $TEMPLATE " > /dev/null ||
210- { msg_error " A problem occurred while re-downloading the LXC template." ; exit 208; }
211-
258+ if ! pct create " $CTID " " ${TEMPLATE_STORAGE} :vztmpl/${TEMPLATE} " " ${PCT_OPTIONS[@]} " & > /dev/null; then
259+ msg_error " Container creation failed. Checking if template is corrupted."
260+
261+ if ! zstdcat " $TEMPLATE_PATH " | tar -tf - > /dev/null 2>&1 ; then
262+ msg_error " Template appears to be corrupted. Removing and re-downloading."
263+ rm -f " $TEMPLATE_PATH "
264+
265+ if ! timeout 120 pveam download " $TEMPLATE_STORAGE " " $TEMPLATE " > /dev/null; then
266+ msg_error " Failed to re-download template."
267+ exit 208
268+ fi
269+
212270 msg_ok " Re-downloaded LXC Template"
271+
213272 if ! pct create " $CTID " " ${TEMPLATE_STORAGE} :vztmpl/${TEMPLATE} " " ${PCT_OPTIONS[@]} " & > /dev/null; then
214- msg_error " A problem occurred while trying to create container after re-downloading template."
273+ msg_error " Container creation failed after re-downloading template."
215274 exit 200
216275 fi
276+ else
277+ msg_error " Container creation failed, but template is not corrupted."
278+ exit 209
217279 fi
280+ fi
218281msg_ok " LXC Container ${BL} $CTID ${CL} ${GN} was successfully created."
0 commit comments