refactor(build.func): extract nested functions, recursion guard, GPU timeout, pvesm cache

Changes:
- Extract 7 functions from build_container() to module level:
  is_gpu_app(), detect_gpu_devices(), configure_usb_passthrough(),
  configure_gpu_passthrough(), configure_additional_devices(),
  get_container_gid(), pvesm_status_cached()
  Prevents function re-declaration on recursive retry attempts.

- Add recursion guard (_BUILD_DEPTH max 3) to build_container()
  to prevent infinite OOM→retry→OOM→retry loops (exit code 250).

- Add 30s timeout to multi-GPU selection prompt with auto-select
  fallback for the first available GPU type.

- Add pvesm_status_cached() with associative array cache keyed by
  arguments. Eliminates ~10 redundant pvesm subprocess calls during
  a single container creation flow. Applied to: check_storage_support(),
  select_storage(), resolve_storage_preselect(), create_lxc_container()
  rootdir/vztmpl validation, validate_storage_space(),
  choose_and_set_storage_for_file(), and settings validation.

- Simplify check_storage_support() from while-read loop to single
  pipeline with grep.
This commit is contained in:
MickLesk
2026-03-23 20:26:36 +01:00
parent c3cb983085
commit 6b9930c8df

View File

@@ -873,10 +873,10 @@ choose_and_set_storage_for_file() {
local content="rootdir"
[[ "$class" == "template" ]] && content="vztmpl"
local count
count=$(pvesm status -content "$content" | awk 'NR>1{print $1}' | wc -l)
count=$(pvesm_status_cached -content "$content" | awk 'NR>1{print $1}' | wc -l)
if [[ "$count" -eq 1 ]]; then
STORAGE_RESULT=$(pvesm status -content "$content" | awk 'NR>1{print $1; exit}')
STORAGE_RESULT=$(pvesm_status_cached -content "$content" | awk 'NR>1{print $1; exit}')
STORAGE_INFO=""
# Validate storage space for auto-picked container storage
@@ -1213,7 +1213,7 @@ load_vars_file() {
var_container_storage | var_template_storage)
# Validate that the storage exists and is active on the current node
local _storage_status
_storage_status=$(pvesm status 2>/dev/null | awk -v s="$var_val" '$1 == s { print $3 }')
_storage_status=$(pvesm_status_cached | awk -v s="$var_val" '$1 == s { print $3 }')
if [[ -z "$_storage_status" ]]; then
msg_warn "Storage '$var_val' from $file not found on this node, ignoring"
continue
@@ -3495,6 +3495,237 @@ start() {
# SECTION 8: CONTAINER CREATION & DEPLOYMENT
# ==============================================================================
# ------------------------------------------------------------------------------
# GPU/USB PASSTHROUGH CONFIGURATION (extracted from build_container for reuse)
# These functions reference globals: LXC_CONFIG, CT_TYPE, CTID, ENABLE_TUN,
# GPU_TYPE, var_gpu, ENABLE_FUSE — all set before invocation in build_container.
# ------------------------------------------------------------------------------
# Check if GPU passthrough is enabled
# Returns true only if var_gpu is explicitly set to "yes"
is_gpu_app() {
[[ "${var_gpu:-no}" == "yes" ]] && return 0
return 1
}
# Detect all available GPU devices
detect_gpu_devices() {
INTEL_DEVICES=()
AMD_DEVICES=()
NVIDIA_DEVICES=()
local pci_vga_info
pci_vga_info=$(lspci -nn 2>/dev/null | grep -E "VGA|Display|3D" || true)
if [[ -z "$pci_vga_info" ]]; then
msg_debug "No VGA/Display/3D PCI devices found"
return 0
fi
if grep -q "\[8086:" <<<"$pci_vga_info"; then
msg_custom "🎮" "${BL}" "Detected Intel GPU"
if [[ -d /dev/dri ]]; then
for d in /dev/dri/renderD* /dev/dri/card*; do
[[ -e "$d" ]] && INTEL_DEVICES+=("$d")
done
fi
fi
if grep -qE "\[1002:|\[1022:" <<<"$pci_vga_info"; then
msg_custom "🎮" "${RD}" "Detected AMD GPU"
if [[ -d /dev/dri ]]; then
if [[ ${#INTEL_DEVICES[@]} -eq 0 ]]; then
for d in /dev/dri/renderD* /dev/dri/card*; do
[[ -e "$d" ]] && AMD_DEVICES+=("$d")
done
fi
fi
fi
if grep -q "\[10de:" <<<"$pci_vga_info"; then
msg_custom "🎮" "${GN}" "Detected NVIDIA GPU"
for d in /dev/nvidia*; do
[[ -c "$d" ]] && NVIDIA_DEVICES+=("$d")
done
if [[ -d /dev/nvidia-caps ]]; then
for d in /dev/nvidia-caps/*; do
[[ -c "$d" ]] && NVIDIA_DEVICES+=("$d")
done
fi
if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
msg_custom "🎮" "${GN}" "Found ${#NVIDIA_DEVICES[@]} NVIDIA device(s) for passthrough"
else
msg_warn "NVIDIA GPU detected via PCI but no /dev/nvidia* devices found"
msg_custom "" "${YW}" "Skipping NVIDIA passthrough (host drivers may not be loaded)"
fi
fi
msg_debug "Intel devices: ${INTEL_DEVICES[*]}"
msg_debug "AMD devices: ${AMD_DEVICES[*]}"
msg_debug "NVIDIA devices: ${NVIDIA_DEVICES[*]}"
}
# Configure USB passthrough for privileged containers
configure_usb_passthrough() {
if [[ "$CT_TYPE" != "0" ]]; then
return 0
fi
msg_info "Configuring automatic USB passthrough (privileged container)"
cat <<EOF >>"$LXC_CONFIG"
# Automatic USB passthrough (privileged container)
lxc.cgroup2.devices.allow: a
lxc.cap.drop:
lxc.cgroup2.devices.allow: c 188:* rwm
lxc.cgroup2.devices.allow: c 189:* rwm
lxc.mount.entry: /dev/serial/by-id dev/serial/by-id none bind,optional,create=dir
lxc.mount.entry: /dev/ttyUSB0 dev/ttyUSB0 none bind,optional,create=file
lxc.mount.entry: /dev/ttyUSB1 dev/ttyUSB1 none bind,optional,create=file
lxc.mount.entry: /dev/ttyACM0 dev/ttyACM0 none bind,optional,create=file
lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=file
EOF
msg_ok "USB passthrough configured"
}
# Configure GPU passthrough
configure_gpu_passthrough() {
if ! is_gpu_app "$APP"; then
return 0
fi
detect_gpu_devices
local gpu_count=0
local available_gpus=()
if [[ ${#INTEL_DEVICES[@]} -gt 0 ]]; then
available_gpus+=("INTEL")
gpu_count=$((gpu_count + 1))
fi
if [[ ${#AMD_DEVICES[@]} -gt 0 ]]; then
available_gpus+=("AMD")
gpu_count=$((gpu_count + 1))
fi
if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
available_gpus+=("NVIDIA")
gpu_count=$((gpu_count + 1))
fi
if [[ $gpu_count -eq 0 ]]; then
msg_custom "" "${YW}" "No GPU devices found for passthrough"
return 0
fi
local selected_gpu=""
if [[ $gpu_count -eq 1 ]]; then
selected_gpu="${available_gpus[0]}"
msg_ok "Automatically configuring ${selected_gpu} GPU passthrough"
else
echo -e "\n${INFO} Multiple GPU types detected:"
for gpu in "${available_gpus[@]}"; do
echo " - $gpu"
done
if ! read -t 30 -rp "Which GPU type to passthrough? (${available_gpus[*]}) [timeout 30s]: " selected_gpu </dev/tty; then
selected_gpu="${available_gpus[0]}"
msg_warn "No response — auto-selecting ${selected_gpu}"
fi
selected_gpu="${selected_gpu^^}"
local valid=0
for gpu in "${available_gpus[@]}"; do
[[ "$selected_gpu" == "$gpu" ]] && valid=1
done
if [[ $valid -eq 0 ]]; then
msg_warn "Invalid selection '${selected_gpu}'. Skipping GPU passthrough."
return 0
fi
fi
local dev_idx=0
case "$selected_gpu" in
INTEL | AMD)
local devices=()
[[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
[[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
local dev_index=0
for dev in "${devices[@]}"; do
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
dev_index=$((dev_index + 1))
done
export GPU_TYPE="$selected_gpu"
msg_ok "${selected_gpu} GPU passthrough configured (${#devices[@]} devices)"
;;
NVIDIA)
if [[ ${#NVIDIA_DEVICES[@]} -eq 0 ]]; then
msg_warn "No NVIDIA devices available for passthrough"
return 0
fi
local dev_index=0
for dev in "${NVIDIA_DEVICES[@]}"; do
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
dev_index=$((dev_index + 1))
done
export GPU_TYPE="NVIDIA"
msg_ok "NVIDIA GPU passthrough configured (${#NVIDIA_DEVICES[@]} devices) - install drivers in container if needed"
;;
esac
}
# Additional device passthrough
configure_additional_devices() {
if [ "$ENABLE_TUN" == "yes" ]; then
cat <<EOF >>"$LXC_CONFIG"
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
EOF
fi
if [[ -e /dev/apex_0 ]]; then
msg_custom "🔌" "${BL}" "Detected Coral TPU - configuring passthrough"
echo "lxc.mount.entry: /dev/apex_0 dev/apex_0 none bind,optional,create=file" >>"$LXC_CONFIG"
fi
}
# Get correct GID inside container
get_container_gid() {
local group="$1"
local gid=$(pct exec "$CTID" -- getent group "$group" 2>/dev/null | cut -d: -f3)
echo "${gid:-44}"
}
# ------------------------------------------------------------------------------
# pvesm_status_cached()
#
# - Caches `pvesm status` output per invocation to avoid repeated subprocess calls
# - Supports -content and -storage filters matching pvesm status syntax
# - Cache key is derived from arguments; cache lifetime is the current shell session
# - Invalidate by unsetting _PVESM_CACHE_* variables
# ------------------------------------------------------------------------------
declare -A _PVESM_CACHE=()
pvesm_status_cached() {
local cache_key="pvesm_${*// /_}"
if [[ -n "${_PVESM_CACHE[$cache_key]+x}" ]]; then
echo "${_PVESM_CACHE[$cache_key]}"
return 0
fi
local result
result=$(pvesm status "$@" 2>/dev/null) || return $?
_PVESM_CACHE["$cache_key"]="$result"
echo "$result"
}
# ------------------------------------------------------------------------------
# build_container()
#
@@ -3509,6 +3740,13 @@ start() {
# - Posts installation telemetry to API if diagnostics enabled
# ------------------------------------------------------------------------------
build_container() {
# Recursion guard: prevent infinite retry loops (OOM→retry→OOM→retry→...)
export _BUILD_DEPTH=$(( ${_BUILD_DEPTH:-0} + 1 ))
if (( _BUILD_DEPTH > 3 )); then
msg_error "Maximum recovery depth reached (${_BUILD_DEPTH}). Aborting to prevent infinite retry loop."
exit 250
fi
# if [ "$VERBOSE" == "yes" ]; then set -x; fi
NET_STRING="-net0 name=eth0,bridge=${BRG:-vmbr0}"
@@ -3704,7 +3942,7 @@ $PCT_OPTIONS_STRING"
msg_info "Validating storage space"
if ! validate_storage_space "$CONTAINER_STORAGE" "$DISK_SIZE" "no"; then
local free_space
free_space=$(pvesm status 2>/dev/null | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
free_space=$(pvesm_status_cached | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
local free_fmt
free_fmt=$(numfmt --to=iec --from-unit=1024 --suffix=B --format %.1f "$free_space" 2>/dev/null || echo "${free_space}KB")
msg_error "Not enough space on '$CONTAINER_STORAGE'. Required: ${DISK_SIZE}GB, Available: ${free_fmt}"
@@ -3722,235 +3960,9 @@ $PCT_OPTIONS_STRING"
# ============================================================================
# GPU/USB PASSTHROUGH CONFIGURATION
# (Functions defined above build_container for reuse across retries)
# ============================================================================
# Check if GPU passthrough is enabled
# Returns true only if var_gpu is explicitly set to "yes"
# Can be set via:
# - Environment variable: var_gpu=yes bash -c "..."
# - CT script default: var_gpu="${var_gpu:-no}"
# - Advanced settings wizard
# - App defaults file: /usr/local/community-scripts/defaults/<app>.vars
is_gpu_app() {
[[ "${var_gpu:-no}" == "yes" ]] && return 0
return 1
}
# Detect all available GPU devices
detect_gpu_devices() {
INTEL_DEVICES=()
AMD_DEVICES=()
NVIDIA_DEVICES=()
# Store PCI info to avoid multiple calls
# grep returns exit 1 when no match — use || true to prevent ERR trap
local pci_vga_info
pci_vga_info=$(lspci -nn 2>/dev/null | grep -E "VGA|Display|3D" || true)
# No GPU-related PCI devices at all? Skip silently.
if [[ -z "$pci_vga_info" ]]; then
msg_debug "No VGA/Display/3D PCI devices found"
return 0
fi
# Check for Intel GPU - look for Intel vendor ID [8086]
if grep -q "\[8086:" <<<"$pci_vga_info"; then
msg_custom "🎮" "${BL}" "Detected Intel GPU"
if [[ -d /dev/dri ]]; then
for d in /dev/dri/renderD* /dev/dri/card*; do
[[ -e "$d" ]] && INTEL_DEVICES+=("$d")
done
fi
fi
# Check for AMD GPU - look for AMD vendor IDs [1002] (AMD/ATI) or [1022] (AMD)
if grep -qE "\[1002:|\[1022:" <<<"$pci_vga_info"; then
msg_custom "🎮" "${RD}" "Detected AMD GPU"
if [[ -d /dev/dri ]]; then
# Only add if not already claimed by Intel
if [[ ${#INTEL_DEVICES[@]} -eq 0 ]]; then
for d in /dev/dri/renderD* /dev/dri/card*; do
[[ -e "$d" ]] && AMD_DEVICES+=("$d")
done
fi
fi
fi
# Check for NVIDIA GPU - look for NVIDIA vendor ID [10de]
if grep -q "\[10de:" <<<"$pci_vga_info"; then
msg_custom "🎮" "${GN}" "Detected NVIDIA GPU"
# Simple passthrough - just bind /dev/nvidia* devices if they exist
# Only include character devices (-c), skip directories like /dev/nvidia-caps
for d in /dev/nvidia*; do
[[ -c "$d" ]] && NVIDIA_DEVICES+=("$d")
done
# Also check for devices inside /dev/nvidia-caps/ directory
if [[ -d /dev/nvidia-caps ]]; then
for d in /dev/nvidia-caps/*; do
[[ -c "$d" ]] && NVIDIA_DEVICES+=("$d")
done
fi
if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
msg_custom "🎮" "${GN}" "Found ${#NVIDIA_DEVICES[@]} NVIDIA device(s) for passthrough"
else
msg_warn "NVIDIA GPU detected via PCI but no /dev/nvidia* devices found"
msg_custom "" "${YW}" "Skipping NVIDIA passthrough (host drivers may not be loaded)"
fi
fi
# Debug output
msg_debug "Intel devices: ${INTEL_DEVICES[*]}"
msg_debug "AMD devices: ${AMD_DEVICES[*]}"
msg_debug "NVIDIA devices: ${NVIDIA_DEVICES[*]}"
}
# Configure USB passthrough for privileged containers
configure_usb_passthrough() {
if [[ "$CT_TYPE" != "0" ]]; then
return 0
fi
msg_info "Configuring automatic USB passthrough (privileged container)"
cat <<EOF >>"$LXC_CONFIG"
# Automatic USB passthrough (privileged container)
lxc.cgroup2.devices.allow: a
lxc.cap.drop:
lxc.cgroup2.devices.allow: c 188:* rwm
lxc.cgroup2.devices.allow: c 189:* rwm
lxc.mount.entry: /dev/serial/by-id dev/serial/by-id none bind,optional,create=dir
lxc.mount.entry: /dev/ttyUSB0 dev/ttyUSB0 none bind,optional,create=file
lxc.mount.entry: /dev/ttyUSB1 dev/ttyUSB1 none bind,optional,create=file
lxc.mount.entry: /dev/ttyACM0 dev/ttyACM0 none bind,optional,create=file
lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=file
EOF
msg_ok "USB passthrough configured"
}
# Configure GPU passthrough
configure_gpu_passthrough() {
# Skip if:
# GPU passthrough is enabled when var_gpu="yes":
# - Set via environment variable: var_gpu=yes bash -c "..."
# - Set in CT script: var_gpu="${var_gpu:-no}"
# - Enabled in advanced_settings wizard
# - Configured in app defaults file
if ! is_gpu_app "$APP"; then
return 0
fi
detect_gpu_devices
# Count available GPU types
local gpu_count=0
local available_gpus=()
if [[ ${#INTEL_DEVICES[@]} -gt 0 ]]; then
available_gpus+=("INTEL")
gpu_count=$((gpu_count + 1))
fi
if [[ ${#AMD_DEVICES[@]} -gt 0 ]]; then
available_gpus+=("AMD")
gpu_count=$((gpu_count + 1))
fi
if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
available_gpus+=("NVIDIA")
gpu_count=$((gpu_count + 1))
fi
if [[ $gpu_count -eq 0 ]]; then
msg_custom "" "${YW}" "No GPU devices found for passthrough"
return 0
fi
local selected_gpu=""
if [[ $gpu_count -eq 1 ]]; then
# Automatic selection for single GPU
selected_gpu="${available_gpus[0]}"
msg_ok "Automatically configuring ${selected_gpu} GPU passthrough"
else
# Multiple GPUs - ask user
echo -e "\n${INFO} Multiple GPU types detected:"
for gpu in "${available_gpus[@]}"; do
echo " - $gpu"
done
read -rp "Which GPU type to passthrough? (${available_gpus[*]}): " selected_gpu </dev/tty
selected_gpu="${selected_gpu^^}"
# Validate selection
local valid=0
for gpu in "${available_gpus[@]}"; do
[[ "$selected_gpu" == "$gpu" ]] && valid=1
done
if [[ $valid -eq 0 ]]; then
msg_warn "Invalid selection. Skipping GPU passthrough."
return 0
fi
fi
# Apply passthrough configuration based on selection
local dev_idx=0
case "$selected_gpu" in
INTEL | AMD)
local devices=()
[[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
[[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
# Use pct set to add devices with proper dev0/dev1 format
# GIDs will be detected and set after container starts
local dev_index=0
for dev in "${devices[@]}"; do
# Add to config using pct set (will be visible in GUI)
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
dev_index=$((dev_index + 1))
done
export GPU_TYPE="$selected_gpu"
msg_ok "${selected_gpu} GPU passthrough configured (${#devices[@]} devices)"
;;
NVIDIA)
if [[ ${#NVIDIA_DEVICES[@]} -eq 0 ]]; then
msg_warn "No NVIDIA devices available for passthrough"
return 0
fi
# Use pct set for NVIDIA devices
local dev_index=0
for dev in "${NVIDIA_DEVICES[@]}"; do
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
dev_index=$((dev_index + 1))
done
export GPU_TYPE="NVIDIA"
msg_ok "NVIDIA GPU passthrough configured (${#NVIDIA_DEVICES[@]} devices) - install drivers in container if needed"
;;
esac
}
# Additional device passthrough
configure_additional_devices() {
# TUN device passthrough
if [ "$ENABLE_TUN" == "yes" ]; then
cat <<EOF >>"$LXC_CONFIG"
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
EOF
fi
# Coral TPU passthrough
if [[ -e /dev/apex_0 ]]; then
msg_custom "🔌" "${BL}" "Detected Coral TPU - configuring passthrough"
echo "lxc.mount.entry: /dev/apex_0 dev/apex_0 none bind,optional,create=file" >>"$LXC_CONFIG"
fi
}
# Execute pre-start configurations
configure_usb_passthrough
configure_gpu_passthrough
@@ -4062,12 +4074,6 @@ EOF
msg_ok "Network in LXC is reachable (ping)"
fi
fi
# Function to get correct GID inside container
get_container_gid() {
local group="$1"
local gid=$(pct exec "$CTID" -- getent group "$group" 2>/dev/null | cut -d: -f3)
echo "${gid:-44}" # Default to 44 if not found
}
fix_gpu_gids
@@ -4736,13 +4742,13 @@ resolve_storage_preselect() {
*) return 1 ;;
esac
[[ -z "$preselect" ]] && return 1
if ! pvesm status -content "$required_content" | awk 'NR>1{print $1}' | grep -qx -- "$preselect"; then
if ! pvesm_status_cached -content "$required_content" | awk 'NR>1{print $1}' | grep -qx -- "$preselect"; then
msg_warn "Preselected storage '${preselect}' does not support content '${required_content}' (or not found)"
return 1
fi
local line total used free
line="$(pvesm status | awk -v s="$preselect" 'NR>1 && $1==s {print $0}')"
line="$(pvesm_status_cached | awk -v s="$preselect" 'NR>1 && $1==s {print $0}')"
if [[ -z "$line" ]]; then
STORAGE_INFO="n/a"
else
@@ -4848,13 +4854,8 @@ fix_gpu_gids() {
}
check_storage_support() {
local CONTENT="$1" VALID=0
while IFS= read -r line; do
local STORAGE_NAME
STORAGE_NAME=$(awk '{print $1}' <<<"$line")
[[ -n "$STORAGE_NAME" ]] && VALID=1
done < <(pvesm status -content "$CONTENT" 2>/dev/null | awk 'NR>1')
[[ $VALID -eq 1 ]]
local CONTENT="$1"
pvesm_status_cached -content "$CONTENT" | awk 'NR>1{print $1; exit}' | grep -q . 2>/dev/null
}
select_storage() {
@@ -4903,7 +4904,7 @@ select_storage() {
STORAGE_MAP["$DISPLAY"]="$TAG"
MENU+=("$DISPLAY" "$INFO" "OFF")
((${#DISPLAY} > COL_WIDTH)) && COL_WIDTH=${#DISPLAY}
done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
done < <(pvesm_status_cached -content "$CONTENT" | awk 'NR>1')
if [[ ${#MENU[@]} -eq 0 ]]; then
msg_error "No storage found for content type '$CONTENT'."
@@ -4961,9 +4962,9 @@ validate_storage_space() {
local required_gb="${2:-8}"
local show_dialog="${3:-no}"
# Get full storage line from pvesm status
# Get full storage line from pvesm status (cached)
local storage_line
storage_line=$(pvesm status 2>/dev/null | awk -v s="$storage" '$1 == s {print $0}')
storage_line=$(pvesm_status_cached | awk -v s="$storage" '$1 == s {print $0}')
# Check if storage exists and is active
if [[ -z "$storage_line" ]]; then
@@ -5202,7 +5203,7 @@ create_lxc_container() {
;;
esac
if ! pvesm status -content rootdir 2>/dev/null | awk 'NR>1{print $1}' | grep -qx "$CONTAINER_STORAGE"; then
if ! pvesm_status_cached -content rootdir | awk 'NR>1{print $1}' | grep -qx "$CONTAINER_STORAGE"; then
msg_error "Storage '$CONTAINER_STORAGE' ($STORAGE_TYPE) does not support 'rootdir' content."
exit 213
fi
@@ -5211,7 +5212,7 @@ create_lxc_container() {
msg_info "Validating template storage '$TEMPLATE_STORAGE'"
TEMPLATE_TYPE=$(grep -E "^[^:]+: $TEMPLATE_STORAGE$" /etc/pve/storage.cfg | cut -d: -f1)
if ! pvesm status -content vztmpl 2>/dev/null | awk 'NR>1{print $1}' | grep -qx "$TEMPLATE_STORAGE"; then
if ! pvesm_status_cached -content vztmpl | awk 'NR>1{print $1}' | grep -qx "$TEMPLATE_STORAGE"; then
msg_warn "Template storage '$TEMPLATE_STORAGE' may not support 'vztmpl'"
fi
msg_ok "Template storage '$TEMPLATE_STORAGE' validated"