From ffb96a6da2f8145394ab21e98020abfa183c1292 Mon Sep 17 00:00:00 2001 From: MickLesk <47820557+MickLesk@users.noreply.github.com> Date: Wed, 23 Sep 2026 09:01:17 +0200 Subject: [PATCH] Stop discarding cloud-init error messages --- pve/vm-core.func | 8 ++++---- vm/cloud-init.func | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/pve/vm-core.func b/pve/vm-core.func index abf9958..d59d93f 100644 --- a/pve/vm-core.func +++ b/pve/vm-core.func @@ -2069,7 +2069,7 @@ vm_select_storage() { if pvesm status -storage "$STORAGE" &>/dev/null; then # The interactive path ends with this too. Skipping it here left # DISK_IMPORT_FORMAT and friends unset for every preselected storage. - STORAGE_TYPE=$(pvesm status -storage "$STORAGE" | awk 'NR>1 {print $2}') + STORAGE_TYPE=$(pvesm status -storage "$STORAGE" 2>/dev/null | awk 'NR>1 {print $2}') vm_apply_storage_layout "$STORAGE_TYPE" msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location." return 0 @@ -2090,9 +2090,9 @@ vm_select_storage() { msg_max_length=$((${#item} + offset)) fi storage_menu+=("$tag" "$item" "OFF") - done < <(pvesm status -content images | awk 'NR>1') + done < <(pvesm status -content images 2>/dev/null | awk 'NR>1') - valid_storage=$(pvesm status -content images | awk 'NR>1') + valid_storage=$(pvesm status -content images 2>/dev/null | awk 'NR>1') if [ -z "$valid_storage" ]; then msg_error "Unable to detect a valid storage location." exit 119 # no valid storage found @@ -2123,7 +2123,7 @@ vm_select_storage() { msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location." msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}." - STORAGE_TYPE=$(pvesm status -storage "$STORAGE" | awk 'NR>1 {print $2}') + STORAGE_TYPE=$(pvesm status -storage "$STORAGE" 2>/dev/null | awk 'NR>1 {print $2}') vm_apply_storage_layout "$STORAGE_TYPE" } diff --git a/vm/cloud-init.func b/vm/cloud-init.func index e1aa06f..ecc6b34 100644 --- a/vm/cloud-init.func +++ b/vm/cloud-init.func @@ -237,10 +237,14 @@ function configure_cloudinit_ssh_keys() { # ------------------------------------------------------------------------------ # _ci_msg - Internal message helper with fallback # ------------------------------------------------------------------------------ -function _ci_msg_info() { msg_info "$1" 2>/dev/null || echo "[INFO] $1"; } -function _ci_msg_ok() { msg_ok "$1" 2>/dev/null || echo "[OK] $1"; } -function _ci_msg_warn() { msg_warn "$1" 2>/dev/null || echo "[WARN] $1"; } -function _ci_msg_error() { msg_error "$1" 2>/dev/null || echo "[ERROR] $1"; } +# The fallback used to be `msg_x "$1" 2>/dev/null || echo ...`, which discarded +# every message msg_warn and msg_error write - both go to stderr - and never +# reached the echo, because those return 0. Errors in here were invisible, so a +# failure surfaced as nothing but the trap's line number. +function _ci_msg_info() { if declare -F msg_info >/dev/null; then msg_info "$1"; else echo "[INFO] $1"; fi; } +function _ci_msg_ok() { if declare -F msg_ok >/dev/null; then msg_ok "$1"; else echo "[OK] $1"; fi; } +function _ci_msg_warn() { if declare -F msg_warn >/dev/null; then msg_warn "$1"; else echo "[WARN] $1" >&2; fi; } +function _ci_msg_error() { if declare -F msg_error >/dev/null; then msg_error "$1"; else echo "[ERROR] $1" >&2; fi; } # ------------------------------------------------------------------------------ # validate_ip_cidr - Validate IP address in CIDR format @@ -578,6 +582,8 @@ function display_cloud_init_info() { echo -e "${TAB:- }${DGN:-}User: ${BGN:-}${CLOUDINIT_USER:-root}${CL:-}" echo -e "${TAB:- }${DGN:-}Password: ${BGN:-}${CLOUDINIT_PASSWORD}${CL:-}" echo -e "${TAB:- }${DGN:-}Credentials: ${BL:-}${CLOUDINIT_CRED_FILE}${CL:-}" + echo -e "${TAB:- }${DGN:-}Console: ${BGN:-}xterm.js${CL:-}${DGN:-} - cloud images use the serial console, noVNC stays blank${CL:-}" + echo -e "${TAB:- }${DGN:-}Cloud-Init needs a minute on first boot before the login works${CL:-}" echo -e "${TAB:- }${RD:-}⚠️ Delete credentials file after noting password!${CL:-}" else echo "" @@ -585,6 +591,8 @@ function display_cloud_init_info() { echo " User: ${CLOUDINIT_USER:-root}" echo " Password: ${CLOUDINIT_PASSWORD}" echo " Credentials: ${CLOUDINIT_CRED_FILE}" + echo " Console: xterm.js - cloud images use the serial console, noVNC stays blank" + echo " Cloud-Init needs a minute on first boot before the login works" echo " ⚠️ Delete credentials file after noting password!" fi fi @@ -681,12 +689,16 @@ function setup_cloud_init_network_no_rename() { fi if [[ -z "$snippet_storage" ]]; then - _ci_msg_error "No active Proxmox storage supporting snippets was found" + _ci_msg_error "A static IP needs a storage with 'snippets' content, and none is active" + _ci_msg_warn "Enable Snippets under Datacenter > Storage on a directory storage, or set CLOUDINIT_SNIPPET_STORAGE" return 1 fi snippet_volid="${snippet_storage}:snippets/${snippet_name}" - snippet_path="$(pvesm path "$snippet_volid")" + if ! snippet_path="$(pvesm path "$snippet_volid" 2>/dev/null)" || [[ -z "$snippet_path" ]]; then + _ci_msg_error "Could not resolve a path for ${snippet_volid}" + return 1 + fi mkdir -p "$(dirname "$snippet_path")"