@@ -36,7 +36,7 @@ trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
36
36
37
37
# This function handles errors
38
38
function 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
40
40
printf " \e[?25h"
41
41
local exit_code=" $? "
42
42
local line_number=" $1 "
@@ -51,13 +51,13 @@ function spinner() {
51
51
local frames=(' ⠋' ' ⠙' ' ⠹' ' ⠸' ' ⠼' ' ⠴' ' ⠦' ' ⠧' ' ⠇' ' ⠏' )
52
52
local spin_i=0
53
53
local interval=0.1
54
- printf " \e[?25l"
54
+ printf " \e[?25l"
55
55
56
56
local color=" ${YWB} "
57
57
58
58
while true ; do
59
59
printf " \r ${color} %s${CL} " " ${frames[spin_i]} "
60
- spin_i=$(( (spin_i + 1 ) % ${# frames[@]} ))
60
+ spin_i=$(( (spin_i + 1 ) % ${# frames[@]} ))
61
61
sleep " $interval "
62
62
done
63
63
}
@@ -70,17 +70,24 @@ function msg_info() {
70
70
SPINNER_PID=$!
71
71
}
72
72
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
+
73
80
# This function displays a success message with a green color.
74
81
function 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
76
83
printf " \e[?25h"
77
84
local msg=" $1 "
78
85
echo -e " ${BFR}${CM}${GN}${msg}${CL} "
79
86
}
80
87
81
88
# This function displays a error message with a red color.
82
89
function 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
84
91
printf " \e[?25h"
85
92
local msg=" $1 "
86
93
echo -e " ${BFR}${CROSS}${RD}${msg}${CL} "
@@ -113,9 +120,12 @@ function select_storage() {
113
120
CONTENT=' vztmpl'
114
121
CONTENT_LABEL=' Container template'
115
122
;;
116
- * ) false || { msg_error " Invalid storage class." ; exit 201; };
123
+ * ) false || {
124
+ msg_error " Invalid storage class."
125
+ exit 201
126
+ } ;;
117
127
esac
118
-
128
+
119
129
# This Queries all storage locations
120
130
local -a MENU
121
131
while read -r line; do
@@ -129,34 +139,60 @@ function select_storage() {
129
139
fi
130
140
MENU+=(" $TAG " " $ITEM " " OFF" )
131
141
done < <( pvesm status -content $CONTENT | awk ' NR>1' )
132
-
142
+
133
143
# Select storage location
134
- if [ $(( ${# MENU[@]} / 3 )) -eq 1 ]; then
144
+ if [ $(( ${# MENU[@]} / 3 )) -eq 1 ]; then
135
145
printf ${MENU[0]}
136
146
else
137
147
local STORAGE
138
148
while [ -z " ${STORAGE: +x} " ]; do
139
149
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
+ }
143
156
if [ $? -ne 0 ]; then
144
157
echo -e " ${CROSS}${RD} Menu aborted by user.${CL} "
145
- exit 0
158
+ exit 0
146
159
fi
147
160
done
148
161
printf " %s" " $STORAGE "
149
162
fi
150
163
}
151
164
# 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
+ }
154
173
155
174
# 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
+ }
157
193
158
194
# 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
160
196
echo -e " ID '$CTID ' is already in use."
161
197
unset CTID
162
198
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."
173
209
174
210
# Update LXC template list
175
211
msg_info " Updating LXC Template List"
212
+ check_network
176
213
pveam update > /dev/null
177
214
msg_ok " Updated LXC Template List"
178
215
179
216
# Get LXC template string
180
217
TEMPLATE_SEARCH=${PCT_OSTYPE} -${PCT_OSVERSION:- }
181
218
mapfile -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
+ }
183
223
TEMPLATE=" ${TEMPLATES[-1]} "
184
-
185
224
TEMPLATE_PATH=" /var/lib/vz/template/cache/$TEMPLATE "
186
225
# 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."
188
228
[[ -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
193
246
fi
247
+ msg_ok " LXC Template is ready to use."
194
248
195
249
# 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
198
252
199
253
# Combine all options
200
254
PCT_OPTIONS=(${PCT_OPTIONS[@]:- ${DEFAULT_PCT_OPTIONS[@]} } )
201
255
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs " $CONTAINER_STORAGE :${PCT_DISK_SIZE:- 8} " )
202
256
203
- # Create container with template integrity check
204
257
msg_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
+
212
270
msg_ok " Re-downloaded LXC Template"
271
+
213
272
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."
215
274
exit 200
216
275
fi
276
+ else
277
+ msg_error " Container creation failed, but template is not corrupted."
278
+ exit 209
217
279
fi
280
+ fi
218
281
msg_ok " LXC Container ${BL} $CTID ${CL} ${GN} was successfully created."
0 commit comments