Refactor storage selection and enforce user prompt

Unifies and refactors storage selection logic to always prompt the user for container and template storage choices unless only one option exists, as per requirement #4. Removes legacy selection functions, updates all relevant install and menu flows to use the new logic, and ensures storage settings are consistently written to vars files and environment variables. Also improves code clarity and maintains storage summary output.
This commit is contained in:
CanbiZ 2025-09-17 13:59:14 +02:00
parent ca28e419ef
commit 8ce34b4ee0

View File

@ -977,7 +977,7 @@ default_var_settings() {
if printenv "$_k" >/dev/null 2>&1; then _HARD_ENV["$_k"]=1; fi
done
# Find default.vars (first valid path wins)
# Find default.vars location
local _find_default_vars
_find_default_vars() {
local f
@ -993,13 +993,20 @@ default_var_settings() {
return 1
}
# Ensure default.vars exists, create with sane defaults if missing
# Create once, with storages already selected, no var_ctid/var_hostname lines
local _ensure_default_vars
_ensure_default_vars() {
_find_default_vars >/dev/null 2>&1 && return 0
local canonical="/usr/local/community-scripts/default.vars"
msg_info "No default.vars found. Creating ${canonical}"
mkdir -p /usr/local/community-scripts
# Pick storages before writing the file (always ask unless only one)
# Create a minimal temp file to write into
: >"$canonical"
# Base content (no var_ctid / var_hostname here)
cat >"$canonical" <<'EOF'
# Community-Scripts defaults (var_* only). Lines starting with # are comments.
# Precedence: ENV var_* > default.vars > built-ins.
@ -1008,11 +1015,6 @@ default_var_settings() {
# Container type
var_unprivileged=1
# Storage
# Example: "local", "docker", ...
# var_template_storage=local
# var_container_storage=local
# Resources
var_cpu=1
var_disk=4
@ -1045,11 +1047,12 @@ var_verbose=no
# Security (root PW) empty => autologin
# var_pw=
# Optional fixed CTID/hostname empty => auto
# var_ctid=
# var_hostname=
EOF
# Now choose storages (always prompt unless just one exists)
choose_and_set_storage_for_file "$canonical" template
choose_and_set_storage_for_file "$canonical" container
chmod 0644 "$canonical"
msg_ok "Created ${canonical}"
}
@ -1091,34 +1094,23 @@ EOF
var_val="${BASH_REMATCH[1]}"
fi
# Unsafe check without regex (formatter-friendly)
local _unsafe=""
case "$var_val" in
*'$('*) _unsafe=1 ;;
*'`'*) _unsafe=1 ;;
*';'*) _unsafe=1 ;;
*'&'*) _unsafe=1 ;;
*'<('*) _unsafe=1 ;;
esac
if [[ -n "$_unsafe" ]]; then
msg_warn "Ignoring ${var_key} from ${file}: unsafe characters"
continue
fi
# Hard env wins
if [[ -n "${_HARD_ENV[$var_key]:-}" ]]; then
continue
fi
# Unsafe characters
case $var_val in
\"*\")
var_val=${var_val#\"}
var_val=${var_val%\"}
;;
\'*\')
var_val=${var_val#\'}
var_val=${var_val%\'}
;;
esac # Hard env wins
[[ -n "${_HARD_ENV[$var_key]:-}" ]] && continue
# Set only if not already exported
if [[ -z "${!var_key+x}" ]]; then
export "${var_key}=${var_val}"
fi
[[ -z "${!var_key+x}" ]] && export "${var_key}=${var_val}"
else
msg_warn "Malformed line in ${file}: ${line}"
fi
done <"$file"
msg_ok "Loaded ${file}"
}
@ -1136,11 +1128,7 @@ EOF
# 3) Map var_verbose → VERBOSE
if [[ -n "${var_verbose:-}" ]]; then
case "${var_verbose,,}" in
1 | yes | true | on) VERBOSE="yes" ;;
0 | no | false | off) VERBOSE="no" ;;
*) VERBOSE="${var_verbose}" ;;
esac
case "${var_verbose,,}" in 1 | yes | true | on) VERBOSE="yes" ;; 0 | no | false | off) VERBOSE="no" ;; *) VERBOSE="${var_verbose}" ;; esac
else
VERBOSE="no"
fi
@ -1457,6 +1445,15 @@ maybe_offer_save_app_defaults() {
rm -f "$new_tmp" "$diff_tmp"
}
ensure_storage_selection_for_vars_file() {
# $1 = vars_file
local vf="$1"
# Always prompt (unless only one choice for that content), per your requirement #4
choose_and_set_storage_for_file "$vf" template
choose_and_set_storage_for_file "$vf" container
echo_storage_summary_from_file "$vf"
}
diagnostics_menu() {
if [ "${DIAGNOSTICS:-no}" = "yes" ]; then
if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
@ -1571,6 +1568,8 @@ install_script() {
METHOD="default"
base_settings "$VERBOSE"
echo_default
# Always ask storages for MyDefaults file (create if missing)
ensure_storage_selection_for_vars_file "/usr/local/community-scripts/default.vars"
;;
2)
header_info
@ -1579,6 +1578,7 @@ install_script() {
METHOD="default"
base_settings "$VERBOSE"
echo_default
ensure_storage_selection_for_vars_file "/usr/local/community-scripts/default.vars"
;;
3)
header_info
@ -1586,6 +1586,8 @@ install_script() {
METHOD="advanced"
base_settings
advanced_settings
# Always ask storages (stored to env var_* so app-defaults will include them)
ensure_storage_selection_for_vars_file "/usr/local/community-scripts/default.vars"
maybe_offer_save_app_defaults
;;
4)
@ -1593,8 +1595,8 @@ install_script() {
msg_error "Failed to apply default.vars"
exit 1
}
select_container_storage "/usr/local/community-scripts/default.vars"
select_template_storage "/usr/local/community-scripts/default.vars"
# Always let user pick storages again (unless only one exists)
ensure_storage_selection_for_vars_file "/usr/local/community-scripts/default.vars"
;;
5)
if [ -f "$(get_app_defaults_path)" ]; then
@ -1604,6 +1606,8 @@ install_script() {
base_settings
_load_vars_file "$(get_app_defaults_path)"
echo_default
# Always let user confirm/change storages for the app defaults
ensure_storage_selection_for_vars_file "$(get_app_defaults_path)"
fi
;;
6)
@ -1613,22 +1617,9 @@ install_script() {
7)
header_info
echo -e "${DEFAULT}${BOLD}${BL}Manage Storage Settings on node $PVEHOST_NAME${CL}"
local vars_file="/usr/local/community-scripts/default.vars"
if [ -f "$(get_app_defaults_path)" ]; then
if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
--title "STORAGE SETTINGS" \
--yesno "Do you want to update App Defaults for ${APP} instead of global defaults?\n\nYes = App Defaults (${APP})\nNo = Global Defaults (default.vars)" 12 72; then
vars_file="$(get_app_defaults_path)"
fi
fi
select_container_storage "$vars_file"
select_template_storage "$vars_file"
_echo_storage_summary "$vars_file"
ensure_storage_selection_for_vars_file "/usr/local/community-scripts/default.vars"
exit 0
;;
8)
echo -e "\n${CROSS}${RD}Script terminated.${CL}\n"
exit 0
@ -1744,72 +1735,58 @@ install_script() {
# fi
# }
select_container_storage() {
local vars_file="$1"
local current
current=$(awk -F= '/^var_container_storage=/ {print $2; exit}' "$vars_file")
local storages
storages=$(pvesm status -content images | awk 'NR>1 {print $1}')
local count
count=$(echo "$storages" | wc -l)
local choice
if [ "$count" -eq 1 ]; then
choice="$storages"
else
# Build menu list: ID + type
local menu_items
menu_items=$(pvesm status -content images | awk -v cur="$current" 'NR>1 {printf "%s %s\n", $1, $2}')
choice=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
--title "Select Container Storage" \
--menu "Choose container storage:" 20 60 10 \
--default-item "$current" \
$menu_items 3>&1 1>&2 2>&3) || return 1
fi
if [ -n "$choice" ]; then
sed -i '/^var_container_storage=/d' "$vars_file"
echo "var_container_storage=$choice" >>"$vars_file"
msg_ok "Updated container storage → $choice"
fi
# ===== Unified storage selection & writing to vars files =====
_write_storage_to_vars() {
# $1 = vars_file, $2 = key (var_container_storage / var_template_storage), $3 = value
local vf="$1" key="$2" val="$3"
# remove uncommented and commented versions to avoid duplicates
sed -i "/^[#[:space:]]*${key}=/d" "$vf"
echo "${key}=${val}" >>"$vf"
}
select_template_storage() {
local vars_file="$1"
local current
current=$(awk -F= '/^var_template_storage=/ {print $2; exit}' "$vars_file")
choose_and_set_storage_for_file() {
# $1 = vars_file, $2 = class ('container'|'template')
local vf="$1" class="$2" key="" current=""
case "$class" in
container) key="var_container_storage" ;;
template) key="var_template_storage" ;;
*)
msg_error "Unknown storage class: $class"
return 1
;;
esac
local storages
storages=$(pvesm status -content vztmpl | awk 'NR>1 {print $1}')
current=$(awk -F= -v k="^${key}=" '$0 ~ k {print $2; exit}' "$vf")
# If only one storage exists for the content type, auto-pick. Else always ask (your wish #4).
local content="rootdir"
[[ "$class" == "template" ]] && content="vztmpl"
local count
count=$(echo "$storages" | wc -l)
count=$(pvesm status -content "$content" | awk 'NR>1{print $1}' | wc -l)
local choice
if [ "$count" -eq 1 ]; then
choice="$storages"
if [[ "$count" -eq 1 ]]; then
STORAGE_RESULT=$(pvesm status -content "$content" | awk 'NR>1{print $1; exit}')
STORAGE_INFO=""
else
local menu_items
menu_items=$(pvesm status -content vztmpl | awk -v cur="$current" 'NR>1 {printf "%s %s\n", $1, $2}')
choice=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
--title "Select Template Storage" \
--menu "Choose template storage:" 20 60 10 \
--default-item "$current" \
$menu_items 3>&1 1>&2 2>&3) || return 1
# If the current value is preselectable, we could show it, but per your requirement we always offer selection
select_storage "$class" || return 1
fi
if [ -n "$choice" ]; then
sed -i '/^var_template_storage=/d' "$vars_file"
echo "var_template_storage=$choice" >>"$vars_file"
msg_ok "Updated template storage → $choice"
_write_storage_to_vars "$vf" "$key" "$STORAGE_RESULT"
# Keep environment in sync for later steps (e.g. app-default save)
if [[ "$class" == "container" ]]; then
export var_container_storage="$STORAGE_RESULT"
export CONTAINER_STORAGE="$STORAGE_RESULT"
else
export var_template_storage="$STORAGE_RESULT"
export TEMPLATE_STORAGE="$STORAGE_RESULT"
fi
msg_ok "Updated ${key} → ${STORAGE_RESULT}"
}
_echo_storage_summary() {
echo_storage_summary_from_file() {
local vars_file="$1"
local ct_store tpl_store
ct_store=$(awk -F= '/^var_container_storage=/ {print $2; exit}' "$vars_file")
@ -1817,7 +1794,7 @@ _echo_storage_summary() {
echo -e "\n${INFO}${BOLD}${DGN}Storage settings from ${vars_file}:${CL}"
echo -e " 📦 Container Storage: ${BGN}${ct_store:-<unset>}${CL}"
echo -e " 📦 Template Storage: ${BGN}${tpl_store:-<unset>}${CL}\n"
echo -e " 📦 Template Storage: ${BGN}${tpl_store:-<unset>}${CL}\n"
}
# ------------------------------------------------------------------------------
@ -2448,6 +2425,7 @@ create_lxc_container() {
# ------------------------------------------------------------------------------
# Storage discovery / selection helpers
# ------------------------------------------------------------------------------
# ===== Storage discovery / selection helpers (ported from create_lxc.sh) =====
resolve_storage_preselect() {
local class="$1" preselect="$2" required_content=""
case "$class" in
@ -2526,17 +2504,6 @@ create_lxc_container() {
;;
esac
if [[ "$CONTENT" == "rootdir" && -n "${STORAGE:-}" ]]; then
if pvesm status -content "$CONTENT" | awk 'NR>1 {print $1}' | grep -qx "$STORAGE"; then
STORAGE_RESULT="$STORAGE"
msg_info "Using preset storage: $STORAGE_RESULT for $CONTENT_LABEL"
return 0
else
msg_error "Preset storage '$STORAGE' is not valid for content type '$CONTENT'."
return 2
fi
fi
declare -A STORAGE_MAP
local -a MENU=()
local COL_WIDTH=0
@ -2566,10 +2533,10 @@ create_lxc_container() {
local WIDTH=$((COL_WIDTH + 42))
while true; do
local DISPLAY_SELECTED
DISPLAY_SELECTED=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
DISPLAY_SELECTED=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
--title "Storage Pools" \
--radiolist "Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
16 "$WIDTH" 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || exit_script
16 "$WIDTH" 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || { exit_script; }
DISPLAY_SELECTED=$(sed 's/[[:space:]]*$//' <<<"$DISPLAY_SELECTED")
if [[ -z "$DISPLAY_SELECTED" || -z "${STORAGE_MAP[$DISPLAY_SELECTED]+_}" ]]; then