diff --git a/misc/build.func b/misc/build.func index bcc237a7d..9aa69ef56 100644 --- a/misc/build.func +++ b/misc/build.func @@ -231,6 +231,100 @@ install_ssh_keys_into_ct() { return 0 } +# ------------------------------------------------------------------------------ +# validate_container_id() +# +# - Validates if a container ID is available for use +# - Checks if ID is already used by VM or LXC container +# - Checks if ID is used in LVM logical volumes +# - Returns 0 if ID is available, 1 if already in use +# ------------------------------------------------------------------------------ +validate_container_id() { + local ctid="$1" + + # Check if ID is numeric + if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then + return 1 + fi + + # Check if config file exists for VM or LXC + if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then + return 1 + fi + + # Check if ID is used in LVM logical volumes + if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then + return 1 + fi + + return 0 +} + +# ------------------------------------------------------------------------------ +# get_valid_container_id() +# +# - Returns a valid, unused container ID +# - If provided ID is valid, returns it +# - Otherwise increments from suggested ID until a free one is found +# - Calls validate_container_id() to check availability +# ------------------------------------------------------------------------------ +get_valid_container_id() { + local suggested_id="${1:-$(pvesh get /cluster/nextid)}" + + while ! validate_container_id "$suggested_id"; do + suggested_id=$((suggested_id + 1)) + done + + echo "$suggested_id" +} + +# ------------------------------------------------------------------------------ +# validate_container_id() +# +# - Validates if a container ID is available for use +# - Checks if ID is already used by VM or LXC container +# - Checks if ID is used in LVM logical volumes +# - Returns 0 if ID is available, 1 if already in use +# ------------------------------------------------------------------------------ +validate_container_id() { + local ctid="$1" + + # Check if ID is numeric + if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then + return 1 + fi + + # Check if config file exists for VM or LXC + if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then + return 1 + fi + + # Check if ID is used in LVM logical volumes + if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then + return 1 + fi + + return 0 +} + +# ------------------------------------------------------------------------------ +# get_valid_container_id() +# +# - Returns a valid, unused container ID +# - If provided ID is valid, returns it +# - Otherwise increments from suggested ID until a free one is found +# - Calls validate_container_id() to check availability +# ------------------------------------------------------------------------------ +get_valid_container_id() { + local suggested_id="${1:-$(pvesh get /cluster/nextid)}" + + while ! validate_container_id "$suggested_id"; do + suggested_id=$((suggested_id + 1)) + done + + echo "$suggested_id" +} + # ------------------------------------------------------------------------------ # find_host_ssh_keys() # @@ -483,7 +577,15 @@ base_settings() { RAM_SIZE="${final_ram}" VERBOSE=${var_verbose:-"${1:-no}"} PW=${var_pw:-""} - CT_ID=${var_ctid:-$NEXTID} + + # Validate and set Container ID + local requested_id="${var_ctid:-$NEXTID}" + if ! validate_container_id "$requested_id"; then + msg_warn "Container ID $requested_id is already in use. Using next available ID: $(get_valid_container_id "$requested_id")" + requested_id=$(get_valid_container_id "$requested_id") + fi + CT_ID="$requested_id" + HN=${var_hostname:-$NSAPP} BRG=${var_brg:-"vmbr0"} NET=${var_net:-"dhcp"} @@ -1308,7 +1410,25 @@ advanced_settings() { --ok-button "Next" --cancel-button "Back" \ --inputbox "\nSet Container ID" 10 58 "$_ct_id" \ 3>&1 1>&2 2>&3); then - _ct_id="${result:-$NEXTID}" + local input_id="${result:-$NEXTID}" + + # Validate that ID is numeric + if ! [[ "$input_id" =~ ^[0-9]+$ ]]; then + whiptail --backtitle "Proxmox VE Helper Scripts" --title "Invalid ID" --msgbox "Container ID must be numeric." 8 58 + continue + fi + + # Check if ID is already in use + if ! validate_container_id "$input_id"; then + if whiptail --backtitle "Proxmox VE Helper Scripts" --title "ID Already In Use" \ + --yesno "Container/VM ID $input_id is already in use.\n\nWould you like to use the next available ID ($(get_valid_container_id "$input_id"))?" 10 58; then + _ct_id=$(get_valid_container_id "$input_id") + else + continue + fi + else + _ct_id="$input_id" + fi ((STEP++)) else ((STEP--)) diff --git a/tools/addon/all-templates.sh b/tools/addon/all-templates.sh index 59bba3256..ed06360a5 100644 --- a/tools/addon/all-templates.sh +++ b/tools/addon/all-templates.sh @@ -42,6 +42,29 @@ function msg() { local TEXT="$1" echo -e "$TEXT" } +function validate_container_id() { + local ctid="$1" + # Check if ID is numeric + if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then + return 1 + fi + # Check if config file exists for VM or LXC + if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then + return 1 + fi + # Check if ID is used in LVM logical volumes + if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then + return 1 + fi + return 0 +} +function get_valid_container_id() { + local suggested_id="${1:-$(pvesh get /cluster/nextid)}" + while ! validate_container_id "$suggested_id"; do + suggested_id=$((suggested_id + 1)) + done + echo "$suggested_id" +} function cleanup_ctid() { if pct status $CTID &>/dev/null; then if [ "$(pct status $CTID | awk '{print $2}')" == "running" ]; then @@ -76,7 +99,15 @@ TEMPLATE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Templat # Setup script environment NAME=$(echo "$TEMPLATE" | grep -oE '^[^-]+-[^-]+') PASS="$(openssl rand -base64 8)" + +# Get valid Container ID CTID=$(pvesh get /cluster/nextid) +if ! validate_container_id "$CTID"; then + warn "Container ID $CTID is already in use." + CTID=$(get_valid_container_id "$CTID") + info "Using next available ID: $CTID" +fi + PCT_OPTIONS=" -features keyctl=1,nesting=1 -hostname $NAME diff --git a/turnkey/turnkey.sh b/turnkey/turnkey.sh index bbfa7e128..6b53cf747 100644 --- a/turnkey/turnkey.sh +++ b/turnkey/turnkey.sh @@ -42,6 +42,29 @@ function msg() { local TEXT="$1" echo -e "$TEXT" } +function validate_container_id() { + local ctid="$1" + # Check if ID is numeric + if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then + return 1 + fi + # Check if config file exists for VM or LXC + if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then + return 1 + fi + # Check if ID is used in LVM logical volumes + if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then + return 1 + fi + return 0 +} +function get_valid_container_id() { + local suggested_id="${1:-$(pvesh get /cluster/nextid)}" + while ! validate_container_id "$suggested_id"; do + suggested_id=$((suggested_id + 1)) + done + echo "$suggested_id" +} function cleanup_ctid() { if pct status $CTID &>/dev/null; then if [ "$(pct status $CTID | awk '{print $2}')" == "running" ]; then @@ -99,9 +122,26 @@ turnkey=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "TurnKey LXCs # Setup script environment PASS="$(openssl rand -base64 8)" # Prompt user to confirm container ID - CTID=$(whiptail --backtitle "Container ID" --title "Choose the Container ID" --inputbox "Enter the conatiner ID..." 8 40 $(pvesh get /cluster/nextid) 3>&1 1>&2 2>&3) +while true; do + CTID=$(whiptail --backtitle "Container ID" --title "Choose the Container ID" --inputbox "Enter the container ID..." 8 40 $(pvesh get /cluster/nextid) 3>&1 1>&2 2>&3) + + # Check if user cancelled + [ -z "$CTID" ] && die "No Container ID selected" + + # Validate Container ID + if ! validate_container_id "$CTID"; then + SUGGESTED_ID=$(get_valid_container_id "$CTID") + if whiptail --backtitle "Container ID" --title "ID Already In Use" --yesno "Container/VM ID $CTID is already in use.\n\nWould you like to use the next available ID ($SUGGESTED_ID)?" 10 58; then + CTID="$SUGGESTED_ID" + break + fi + # User declined, loop back to input + else + break + fi +done # Prompt user to confirm Hostname - HOST_NAME=$(whiptail --backtitle "Hostname" --title "Choose the Hostname" --inputbox "Enter the containers Hostname..." 8 40 "turnkey-${turnkey}" 3>&1 1>&2 2>&3) +HOST_NAME=$(whiptail --backtitle "Hostname" --title "Choose the Hostname" --inputbox "Enter the containers Hostname..." 8 40 "turnkey-${turnkey}" 3>&1 1>&2 2>&3) PCT_OPTIONS=" -features keyctl=1,nesting=1 -hostname $HOST_NAME @@ -206,8 +246,8 @@ echo "TurnKey ${turnkey} password: ${PASS}" >>~/turnkey-${turnkey}.creds # file TUN_DEVICE_REQUIRED=("openvpn") # Setup this way in case future turnkeys also need tun access if printf '%s\n' "${TUN_DEVICE_REQUIRED[@]}" | grep -qw "${turnkey}"; then info "${turnkey} requires access to /dev/net/tun on the host. Modifying the container configuration to allow this." - echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >> /etc/pve/lxc/${CTID}.conf - echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file 0 0" >> /etc/pve/lxc/${CTID}.conf + echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >>/etc/pve/lxc/${CTID}.conf + echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file 0 0" >>/etc/pve/lxc/${CTID}.conf sleep 5 fi