From 211f89e03e373a1a8bc5dd4b802b130417e81696 Mon Sep 17 00:00:00 2001 From: MacRimi <123239993+MacRimi@users.noreply.github.com> Date: Tue, 28 Jan 2025 20:47:18 +0100 Subject: [PATCH] Update import-disk-image.sh --- scripts/import-disk-image.sh | 185 ++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 56 deletions(-) diff --git a/scripts/import-disk-image.sh b/scripts/import-disk-image.sh index 9223ef5..b64d650 100644 --- a/scripts/import-disk-image.sh +++ b/scripts/import-disk-image.sh @@ -1,7 +1,30 @@ #!/bin/bash -# Source utility functions from local installation -source "/usr/local/share/proxmenux/utils.sh" +# ========================================================== +# 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" +LANGUAGE=$(jq -r '.language' "$BASE_DIR/config.json" 2>/dev/null || echo "en") + + + +# 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 # Path where disk images are stored IMAGES_DIR="/var/lib/vz/template/images/" @@ -9,31 +32,35 @@ IMAGES_DIR="/var/lib/vz/template/images/" # Check if there are any images in the directory IMAGES=$(ls -A "$IMAGES_DIR" | grep -E "\.(img|qcow2|vmdk)$") if [ -z "$IMAGES" ]; then - whiptail --title "$(translate 'No Images Available')" --msgbox "$(translate 'No disk images available for import in') $IMAGES_DIR\n\n$(translate 'Supported formats: .img, .qcow2, .vmdk')\n\n$(translate 'Please add some images and try again.')" 12 60 + 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}" exit 0 fi # Check dependencies -check_dependencies qm whiptail jq +check_dependencies qm whiptail jq || exit 1 # Initial setup if ! [ -d "$IMAGES_DIR" ]; then - msg_info "$(translate 'Creating images directory...')" + msg_info "$(translate 'Creating images directory')" mkdir -p "$IMAGES_DIR" msg_ok "$(translate 'Images directory created')" fi # Display initial message -whiptail --title "$(translate 'Import Disk Image')" --msgbox "$(translate 'Please ensure that the disk images you want to import are located in:')\n\n$IMAGES_DIR\n\n$(translate 'Supported formats: .img, .qcow2, .vmdk.')" 12 60 +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 + + # 1. Select VM -msg_info "$(translate 'Getting VM list...')" -VM_LIST=$(qm list | awk 'NR>1 {print $1, $2}') +msg_info "$(translate 'Getting VM list')" +VM_LIST=$(qm list | awk 'NR>1 {print $1" "$2}') if [ -z "$VM_LIST" ]; then msg_error "$(translate 'No VMs available in the system')" exit 1 fi -msg_ok "$(translate 'VM list retrieved')" +msg_ok "$(translate 'VM list obtained')" 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) @@ -42,20 +69,22 @@ if [ -z "$VMID" ]; then exit 1 fi + + # 2. Select storage volume -msg_info "$(translate 'Getting storage volumes...')" +msg_info "$(translate 'Getting storage volumes')" 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 -msg_ok "$(translate 'Storage volumes retrieved')" +msg_ok "$(translate 'Storage volumes obtained')" # Create an array of storage options for whiptail STORAGE_OPTIONS=() -for storage in $STORAGE_LIST; do - STORAGE_OPTIONS+=("$storage" "$storage") -done +while read -r storage; do + STORAGE_OPTIONS+=("$storage" "") +done <<< "$STORAGE_LIST" 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) @@ -64,20 +93,22 @@ if [ -z "$STORAGE" ]; then exit 1 fi + + # 3. Select disk images -msg_info "$(translate 'Scanning for disk images...')" +msg_info "$(translate 'Scanning disk images')" if [ -z "$IMAGES" ]; then msg_error "$(translate 'No compatible disk images found in') $IMAGES_DIR" exit 0 fi msg_ok "$(translate 'Disk images found')" -IMAGE_LIST="" -for img in $IMAGES; do - IMAGE_LIST="$IMAGE_LIST $img OFF" -done +IMAGE_OPTIONS=() +while read -r img; do + IMAGE_OPTIONS+=("$img" "" "OFF") +done <<< "$IMAGES" -SELECTED_IMAGES=$(whiptail --title "$(translate 'Select Disk Images')" --checklist "$(translate 'Select the disk images to import:')" 20 60 10 $IMAGE_LIST 3>&1 1>&2 2>&3) +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) if [ -z "$SELECTED_IMAGES" ]; then msg_error "$(translate 'No images selected')" @@ -86,26 +117,16 @@ fi # 4. Import each selected image for IMAGE in $SELECTED_IMAGES; do + # Remove quotes from selected image IMAGE=$(echo "$IMAGE" | tr -d '"') - # 5. Select disk format for each image - FORMAT=$(whiptail --title "$(translate 'Disk Format')" --menu "$(translate 'Select disk format for image:') $IMAGE" 15 40 4 \ - "raw" "$(translate 'Raw format')" \ - "qcow2" "$(translate 'QCOW2 format')" \ - "vmdk" "$(translate 'VMDK format')" 3>&1 1>&2 2>&3) - - if [ -z "$FORMAT" ]; then - msg_error "$(translate 'No disk format selected for') $IMAGE" - continue - fi - - # 6. Select interface type for each image - INTERFACE=$(whiptail --title "$(translate 'Interface Type')" --menu "$(translate 'Select interface type for image:') $IMAGE" 15 40 4 \ - "scsi" "$(translate 'SCSI')" \ - "sata" "$(translate 'SATA')" \ - "virtio" "$(translate 'VirtIO')" \ - "ide" "$(translate 'IDE')" 3>&1 1>&2 2>&3) + # 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) if [ -z "$INTERFACE" ]; then msg_error "$(translate 'No interface type selected for') $IMAGE" @@ -114,34 +135,86 @@ for IMAGE in $SELECTED_IMAGES; do FULL_PATH="$IMAGES_DIR/$IMAGE" - msg_info "$(translate 'Importing image:') $IMAGE $(translate 'as') ${FORMAT}..." + # Show initial message + msg_info "$(translate 'Importing image:')" - ( - if qm importdisk "$VMID" "$FULL_PATH" "$STORAGE" --format "$FORMAT"; then + # Temporary file to capture the imported disk + TEMP_DISK_FILE=$(mktemp) + + + # 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 + # Find the next available disk slot - NEXT_SLOT=$(qm config "$VMID" | grep -oP "${INTERFACE}\d+" | sort -n | tail -n1 | sed "s/${INTERFACE}//") - NEXT_SLOT=$((NEXT_SLOT + 1)) + 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 - IMPORTED_DISK=$(qm config "$VMID" | grep -oP "${STORAGE}:[^\s]+") + # Ask if SSD emulation is desired + 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 - if [ -n "$IMPORTED_DISK" ]; then - if qm set "$VMID" --${INTERFACE}${NEXT_SLOT} "$IMPORTED_DISK"; then - msg_ok "$(translate 'Successfully imported') $IMAGE $(translate 'as') ${INTERFACE}${NEXT_SLOT}" - else - msg_error "$(translate 'Failed to configure disk') ${INTERFACE}${NEXT_SLOT} $(translate 'for VM') $VMID" + msg_info "$(translate 'Configuring disk')" + + # 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}" + + # 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')" + 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 fi else - msg_error "$(translate 'Failed to find imported disk')" + msg_error "$(translate 'Could not configure disk') ${INTERFACE}${NEXT_SLOT} $(translate 'for VM') $VMID" fi else - msg_error "$(translate 'Failed to import') $IMAGE" + msg_error "$(translate 'Could not find the imported disk')" fi - ) & - - spinner - wait + else + msg_error "$(translate 'Could not import') $IMAGE" + fi done msg_ok "$(translate 'All selected images have been processed')" -exit 0 -