Update create_lxc.sh
This commit is contained in:
parent
0c903faa0b
commit
b444636864
@ -205,7 +205,6 @@ if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# This checks for the presence of valid Container Storage and Template Storage locations
|
# This checks for the presence of valid Container Storage and Template Storage locations
|
||||||
msg_info "Validating storage"
|
|
||||||
if ! check_storage_support "rootdir"; then
|
if ! check_storage_support "rootdir"; then
|
||||||
msg_error "No valid storage found for 'rootdir' [Container]"
|
msg_error "No valid storage found for 'rootdir' [Container]"
|
||||||
exit 1
|
exit 1
|
||||||
@ -280,158 +279,196 @@ fi
|
|||||||
# Update LXC template list
|
# Update LXC template list
|
||||||
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
|
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
|
||||||
case "$PCT_OSTYPE" in
|
case "$PCT_OSTYPE" in
|
||||||
debian | ubuntu)
|
debian | ubuntu) TEMPLATE_PATTERN="-standard_" ;;
|
||||||
TEMPLATE_PATTERN="-standard_"
|
alpine | fedora | rocky | centos) TEMPLATE_PATTERN="-default_" ;;
|
||||||
;;
|
*) TEMPLATE_PATTERN="" ;;
|
||||||
alpine | fedora | rocky | centos)
|
|
||||||
TEMPLATE_PATTERN="-default_"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
TEMPLATE_PATTERN=""
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# 1. Check local templates first
|
|
||||||
msg_info "Searching for template '$TEMPLATE_SEARCH'"
|
msg_info "Searching for template '$TEMPLATE_SEARCH'"
|
||||||
mapfile -t TEMPLATES < <(
|
|
||||||
pveam list "$TEMPLATE_STORAGE" |
|
# 1. get / check local templates
|
||||||
|
mapfile -t LOCAL_TEMPLATES < <(
|
||||||
|
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
|
||||||
awk -v s="$TEMPLATE_SEARCH" -v p="$TEMPLATE_PATTERN" '$1 ~ s && $1 ~ p {print $1}' |
|
awk -v s="$TEMPLATE_SEARCH" -v p="$TEMPLATE_PATTERN" '$1 ~ s && $1 ~ p {print $1}' |
|
||||||
sed 's/.*\///' | sort -t - -k 2 -V
|
sed 's/.*\///' | sort -t - -k 2 -V
|
||||||
)
|
)
|
||||||
|
|
||||||
if [ ${#TEMPLATES[@]} -gt 0 ]; then
|
# 2. get online templates
|
||||||
|
pveam update >/dev/null 2>&1 || msg_warn "Could not update template catalog (pveam update failed)."
|
||||||
|
mapfile -t ONLINE_TEMPLATES < <(
|
||||||
|
pveam available -section system 2>/dev/null |
|
||||||
|
sed -n "s/.*\($TEMPLATE_SEARCH.*$TEMPLATE_PATTERN.*\)/\1/p" |
|
||||||
|
sort -t - -k 2 -V
|
||||||
|
)
|
||||||
|
ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]:-}"
|
||||||
|
|
||||||
|
# 3. Local vs Online
|
||||||
|
if [ ${#LOCAL_TEMPLATES[@]} -gt 0 ]; then
|
||||||
|
TEMPLATE="${LOCAL_TEMPLATES[-1]}"
|
||||||
TEMPLATE_SOURCE="local"
|
TEMPLATE_SOURCE="local"
|
||||||
else
|
else
|
||||||
msg_info "No local template found, checking online repository"
|
TEMPLATE="$ONLINE_TEMPLATE"
|
||||||
pveam update >/dev/null 2>&1
|
|
||||||
mapfile -t TEMPLATES < <(
|
|
||||||
pveam update >/dev/null 2>&1 &&
|
|
||||||
pveam available -section system |
|
|
||||||
sed -n "s/.*\($TEMPLATE_SEARCH.*$TEMPLATE_PATTERN.*\)/\1/p" |
|
|
||||||
sort -t - -k 2 -V
|
|
||||||
)
|
|
||||||
TEMPLATE_SOURCE="online"
|
TEMPLATE_SOURCE="online"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TEMPLATE="${TEMPLATES[-1]}"
|
# 4. Getting Path (universal, also for nfs/cifs)
|
||||||
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null ||
|
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
|
||||||
echo "/var/lib/vz/template/cache/$TEMPLATE")"
|
if [[ -z "$TEMPLATE_PATH" ]]; then
|
||||||
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
|
TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
|
||||||
|
if [[ -n "$TEMPLATE_BASE" ]]; then
|
||||||
msg_debug "TEMPLATE_SEARCH=$TEMPLATE_SEARCH"
|
TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
|
||||||
msg_debug "TEMPLATES=(${TEMPLATES[*]})"
|
fi
|
||||||
msg_debug "Selected TEMPLATE=$TEMPLATE"
|
|
||||||
msg_debug "TEMPLATE_PATH=$TEMPLATE_PATH"
|
|
||||||
|
|
||||||
# 4. Validate template (exists & not corrupted)
|
|
||||||
TEMPLATE_VALID=1
|
|
||||||
if [ ! -s "$TEMPLATE_PATH" ]; then
|
|
||||||
TEMPLATE_VALID=0
|
|
||||||
elif ! tar --use-compress-program=zstdcat -tf "$TEMPLATE_PATH" >/dev/null 2>&1; then
|
|
||||||
TEMPLATE_VALID=0
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$TEMPLATE_VALID" -eq 0 ]; then
|
if [[ -z "$TEMPLATE_PATH" ]]; then
|
||||||
msg_warn "Template $TEMPLATE is missing or corrupted. Re-downloading."
|
msg_error "Unable to resolve template path for $TEMPLATE_STORAGE. Check storage type and permissions."
|
||||||
|
exit 220
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
|
||||||
|
msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
|
||||||
|
|
||||||
|
# 5. Validation
|
||||||
|
NEED_DOWNLOAD=0
|
||||||
|
if [[ ! -f "$TEMPLATE_PATH" ]]; then
|
||||||
|
msg_info "Template not present locally – will download."
|
||||||
|
NEED_DOWNLOAD=1
|
||||||
|
elif [[ ! -r "$TEMPLATE_PATH" ]]; then
|
||||||
|
msg_error "Template file exists but is not readable – check permissions."
|
||||||
|
exit 221
|
||||||
|
elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||||
|
msg_warn "Template file too small (<1MB) – re-downloading."
|
||||||
|
NEED_DOWNLOAD=1
|
||||||
|
elif ! zstdcat "$TEMPLATE_PATH" | tar -tf - &>/dev/null; then
|
||||||
|
msg_warn "Template appears corrupted – re-downloading."
|
||||||
|
NEED_DOWNLOAD=1
|
||||||
|
else
|
||||||
|
msg_ok "Template $TEMPLATE is present and valid."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 6. Update-Check (if local exist)
|
||||||
|
if [[ "$TEMPLATE_SOURCE" == "local" && -n "$ONLINE_TEMPLATE" && "$TEMPLATE" != "$ONLINE_TEMPLATE" ]]; then
|
||||||
|
msg_warn "Local template is outdated: $TEMPLATE (latest available: $ONLINE_TEMPLATE)"
|
||||||
|
if whiptail --yesno "A newer template is available:\n$ONLINE_TEMPLATE\n\nDo you want to download and use it instead?" 12 70; then
|
||||||
|
TEMPLATE="$ONLINE_TEMPLATE"
|
||||||
|
NEED_DOWNLOAD=1
|
||||||
|
else
|
||||||
|
msg_info "Continuing with local template $TEMPLATE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7. Download if needed
|
||||||
|
if [[ "$NEED_DOWNLOAD" -eq 1 ]]; then
|
||||||
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
||||||
for attempt in {1..3}; do
|
for attempt in {1..3}; do
|
||||||
msg_info "Attempt $attempt: Downloading LXC template..."
|
msg_info "Attempt $attempt: Downloading template $TEMPLATE to $TEMPLATE_STORAGE"
|
||||||
if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1; then
|
if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1; then
|
||||||
msg_ok "Template download successful."
|
msg_ok "Template download successful."
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if [ $attempt -eq 3 ]; then
|
if [ $attempt -eq 3 ]; then
|
||||||
msg_error "Failed after 3 attempts. Please check network access or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
|
msg_error "Failed after 3 attempts. Please check network access, permissions, or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
|
||||||
exit 208
|
exit 222
|
||||||
fi
|
fi
|
||||||
sleep $((attempt * 5))
|
sleep $((attempt * 5))
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_info "Creating LXC Container"
|
# 8. Final Check – Template usability
|
||||||
# Check and fix subuid/subgid
|
if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then
|
||||||
|
msg_error "Template $TEMPLATE not available in storage $TEMPLATE_STORAGE after download."
|
||||||
|
exit 223
|
||||||
|
fi
|
||||||
|
msg_ok "Template $TEMPLATE is ready for container creation."
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Create LXC Container with validation, recovery and debug option
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
msg_info "Creating LXC container"
|
||||||
|
|
||||||
|
# Ensure subuid/subgid entries exist
|
||||||
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
|
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
|
||||||
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
|
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
|
||||||
|
|
||||||
# Combine all options
|
# Assemble pct options
|
||||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
||||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
|
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
|
||||||
|
|
||||||
# Secure creation of the LXC container with lock and template check
|
# Secure with lockfile
|
||||||
lockfile="/tmp/template.${TEMPLATE}.lock"
|
lockfile="/tmp/template.${TEMPLATE}.lock"
|
||||||
msg_debug "Creating lockfile: $lockfile"
|
|
||||||
exec 9>"$lockfile" || {
|
exec 9>"$lockfile" || {
|
||||||
msg_error "Failed to create lock file '$lockfile'."
|
msg_error "Failed to create lock file '$lockfile'."
|
||||||
exit 200
|
exit 200
|
||||||
}
|
}
|
||||||
flock -w 60 9 || {
|
flock -w 60 9 || {
|
||||||
msg_error "Timeout while waiting for template lock"
|
msg_error "Timeout while waiting for template lock."
|
||||||
exit 211
|
exit 211
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGFILE="/tmp/pct_create_${CTID}.log"
|
||||||
msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
|
msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
|
||||||
|
msg_debug "Logfile: $LOGFILE"
|
||||||
|
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
# First attempt
|
||||||
|
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then
|
||||||
msg_error "Container creation failed on ${TEMPLATE_STORAGE}. Checking template..."
|
msg_error "Container creation failed on ${TEMPLATE_STORAGE}. Checking template..."
|
||||||
|
|
||||||
|
# Validate template file
|
||||||
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||||
msg_error "Template file too small or missing – re-downloading."
|
msg_warn "Template file too small or missing – re-downloading."
|
||||||
rm -f "$TEMPLATE_PATH"
|
rm -f "$TEMPLATE_PATH"
|
||||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
|
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
|
||||||
elif ! zstdcat "$TEMPLATE_PATH" | tar -tf - &>/dev/null; then
|
elif ! zstdcat "$TEMPLATE_PATH" | tar -tf - &>/dev/null; then
|
||||||
msg_error "Template appears to be corrupted – re-downloading."
|
msg_warn "Template appears corrupted – re-downloading."
|
||||||
rm -f "$TEMPLATE_PATH"
|
rm -f "$TEMPLATE_PATH"
|
||||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
|
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
|
||||||
else
|
fi
|
||||||
# --- NEW FALLBACK LOGIC ---
|
|
||||||
|
# Retry after repair
|
||||||
|
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
||||||
|
# Fallback to local storage
|
||||||
if [[ "$TEMPLATE_STORAGE" != "local" ]]; then
|
if [[ "$TEMPLATE_STORAGE" != "local" ]]; then
|
||||||
msg_warn "Retrying container creation with fallback to local template storage..."
|
msg_warn "Retrying container creation with fallback to local storage..."
|
||||||
LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
||||||
if [ ! -f "$LOCAL_TEMPLATE_PATH" ]; then
|
if [ ! -f "$LOCAL_TEMPLATE_PATH" ]; then
|
||||||
msg_info "Downloading template to local..."
|
msg_info "Downloading template to local..."
|
||||||
msg_debug "pveam download local $TEMPLATE"
|
pveam download local "$TEMPLATE" >/dev/null 2>&1
|
||||||
pveam download local "$TEMPLATE"
|
|
||||||
fi
|
fi
|
||||||
msg_debug "pct create command (fallback): pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
|
if pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
||||||
if pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
msg_ok "Container successfully created using local fallback."
|
||||||
msg_ok "Container successfully created using fallback to local template storage."
|
|
||||||
else
|
else
|
||||||
msg_error "Container creation failed even with fallback to local."
|
msg_error "Container creation failed even with local fallback. See $LOGFILE"
|
||||||
|
# Ask user if they want debug output
|
||||||
|
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
|
||||||
|
set -x
|
||||||
|
bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE"
|
||||||
|
set +x
|
||||||
|
fi
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
# Skip remaining error handling since fallback worked
|
|
||||||
continue
|
|
||||||
else
|
else
|
||||||
msg_error "Template is valid, but container creation still failed on local."
|
msg_error "Container creation failed on local storage. See $LOGFILE"
|
||||||
|
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
|
||||||
|
set -x
|
||||||
|
bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE"
|
||||||
|
set +x
|
||||||
|
fi
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Verify container exists
|
||||||
if ! pct list | awk '{print $1}' | grep -qx "$CTID"; then
|
if ! pct list | awk '{print $1}' | grep -qx "$CTID"; then
|
||||||
msg_error "Container ID $CTID not listed in 'pct list' – unexpected failure."
|
msg_error "Container ID $CTID not listed in 'pct list'. See $LOGFILE"
|
||||||
exit 215
|
exit 215
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Verify config rootfs
|
||||||
if ! grep -q '^rootfs:' "/etc/pve/lxc/$CTID.conf"; then
|
if ! grep -q '^rootfs:' "/etc/pve/lxc/$CTID.conf"; then
|
||||||
msg_error "RootFS entry missing in container config – storage not correctly assigned."
|
msg_error "RootFS entry missing in container config. See $LOGFILE"
|
||||||
exit 216
|
exit 216
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -q '^hostname:' "/etc/pve/lxc/$CTID.conf"; then
|
|
||||||
CT_HOSTNAME=$(grep '^hostname:' "/etc/pve/lxc/$CTID.conf" | awk '{print $2}')
|
|
||||||
if [[ ! "$CT_HOSTNAME" =~ ^[a-z0-9-]+$ ]]; then
|
|
||||||
msg_warn "Hostname '$CT_HOSTNAME' contains invalid characters – may cause issues with networking or DNS."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${PCT_RAM_SIZE:-2048}" -lt 1024 ]]; then
|
|
||||||
msg_warn "Configured RAM (${PCT_RAM_SIZE}MB) is below 1024MB – some apps may not work properly."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# comment out 19.08.2025 - PCT Options not correct, message every new lxc (without fuse too)
|
|
||||||
# if [[ "${PCT_UNPRIVILEGED:-1}" == "1" && " ${PCT_OPTIONS[*]} " == *"fuse=1"* ]]; then
|
|
||||||
# msg_warn "Unprivileged container with FUSE may fail unless extra device mappings are configured."
|
|
||||||
# fi
|
|
||||||
|
|
||||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user