2025-01-14 11:42:26 +01:00
#!/bin/bash
2025-01-28 20:47:18 +01:00
# ==========================================================
# ProxMenu - A menu-driven script for Proxmox VE management
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE)
# Version : 1.0
# Last Updated: 28/01/2025
# ==========================================================
# Configuration
UTILS_URL = "https://raw.githubusercontent.com/MacRimi/ProxMenux/main/scripts/utils.sh"
BASE_DIR = "/usr/local/share/proxmenux"
CACHE_FILE = " $BASE_DIR /cache.json "
VENV_PATH = "/opt/googletrans-env"
2025-01-29 17:35:54 +01:00
LANGUAGE = $( jq -r '.language // "en"' " $BASE_DIR /config.json " 2>/dev/null)
2025-01-28 20:47:18 +01:00
# Try to load utils.sh from GitHub
if ! source <( curl -sSf " $UTILS_URL " ) ; then
echo " $( translate 'Error: Could not load utils.sh from' ) $UTILS_URL "
exit 1
fi
2025-01-26 19:40:00 +01:00
# Path where disk images are stored
2025-01-14 11:42:26 +01:00
IMAGES_DIR = "/var/lib/vz/template/images/"
2025-01-26 19:58:48 +01:00
# Check if there are any images in the directory
2025-01-26 20:04:50 +01:00
IMAGES = $( ls -A " $IMAGES_DIR " | grep -E " \.(img|qcow2|vmdk) $" )
if [ -z " $IMAGES " ] ; then
2025-01-28 20:47:18 +01:00
msg_error " $( translate 'No images available for import in' ) $IMAGES_DIR "
echo -e " ${ YW } $( translate 'Supported formats: .img, .qcow2, .vmdk' ) ${ CL } "
echo -e " ${ YW } $( translate 'Please add some images and try again.' ) ${ CL } "
2025-01-26 19:58:48 +01:00
exit 0
fi
2025-01-29 23:09:38 +01:00
2025-01-26 19:40:00 +01:00
# Initial setup
2025-01-14 11:42:26 +01:00
if ! [ -d " $IMAGES_DIR " ] ; then
2025-01-28 20:47:18 +01:00
msg_info " $( translate 'Creating images directory' ) "
2025-01-14 11:42:26 +01:00
mkdir -p " $IMAGES_DIR "
2025-01-26 19:40:00 +01:00
msg_ok " $( translate 'Images directory created' ) "
2025-01-14 11:42:26 +01:00
fi
2025-01-26 19:40:00 +01:00
# Display initial message
2025-01-28 20:47:18 +01:00
whiptail --title " $( translate 'Import Disk Image' ) " --msgbox " $( translate 'Make sure the disk images you want to import are located in:' ) \n\n $IMAGES_DIR \n\n $( translate 'Supported formats: .img, .qcow2, .vmdk.' ) " 12 60
2025-01-14 11:42:26 +01:00
2025-01-26 19:40:00 +01:00
# 1. Select VM
2025-01-28 20:47:18 +01:00
msg_info " $( translate 'Getting VM list' ) "
VM_LIST = $( qm list | awk 'NR>1 {print $1" "$2}' )
2025-01-14 15:21:53 +01:00
if [ -z " $VM_LIST " ] ; then
2025-01-26 19:40:00 +01:00
msg_error " $( translate 'No VMs available in the system' ) "
2025-01-14 11:42:26 +01:00
exit 1
fi
2025-01-28 20:47:18 +01:00
msg_ok " $( translate 'VM list obtained' ) "
2025-01-14 11:42:26 +01:00
2025-01-26 19:40:00 +01:00
VMID = $( whiptail --title " $( translate 'Select VM' ) " --menu " $( translate 'Select the VM where you want to import the disk image:' ) " 15 60 8 $VM_LIST 3>& 1 1>& 2 2>& 3)
2025-01-14 11:42:26 +01:00
if [ -z " $VMID " ] ; then
2025-01-26 19:40:00 +01:00
msg_error " $( translate 'No VM selected' ) "
exit 1
fi
2025-01-28 20:47:18 +01:00
2025-01-26 20:23:52 +01:00
# 2. Select storage volume
2025-01-28 20:47:18 +01:00
msg_info " $( translate 'Getting storage volumes' ) "
2025-01-26 20:23:52 +01:00
STORAGE_LIST = $( pvesm status -content images | awk 'NR>1 {print $1}' )
if [ -z " $STORAGE_LIST " ] ; then
msg_error " $( translate 'No storage volumes available' ) "
exit 1
fi
2025-01-28 20:47:18 +01:00
msg_ok " $( translate 'Storage volumes obtained' ) "
2025-01-26 20:23:52 +01:00
2025-01-26 20:27:28 +01:00
# Create an array of storage options for whiptail
STORAGE_OPTIONS = ( )
2025-01-28 20:47:18 +01:00
while read -r storage; do
STORAGE_OPTIONS += ( " $storage " "" )
done <<< " $STORAGE_LIST "
2025-01-26 20:27:28 +01:00
STORAGE = $( whiptail --title " $( translate 'Select Storage' ) " --menu " $( translate 'Select the storage volume for disk import:' ) " 15 60 8 " ${ STORAGE_OPTIONS [@] } " 3>& 1 1>& 2 2>& 3)
2025-01-26 20:23:52 +01:00
if [ -z " $STORAGE " ] ; then
msg_error " $( translate 'No storage selected' ) "
exit 1
fi
2025-01-28 20:47:18 +01:00
2025-01-26 20:23:52 +01:00
# 3. Select disk images
2025-01-28 20:47:18 +01:00
msg_info " $( translate 'Scanning disk images' ) "
2025-01-26 20:04:50 +01:00
if [ -z " $IMAGES " ] ; then
msg_error " $( translate 'No compatible disk images found in' ) $IMAGES_DIR "
exit 0
fi
2025-01-26 19:40:00 +01:00
msg_ok " $( translate 'Disk images found' ) "
2025-01-28 20:47:18 +01:00
IMAGE_OPTIONS = ( )
while read -r img; do
IMAGE_OPTIONS += ( " $img " "" "OFF" )
done <<< " $IMAGES "
2025-01-14 11:42:26 +01:00
2025-01-28 20:47:18 +01:00
SELECTED_IMAGES = $( whiptail --title " $( translate 'Select Disk Images' ) " --checklist " $( translate 'Select the disk images to import:' ) " 20 60 10 " ${ IMAGE_OPTIONS [@] } " 3>& 1 1>& 2 2>& 3)
2025-01-14 15:21:53 +01:00
2025-01-26 19:40:00 +01:00
if [ -z " $SELECTED_IMAGES " ] ; then
msg_error " $( translate 'No images selected' ) "
2025-01-14 15:21:53 +01:00
exit 1
fi
2025-01-26 20:23:52 +01:00
# 4. Import each selected image
2025-01-26 19:40:00 +01:00
for IMAGE in $SELECTED_IMAGES ; do
2025-01-28 20:47:18 +01:00
2025-01-26 19:40:00 +01:00
# Remove quotes from selected image
IMAGE = $( echo " $IMAGE " | tr -d '"' )
2025-01-28 20:47:18 +01:00
# 5. Select interface type for each image
INTERFACE = $( whiptail --title " $( translate 'Interface Type' ) " --menu " $( translate 'Select the interface type for the image:' ) $IMAGE " 15 40 4 \
"sata" "SATA" \
"scsi" "SCSI" \
"virtio" "VirtIO" \
"ide" "IDE" 3>& 1 1>& 2 2>& 3)
2025-01-14 11:42:26 +01:00
2025-01-26 20:23:52 +01:00
if [ -z " $INTERFACE " ] ; then
msg_error " $( translate 'No interface type selected for' ) $IMAGE "
continue
fi
2025-01-14 15:21:53 +01:00
2025-01-26 20:23:52 +01:00
FULL_PATH = " $IMAGES_DIR / $IMAGE "
2025-01-14 15:21:53 +01:00
2025-01-28 20:47:18 +01:00
# Show initial message
msg_info " $( translate 'Importing image:' ) "
# Temporary file to capture the imported disk
TEMP_DISK_FILE = $( mktemp)
2025-01-26 20:27:28 +01:00
2025-01-28 20:47:18 +01:00
# Execute the command and process its output in real-time
qm importdisk " $VMID " " $FULL_PATH " " $STORAGE " 2>& 1 | while read -r line; do
if [ [ " $line " = ~ transferred ] ] ; then
# Extract the progress percentage
PERCENT = $( echo " $line " | grep -oP "\(\d+\.\d+%\)" | tr -d '()%' )
# Show progress with custom format without translation
echo -ne " \r ${ TAB } ${ YW } - $( translate 'Importing image:' ) $IMAGE - ${ CL } ${ PERCENT } % "
elif [ [ " $line " = ~ successfully\ imported\ disk ] ] ; then
# Extract the imported disk name and save it to the temporary file
echo " $line " | grep -oP "(?<=successfully imported disk ').*(?=')" > " $TEMP_DISK_FILE "
fi
done
echo -ne "\n"
IMPORT_STATUS = ${ PIPESTATUS [0] } # Capture the exit status of the main command
if [ $IMPORT_STATUS -eq 0 ] ; then
msg_ok " $( translate 'Image imported successfully' ) "
# Read the imported disk from the temporary file
IMPORTED_DISK = $( cat " $TEMP_DISK_FILE " )
rm -f " $TEMP_DISK_FILE " # Delete the temporary file
if [ -n " $IMPORTED_DISK " ] ; then
2025-01-26 20:23:52 +01:00
# Find the next available disk slot
2025-01-28 20:47:18 +01:00
EXISTING_DISKS = $( qm config " $VMID " | grep -oP " ${ INTERFACE } \d+ " | sort -n)
if [ -z " $EXISTING_DISKS " ] ; then
# If there are no existing disks, start from 0
NEXT_SLOT = 0
else
# If there are existing disks, take the last one and add 1
LAST_SLOT = $( echo " $EXISTING_DISKS " | tail -n1 | sed " s/ ${ INTERFACE } // " )
NEXT_SLOT = $(( LAST_SLOT + 1 ))
fi
2025-01-29 17:27:37 +01:00
2025-01-28 20:47:18 +01:00
2025-01-29 17:27:37 +01:00
# Ask if SSD emulation is desired (only for non-VirtIO interfaces)
if [ " $INTERFACE " != "virtio" ] ; then
if ( whiptail --title " $( translate 'SSD Emulation' ) " --yesno " $( translate 'Do you want to use SSD emulation for this disk?' ) " 10 60) ; then
SSD_OPTION = ",ssd=1"
else
SSD_OPTION = ""
fi
2025-01-28 20:47:18 +01:00
else
SSD_OPTION = ""
fi
2025-01-29 17:27:37 +01:00
2025-01-28 20:47:18 +01:00
msg_info " $( translate 'Configuring disk' ) "
2025-01-26 20:27:28 +01:00
2025-01-28 20:47:18 +01:00
# Configure the disk in the VM
if qm set " $VMID " --${ INTERFACE } ${ NEXT_SLOT } " $IMPORTED_DISK ${ SSD_OPTION } " & >/dev/null; then
msg_ok " $( translate 'Image' ) $IMAGE $( translate 'configured as' ) ${ INTERFACE } ${ NEXT_SLOT } "
2025-01-26 20:27:28 +01:00
2025-01-28 20:47:18 +01:00
# Ask if the disk should be bootable
if ( whiptail --title " $( translate 'Make Bootable' ) " --yesno " $( translate 'Do you want to make this disk bootable?' ) " 10 60) ; then
msg_info " $( translate 'Configuring disk as bootable' ) "
2025-01-29 17:27:37 +01:00
2025-01-28 20:47:18 +01:00
if qm set " $VMID " --boot c --bootdisk ${ INTERFACE } ${ NEXT_SLOT } & >/dev/null; then
msg_ok " $( translate 'Disk configured as bootable' ) "
else
msg_error " $( translate 'Could not configure the disk as bootable' ) "
fi
2025-01-26 20:27:28 +01:00
fi
2025-01-26 19:40:00 +01:00
else
2025-01-28 20:47:18 +01:00
msg_error " $( translate 'Could not configure disk' ) ${ INTERFACE } ${ NEXT_SLOT } $( translate 'for VM' ) $VMID "
2025-01-26 19:40:00 +01:00
fi
else
2025-01-28 20:47:18 +01:00
msg_error " $( translate 'Could not find the imported disk' ) "
2025-01-26 19:40:00 +01:00
fi
2025-01-28 20:47:18 +01:00
else
msg_error " $( translate 'Could not import' ) $IMAGE "
fi
2025-01-14 11:42:26 +01:00
done
2025-01-26 19:40:00 +01:00
msg_ok " $( translate 'All selected images have been processed' ) "
2025-01-28 21:19:24 +01:00
sleep 2