core: extend storage type support (rbd, nfs, cifs) and validation (iscidirect, isci, zfs, cephfs, pbs) (#9646)

* core: enhance storage type validation and error codes

Improve storage validation for LXC container creation with
explicit checks for unsupported storage types.

Changes:
- Add validation for storage types that don't support containers:
  - iscsidirect (exit 212) - VMs only
  - iscsi/zfs (exit 213) - no rootdir support
  - cephfs (exit 219) - use RBD instead
  - pbs (exit 224) - backups only
- Add connectivity check for network storage (linstor, rbd, nfs, cifs)
- Simplify storage content validation using pvesm status
- Reorganize Proxmox error codes (200-231) for consistency
- Update error messages to be more descriptive and actionable

This helps users identify storage compatibility issues early
before container creation fails with cryptic errors.

* Update build.func
This commit is contained in:
CanbiZ 2025-12-04 19:41:01 +01:00 committed by GitHub
parent 5780dc1532
commit 0f7c201b57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 66 additions and 67 deletions

View File

@ -3211,42 +3211,29 @@ create_lxc_container() {
fi fi
fi fi
# Validate content types msg_info "Validating storage '$CONTAINER_STORAGE'"
msg_info "Validating content types of storage '$CONTAINER_STORAGE'" STORAGE_TYPE=$(grep -E "^[^:]+: $CONTAINER_STORAGE$" /etc/pve/storage.cfg | cut -d: -f1 | head -1)
STORAGE_CONTENT=$(grep -A4 -E "^(zfspool|dir|lvmthin|lvm|linstor): $CONTAINER_STORAGE" /etc/pve/storage.cfg | grep content | awk '{$1=""; print $0}' | xargs)
msg_debug "Storage '$CONTAINER_STORAGE' has content types: $STORAGE_CONTENT"
# Check storage type for special handling case "$STORAGE_TYPE" in
STORAGE_TYPE=$(grep -E "^[^:]+: $CONTAINER_STORAGE$" /etc/pve/storage.cfg | cut -d: -f1) iscsidirect) exit 212 ;;
if [[ "$STORAGE_TYPE" == "linstor" ]]; then iscsi | zfs) exit 213 ;;
msg_info "Detected LINSTOR storage - verifying cluster connectivity" cephfs) exit 219 ;;
if ! pvesm status -storage "$CONTAINER_STORAGE" &>/dev/null; then pbs) exit 224 ;;
msg_error "LINSTOR storage '$CONTAINER_STORAGE' not accessible. Check LINSTOR cluster health." linstor | rbd | nfs | cifs)
exit 217 pvesm status -storage "$CONTAINER_STORAGE" &>/dev/null || exit 217
fi ;;
fi esac
grep -qw "rootdir" <<<"$STORAGE_CONTENT" || { pvesm status -content rootdir 2>/dev/null | awk 'NR>1{print $1}' | grep -qx "$CONTAINER_STORAGE" || exit 213
msg_error "Storage '$CONTAINER_STORAGE' does not support 'rootdir'. Cannot create LXC." msg_ok "Storage '$CONTAINER_STORAGE' ($STORAGE_TYPE) validated"
exit 217
}
$STD msg_ok "Storage '$CONTAINER_STORAGE' supports 'rootdir'"
msg_info "Validating content types of template storage '$TEMPLATE_STORAGE'" msg_info "Validating template storage '$TEMPLATE_STORAGE'"
TEMPLATE_CONTENT=$(grep -A4 -E "^[^:]+: $TEMPLATE_STORAGE" /etc/pve/storage.cfg | grep content | awk '{$1=""; print $0}' | xargs)
msg_debug "Template storage '$TEMPLATE_STORAGE' has content types: $TEMPLATE_CONTENT"
# Check if template storage is LINSTOR (may need special handling)
TEMPLATE_TYPE=$(grep -E "^[^:]+: $TEMPLATE_STORAGE$" /etc/pve/storage.cfg | cut -d: -f1) TEMPLATE_TYPE=$(grep -E "^[^:]+: $TEMPLATE_STORAGE$" /etc/pve/storage.cfg | cut -d: -f1)
if [[ "$TEMPLATE_TYPE" == "linstor" ]]; then
msg_info "Template storage uses LINSTOR - ensuring resource availability"
fi
if ! grep -qw "vztmpl" <<<"$TEMPLATE_CONTENT"; then if ! pvesm status -content vztmpl 2>/dev/null | awk 'NR>1{print $1}' | grep -qx "$TEMPLATE_STORAGE"; then
msg_warn "Template storage '$TEMPLATE_STORAGE' does not declare 'vztmpl'. This may cause pct create to fail." msg_warn "Template storage '$TEMPLATE_STORAGE' may not support 'vztmpl'"
else
$STD msg_ok "Template storage '$TEMPLATE_STORAGE' supports 'vztmpl'"
fi fi
msg_ok "Template storage '$TEMPLATE_STORAGE' validated"
# Free space check # Free space check
STORAGE_FREE=$(pvesm status | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }') STORAGE_FREE=$(pvesm status | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
@ -3261,7 +3248,7 @@ create_lxc_container() {
msg_info "Checking cluster quorum" msg_info "Checking cluster quorum"
if ! pvecm status | awk -F':' '/^Quorate/ { exit ($2 ~ /Yes/) ? 0 : 1 }'; then if ! pvecm status | awk -F':' '/^Quorate/ { exit ($2 ~ /Yes/) ? 0 : 1 }'; then
msg_error "Cluster is not quorate. Start all nodes or configure quorum device (QDevice)." msg_error "Cluster is not quorate. Start all nodes or configure quorum device (QDevice)."
exit 201 exit 210
fi fi
msg_ok "Cluster is quorate" msg_ok "Cluster is quorate"
fi fi
@ -3298,6 +3285,14 @@ create_lxc_container() {
ONLINE_TEMPLATE="" ONLINE_TEMPLATE=""
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}" [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
count=0
for idx in "${!ONLINE_TEMPLATES[@]}"; do
((count++))
[[ $count -ge 3 ]] && break
done
fi
if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${LOCAL_TEMPLATES[-1]}" TEMPLATE="${LOCAL_TEMPLATES[-1]}"
TEMPLATE_SOURCE="local" TEMPLATE_SOURCE="local"
@ -3525,7 +3520,6 @@ create_lxc_container() {
if [[ "$PCT_OSTYPE" == "debian" ]]; then if [[ "$PCT_OSTYPE" == "debian" ]]; then
OSVER="$(parse_template_osver "$TEMPLATE")" OSVER="$(parse_template_osver "$TEMPLATE")"
if [[ -n "$OSVER" ]]; then if [[ -n "$OSVER" ]]; then
# Proactive, but without abort only offer
offer_lxc_stack_upgrade_and_maybe_retry "no" || true offer_lxc_stack_upgrade_and_maybe_retry "no" || true
fi fi
fi fi
@ -3554,7 +3548,7 @@ create_lxc_container() {
} }
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 202 exit 211
} }
LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log" LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log"
@ -3603,12 +3597,12 @@ create_lxc_container() {
0) : ;; # success - container created, continue 0) : ;; # success - container created, continue
2) 2)
echo "Upgrade was declined. Please update and re-run: echo "Upgrade was declined. Please update and re-run:
apt update && apt install --only-upgrade pve-container lxc-pve" apt update && apt install --only-upgrade pve-container lxc-pve"
exit 213 exit 231
;; ;;
3) 3)
echo "Upgrade and/or retry failed. Please inspect: $LOGFILE" echo "Upgrade and/or retry failed. Please inspect: $LOGFILE"
exit 213 exit 231
;; ;;
esac esac
else else
@ -3635,12 +3629,12 @@ create_lxc_container() {
0) : ;; # success - container created, continue 0) : ;; # success - container created, continue
2) 2)
echo "Upgrade was declined. Please update and re-run: echo "Upgrade was declined. Please update and re-run:
apt update && apt install --only-upgrade pve-container lxc-pve" apt update && apt install --only-upgrade pve-container lxc-pve"
exit 213 exit 231
;; ;;
3) 3)
echo "Upgrade and/or retry failed. Please inspect: $LOGFILE" echo "Upgrade and/or retry failed. Please inspect: $LOGFILE"
exit 213 exit 231
;; ;;
esac esac
else else

View File

@ -34,9 +34,9 @@
# * Node.js/npm errors (243-249, 254) # * Node.js/npm errors (243-249, 254)
# * Python/pip/uv errors (210-212) # * Python/pip/uv errors (210-212)
# * PostgreSQL errors (231-234) # * PostgreSQL errors (231-234)
# * MySQL/MariaDB errors (260-263) # * MySQL/MariaDB errors (241-244)
# * MongoDB errors (251-253) # * MongoDB errors (251-254)
# * Proxmox custom codes (200-209, 213-223, 225) # * Proxmox custom codes (200-231)
# - Returns description string for given exit code # - Returns description string for given exit code
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
explain_exit_code() { explain_exit_code() {
@ -79,38 +79,43 @@ explain_exit_code() {
234) echo "PostgreSQL: Fatal error in query / syntax" ;; 234) echo "PostgreSQL: Fatal error in query / syntax" ;;
# --- MySQL / MariaDB --- # --- MySQL / MariaDB ---
260) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;; 241) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;;
261) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;; 242) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;;
262) echo "MySQL/MariaDB: Database does not exist" ;; 243) echo "MySQL/MariaDB: Database does not exist" ;;
263) echo "MySQL/MariaDB: Fatal error in query / syntax" ;; 244) echo "MySQL/MariaDB: Fatal error in query / syntax" ;;
# --- MongoDB --- # --- MongoDB ---
251) echo "MongoDB: Connection failed (server not running)" ;; 251) echo "MongoDB: Connection failed (server not running)" ;;
252) echo "MongoDB: Authentication failed (bad user/password)" ;; 252) echo "MongoDB: Authentication failed (bad user/password)" ;;
253) echo "MongoDB: Database not found" ;; 253) echo "MongoDB: Database not found" ;;
254) echo "MongoDB: Fatal query error" ;;
# --- Proxmox Custom Codes --- # --- Proxmox Custom Codes ---
200) echo "Custom: Failed to create lock file" ;; 200) echo "Proxmox: Failed to create lock file" ;;
201) echo "Custom: Cluster not quorate" ;; 203) echo "Proxmox: Missing CTID variable" ;;
202) echo "Custom: Timeout waiting for template lock (concurrent download in progress)" ;; 204) echo "Proxmox: Missing PCT_OSTYPE variable" ;;
203) echo "Custom: Missing CTID variable" ;; 205) echo "Proxmox: Invalid CTID (<100)" ;;
204) echo "Custom: Missing PCT_OSTYPE variable" ;; 206) echo "Proxmox: CTID already in use" ;;
205) echo "Custom: Invalid CTID (<100)" ;; 207) echo "Proxmox: Password contains unescaped special characters" ;;
206) echo "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)" ;; 208) echo "Proxmox: Invalid configuration (DNS/MAC/Network format)" ;;
207) echo "Custom: Password contains unescaped special characters (-, /, \\, *, etc.)" ;; 209) echo "Proxmox: Container creation failed" ;;
208) echo "Custom: Invalid configuration (DNS/MAC/Network format error)" ;; 210) echo "Proxmox: Cluster not quorate" ;;
209) echo "Custom: Container creation failed (check logs for pct create output)" ;; 211) echo "Proxmox: Timeout waiting for template lock" ;;
213) echo "Custom: LXC stack upgrade/retry failed (outdated pve-container - check https://github.com/community-scripts/ProxmoxVE/discussions/8126)" ;; 212) echo "Proxmox: Storage type 'iscsidirect' does not support containers (VMs only)" ;;
214) echo "Custom: Not enough storage space" ;; 213) echo "Proxmox: Storage type does not support 'rootdir' content" ;;
215) echo "Custom: Container created but not listed (ghost state - check /etc/pve/lxc/)" ;; 214) echo "Proxmox: Not enough storage space" ;;
216) echo "Custom: RootFS entry missing in config (incomplete creation)" ;; 215) echo "Proxmox: Container created but not listed (ghost state)" ;;
217) echo "Custom: Storage does not support rootdir (check storage capabilities)" ;; 216) echo "Proxmox: RootFS entry missing in config" ;;
218) echo "Custom: Template file corrupted or incomplete download (size <1MB or invalid archive)" ;; 217) echo "Proxmox: Storage not accessible" ;;
220) echo "Custom: Unable to resolve template path" ;; 219) echo "Proxmox: CephFS does not support containers - use RBD" ;;
221) echo "Custom: Template file exists but not readable (check file permissions)" ;; 224) echo "Proxmox: PBS storage is for backups only" ;;
222) echo "Custom: Template download failed after 3 attempts (network/storage issue)" ;; 218) echo "Proxmox: Template file corrupted or incomplete" ;;
223) echo "Custom: Template not available after download (storage sync issue)" ;; 220) echo "Proxmox: Unable to resolve template path" ;;
225) echo "Custom: No template available for OS/Version (check 'pveam available')" ;; 221) echo "Proxmox: Template file not readable" ;;
222) echo "Proxmox: Template download failed" ;;
223) echo "Proxmox: Template not available after download" ;;
225) echo "Proxmox: No template available for OS/Version" ;;
231) echo "Proxmox: LXC stack upgrade failed" ;;
# --- Default --- # --- Default ---
*) echo "Unknown error" ;; *) echo "Unknown error" ;;