mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-07-28 08:42:54 +02:00
core: fix OS version fallback when the host catalog lacks the requested version & harden template validation (#16068)
This commit is contained in:
committed by
GitHub
parent
7cee1cb96a
commit
895cc7fdcf
+115
-138
@@ -895,6 +895,108 @@ choose_and_set_storage_for_file() {
|
|||||||
# SECTION 5: CONFIGURATION & DEFAULTS MANAGEMENT
|
# SECTION 5: CONFIGURATION & DEFAULTS MANAGEMENT
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Distinct versions of OS type $1 in the cached pveam catalog (no network).
|
||||||
|
# `pveam available` prints "<section>\t<template>" - the name is field 2.
|
||||||
|
# Must never fail: callers capture this via mapfile < <(...).
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
_list_os_versions() {
|
||||||
|
local ostype="${1:-}"
|
||||||
|
[[ -n "$ostype" ]] || return 0
|
||||||
|
pveam available -section system 2>/dev/null |
|
||||||
|
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
|
||||||
|
awk '{print $2}' |
|
||||||
|
sed -nE "s/^${ostype}-([0-9]+(\.[0-9]+)?).*/\1/p" |
|
||||||
|
sort -u -V || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Catalog templates matching prefix $1 and variant $2 ("debian-13" +
|
||||||
|
# "-standard_"), oldest first. Same no-fail contract as _list_os_versions.
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
_list_templates() {
|
||||||
|
local search="${1:-}" pattern="${2:-}"
|
||||||
|
[[ -n "$search" ]] || return 0
|
||||||
|
pveam available -section system 2>/dev/null |
|
||||||
|
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
|
||||||
|
awk '{print $2}' |
|
||||||
|
grep -E "^${search}.*${pattern}" |
|
||||||
|
sort -t - -k 2 -V || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Maps var_version onto a version this host's catalog actually has, before the
|
||||||
|
# settings summary is printed. Availability comes from `pveam available` only -
|
||||||
|
# never inferred from the PVE release (an updated 8.4 may carry templates an
|
||||||
|
# older 8.x never saw, and entries drop out again at EOL).
|
||||||
|
# Picks the nearest version, newer wins on a tie. Interactive: menu with that
|
||||||
|
# candidate preselected; unattended: takes it with a warning.
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
resolve_os_version() {
|
||||||
|
local ostype="${var_os:-}" want="${var_version:-}"
|
||||||
|
[[ -n "$ostype" && -n "$want" ]] || return 0
|
||||||
|
|
||||||
|
# ARM64 pulls from linuxcontainers.org, the pveam catalog says nothing there
|
||||||
|
[[ "$(dpkg --print-architecture 2>/dev/null)" == "arm64" ]] && return 0
|
||||||
|
|
||||||
|
local -a versions=()
|
||||||
|
mapfile -t versions < <(_list_os_versions "$ostype")
|
||||||
|
[[ ${#versions[@]} -gt 0 ]] || return 0
|
||||||
|
|
||||||
|
local v
|
||||||
|
for v in "${versions[@]}"; do
|
||||||
|
[[ "$v" == "$want" ]] && return 0
|
||||||
|
done
|
||||||
|
|
||||||
|
# Already downloaded counts as available even if the catalog dropped it
|
||||||
|
if [[ -n "${TEMPLATE_STORAGE:-}" ]] &&
|
||||||
|
pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "/${ostype}-${want}-"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local candidate
|
||||||
|
candidate=$(printf '%s\n' "${versions[@]}" | awk -v want="$want" '
|
||||||
|
function num(v, a) { split(v, a, "."); return a[1] * 10000 + (a[2] + 0) }
|
||||||
|
BEGIN { w = num(want); best = ""; bestd = -1 }
|
||||||
|
{
|
||||||
|
d = num($0) - w
|
||||||
|
ad = (d < 0) ? -d : d
|
||||||
|
if (bestd < 0 || ad < bestd || (ad == bestd && d > 0)) { bestd = ad; best = $0 }
|
||||||
|
}
|
||||||
|
END { print best }
|
||||||
|
')
|
||||||
|
[[ -n "$candidate" ]] || return 0
|
||||||
|
|
||||||
|
msg_warn "${ostype^} ${want} is not in this host's template catalog (PVE ${PVEVERSION:-unknown})"
|
||||||
|
|
||||||
|
if [[ "${PHS_SILENT:-0}" != "1" ]] && command -v whiptail &>/dev/null && [ -t 0 ] && [[ "$TERM" != "dumb" ]]; then
|
||||||
|
local -a menu=()
|
||||||
|
while read -r v; do
|
||||||
|
if [[ "$v" == "$candidate" ]]; then
|
||||||
|
menu+=("$v" "closest to ${want} (recommended)")
|
||||||
|
else
|
||||||
|
menu+=("$v" " ")
|
||||||
|
fi
|
||||||
|
done < <(printf '%s\n' "${versions[@]}" | sort -rV)
|
||||||
|
|
||||||
|
local choice
|
||||||
|
choice=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||||
|
--title "OS VERSION NOT AVAILABLE" \
|
||||||
|
--ok-button "Use" --cancel-button "Exit" \
|
||||||
|
--menu "\n${ostype^} ${want} is not available on this Proxmox host.\n\nSelect the version to use instead:" \
|
||||||
|
20 70 8 "${menu[@]}" --default-item "$candidate" \
|
||||||
|
3>&1 1>&2 2>&3) || exit_script
|
||||||
|
candidate="$choice"
|
||||||
|
else
|
||||||
|
msg_warn "Unattended run - continuing with ${ostype} ${candidate}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
var_version="$candidate"
|
||||||
|
export var_version
|
||||||
|
msg_ok "Using ${ostype} ${var_version} instead of ${want}"
|
||||||
|
return 0 # last call in base_settings(), which runs under errexit
|
||||||
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# base_settings()
|
# base_settings()
|
||||||
#
|
#
|
||||||
@@ -1068,8 +1170,11 @@ base_settings() {
|
|||||||
var_os="debian"
|
var_os="debian"
|
||||||
fi
|
fi
|
||||||
if [ -z "$var_version" ]; then
|
if [ -z "$var_version" ]; then
|
||||||
var_version="12"
|
var_version="13"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# every install path passes here, and still before any summary is printed
|
||||||
|
resolve_os_version
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -6479,7 +6584,7 @@ create_lxc_container() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
ONLINE_TEMPLATES=()
|
ONLINE_TEMPLATES=()
|
||||||
mapfile -t ONLINE_TEMPLATES < <(pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | awk '{print $2}' | grep -E "^${TEMPLATE_SEARCH}.*${TEMPLATE_PATTERN}" | sort -t - -k 2 -V 2>/dev/null || true)
|
mapfile -t ONLINE_TEMPLATES < <(_list_templates "$TEMPLATE_SEARCH" "$TEMPLATE_PATTERN")
|
||||||
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
|
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
|
||||||
|
|
||||||
TEMPLATE="$ONLINE_TEMPLATE"
|
TEMPLATE="$ONLINE_TEMPLATE"
|
||||||
@@ -6487,58 +6592,13 @@ create_lxc_container() {
|
|||||||
msg_ok "Template search completed"
|
msg_ok "Template search completed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If still no template, try to find alternatives
|
# resolve_os_version() already validated the version, so this means the
|
||||||
|
# variant (TEMPLATE_PATTERN) is missing - a catalog issue, don't auto-repair
|
||||||
if [[ -z "$TEMPLATE" ]]; then
|
if [[ -z "$TEMPLATE" ]]; then
|
||||||
msg_warn "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
|
msg_error "No ${TEMPLATE_PATTERN#-} template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
|
||||||
|
msg_custom "ℹ️" "${YW}" "Refresh the catalog and check what this host offers:"
|
||||||
# Get all available versions for this OS type
|
echo -e "${TAB} pveam update && pveam available -section system | grep '${PCT_OSTYPE}-'"
|
||||||
AVAILABLE_VERSIONS=()
|
exit 225
|
||||||
mapfile -t AVAILABLE_VERSIONS < <(
|
|
||||||
pveam available -section system 2>/dev/null |
|
|
||||||
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
|
|
||||||
awk -F'\t' '{print $1}' |
|
|
||||||
grep "^${PCT_OSTYPE}-" |
|
|
||||||
sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
|
|
||||||
sort -u -V 2>/dev/null
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "${BL}Available ${PCT_OSTYPE} versions:${CL}"
|
|
||||||
for i in "${!AVAILABLE_VERSIONS[@]}"; do
|
|
||||||
echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or press Enter to cancel: " choice </dev/tty
|
|
||||||
|
|
||||||
if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
|
|
||||||
PCT_OSVERSION="${AVAILABLE_VERSIONS[$((choice - 1))]}"
|
|
||||||
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION}"
|
|
||||||
|
|
||||||
ONLINE_TEMPLATES=()
|
|
||||||
mapfile -t ONLINE_TEMPLATES < <(
|
|
||||||
pveam available -section system 2>/dev/null |
|
|
||||||
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
|
|
||||||
awk '{print $2}' |
|
|
||||||
grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
|
|
||||||
sort -t - -k 2 -V 2>/dev/null || true
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
|
|
||||||
TEMPLATE="${ONLINE_TEMPLATES[-1]}"
|
|
||||||
TEMPLATE_SOURCE="online"
|
|
||||||
else
|
|
||||||
msg_error "No templates available for ${PCT_OSTYPE} ${PCT_OSVERSION}"
|
|
||||||
exit 225
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
msg_custom "🚫" "${YW}" "Installation cancelled"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
msg_error "No ${PCT_OSTYPE} templates available"
|
|
||||||
exit 225
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
|
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
|
||||||
@@ -6553,93 +6613,10 @@ create_lxc_container() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
[[ -n "$TEMPLATE_PATH" ]] || {
|
[[ -n "$TEMPLATE_PATH" ]] || {
|
||||||
if [[ -z "$TEMPLATE" ]]; then
|
msg_error "Could not resolve a storage path for template ${TEMPLATE}"
|
||||||
msg_error "Template ${PCT_OSTYPE} ${PCT_OSVERSION} not available"
|
exit 220
|
||||||
|
|
||||||
# Get available versions
|
|
||||||
mapfile -t AVAILABLE_VERSIONS < <(
|
|
||||||
pveam available -section system 2>/dev/null |
|
|
||||||
grep "^${PCT_OSTYPE}-" |
|
|
||||||
sed -E 's/.*'"${PCT_OSTYPE}"'-([0-9]+\.[0-9]+).*/\1/' |
|
|
||||||
grep -E '^[0-9]+\.[0-9]+$' |
|
|
||||||
sort -u -V 2>/dev/null || sort -u
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
|
|
||||||
echo -e "\n${BL}Available versions:${CL}"
|
|
||||||
for i in "${!AVAILABLE_VERSIONS[@]}"; do
|
|
||||||
echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or press Enter to exit: " choice </dev/tty
|
|
||||||
|
|
||||||
if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
|
|
||||||
export var_version="${AVAILABLE_VERSIONS[$((choice - 1))]}"
|
|
||||||
export PCT_OSVERSION="$var_version"
|
|
||||||
msg_ok "Switched to ${PCT_OSTYPE} ${var_version}"
|
|
||||||
|
|
||||||
# Retry template search with new version
|
|
||||||
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
|
|
||||||
|
|
||||||
mapfile -t LOCAL_TEMPLATES < <(
|
|
||||||
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
|
|
||||||
awk -v search="${TEMPLATE_SEARCH}-" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
|
|
||||||
sed 's|.*/||' | sort -t - -k 2 -V
|
|
||||||
)
|
|
||||||
mapfile -t ONLINE_TEMPLATES < <(
|
|
||||||
pveam available -section system 2>/dev/null |
|
|
||||||
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
|
|
||||||
awk '{print $2}' |
|
|
||||||
grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
|
|
||||||
sort -t - -k 2 -V 2>/dev/null || true
|
|
||||||
)
|
|
||||||
ONLINE_TEMPLATE=""
|
|
||||||
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
|
|
||||||
|
|
||||||
if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
|
|
||||||
TEMPLATE="${LOCAL_TEMPLATES[-1]}"
|
|
||||||
TEMPLATE_SOURCE="local"
|
|
||||||
else
|
|
||||||
TEMPLATE="$ONLINE_TEMPLATE"
|
|
||||||
TEMPLATE_SOURCE="online"
|
|
||||||
fi
|
|
||||||
|
|
||||||
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
|
|
||||||
if [[ -z "$TEMPLATE_PATH" ]]; then
|
|
||||||
TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
|
|
||||||
[[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If we still don't have a path but have a valid template name, construct it
|
|
||||||
if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
|
|
||||||
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -n "$TEMPLATE_PATH" ]] || {
|
|
||||||
msg_error "Template still not found after version change"
|
|
||||||
exit 220
|
|
||||||
}
|
|
||||||
else
|
|
||||||
msg_custom "🚫" "${YW}" "Installation cancelled"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
msg_error "No ${PCT_OSTYPE} templates available"
|
|
||||||
exit 220
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate that we found a template
|
|
||||||
if [[ -z "$TEMPLATE" ]]; then
|
|
||||||
msg_error "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
|
|
||||||
msg_custom "ℹ️" "${YW}" "Please check:"
|
|
||||||
msg_custom " •" "${YW}" "Is pveam catalog available? (run: pveam available -section system)"
|
|
||||||
msg_custom " •" "${YW}" "Does the template exist for your OS version?"
|
|
||||||
exit 225
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
|
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
|
||||||
msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
|
msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
|
||||||
|
|
||||||
|
|||||||
@@ -376,10 +376,11 @@ error_handler() {
|
|||||||
active_log="$BUILD_LOG"
|
active_log="$BUILD_LOG"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# stderr: the trap can fire inside a $(...) capture that would eat this as data
|
||||||
if [[ -n "$active_log" && -s "$active_log" ]]; then
|
if [[ -n "$active_log" && -s "$active_log" ]]; then
|
||||||
echo -e "\n${TAB}--- Last 20 lines of log ---"
|
echo -e "\n${TAB}--- Last 20 lines of log ---" >&2
|
||||||
tail -n 20 "$active_log"
|
tail -n 20 "$active_log" >&2
|
||||||
echo -e "${TAB}-----------------------------------\n"
|
echo -e "${TAB}-----------------------------------\n" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Node.js heap OOM detection with actionable guidance ──
|
# ── Node.js heap OOM detection with actionable guidance ──
|
||||||
|
|||||||
Reference in New Issue
Block a user