all-templates.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #!/usr/bin/env bash
  2. # Copyright (c) 2021-2023 tteck
  3. # Author: tteck (tteckster)
  4. # License: MIT
  5. # https://github.com/tteck/Proxmox/raw/main/LICENSE
  6. function header_info {
  7. clear
  8. cat <<"EOF"
  9. ___ ____ ______ __ __
  10. / _ | / / / /_ __/__ __ _ ___ / /__ _/ /____ ___
  11. / __ |/ / / / / / -_) ' \/ _ \/ / _ `/ __/ -_|_-<
  12. /_/ |_/_/_/ /_/ \__/_/_/_/ .__/_/\_,_/\__/\__/___/
  13. /_/
  14. EOF
  15. }
  16. set -eEuo pipefail
  17. shopt -s expand_aliases
  18. alias die='EXIT=$? LINE=$LINENO error_exit'
  19. trap die ERR
  20. function error_exit() {
  21. trap - ERR
  22. local DEFAULT='Unknown failure occured.'
  23. local REASON="\e[97m${1:-$DEFAULT}\e[39m"
  24. local FLAG="\e[91m[ERROR] \e[93m$EXIT@$LINE"
  25. msg "$FLAG $REASON" 1>&2
  26. [ ! -z ${CTID-} ] && cleanup_ctid
  27. exit $EXIT
  28. }
  29. function warn() {
  30. local REASON="\e[97m$1\e[39m"
  31. local FLAG="\e[93m[WARNING]\e[39m"
  32. msg "$FLAG $REASON"
  33. }
  34. function info() {
  35. local REASON="$1"
  36. local FLAG="\e[36m[INFO]\e[39m"
  37. msg "$FLAG $REASON"
  38. }
  39. function msg() {
  40. local TEXT="$1"
  41. echo -e "$TEXT"
  42. }
  43. function cleanup_ctid() {
  44. if pct status $CTID &>/dev/null; then
  45. if [ "$(pct status $CTID | awk '{print $2}')" == "running" ]; then
  46. pct stop $CTID
  47. fi
  48. pct destroy $CTID
  49. fi
  50. }
  51. # Stop Proxmox VE Monitor-All if running
  52. if systemctl is-active -q ping-instances.service; then
  53. systemctl stop ping-instances.service
  54. fi
  55. header_info
  56. echo "Loading..."
  57. pveam update >/dev/null 2>&1
  58. whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Templates" --yesno "This will allow for the creation of one of the many Template LXC Containers. Proceed?" 10 68 || exit
  59. TEMPLATE_MENU=()
  60. MSG_MAX_LENGTH=0
  61. while read -r TAG ITEM; do
  62. OFFSET=2
  63. ((${#ITEM} + OFFSET > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH=${#ITEM}+OFFSET
  64. TEMPLATE_MENU+=("$ITEM" "$TAG " "OFF")
  65. done < <(pveam available)
  66. TEMPLATE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Template LXCs" --radiolist "\nSelect a Template LXC to create:\n" 16 $((MSG_MAX_LENGTH + 58)) 10 "${TEMPLATE_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"') || exit
  67. [ -z "$TEMPLATE" ] && {
  68. whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Template LXC Selected" --msgbox "It appears that no Template LXC container was selected" 10 68
  69. msg "Done"
  70. exit
  71. }
  72. # Setup script environment
  73. NAME=$(echo "$TEMPLATE" | grep -oE '^[^-]+-[^-]+')
  74. PASS="$(openssl rand -base64 8)"
  75. CTID=$(pvesh get /cluster/nextid)
  76. PCT_OPTIONS="
  77. -features keyctl=1,nesting=1
  78. -hostname $NAME
  79. -tags proxmox-helper-scripts
  80. -onboot 0
  81. -cores 2
  82. -memory 2048
  83. -password $PASS
  84. -net0 name=eth0,bridge=vmbr0,ip=dhcp
  85. -unprivileged 1
  86. "
  87. DEFAULT_PCT_OPTIONS=(
  88. -arch $(dpkg --print-architecture)
  89. )
  90. # Set the CONTENT and CONTENT_LABEL variables
  91. function select_storage() {
  92. local CLASS=$1
  93. local CONTENT
  94. local CONTENT_LABEL
  95. case $CLASS in
  96. container)
  97. CONTENT='rootdir'
  98. CONTENT_LABEL='Container'
  99. ;;
  100. template)
  101. CONTENT='vztmpl'
  102. CONTENT_LABEL='Container template'
  103. ;;
  104. *) false || die "Invalid storage class." ;;
  105. esac
  106. # Query all storage locations
  107. local -a MENU
  108. while read -r line; do
  109. local TAG=$(echo $line | awk '{print $1}')
  110. local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
  111. local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
  112. local ITEM=" Type: $TYPE Free: $FREE "
  113. local OFFSET=2
  114. if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
  115. local MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
  116. fi
  117. MENU+=("$TAG" "$ITEM" "OFF")
  118. done < <(pvesm status -content $CONTENT | awk 'NR>1')
  119. # Select storage location
  120. if [ $((${#MENU[@]} / 3)) -eq 0 ]; then
  121. warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
  122. die "Unable to detect valid storage location."
  123. elif [ $((${#MENU[@]} / 3)) -eq 1 ]; then
  124. printf ${MENU[0]}
  125. else
  126. local STORAGE
  127. while [ -z "${STORAGE:+x}" ]; do
  128. STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
  129. "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\n\n" \
  130. 16 $(($MSG_MAX_LENGTH + 23)) 6 \
  131. "${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted."
  132. done
  133. printf $STORAGE
  134. fi
  135. }
  136. header_info
  137. # Get template storage
  138. TEMPLATE_STORAGE=$(select_storage template) || exit
  139. info "Using '$TEMPLATE_STORAGE' for template storage."
  140. # Get container storage
  141. CONTAINER_STORAGE=$(select_storage container) || exit
  142. info "Using '$CONTAINER_STORAGE' for container storage."
  143. # Download template
  144. msg "Downloading LXC template (Patience)..."
  145. pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || die "A problem occured while downloading the LXC template."
  146. # Create variable for 'pct' options
  147. PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
  148. [[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
  149. # Create LXC
  150. msg "Creating LXC container..."
  151. pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[@]} >/dev/null ||
  152. die "A problem occured while trying to create container."
  153. # Save password
  154. echo "$NAME password: ${PASS}" >>~/$NAME.creds # file is located in the Proxmox root directory
  155. # Start container
  156. msg "Starting LXC Container..."
  157. pct start "$CTID"
  158. sleep 5
  159. # Get container IP
  160. set +eEuo pipefail
  161. max_attempts=5
  162. attempt=1
  163. IP=""
  164. while [[ $attempt -le $max_attempts ]]; do
  165. IP=$(pct exec $CTID ip a show dev eth0 | grep -oP 'inet \K[^/]+')
  166. if [[ -n $IP ]]; then
  167. break
  168. else
  169. warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
  170. sleep 5
  171. ((attempt++))
  172. fi
  173. done
  174. if [[ -z $IP ]]; then
  175. warn "Maximum number of attempts reached. IP address not found."
  176. IP="NOT FOUND"
  177. fi
  178. set -eEuo pipefail
  179. # Start Proxmox VE Monitor-All if available
  180. if [[ -f /etc/systemd/system/ping-instances.service ]]; then
  181. systemctl start ping-instances.service
  182. fi
  183. # Success message
  184. header_info
  185. echo
  186. info "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
  187. echo
  188. info "Proceed to the LXC console to complete the setup."
  189. echo
  190. info "login: root"
  191. info "password: $PASS"
  192. echo