mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-06-28 04:06:54 +00:00
Update menu create VM
This commit is contained in:
parent
756eb8e741
commit
e637a5327c
156
scripts/vm/create_vm.sh
Normal file
156
scripts/vm/create_vm.sh
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# ProxMenux - Create VM Entry Point
|
||||||
|
# ================================================
|
||||||
|
# Author : MacRimi
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
|
||||||
|
VM_REPO="$REPO_URL/scripts/vm"
|
||||||
|
MENU_REPO="$REPO_URL/scripts/menus"
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
|
||||||
|
[[ -f "$UTILS_FILE" ]] && source "$UTILS_FILE"
|
||||||
|
|
||||||
|
|
||||||
|
source <(curl -s "$VM_REPO/vm_configurator.sh")
|
||||||
|
source <(curl -s "$VM_REPO/disk_selector.sh")
|
||||||
|
source <(curl -s "$VM_REPO/vm_creator.sh")
|
||||||
|
source <(curl -s "$VM_REPO/guest_agent_config.sh")
|
||||||
|
|
||||||
|
|
||||||
|
if [[ -f "$UTILS_FILE" ]]; then
|
||||||
|
source "$UTILS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
# Load modules
|
||||||
|
[[ -f "$UTILS_FILE" ]] && source "$UTILS_FILE"
|
||||||
|
[[ -f "$VM_CONFIG" ]] && source "$VM_CONFIG"
|
||||||
|
[[ -f "$DISK_SELECTOR" ]] && source "$DISK_SELECTOR"
|
||||||
|
[[ -f "$VM_CREATOR" ]] && source "$VM_CREATOR"
|
||||||
|
[[ -f "$LINUX_ISO" ]] && source "$LINUX_ISO"
|
||||||
|
[[ -f "$GUEST_AGENT" ]] && source "$GUEST_AGENT"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function header_info() {
|
||||||
|
clear
|
||||||
|
show_proxmenux_logo
|
||||||
|
echo -e "${BL}╔═══════════════════════════════════════════════╗${CL}"
|
||||||
|
echo -e "${BL}║ ║${CL}"
|
||||||
|
echo -e "${BL}║${YWB} ProxMenux VM Creator ${BL}║${CL}"
|
||||||
|
echo -e "${BL}║ ║${CL}"
|
||||||
|
echo -e "${BL}╚═══════════════════════════════════════════════╝${CL}"
|
||||||
|
echo -e
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# MAIN EXECUTION
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
header_info
|
||||||
|
echo -e "\n Loading..."
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function start_vm_configuration() {
|
||||||
|
|
||||||
|
if (whiptail --title "ProxMenux" --yesno "$(translate "Use Default Settings?")" --no-button "$(translate "Advanced")" 10 60); then
|
||||||
|
header_info
|
||||||
|
load_default_vm_config "$OS_TYPE"
|
||||||
|
|
||||||
|
if [[ -z "$HN" ]]; then
|
||||||
|
HN=$(whiptail --inputbox "$(translate "Enter a name for the new virtual machine:")" 10 60 --title "VM Hostname" 3>&1 1>&2 2>&3)
|
||||||
|
[[ -z "$HN" ]] && HN="custom-vm"
|
||||||
|
fi
|
||||||
|
|
||||||
|
apply_default_vm_config
|
||||||
|
else
|
||||||
|
header_info
|
||||||
|
echo -e "${CUS}$(translate "Using advanced configuration")${CL}"
|
||||||
|
configure_vm_advanced "$OS_TYPE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
OS_TYPE=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(translate "Select System Type")" \
|
||||||
|
--menu "$(translate "Choose the type of virtual system to install:")" 18 64 8 \
|
||||||
|
1 "$(translate "Create") VM System NAS" \
|
||||||
|
2 "$(translate "Create") VM System Windows" \
|
||||||
|
3 "$(translate "Create") VM System Linux" \
|
||||||
|
4 "$(translate "Create") VM System Others (based Linux)" \
|
||||||
|
5 "$(translate "Return to Main Menu")" \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
|
||||||
|
[[ $? -ne 0 || "$OS_TYPE" == "5" ]] && exec bash <(curl -s "$MENU_REPO/main_menu.sh")
|
||||||
|
|
||||||
|
case "$OS_TYPE" in
|
||||||
|
1)
|
||||||
|
source <(curl -fsSL "$ISO_REPO/select_nas_iso.sh") && select_nas_iso || continue
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
source <(curl -fsSL "$ISO_REPO/select_windows_iso.sh") && select_windows_iso || continue
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
source <(curl -fsSL "$ISO_REPO/select_linux_iso.sh") && select_linux_iso || continue
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
source <(curl -fsSL "$ISO_REPO/select_linux_iso.sh") && select_linux_other_scripts || continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
if ! confirm_vm_creation; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
start_vm_configuration || continue
|
||||||
|
|
||||||
|
|
||||||
|
select_disk_type
|
||||||
|
if [[ -z "$DISK_TYPE" ]]; then
|
||||||
|
msg_error "$(translate "Disk type selection failed or cancelled")"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
create_vm
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function start_vm_configuration() {
|
||||||
|
|
||||||
|
if (whiptail --title "ProxMenux" --yesno "$(translate "Use Default Settings?")" --no-button "$(translate "Advanced")" 10 60); then
|
||||||
|
header_info
|
||||||
|
load_default_vm_config "$OS_TYPE"
|
||||||
|
|
||||||
|
if [[ -z "$HN" ]]; then
|
||||||
|
HN=$(whiptail --inputbox "$(translate "Enter a name for the new virtual machine:")" 10 60 --title "VM Hostname" 3>&1 1>&2 2>&3)
|
||||||
|
[[ -z "$HN" ]] && HN="custom-vm"
|
||||||
|
fi
|
||||||
|
|
||||||
|
apply_default_vm_config
|
||||||
|
else
|
||||||
|
header_info
|
||||||
|
echo -e "${CUS}$(translate "Using advanced configuration")${CL}"
|
||||||
|
configure_vm_advanced "$OS_TYPE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
280
scripts/vm/disk_selector.sh
Normal file
280
scripts/vm/disk_selector.sh
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Disk Selector Module - ProxMenux
|
||||||
|
# ==========================================================
|
||||||
|
# Reutiliza la lógica original de selección de discos
|
||||||
|
# virtuales y físicos con integración de traducciones
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
|
||||||
|
if [[ -f "$UTILS_FILE" ]]; then
|
||||||
|
source "$UTILS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
function select_disk_type() {
|
||||||
|
DISK_TYPE=$(whiptail --backtitle "ProxMenux" --title "DISK TYPE" --menu "$(translate "Choose disk type:")" 12 58 2 \
|
||||||
|
"virtual" "$(translate "Create virtual disk")" \
|
||||||
|
"passthrough" "$(translate "Use physical disk passthrough")" \
|
||||||
|
--ok-button "Select" --cancel-button "Cancel" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ -z "$DISK_TYPE" ]] && return 1
|
||||||
|
|
||||||
|
if [[ "$DISK_TYPE" == "virtual" ]]; then
|
||||||
|
select_virtual_disk
|
||||||
|
else
|
||||||
|
select_passthrough_disk
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Select Virtual Disks
|
||||||
|
# ==========================================================
|
||||||
|
function select_virtual_disk() {
|
||||||
|
|
||||||
|
VIRTUAL_DISKS=()
|
||||||
|
|
||||||
|
# Loop to add multiple disks
|
||||||
|
local add_more_disks=true
|
||||||
|
while $add_more_disks; do
|
||||||
|
|
||||||
|
msg_info "Detecting available storage volumes..."
|
||||||
|
|
||||||
|
# Get list of available storage
|
||||||
|
STORAGE_MENU=()
|
||||||
|
while read -r line; do
|
||||||
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
|
TYPE=$(echo $line | awk '{print $2}')
|
||||||
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format "%.2f" | awk '{printf( "%9sB", $6)}')
|
||||||
|
ITEM=$(printf "%-15s %-10s %-15s" "$TAG" "$TYPE" "$FREE")
|
||||||
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
|
|
||||||
|
# Check that storage is available
|
||||||
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
|
if [ -z "$VALID" ]; then
|
||||||
|
msg_error "Unable to detect a valid storage location."
|
||||||
|
sleep 2
|
||||||
|
select_disk_type
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Select storage
|
||||||
|
if [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
|
else
|
||||||
|
|
||||||
|
kill $SPINNER_PID > /dev/null
|
||||||
|
STORAGE=$(whiptail --backtitle "ProxMenuX" --title "$(translate "Select Storage Volume")" --radiolist \
|
||||||
|
"$(translate "Choose the storage volume for the virtual disk:\n")" 20 78 10 \
|
||||||
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ -z "$STORAGE" ]; then
|
||||||
|
if [ ${#VIRTUAL_DISKS[@]} -eq 0 ]; then
|
||||||
|
msg_error "No storage selected. At least one disk is required."
|
||||||
|
select_disk_type
|
||||||
|
else
|
||||||
|
add_more_disks=false
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Request disk size
|
||||||
|
DISK_SIZE=$(whiptail --backtitle "ProxMenuX" --inputbox "$(translate "System Disk Size (GB)")" 8 58 32 --title "VIRTUAL DISK" --cancel-button Cancel 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
if [ ${#VIRTUAL_DISKS[@]} -eq 0 ]; then
|
||||||
|
msg_error "Disk size not specified. At least one disk is required."
|
||||||
|
sleep 2
|
||||||
|
select_disk_type
|
||||||
|
|
||||||
|
else
|
||||||
|
add_more_disks=false
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$DISK_SIZE" ]; then
|
||||||
|
DISK_SIZE="32"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store the configuration in the disk list
|
||||||
|
VIRTUAL_DISKS+=("${STORAGE}:${DISK_SIZE}")
|
||||||
|
|
||||||
|
|
||||||
|
# Ask if you want to create another disk
|
||||||
|
if ! whiptail --backtitle "ProxMenuX" --title "$(translate "Add Another Disk")" \
|
||||||
|
--yesno "$(translate "Do you want to add another virtual disk?")" 8 58; then
|
||||||
|
add_more_disks=false
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Show summary of the created disks
|
||||||
|
if [ ${#VIRTUAL_DISKS[@]} -gt 0 ]; then
|
||||||
|
|
||||||
|
msg_ok "Virtual Disks Created:"
|
||||||
|
for i in "${!VIRTUAL_DISKS[@]}"; do
|
||||||
|
echo -e "${TAB}${BL}- Disk $((i+1)): ${VIRTUAL_DISKS[$i]}GB${CL}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
export VIRTUAL_DISKS
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Select Physical Disks
|
||||||
|
# ==========================================================
|
||||||
|
function select_passthrough_disk() {
|
||||||
|
|
||||||
|
msg_info "$(translate "Detecting available disks...")"
|
||||||
|
|
||||||
|
FREE_DISKS=()
|
||||||
|
|
||||||
|
USED_DISKS=$(lsblk -n -o PKNAME,TYPE | grep 'lvm' | awk '{print "/dev/" $1}')
|
||||||
|
MOUNTED_DISKS=$(lsblk -ln -o NAME,MOUNTPOINT | awk '$2!="" {print "/dev/" $1}')
|
||||||
|
|
||||||
|
ZFS_DISKS=""
|
||||||
|
ZFS_RAW=$(zpool list -v -H 2>/dev/null | awk '{print $1}' | grep -v '^NAME$' | grep -v '^-' | grep -v '^mirror')
|
||||||
|
|
||||||
|
for entry in $ZFS_RAW; do
|
||||||
|
path=""
|
||||||
|
if [[ "$entry" == wwn-* || "$entry" == ata-* ]]; then
|
||||||
|
if [ -e "/dev/disk/by-id/$entry" ]; then
|
||||||
|
path=$(readlink -f "/dev/disk/by-id/$entry")
|
||||||
|
fi
|
||||||
|
elif [[ "$entry" == /dev/* ]]; then
|
||||||
|
path="$entry"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$path" ]; then
|
||||||
|
base_disk=$(lsblk -no PKNAME "$path" 2>/dev/null)
|
||||||
|
if [ -n "$base_disk" ]; then
|
||||||
|
ZFS_DISKS+="/dev/$base_disk"$'\n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
ZFS_DISKS=$(echo "$ZFS_DISKS" | sort -u)
|
||||||
|
LVM_DEVICES=$(pvs --noheadings -o pv_name 2> >(grep -v 'File descriptor .* leaked') | xargs -n1 readlink -f | sort -u)
|
||||||
|
|
||||||
|
RAID_ACTIVE=$(grep -Po 'md\d+\s*:\s*active\s+raid[0-9]+' /proc/mdstat | awk '{print $1}' | sort -u)
|
||||||
|
|
||||||
|
while read -r DISK; do
|
||||||
|
[[ "$DISK" =~ /dev/zd ]] && continue
|
||||||
|
|
||||||
|
INFO=($(lsblk -dn -o MODEL,SIZE "$DISK"))
|
||||||
|
MODEL="${INFO[@]::${#INFO[@]}-1}"
|
||||||
|
SIZE="${INFO[-1]}"
|
||||||
|
LABEL=""
|
||||||
|
SHOW_DISK=true
|
||||||
|
|
||||||
|
IS_MOUNTED=false
|
||||||
|
IS_RAID=false
|
||||||
|
IS_ZFS=false
|
||||||
|
IS_LVM=false
|
||||||
|
|
||||||
|
while read -r part fstype; do
|
||||||
|
[[ "$fstype" == "zfs_member" ]] && IS_ZFS=true
|
||||||
|
[[ "$fstype" == "linux_raid_member" ]] && IS_RAID=true
|
||||||
|
[[ "$fstype" == "LVM2_member" ]] && IS_LVM=true
|
||||||
|
if grep -q "/dev/$part" <<< "$MOUNTED_DISKS"; then
|
||||||
|
IS_MOUNTED=true
|
||||||
|
fi
|
||||||
|
done < <(lsblk -ln -o NAME,FSTYPE "$DISK" | tail -n +2)
|
||||||
|
|
||||||
|
REAL_PATH=$(readlink -f "$DISK")
|
||||||
|
if echo "$LVM_DEVICES" | grep -qFx "$REAL_PATH"; then
|
||||||
|
IS_MOUNTED=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
USED_BY=""
|
||||||
|
REAL_PATH=$(readlink -f "$DISK")
|
||||||
|
CONFIG_DATA=$(cat /etc/pve/qemu-server/*.conf /etc/pve/lxc/*.conf 2>/dev/null)
|
||||||
|
|
||||||
|
if grep -Fq "$REAL_PATH" <<< "$CONFIG_DATA"; then
|
||||||
|
USED_BY="⚠ $(translate "In use")"
|
||||||
|
else
|
||||||
|
for SYMLINK in /dev/disk/by-id/*; do
|
||||||
|
if [[ "$(readlink -f "$SYMLINK")" == "$REAL_PATH" ]]; then
|
||||||
|
if grep -Fq "$SYMLINK" <<< "$CONFIG_DATA"; then
|
||||||
|
USED_BY="⚠ $(translate "In use")"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $IS_RAID && grep -q "$DISK" <<< "$(cat /proc/mdstat)" && grep -q "active raid" /proc/mdstat; then
|
||||||
|
SHOW_DISK=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $IS_ZFS || $IS_MOUNTED || [[ "$ZFS_DISKS" == *"$DISK"* ]]; then
|
||||||
|
SHOW_DISK=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $SHOW_DISK; then
|
||||||
|
[[ -n "$USED_BY" ]] && LABEL+=" [$USED_BY]"
|
||||||
|
[[ "$IS_RAID" == true ]] && LABEL+=" ⚠ RAID"
|
||||||
|
[[ "$IS_LVM" == true ]] && LABEL+=" ⚠ LVM"
|
||||||
|
[[ "$IS_ZFS" == true ]] && LABEL+=" ⚠ ZFS"
|
||||||
|
DESCRIPTION=$(printf "%-30s %10s%s" "$MODEL" "$SIZE" "$LABEL")
|
||||||
|
FREE_DISKS+=("$DISK" "$DESCRIPTION" "OFF")
|
||||||
|
fi
|
||||||
|
done < <(lsblk -dn -e 7,11 -o PATH)
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${#FREE_DISKS[@]}" -eq 0 ]; then
|
||||||
|
cleanup
|
||||||
|
whiptail --title "Error" --msgbox "$(translate "No disks available for this VM.")" 8 40
|
||||||
|
select_disk_type
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAX_WIDTH=$(printf "%s\n" "${FREE_DISKS[@]}" | awk '{print length}' | sort -nr | head -n1)
|
||||||
|
TOTAL_WIDTH=$((MAX_WIDTH + 20))
|
||||||
|
[ $TOTAL_WIDTH -lt 50 ] && TOTAL_WIDTH=50
|
||||||
|
cleanup
|
||||||
|
SELECTED_DISKS=$(whiptail --title "Select Disks" --checklist \
|
||||||
|
"$(translate "Select the disks you want to use (use spacebar to select):")" 20 $TOTAL_WIDTH 10 \
|
||||||
|
"${FREE_DISKS[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
if [ -z "$SELECTED_DISKS" ]; then
|
||||||
|
msg_error "Disk not specified. At least one disk is required."
|
||||||
|
sleep 2
|
||||||
|
select_disk_type
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
msg_ok "Disk passthrough selected:"
|
||||||
|
PASSTHROUGH_DISKS=()
|
||||||
|
for DISK in $(echo "$SELECTED_DISKS" | tr -d '"'); do
|
||||||
|
DISK_INFO=$(lsblk -ndo MODEL,SIZE "$DISK" | xargs)
|
||||||
|
echo -e "${TAB}${CL}${BL}- $DISK $DISK_INFO${GN}${CL}"
|
||||||
|
PASSTHROUGH_DISKS+=("$DISK")
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
# ==========================================================
|
49
scripts/vm/guest_agent_config.sh
Normal file
49
scripts/vm/guest_agent_config.sh
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Guest Agent Configurator - ProxMenux
|
||||||
|
# ==========================================================
|
||||||
|
# Añade soporte al QEMU Guest Agent y dispositivos útiles.
|
||||||
|
# Se adapta según el sistema operativo.
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
|
||||||
|
if [[ -f "$UTILS_FILE" ]]; then
|
||||||
|
source "$UTILS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function configure_guest_agent() {
|
||||||
|
if [[ -z "$VMID" ]]; then
|
||||||
|
msg_error "$(translate "No VMID defined. Cannot apply guest agent config.")"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "$(translate "Adding QEMU Guest Agent support...")"
|
||||||
|
|
||||||
|
# Habilitar el agente en la VM
|
||||||
|
qm set "$VMID" -agent enabled=1 >/dev/null 2>&1
|
||||||
|
|
||||||
|
# Añadir canal de comunicación virtio
|
||||||
|
qm set "$VMID" -chardev socket,id=qga0,path=/var/run/qemu-server/$VMID.qga,server=on,wait=off >/dev/null 2>&1
|
||||||
|
qm set "$VMID" -device virtio-serial-pci -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 >/dev/null 2>&1
|
||||||
|
|
||||||
|
msg_ok "$(translate "Guest Agent configuration applied")"
|
||||||
|
|
||||||
|
if [[ "$OS_TYPE" == "windows" ]]; then
|
||||||
|
echo -e "${YW}$(translate "Reminder: You must install the QEMU Guest Agent inside the Windows VM")${NC}"
|
||||||
|
echo -e "${YW}$(translate "Tip: Also mount the VirtIO ISO for drivers and guest agent installer")${NC}"
|
||||||
|
echo -e "${TAB}- https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/"
|
||||||
|
elif [[ "$OS_TYPE" == "linux" || "$OS_TYPE" == "lite" ]]; then
|
||||||
|
echo -e "${YW}$(translate "Tip: You can install the QEMU Guest Agent inside the VM with:")${NC}"
|
||||||
|
echo -e "${TAB}apt install qemu-guest-agent -y && systemctl enable --now qemu-guest-agent"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
239
scripts/vm/select_linux_iso.sh
Normal file
239
scripts/vm/select_linux_iso.sh
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==============================================================
|
||||||
|
# ProxMenux - Linux Installer Entry
|
||||||
|
# ==============================================================
|
||||||
|
|
||||||
|
# Configuración base y entorno
|
||||||
|
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
ISO_DIR="/var/lib/vz/template/iso"
|
||||||
|
|
||||||
|
[[ -f "$UTILS_FILE" ]] && source "$UTILS_FILE"
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
# ==============================================================
|
||||||
|
# FUNCIONES PRINCIPALES
|
||||||
|
# ==============================================================
|
||||||
|
|
||||||
|
function select_linux_iso() {
|
||||||
|
local EXIT_FLAG="no"
|
||||||
|
|
||||||
|
while [[ "$EXIT_FLAG" != "yes" ]]; do
|
||||||
|
CHOICE=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(translate "Linux Installation Options")" \
|
||||||
|
--menu "$(translate "Select the type of Linux installation:")" 15 70 6 \
|
||||||
|
1 "$(translate "Install from ISO (Ubuntu, Debian, Fedora...)")" \
|
||||||
|
2 "$(translate "Install with Cloud-Init script (Automated)")" \
|
||||||
|
3 "$(translate "Use custom ISO from storage")" \
|
||||||
|
4 "$(translate "Back to Main Menu")" \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
if [[ $? -ne 0 ]] || [[ "$CHOICE" == "4" ]]; then
|
||||||
|
unset ISO_NAME ISO_TYPE ISO_URL ISO_FILE ISO_PATH HN
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$CHOICE" in
|
||||||
|
1)
|
||||||
|
select_linux_iso_official && EXIT_FLAG="yes"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
select_linux_cloudinit
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
select_linux_custom_iso && EXIT_FLAG="yes"
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function select_linux_iso_official() {
|
||||||
|
DISTROS=(
|
||||||
|
"Ubuntu 22.04|Desktop|ProxMenux|https://releases.ubuntu.com/22.04/ubuntu-22.04.5-desktop-amd64.iso"
|
||||||
|
"Ubuntu 20.04|Desktop|ProxMenux|https://releases.ubuntu.com/20.04/ubuntu-20.04.6-desktop-amd64.iso"
|
||||||
|
"Ubuntu 22.04 Server|CLI|ProxMenux|https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso"
|
||||||
|
"Ubuntu 20.04 Server|CLI|ProxMenux|https://releases.ubuntu.com/20.04/ubuntu-20.04.6-live-server-amd64.iso"
|
||||||
|
"Debian 12|Desktop|ProxMenux|https://cdimage.debian.org/debian-cd/current/amd64/iso-dvd/debian-12.10.0-amd64-DVD-1.iso"
|
||||||
|
"Debian 11|Desktop|ProxMenux|https://cdimage.debian.org/cdimage/archive/11.11.0/amd64/iso-dvd/debian-11.11.0-amd64-DVD-1.iso"
|
||||||
|
"Debian 12 Netinst|CLI|ProxMenux|https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.10.0-amd64-netinst.iso"
|
||||||
|
"Debian 11 Netinst|CLI|ProxMenux|https://cdimage.debian.org/cdimage/archive/11.11.0/amd64/iso-cd/debian-11.11.0-amd64-netinst.iso"
|
||||||
|
"Fedora Workstation 42|Desktop|ProxMenux|https://download.fedoraproject.org/pub/fedora/linux/releases/42/Workstation/x86_64/iso/Fedora-Workstation-Live-42-1.1.x86_64.iso"
|
||||||
|
"Rocky Linux 9.5|Desktop|ProxMenux|https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.5-x86_64-dvd.iso"
|
||||||
|
"Linux Mint 22.1|Desktop|ProxMenux|https://mirrors.edge.kernel.org/linuxmint/stable/22.1/linuxmint-22.1-cinnamon-64bit.iso"
|
||||||
|
"openSUSE Leap 15.6|Desktop|ProxMenux|https://download.opensuse.org/distribution/leap/15.6/iso/openSUSE-Leap-15.6-DVD-x86_64-Media.iso"
|
||||||
|
"Alpine Linux 3.21|Desktop|ProxMenux|https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-virt-3.21.3-x86_64.iso"
|
||||||
|
"Kali Linux 2025.1|Desktop|ProxMenux|https://cdimage.kali.org/kali-2025.1c/kali-linux-2025.1c-qemu-amd64.7z"
|
||||||
|
"Manjaro 25.0|Desktop|ProxMenux|https://download.manjaro.org/gnome/25.0.0/manjaro-gnome-25.0.0-250414-linux612.iso"
|
||||||
|
)
|
||||||
|
|
||||||
|
MENU_OPTIONS=()
|
||||||
|
INDEX=0
|
||||||
|
for entry in "${DISTROS[@]}"; do
|
||||||
|
IFS='|' read -r NAME TYPE SOURCE URL <<< "$entry"
|
||||||
|
LINE=$(printf "%-40s │ %-10s │ %s" "$NAME" "$TYPE" "$SOURCE")
|
||||||
|
MENU_OPTIONS+=("$INDEX" "$LINE")
|
||||||
|
URLS[$INDEX]="$entry"
|
||||||
|
((INDEX++))
|
||||||
|
done
|
||||||
|
|
||||||
|
HEADER="%-42s │ %-10s │ %s"
|
||||||
|
HEADER_TEXT=$(printf "$HEADER" "Distribution" "Type" "Source")
|
||||||
|
|
||||||
|
CHOICE=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(translate "Official Linux Distributions")" \
|
||||||
|
--menu "$(translate "Select the Linux distribution to install:")\n\n$HEADER_TEXT" 20 90 12 \
|
||||||
|
"${MENU_OPTIONS[@]}" \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ $? -ne 0 ]] && return 1
|
||||||
|
|
||||||
|
SELECTED="${URLS[$CHOICE]}"
|
||||||
|
IFS='|' read -r ISO_NAME ISO_TYPE SOURCE ISO_URL <<< "$SELECTED"
|
||||||
|
ISO_FILE=$(basename "$ISO_URL")
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
|
||||||
|
HN=$(echo "$ISO_NAME" | \
|
||||||
|
sed 's/ (.*)//' | \
|
||||||
|
tr -cs '[:alnum:]' '-' | \
|
||||||
|
sed 's/^-*//' | \
|
||||||
|
sed 's/-*$//' | \
|
||||||
|
cut -c1-63)
|
||||||
|
|
||||||
|
export ISO_NAME ISO_TYPE ISO_URL ISO_FILE ISO_PATH HN
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function select_linux_cloudinit() {
|
||||||
|
local CLOUDINIT_OPTIONS=(
|
||||||
|
"1" "Arch Linux (Cloud-Init automated) │ Helper Scripts"
|
||||||
|
"2" "Debian 12 (Cloud-Init automated) │ Helper Scripts"
|
||||||
|
"3" "Ubuntu 22.04 (Cloud-Init automated) │ Helper Scripts"
|
||||||
|
"4" "Ubuntu 24.04 (Cloud-Init automated) │ Helper Scripts"
|
||||||
|
"5" "Ubuntu 24.10 (Cloud-Init automated) │ Helper Scripts"
|
||||||
|
"6" "$(translate "Return to Main Menu")"
|
||||||
|
)
|
||||||
|
|
||||||
|
local script_selection
|
||||||
|
script_selection=$(dialog --backtitle "ProxMenux" --title "$(translate "Cloud-Init Automated Installers")" \
|
||||||
|
--menu "$(translate "Select a pre-configured Linux VM script to execute:")" 20 78 10 \
|
||||||
|
"${CLOUDINIT_OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ $? -ne 0 ]] && return
|
||||||
|
|
||||||
|
case "$script_selection" in
|
||||||
|
1)
|
||||||
|
bash <(curl -s "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/archlinux-vm.sh")
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
bash <(curl -s "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/debian-vm.sh")
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
bash <(curl -s "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/ubuntu2204-vm.sh")
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
bash <(curl -s "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/ubuntu2404-vm.sh")
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
bash <(curl -s "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/ubuntu2410-vm.sh")
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
msg_success "$(translate "Press Enter to return to menu...")"
|
||||||
|
read -r
|
||||||
|
|
||||||
|
whiptail --title "Proxmox VE Helper-Scripts" \
|
||||||
|
--msgbox "$(translate "Visit the website to discover more scripts, stay updated with the latest updates, and support the project:\n\nhttps://community-scripts.github.io/ProxmoxVE")" 15 70
|
||||||
|
|
||||||
|
exec bash <(curl -s "$REPO_URL/scripts/vm/create_vm.sh")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function select_linux_custom_iso() {
|
||||||
|
ISO_LIST=()
|
||||||
|
while read -r line; do
|
||||||
|
FILENAME=$(basename "$line")
|
||||||
|
SIZE=$(du -h "$line" | cut -f1)
|
||||||
|
ISO_LIST+=("$FILENAME" "$SIZE")
|
||||||
|
done < <(find "$ISO_DIR" -type f -iname "*.iso" | sort)
|
||||||
|
|
||||||
|
if [[ ${#ISO_LIST[@]} -eq 0 ]]; then
|
||||||
|
msg_error "$(translate "No ISO images found in $ISO_DIR.")"
|
||||||
|
sleep 2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ISO_FILE=$(dialog --backtitle "ProxMenux" --title "$(translate "Available ISO Images")" \
|
||||||
|
--menu "$(translate "Select a custom ISO to use:")" 20 70 10 \
|
||||||
|
"${ISO_LIST[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
if [[ -z "$ISO_FILE" ]]; then
|
||||||
|
msg_warn "$(translate "No ISO selected.")"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
ISO_NAME="$ISO_FILE"
|
||||||
|
|
||||||
|
export ISO_PATH ISO_FILE ISO_NAME
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function select_linux_other_scripts() {
|
||||||
|
local OTHER_OPTIONS=(
|
||||||
|
"1" "Home Assistant OS VM (HAOS) │ Helper Scripts"
|
||||||
|
"2" "Docker VM (Debian + SSH + Docker) │ Helper Scripts"
|
||||||
|
"3" "$(translate "Return to Main Menu")"
|
||||||
|
)
|
||||||
|
|
||||||
|
local choice
|
||||||
|
choice=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(translate "Other Prebuilt Linux VMs")" \
|
||||||
|
--menu "$(translate "Select one of the ready-to-run Linux VMs:")" 18 78 10 \
|
||||||
|
"${OTHER_OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ $? -ne 0 ]] && return
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/haos-vm.sh)"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/docker-vm.sh)"
|
||||||
|
|
||||||
|
# Mostrar credenciales
|
||||||
|
whiptail --title "Docker VM Info" \
|
||||||
|
--msgbox "$(translate "Default Login Credentials:\n\nUsername: root\nPassword: docker")" 12 50
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
msg_success "$(translate "Press Enter to return to menu...")"
|
||||||
|
read -r
|
||||||
|
|
||||||
|
whiptail --title "Proxmox VE Helper-Scripts" \
|
||||||
|
--msgbox "$(translate "Visit the website to discover more scripts, stay updated with the latest updates, and support the project:\n\nhttps://community-scripts.github.io/ProxmoxVE")" 15 70
|
||||||
|
|
||||||
|
exec bash <(curl -s "$REPO_URL/scripts/vm/create_vm.sh")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
94
scripts/vm/select_nas_iso.sh
Normal file
94
scripts/vm/select_nas_iso.sh
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==============================================================
|
||||||
|
# ProxMenux - NAS ISO Selector (Dialog Edition)
|
||||||
|
# ==============================================================
|
||||||
|
|
||||||
|
# Configuración Base
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
|
||||||
|
|
||||||
|
[[ -f "$UTILS_FILE" ]] && source "$UTILS_FILE"
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
ISO_DIR="/var/lib/vz/template/iso"
|
||||||
|
mkdir -p "$ISO_DIR"
|
||||||
|
|
||||||
|
function select_nas_iso() {
|
||||||
|
|
||||||
|
local NAS_OPTIONS=(
|
||||||
|
"1" "Synology DSM VM"
|
||||||
|
"2" "TrueNAS SCALE VM (Fangtooth)"
|
||||||
|
"3" "TrueNAS CORE VM (FreeBSD based)"
|
||||||
|
"4" "OpenMediaVault VM (Debian based)"
|
||||||
|
"5" "Rockstor VM (openSUSE based)"
|
||||||
|
"6" "ZimaOS VM (R0GGER proxmox-zimaos)"
|
||||||
|
"7" "$(translate "Return to Main Menu")"
|
||||||
|
)
|
||||||
|
|
||||||
|
local NAS_TYPE
|
||||||
|
NAS_TYPE=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(translate "NAS Systems")" \
|
||||||
|
--menu "$(translate "Select the NAS system to install:")" 18 64 10 \
|
||||||
|
"${NAS_OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
# Si se pulsa ESC o Cancelar
|
||||||
|
[[ $? -ne 0 ]] && return 1
|
||||||
|
|
||||||
|
case "$NAS_TYPE" in
|
||||||
|
1)
|
||||||
|
bash <(curl -s "$REPO_URL/scripts/vm/synology.sh")
|
||||||
|
msg_success "$(translate "Press Enter to return to menu...")"
|
||||||
|
read -r
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
ISO_NAME="TrueNAS SCALE 25 (Fangtooth)"
|
||||||
|
ISO_URL="https://download.truenas.com/TrueNAS-SCALE-Fangtooth/25.04.0/TrueNAS-SCALE-25.04.0.iso"
|
||||||
|
ISO_FILE="TrueNAS-SCALE-25.04.0.iso"
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
HN="TrueNAS-Scale"
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
ISO_NAME="TrueNAS CORE 13.3"
|
||||||
|
ISO_URL="https://download.freenas.org/13.3/STABLE/latest/x64/TrueNAS-13.3-U1.2.iso"
|
||||||
|
ISO_FILE="TrueNAS-13.3-U1.2.iso"
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
HN="TrueNAS-Core"
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
ISO_NAME="OpenMediaVault 7.4.17"
|
||||||
|
ISO_URL="https://sourceforge.net/projects/openmediavault/files/iso/7.4.17/openmediavault_7.4.17-amd64.iso/download"
|
||||||
|
ISO_FILE="openmediavault_7.4.17-amd64.iso"
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
HN="OpenMediaVault"
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
ISO_NAME="Rockstor"
|
||||||
|
ISO_URL="https://rockstor.com/downloads/installer/leap/15.6/x86_64/Rockstor-Leap15.6-generic.x86_64-5.0.15-0.install.iso"
|
||||||
|
ISO_FILE="Rockstor-Leap15.6-generic.x86_64-5.0.15-0.install.iso"
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
HN="Rockstor"
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
bash -c "$(wget -qLO - https://raw.githubusercontent.com/R0GGER/proxmox-zimaos/refs/heads/main/zimaos_zimacube.sh)"
|
||||||
|
msg_success "$(translate "Press Enter to return to menu...")"
|
||||||
|
read -r
|
||||||
|
|
||||||
|
whiptail --title "Proxmox VE - ZimaOS" \
|
||||||
|
--msgbox "$(translate "ZimaOS installer script by R0GGER\n\nVisit the GitHub repo to learn more, contribute, or support the project:\n\nhttps://github.com/R0GGER/proxmox-zimaos")" 15 70
|
||||||
|
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
7)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
export ISO_NAME ISO_URL ISO_FILE ISO_PATH HN
|
||||||
|
return 0
|
||||||
|
}
|
88
scripts/vm/select_windows_iso.sh
Normal file
88
scripts/vm/select_windows_iso.sh
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==============================================================
|
||||||
|
# ProxMenux - Windows ISO Selector (Dialog Edition)
|
||||||
|
# ==============================================================
|
||||||
|
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
ISO_DIR="/var/lib/vz/template/iso"
|
||||||
|
|
||||||
|
[[ -f "$UTILS_FILE" ]] && source "$UTILS_FILE"
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
mkdir -p "$ISO_DIR"
|
||||||
|
|
||||||
|
function select_windows_iso() {
|
||||||
|
local CHOICE
|
||||||
|
CHOICE=$(dialog --backtitle "ProxMenux" --title "$(translate "Windows ISO")" \
|
||||||
|
--menu "$(translate "Select how to provide the Windows ISO:")" 15 60 5 \
|
||||||
|
1 "$(translate "Use existing ISO from storage")" \
|
||||||
|
2 "$(translate "Download ISO using UUP Dump")" \
|
||||||
|
3 "$(translate "Return to Main Menu")" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ $? -ne 0 ]] && return 1 # ESC o cancelar
|
||||||
|
|
||||||
|
case "$CHOICE" in
|
||||||
|
1)
|
||||||
|
select_existing_iso || return 1
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
if source <(curl -fsSL "$UUP_REPO/uupdump_creator.sh"); then
|
||||||
|
run_uupdump_creator || return 1
|
||||||
|
detect_latest_iso_created || return 1
|
||||||
|
else
|
||||||
|
msg_error "$(translate "UUP Dump script not found.")"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function select_existing_iso() {
|
||||||
|
ISO_LIST=()
|
||||||
|
while read -r line; do
|
||||||
|
FILENAME=$(basename "$line")
|
||||||
|
SIZE=$(du -h "$line" | cut -f1)
|
||||||
|
ISO_LIST+=("$FILENAME" "$SIZE")
|
||||||
|
done < <(find "$ISO_DIR" -type f -iname "*.iso" ! -iname "virtio*" | sort)
|
||||||
|
|
||||||
|
if [[ ${#ISO_LIST[@]} -eq 0 ]]; then
|
||||||
|
msg_error "$(translate "No ISO images found in $ISO_DIR.")"
|
||||||
|
sleep 2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ISO_FILE=$(dialog --backtitle "ProxMenux" --title "$(translate "Available ISO Images")" \
|
||||||
|
--menu "$(translate "Choose a Windows ISO to use:")" 20 70 10 \
|
||||||
|
"${ISO_LIST[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ -z "$ISO_FILE" ]] && msg_warn "$(translate "No ISO selected.")" && return 1
|
||||||
|
|
||||||
|
ISO_PATH="$ISO_DIR/$ISO_FILE"
|
||||||
|
ISO_NAME="$ISO_FILE"
|
||||||
|
|
||||||
|
export ISO_PATH ISO_FILE ISO_NAME
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function detect_latest_iso_created() {
|
||||||
|
ISO_FILE=$(find "$ISO_DIR" -maxdepth 1 -type f -iname "*.iso" ! -iname "virtio*" -printf "%T@ %p\n" | sort -n | awk '{print $2}' | tail -n 1)
|
||||||
|
|
||||||
|
if [[ -z "$ISO_FILE" ]]; then
|
||||||
|
msg_error "$(translate "No ISO file detected after UUP Dump process.")"
|
||||||
|
sleep 2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ISO_NAME=$(basename "$ISO_FILE")
|
||||||
|
ISO_PATH="$ISO_FILE"
|
||||||
|
|
||||||
|
export ISO_PATH ISO_FILE ISO_NAME
|
||||||
|
return 0
|
||||||
|
}
|
162
scripts/vm/uupdump_creator.sh
Normal file
162
scripts/vm/uupdump_creator.sh
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==============================================================
|
||||||
|
# ProxMenux - Windows ISO Creator from UUP Dump
|
||||||
|
# ==============================================================
|
||||||
|
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
|
||||||
|
if [[ -f "$UTILS_FILE" ]]; then
|
||||||
|
source "$UTILS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
function run_uupdump_creator() {
|
||||||
|
|
||||||
|
clear
|
||||||
|
show_proxmenux_logo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DEPS=(curl aria2 cabextract wimtools genisoimage gettext)
|
||||||
|
NEEDED=()
|
||||||
|
|
||||||
|
for pkg in "${DEPS[@]}"; do
|
||||||
|
if ! command -v "$pkg" &>/dev/null; then
|
||||||
|
NEEDED+=("$pkg")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${#NEEDED[@]} -gt 0 ]]; then
|
||||||
|
msg_info "Installing dependencies for create image ISO from UUP Dump..."
|
||||||
|
apt-get update -qq >/dev/null
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y "${NEEDED[@]}" >/dev/null 2>&1
|
||||||
|
msg_ok "Dependencies successfully installed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TMP_DIR="/root/uup-temp"
|
||||||
|
OUT_DIR="/var/lib/vz/template/iso"
|
||||||
|
CONVERTER="/root/uup-converter"
|
||||||
|
|
||||||
|
mkdir -p "$TMP_DIR" "$OUT_DIR"
|
||||||
|
cd "$TMP_DIR" || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
UUP_URL=$(whiptail --inputbox "$(translate "Paste the UUP Dump URL here")" 10 90 3>&1 1>&2 2>&3)
|
||||||
|
[[ $? -ne 0 ]] && msg_error "$(translate "Cancelled by user.")" && exit 1
|
||||||
|
|
||||||
|
|
||||||
|
if [[ ! "$UUP_URL" =~ id=.+\&pack=.+\&edition=.+ ]]; then
|
||||||
|
msg_error "$(translate "The URL does not contain the required parameters (id, pack, edition).")"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_ID=$(echo "$UUP_URL" | grep -oP 'id=\K[^&]+')
|
||||||
|
LANG=$(echo "$UUP_URL" | grep -oP 'pack=\K[^&]+')
|
||||||
|
EDITION=$(echo "$UUP_URL" | grep -oP 'edition=\K[^&]+')
|
||||||
|
ARCH="amd64"
|
||||||
|
|
||||||
|
echo -e "\n${BGN}=============== UUP Dump Creator ===============${CL}"
|
||||||
|
echo -e " ${BGN}🆔 ID:${CL} ${DGN}$BUILD_ID${CL}"
|
||||||
|
echo -e " ${BGN}🌐 Language:${CL} ${DGN}$LANG${CL}"
|
||||||
|
echo -e " ${BGN}💿 Edition:${CL} ${DGN}$EDITION${CL}"
|
||||||
|
echo -e " ${BGN}🖥️ Architecture:${CL} ${DGN}$ARCH${CL}"
|
||||||
|
echo -e "${BGN}===============================================${CL}\n"
|
||||||
|
|
||||||
|
|
||||||
|
if [[ ! -f "$CONVERTER/convert.sh" ]]; then
|
||||||
|
echo "📦 $(translate "Downloading UUP converter...")"
|
||||||
|
mkdir -p "$CONVERTER"
|
||||||
|
cd "$CONVERTER" || exit 1
|
||||||
|
wget -q https://git.uupdump.net/uup-dump/converter/archive/refs/heads/master.tar.gz -O converter.tar.gz
|
||||||
|
tar -xzf converter.tar.gz --strip-components=1
|
||||||
|
chmod +x convert.sh
|
||||||
|
cd "$TMP_DIR" || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Crear script de descarga uup_download_linux.sh
|
||||||
|
cat > uup_download_linux.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
mkdir -p files
|
||||||
|
echo "https://git.uupdump.net/uup-dump/converter/archive/refs/heads/master.tar.gz" > files/converter_multi
|
||||||
|
|
||||||
|
for prog in aria2c cabextract wimlib-imagex chntpw; do
|
||||||
|
which \$prog &>/dev/null || { echo "\$prog not found."; exit 1; }
|
||||||
|
done
|
||||||
|
which genisoimage &>/dev/null || which mkisofs &>/dev/null || { echo "genisoimage/mkisofs not found."; exit 1; }
|
||||||
|
|
||||||
|
destDir="UUPs"
|
||||||
|
tempScript="aria2_script.\$RANDOM.txt"
|
||||||
|
|
||||||
|
aria2c --no-conf --console-log-level=warn --log-level=info --log="aria2_download.log" \
|
||||||
|
-x16 -s16 -j2 --allow-overwrite=true --auto-file-renaming=false -d"files" -i"files/converter_multi" || exit 1
|
||||||
|
|
||||||
|
aria2c --no-conf --console-log-level=warn --log-level=info --log="aria2_download.log" \
|
||||||
|
-o"\$tempScript" --allow-overwrite=true --auto-file-renaming=false \
|
||||||
|
"https://uupdump.net/get.php?id=$BUILD_ID&pack=$LANG&edition=$EDITION&aria2=2" || exit 1
|
||||||
|
|
||||||
|
grep '#UUPDUMP_ERROR:' "\$tempScript" && { echo "❌ Error generating UUP download list."; exit 1; }
|
||||||
|
|
||||||
|
aria2c --no-conf --console-log-level=warn --log-level=info --log="aria2_download.log" \
|
||||||
|
-x16 -s16 -j5 -c -R -d"\$destDir" -i"\$tempScript" || exit 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x uup_download_linux.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
./uup_download_linux.sh
|
||||||
|
# ==========================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UUP_FOLDER=$(find "$TMP_DIR" -type d -name "UUPs" | head -n1)
|
||||||
|
[[ -z "$UUP_FOLDER" ]] && msg_error "$(translate "No UUP folder found.")" && exit 1
|
||||||
|
|
||||||
|
|
||||||
|
echo -e "\n${GN}=======================================${CL}"
|
||||||
|
echo -e " 💿 ${GN}Starting ISO conversion...${CL}"
|
||||||
|
echo -e "${GN}=======================================${CL}\n"
|
||||||
|
|
||||||
|
"$CONVERTER/convert.sh" wim "$UUP_FOLDER" 1
|
||||||
|
|
||||||
|
|
||||||
|
ISO_FILE=$(find "$TMP_DIR" "$CONVERTER" "$UUP_FOLDER" -maxdepth 1 -iname "*.iso" | head -n1)
|
||||||
|
if [[ -f "$ISO_FILE" ]]; then
|
||||||
|
mv "$ISO_FILE" "$OUT_DIR/"
|
||||||
|
msg_ok "$(translate "ISO created successfully:") $OUT_DIR/$(basename "$ISO_FILE")"
|
||||||
|
|
||||||
|
|
||||||
|
msg_ok "$(translate "Cleaning temporary files...")"
|
||||||
|
rm -rf "$TMP_DIR" "$CONVERTER"
|
||||||
|
|
||||||
|
export LANGUAGE=C
|
||||||
|
export LANG=C
|
||||||
|
export LC_ALL=C
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
msg_success "$(translate "Press Enter to return to menu...")"
|
||||||
|
read -r
|
||||||
|
else
|
||||||
|
msg_warn "$(translate "No ISO was generated.")"
|
||||||
|
|
||||||
|
export LANGUAGE=C
|
||||||
|
export LANG=C
|
||||||
|
export LC_ALL=C
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
msg_success "$(translate "Press Enter to return to menu...")"
|
||||||
|
read -r
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
229
scripts/vm/vm_configurator.sh
Normal file
229
scripts/vm/vm_configurator.sh
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# VM Configuration Module - ProxMenux
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
|
||||||
|
if [[ -f "$UTILS_FILE" ]]; then
|
||||||
|
source "$UTILS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
|
||||||
|
function confirm_vm_creation() {
|
||||||
|
clear
|
||||||
|
local CONFIRM_TITLE="${HN:-$(translate "New Virtual Machine")}"
|
||||||
|
local CONFIRM_MSG="$(translate "This will create a new VM") $CONFIRM_TITLE. $(translate "Proceed?")"
|
||||||
|
|
||||||
|
if ! whiptail --backtitle "ProxMenux" --title "$CONFIRM_TITLE" --yesno "$CONFIRM_MSG" 10 60; then
|
||||||
|
header_info
|
||||||
|
msg_warn "$(translate "VM creation cancelled by user.")"
|
||||||
|
sleep 1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function generate_mac() {
|
||||||
|
local GEN_MAC="02"
|
||||||
|
for i in {1..5}; do
|
||||||
|
BYTE=$(printf "%02X" $((RANDOM % 256)))
|
||||||
|
GEN_MAC="${GEN_MAC}:${BYTE}"
|
||||||
|
done
|
||||||
|
echo "$GEN_MAC"
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_default_vm_config() {
|
||||||
|
local os_type="$1"
|
||||||
|
|
||||||
|
VMID=$(pvesh get /cluster/nextid 2>/dev/null || echo "100")
|
||||||
|
MAC=$(generate_mac)
|
||||||
|
|
||||||
|
case "$os_type" in
|
||||||
|
"1")
|
||||||
|
|
||||||
|
CORE_COUNT="2"
|
||||||
|
RAM_SIZE="8192"
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
BIOS_TYPE=" -bios ovmf"
|
||||||
|
START_VM="no"
|
||||||
|
;;
|
||||||
|
"2")
|
||||||
|
|
||||||
|
CORE_COUNT="4"
|
||||||
|
RAM_SIZE="8192"
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
BIOS_TYPE=" -bios ovmf"
|
||||||
|
START_VM="no"
|
||||||
|
;;
|
||||||
|
"3")
|
||||||
|
|
||||||
|
CORE_COUNT="2"
|
||||||
|
RAM_SIZE="4096"
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
BIOS_TYPE=" -bios ovmf"
|
||||||
|
START_VM="no"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
[[ -z "$CORE_COUNT" ]] && CORE_COUNT="2"
|
||||||
|
[[ -z "$RAM_SIZE" ]] && RAM_SIZE="4096"
|
||||||
|
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
BRG="vmbr0"
|
||||||
|
VLAN=""
|
||||||
|
MTU=""
|
||||||
|
SERIAL_PORT="socket"
|
||||||
|
FORMAT=""
|
||||||
|
DISK_CACHE=""
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function apply_default_vm_config() {
|
||||||
|
echo -e "${DEF}$(translate "Applying default VM configuration")${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Virtual Machine ID")${CL}: ${BGN}$VMID${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Hostname")${CL}: ${BGN}$HN${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "CPU Cores")${CL}: ${BGN}$CORE_COUNT${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "RAM Size")${CL}: ${BGN}$RAM_SIZE MiB${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Machine Type")${CL}: ${BGN}${MACHINE/ -machine /}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "BIOS Type")${CL}: ${BGN}${BIOS_TYPE/ -bios /}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "CPU Model")${CL}: ${BGN}${CPU_TYPE/ -cpu /}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Network Bridge")${CL}: ${BGN}$BRG${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "MAC Address")${CL}: ${BGN}$MAC${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Start VM after creation")${CL}: ${BGN}$START_VM${CL}"
|
||||||
|
echo -e
|
||||||
|
echo -e "${DEF}$(translate "Creating VM with the above configuration")${CL}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function configure_vm_advanced() {
|
||||||
|
header_info
|
||||||
|
|
||||||
|
# Obtener el siguiente ID libre
|
||||||
|
NEXTID=$(pvesh get /cluster/nextid 2>/dev/null || echo "100")
|
||||||
|
[[ -z "$MAC" ]] && MAC=$(generate_mac)
|
||||||
|
|
||||||
|
# VMID
|
||||||
|
while true; do
|
||||||
|
VMID=$(whiptail --backtitle "ProxMenux" \
|
||||||
|
--inputbox "$(translate "Set Virtual Machine ID")" 8 60 "$NEXTID" \
|
||||||
|
--title "VM ID" --cancel-button Exit 3>&1 1>&2 2>&3) || return 1
|
||||||
|
|
||||||
|
if [[ -z "$VMID" ]]; then
|
||||||
|
VMID="$NEXTID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if qm status "$VMID" &>/dev/null || pct status "$VMID" &>/dev/null; then
|
||||||
|
msg_error "$(translate "ID already in use. Please choose another.")"
|
||||||
|
sleep 1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Hostname
|
||||||
|
HN=$(whiptail --backtitle "ProxMenux" \
|
||||||
|
--inputbox "$(translate "Set Hostname")" 8 60 "$HN" \
|
||||||
|
--title "Hostname" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
[[ -z "$HN" ]] && HN="vm-proxmenux"
|
||||||
|
|
||||||
|
# Machine Type
|
||||||
|
MACHINE_TYPE=$(whiptail --backtitle "ProxMenux" --title "$(translate "Machine Type")" \
|
||||||
|
--radiolist "$(translate "Select machine type")" 10 60 2 \
|
||||||
|
"q35" "QEMU q35" ON \
|
||||||
|
"i440fx" "Legacy i440fx" OFF 3>&1 1>&2 2>&3) || return 1
|
||||||
|
[[ "$MACHINE_TYPE" == "q35" ]] && MACHINE=" -machine q35" && FORMAT="" || MACHINE="" && FORMAT=",efitype=4m"
|
||||||
|
|
||||||
|
# BIOS
|
||||||
|
BIOS=$(whiptail --backtitle "ProxMenux" --title "$(translate "BIOS Type")" \
|
||||||
|
--radiolist "$(translate "Choose BIOS type")" 10 60 2 \
|
||||||
|
"ovmf" "UEFI (OVMF)" ON \
|
||||||
|
"seabios" "Legacy BIOS (SeaBIOS)" OFF 3>&1 1>&2 2>&3) || return 1
|
||||||
|
BIOS_TYPE=" -bios $BIOS"
|
||||||
|
|
||||||
|
# CPU Type
|
||||||
|
CPU_CHOICE=$(whiptail --backtitle "ProxMenux" --title "$(translate "CPU Model")" \
|
||||||
|
--radiolist "$(translate "Select CPU model")" 10 60 2 \
|
||||||
|
"host" "Host (recommended)" ON \
|
||||||
|
"kvm64" "Generic KVM64" OFF 3>&1 1>&2 2>&3) || return 1
|
||||||
|
[[ "$CPU_CHOICE" == "host" ]] && CPU_TYPE=" -cpu host" || CPU_TYPE=" -cpu kvm64"
|
||||||
|
|
||||||
|
# Core Count
|
||||||
|
CORE_COUNT=$(whiptail --backtitle "ProxMenux" --inputbox "$(translate "Number of CPU cores (default: 2)")" \
|
||||||
|
8 60 "${CORE_COUNT:-2}" --title "CPU Cores" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
[[ -z "$CORE_COUNT" ]] && CORE_COUNT="2"
|
||||||
|
|
||||||
|
# RAM
|
||||||
|
RAM_SIZE=$(whiptail --backtitle "ProxMenux" --inputbox "$(translate "Amount of RAM in MiB (default: 4096)")" \
|
||||||
|
8 60 "${RAM_SIZE:-4096}" --title "RAM" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
[[ -z "$RAM_SIZE" ]] && RAM_SIZE="4096"
|
||||||
|
|
||||||
|
# Bridge
|
||||||
|
BRG=$(whiptail --backtitle "ProxMenux" --inputbox "$(translate "Set network bridge (default: vmbr0)")" \
|
||||||
|
8 60 "${BRG:-vmbr0}" --title "Bridge" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
|
||||||
|
# MAC
|
||||||
|
MAC_INPUT=$(whiptail --backtitle "ProxMenux" --inputbox "$(translate "Set MAC Address (leave empty for automatic)")" \
|
||||||
|
8 60 "$MAC" --title "MAC Address" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
[[ -z "$MAC_INPUT" ]] && MAC=$(generate_mac) || MAC="$MAC_INPUT"
|
||||||
|
|
||||||
|
# VLAN
|
||||||
|
VLAN_INPUT=$(whiptail --backtitle "ProxMenux" --inputbox "$(translate "Set VLAN (leave empty for none)")" \
|
||||||
|
8 60 "" --title "VLAN" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
VLAN=""
|
||||||
|
[[ -n "$VLAN_INPUT" ]] && VLAN=",tag=$VLAN_INPUT"
|
||||||
|
|
||||||
|
# MTU
|
||||||
|
MTU_INPUT=$(whiptail --backtitle "ProxMenux" --inputbox "$(translate "Set MTU (leave empty for default)")" \
|
||||||
|
8 60 "" --title "MTU" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
MTU=""
|
||||||
|
[[ -n "$MTU_INPUT" ]] && MTU=",mtu=$MTU_INPUT"
|
||||||
|
|
||||||
|
# Serial Port
|
||||||
|
if (whiptail --backtitle "ProxMenux" --title "Serial Port" \
|
||||||
|
--yesno "$(translate "Do you want to enable the serial port") (socket)?" 10 60); then
|
||||||
|
SERIAL_PORT="socket"
|
||||||
|
else
|
||||||
|
SERIAL_PORT=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start VM
|
||||||
|
if (whiptail --backtitle "ProxMenux" --title "$(translate "Start VM")" \
|
||||||
|
--yesno "$(translate "Start VM after creation?")" 10 60); then
|
||||||
|
START_VM="yes"
|
||||||
|
else
|
||||||
|
START_VM="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${CUS}$(translate "Using advanced configuration")${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Virtual Machine ID")${CL}: ${BGN}$VMID${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Hostname")${CL}: ${BGN}$HN${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "CPU Cores")${CL}: ${BGN}$CORE_COUNT${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "RAM Size")${CL}: ${BGN}$RAM_SIZE MiB${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Machine Type")${CL}: ${BGN}${MACHINE/ -machine /}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "BIOS Type")${CL}: ${BGN}${BIOS_TYPE/ -bios /}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "CPU Model")${CL}: ${BGN}${CPU_TYPE/ -cpu /}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Network Bridge")${CL}: ${BGN}$BRG${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "MAC Address")${CL}: ${BGN}$MAC${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "VLAN")${CL}: ${BGN}${VLAN:-None}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Interface MTU")${CL}: ${BGN}${MTU:-Default}${CL}"
|
||||||
|
echo -e " ${TAB}${DGN}$(translate "Start VM")${CL}: ${BGN}$START_VM${CL}"
|
||||||
|
echo -e
|
||||||
|
echo -e "${CUS}$(translate "Creating VM with the above configuration")${CL}"
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
327
scripts/vm/vm_creator.sh
Normal file
327
scripts/vm/vm_creator.sh
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# VM Creator Module - ProxMenux
|
||||||
|
# ==========================================================
|
||||||
|
# Este módulo recibe las variables globales y crea la VM
|
||||||
|
# con su configuración, discos y descripción.
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
BASE_DIR="/usr/local/share/proxmenux"
|
||||||
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
||||||
|
VENV_PATH="/opt/googletrans-env"
|
||||||
|
|
||||||
|
if [[ -f "$UTILS_FILE" ]]; then
|
||||||
|
source "$UTILS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_language
|
||||||
|
initialize_cache
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Función para montar ISOs
|
||||||
|
# ==========================================================
|
||||||
|
function mount_iso_to_vm() {
|
||||||
|
local vmid="$1"
|
||||||
|
local iso_path="$2"
|
||||||
|
local device="$3"
|
||||||
|
|
||||||
|
if [[ -f "$iso_path" ]]; then
|
||||||
|
local iso_basename
|
||||||
|
iso_basename=$(basename "$iso_path")
|
||||||
|
qm set "$vmid" -$device "local:iso/$iso_basename,media=cdrom" >/dev/null 2>&1
|
||||||
|
msg_ok "$(translate "Mounted ISO on device") $device → $iso_basename"
|
||||||
|
else
|
||||||
|
msg_warn "$(translate "ISO not found to mount on device") $device"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Select Interface Type
|
||||||
|
# ==========================================================
|
||||||
|
function select_interface_type() {
|
||||||
|
INTERFACE_TYPE=$(whiptail --backtitle "ProxMenux" --title "$(translate "Select Disk Interface")" --radiolist \
|
||||||
|
"$(translate "Select the bus type for the disks:")" 15 70 4 \
|
||||||
|
"scsi" "$(translate "SCSI (recommended for Linux and Windows)")" ON \
|
||||||
|
"sata" "$(translate "SATA (standard - high compatibility)")" OFF \
|
||||||
|
"virtio" "$(translate "VirtIO (advanced - high performance)")" OFF \
|
||||||
|
"ide" "IDE (legacy)" OFF \
|
||||||
|
3>&1 1>&2 2>&3) || exit 1
|
||||||
|
|
||||||
|
case "$INTERFACE_TYPE" in
|
||||||
|
"scsi"|"sata")
|
||||||
|
DISCARD_OPTS=",discard=on,ssd=on"
|
||||||
|
;;
|
||||||
|
"virtio")
|
||||||
|
DISCARD_OPTS=",discard=on"
|
||||||
|
;;
|
||||||
|
"ide")
|
||||||
|
DISCARD_OPTS=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
msg_ok "$(translate "Disk interface selected:") $INTERFACE_TYPE"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Función select_efi_storage (no cambia)
|
||||||
|
# ==========================================================
|
||||||
|
function select_efi_storage() {
|
||||||
|
local vmid=$1
|
||||||
|
local STORAGE=""
|
||||||
|
|
||||||
|
STORAGE_MENU=()
|
||||||
|
while read -r line; do
|
||||||
|
TAG=$(echo "$line" | awk '{print $1}')
|
||||||
|
TYPE=$(echo "$line" | awk '{printf "%-10s", $2}')
|
||||||
|
FREE=$(echo "$line" | numfmt --field 4-6 --from-unit=K --to=iec --format "%.2f" | awk '{printf("%9sB", $6)}')
|
||||||
|
STORAGE_MENU+=("$TAG" "Type: $TYPE Free: $FREE" "OFF")
|
||||||
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
|
|
||||||
|
if [ ${#STORAGE_MENU[@]} -eq 0 ]; then
|
||||||
|
msg_error "$(translate "Unable to detect a valid storage location for EFI disk.")"
|
||||||
|
exit 1
|
||||||
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
|
else
|
||||||
|
STORAGE=$(whiptail --backtitle "ProxMenux" --title "$(translate "EFI Disk Storage")" --radiolist \
|
||||||
|
"$(translate "Choose the storage volume for the EFI disk (4MB):")" 16 70 6 \
|
||||||
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$STORAGE"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Función principal para crear la VM
|
||||||
|
# ==========================================================
|
||||||
|
function create_vm() {
|
||||||
|
local BOOT_ORDER=""
|
||||||
|
local DISK_INFO=""
|
||||||
|
local DISK_INDEX=0
|
||||||
|
local ISO_DIR="/var/lib/vz/template/iso"
|
||||||
|
|
||||||
|
|
||||||
|
# Descargar ISO si es necesario
|
||||||
|
if [[ -n "$ISO_PATH" && -n "$ISO_URL" && ! -f "$ISO_PATH" ]]; then
|
||||||
|
# Detectar si es una URL de SourceForge
|
||||||
|
if [[ "$ISO_URL" == *"sourceforge.net"* ]]; then
|
||||||
|
# SourceForge necesita --content-disposition para descargar correctamente
|
||||||
|
wget --content-disposition --show-progress -O "$ISO_PATH" "$ISO_URL"
|
||||||
|
else
|
||||||
|
# Normal para el resto
|
||||||
|
wget --no-verbose --show-progress -O "$ISO_PATH" "$ISO_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verificar si se descargó bien
|
||||||
|
if [[ -f "$ISO_PATH" ]]; then
|
||||||
|
msg_ok "$(translate "ISO image downloaded")"
|
||||||
|
else
|
||||||
|
msg_error "$(translate "Failed to download ISO image")"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Crear la VM base primero (mínima)
|
||||||
|
qm create "$VMID" -agent 1${MACHINE} -tablet 0 -localtime 1${BIOS_TYPE}${CPU_TYPE} \
|
||||||
|
-cores "$CORE_COUNT" -memory "$RAM_SIZE" -name "$HN" -tags proxmenux \
|
||||||
|
-net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -ostype l26 \
|
||||||
|
-scsihw virtio-scsi-pci \
|
||||||
|
$( [[ -n "$SERIAL_PORT" ]] && echo "-serial0 $SERIAL_PORT" )
|
||||||
|
|
||||||
|
msg_ok "$(translate "Base VM created with ID") $VMID"
|
||||||
|
|
||||||
|
|
||||||
|
# Crear disco EFI si corresponde
|
||||||
|
if [[ "$BIOS_TYPE" == *"ovmf"* ]]; then
|
||||||
|
msg_info "$(translate "Configuring EFI disk")"
|
||||||
|
EFI_STORAGE=$(select_efi_storage "$VMID")
|
||||||
|
EFI_DISK_NAME="vm-${VMID}-disk-efivars"
|
||||||
|
|
||||||
|
STORAGE_TYPE=$(pvesm status -storage "$EFI_STORAGE" | awk 'NR>1 {print $2}')
|
||||||
|
case "$STORAGE_TYPE" in
|
||||||
|
nfs | dir)
|
||||||
|
EFI_DISK_EXT=".raw"
|
||||||
|
EFI_DISK_REF="$VMID/"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
EFI_DISK_EXT=""
|
||||||
|
EFI_DISK_REF=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if pvesm alloc "$EFI_STORAGE" "$VMID" "$EFI_DISK_NAME$EFI_DISK_EXT" 4M >/dev/null 2>&1; then
|
||||||
|
if qm set "$VMID" -efidisk0 "$EFI_STORAGE:${EFI_DISK_REF}$EFI_DISK_NAME$EFI_DISK_EXT,pre-enrolled-keys=0" >/dev/null 2>&1; then
|
||||||
|
msg_ok "$(translate "EFI disk created and configured on") $EFI_STORAGE"
|
||||||
|
else
|
||||||
|
msg_error "$(translate "Failed to configure EFI disk")"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_error "$(translate "Failed to create EFI disk")"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Crear discos virtuales o físicos con interfaz seleccionada
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
# Primero seleccionar la interfaz
|
||||||
|
select_interface_type
|
||||||
|
|
||||||
|
if [[ "$DISK_TYPE" == "virtual" && ${#VIRTUAL_DISKS[@]} -gt 0 ]]; then
|
||||||
|
for i in "${!VIRTUAL_DISKS[@]}"; do
|
||||||
|
DISK_INDEX=$((i+1))
|
||||||
|
IFS=':' read -r STORAGE SIZE <<< "${VIRTUAL_DISKS[$i]}"
|
||||||
|
DISK_NAME="vm-${VMID}-disk-${DISK_INDEX}"
|
||||||
|
SLOT_NAME="${INTERFACE_TYPE}${i}"
|
||||||
|
|
||||||
|
STORAGE_TYPE=$(pvesm status -storage "$STORAGE" | awk 'NR>1 {print $2}')
|
||||||
|
case "$STORAGE_TYPE" in
|
||||||
|
dir|nfs)
|
||||||
|
DISK_EXT=".raw"
|
||||||
|
DISK_REF="$VMID/"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
DISK_EXT=""
|
||||||
|
DISK_REF=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if pvesm alloc "$STORAGE" "$VMID" "$DISK_NAME$DISK_EXT" "$SIZE"G >/dev/null 2>&1; then
|
||||||
|
qm set "$VMID" -$SLOT_NAME "$STORAGE:${DISK_REF}${DISK_NAME}${DISK_EXT}${DISCARD_OPTS}" >/dev/null
|
||||||
|
msg_ok "$(translate "Virtual disk") $DISK_INDEX ${SIZE}GB - $STORAGE ($SLOT_NAME)"
|
||||||
|
DISK_INFO+="<p>Virtual Disk $DISK_INDEX: ${SIZE}GB ($STORAGE / $SLOT_NAME)</p>"
|
||||||
|
[[ -z "$BOOT_ORDER" ]] && BOOT_ORDER="$SLOT_NAME"
|
||||||
|
else
|
||||||
|
msg_error "$(translate "Failed to create disk") $DISK_INDEX"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$DISK_TYPE" == "passthrough" && ${#PASSTHROUGH_DISKS[@]} -gt 0 ]]; then
|
||||||
|
for i in "${!PASSTHROUGH_DISKS[@]}"; do
|
||||||
|
SLOT_NAME="${INTERFACE_TYPE}${i}"
|
||||||
|
DISK="${PASSTHROUGH_DISKS[$i]}"
|
||||||
|
MODEL=$(lsblk -ndo MODEL "$DISK")
|
||||||
|
SIZE=$(lsblk -ndo SIZE "$DISK")
|
||||||
|
qm set "$VMID" -$SLOT_NAME "$DISK${DISCARD_OPTS}" >/dev/null 2>&1
|
||||||
|
msg_ok "$(translate "Passthrough disk assigned") ($DISK → $SLOT_NAME)"
|
||||||
|
DISK_INFO+="<p>Passthrough Disk $((i+1)): $DISK ($MODEL $SIZE)</p>"
|
||||||
|
[[ -z "$BOOT_ORDER" ]] && BOOT_ORDER="$SLOT_NAME"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Ahora montamos las ISOs
|
||||||
|
if [[ -f "$ISO_PATH" ]]; then
|
||||||
|
mount_iso_to_vm "$VMID" "$ISO_PATH" "ide2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Para Windows, preguntar y montar ISO VirtIO
|
||||||
|
if [[ "$OS_TYPE" == "windows" ]]; then
|
||||||
|
local VIRTIO_DIR="/var/lib/vz/template/iso"
|
||||||
|
local VIRTIO_SELECTED=""
|
||||||
|
local VIRTIO_DOWNLOAD_URL="https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
VIRTIO_OPTION=$(whiptail --title "ProxMenux - VirtIO Drivers" --menu "$(translate "Select how to provide VirtIO drivers")" 15 70 2 \
|
||||||
|
"1" "$(translate "Download latest VirtIO ISO automatically")" \
|
||||||
|
"2" "$(translate "Use existing VirtIO ISO from storage")" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
[[ $? -ne 0 ]] && msg_warn "$(translate "VirtIO ISO selection cancelled.")" && break
|
||||||
|
|
||||||
|
case "$VIRTIO_OPTION" in
|
||||||
|
1)
|
||||||
|
|
||||||
|
if [[ -f "$VIRTIO_DIR/virtio-win.iso" ]]; then
|
||||||
|
if whiptail --title "ProxMenux" --yesno "$(translate "A VirtIO ISO already exists. Do you want to overwrite it?")" 10 60; then
|
||||||
|
wget -q --show-progress -O "$VIRTIO_DIR/virtio-win.iso" "$VIRTIO_DOWNLOAD_URL"
|
||||||
|
if [[ -f "$VIRTIO_DIR/virtio-win.iso" ]]; then
|
||||||
|
msg_ok "$(translate "VirtIO driver ISO downloaded successfully.")"
|
||||||
|
else
|
||||||
|
msg_error "$(translate "Failed to download VirtIO driver ISO.")"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
wget -q --show-progress -O "$VIRTIO_DIR/virtio-win.iso" "$VIRTIO_DOWNLOAD_URL"
|
||||||
|
if [[ -f "$VIRTIO_DIR/virtio-win.iso" ]]; then
|
||||||
|
msg_ok "$(translate "VirtIO driver ISO downloaded successfully.")"
|
||||||
|
else
|
||||||
|
msg_error "$(translate "Failed to download VirtIO driver ISO.")"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
VIRTIO_SELECTED="$VIRTIO_DIR/virtio-win.iso"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
|
||||||
|
VIRTIO_LIST=()
|
||||||
|
while read -r line; do
|
||||||
|
FILENAME=$(basename "$line")
|
||||||
|
SIZE=$(du -h "$line" | cut -f1)
|
||||||
|
VIRTIO_LIST+=("$FILENAME" "$SIZE")
|
||||||
|
done < <(find "$VIRTIO_DIR" -type f -iname "virtio*.iso" | sort)
|
||||||
|
|
||||||
|
if [[ ${#VIRTIO_LIST[@]} -eq 0 ]]; then
|
||||||
|
msg_warn "$(translate "No VirtIO ISO found. Please download one.")"
|
||||||
|
continue # Volver a preguntar
|
||||||
|
fi
|
||||||
|
|
||||||
|
VIRTIO_FILE=$(whiptail --title "ProxMenux - VirtIO ISOs" --menu "$(translate "Select a VirtIO ISO to use:")" 20 70 10 "${VIRTIO_LIST[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
if [[ -n "$VIRTIO_FILE" ]]; then
|
||||||
|
VIRTIO_SELECTED="$VIRTIO_DIR/$VIRTIO_FILE"
|
||||||
|
else
|
||||||
|
msg_warn "$(translate "No VirtIO ISO selected. Please choose again.")"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ -n "$VIRTIO_SELECTED" && -f "$VIRTIO_SELECTED" ]]; then
|
||||||
|
mount_iso_to_vm "$VMID" "$VIRTIO_SELECTED" "ide3"
|
||||||
|
else
|
||||||
|
msg_warn "$(translate "VirtIO ISO not found after selection.")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
break
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Configurar el orden de arranque (primer disco, luego CD)
|
||||||
|
local BOOT_FINAL="$BOOT_ORDER"
|
||||||
|
[[ -f "$ISO_PATH" ]] && BOOT_FINAL="$BOOT_ORDER;ide2"
|
||||||
|
qm set "$VMID" -boot order="$BOOT_FINAL" >/dev/null
|
||||||
|
msg_ok "$(translate "Boot order set to") $BOOT_FINAL"
|
||||||
|
|
||||||
|
# Crear descripción
|
||||||
|
local DESC="<div align='center'><h1>$HN</h1><p>Created with ProxMenux</p>$DISK_INFO</div>"
|
||||||
|
qm set "$VMID" -description "$DESC" >/dev/null
|
||||||
|
msg_ok "$(translate "VM description configured")"
|
||||||
|
|
||||||
|
# Arrancar la VM si corresponde
|
||||||
|
if [[ "$START_VM" == "yes" ]]; then
|
||||||
|
qm start "$VMID"
|
||||||
|
msg_ok "$(translate "VM started")"
|
||||||
|
fi
|
||||||
|
configure_guest_agent
|
||||||
|
msg_success "$(translate "VM creation completed")"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user