Skip to content

Instantly share code, notes, and snippets.

@NotYusta
Last active October 3, 2024 15:13
Show Gist options
  • Save NotYusta/d27af648105abd6778146de890af1770 to your computer and use it in GitHub Desktop.
Save NotYusta/d27af648105abd6778146de890af1770 to your computer and use it in GitHub Desktop.
Proxmox Import VM Disk (Formatted) - <vm-id> <image-file> <storage> <label> <slot> (0-20, can be single or ranges)
#!/bin/bash
# Function to check the exit status of the last command
check_error() {
if [ $? -ne 0 ]; then
echo "Error: $1"
exit 1
fi
}
# Check if at least 4 arguments are provided
if [ $# -lt 4 ]; then
echo "Usage: $0 <vmid> <source_disk_path> <storage_target> <disk_label> [<disk_slot>]"
exit 1
fi
# Assigning variables based on input
VMID=$1
SOURCE_DISK_PATH=$2
STORAGE_TARGET=$3
DISK_LABEL=$4
DISK_SLOT=${5:-""} # Optional disk slot; if not provided, it's empty
# Check if the specified storage exists
if ! pvesm status | grep -q "$STORAGE_TARGET"; then
echo "Error: Storage target '$STORAGE_TARGET' not found."
exit 1
fi
# Get the storage path directly from the storage configuration
STORAGE_PATH=$(grep -A 3 "^dir: $STORAGE_TARGET" /etc/pve/storage.cfg | grep "path" | awk '{print $2}')
# If the storage path could not be determined, exit with error
if [ -z "$STORAGE_PATH" ]; then
echo "Failed to determine the storage path for '$STORAGE_TARGET'. Please check the storage ID."
exit 1
fi
# Define the path where the VM's disks are stored
DISK_PATH="$STORAGE_PATH/images/$VMID/"
# Check if a disk with the label already exists
if [ -f "$DISK_PATH/${DISK_LABEL}.qcow2" ]; then
echo "Error: A disk with the label '${DISK_LABEL}.qcow2' already exists."
exit 1
fi
# Process disk slot input
if [ ! -z "$DISK_SLOT" ]; then
# Check if a specific disk slot is provided
if [[ "$DISK_SLOT" == *"-"* ]]; then
# Handle the range of slots
IFS='-' read -r START END <<<"$DISK_SLOT"
# Validate range
if ! [[ "$START" =~ ^[0-9]+$ && "$END" =~ ^[0-9]+$ ]] || [ "$START" -gt "$END" ] || [ "$START" -lt 0 ] || [ "$END" -gt 20 ]; then
echo "Error: Range must be between 0 and 20, and start must be less than or equal to end."
exit 1
fi
for ((SLOT = START; SLOT <= END; SLOT++)); do
if ! grep -q "scsi$SLOT" "/etc/pve/qemu-server/$VMID.conf"; then
echo "Checking if slot $SLOT is available..."
# Check if disk already exists in this slot
if [ ! -f "$DISK_PATH/vm-$VMID-disk-$SLOT.qcow2" ]; then
# Slot is available; proceed to import disk
echo "Slot $SLOT is available for import."
# (Add your import logic here)
break # Break out of the loop if a free slot is found
else
echo "Error: Disk already exists in slot $SLOT. Checking next slot."
fi
else
echo "Slot $SLOT is already in use. Checking next slot."
fi
done
# Check if a valid slot was found in the range
if [ "$SLOT" -gt "$END" ]; then
echo "Error: No available slots in the specified range."
exit 1
fi
else
# Handle a single slot
if ! [[ "$DISK_SLOT" =~ ^[0-9]+$ ]] || [ "$DISK_SLOT" -lt 0 ] || [ "$DISK_SLOT" -gt 20 ]; then
echo "Error: Disk slot must be an integer between 0 and 20."
exit 1
fi
SLOT="$DISK_SLOT" # Assign the valid single slot value
# Debugging output to verify SLOT value
echo "Validated SLOT: $SLOT"
if ! grep -q "scsi$SLOT" "/etc/pve/qemu-server/$VMID.conf"; then
# Check if disk already exists in this slot
if [ ! -f "$DISK_PATH/vm-$VMID-disk-$SLOT.qcow2" ]; then
# Slot is available; proceed to import disk
echo "Slot $SLOT is available for import."
# (Add your import logic here)
else
echo "Error: Disk already exists in slot $SLOT."
exit 1
fi
else
echo "Error: Disk slot $SLOT is already in use."
exit 1
fi
fi
else
# Loop through available slots if no specific slot is provided
for DISK_SLOT in {0..20}; do
if ! grep -q "scsi$DISK_SLOT" "/etc/pve/qemu-server/$VMID.conf"; then
echo "Checking if slot $DISK_SLOT is available..."
if [ ! -f "$DISK_PATH/vm-$VMID-disk-$DISK_SLOT.qcow2" ]; then
# Slot is available; proceed to import disk
echo "Slot $DISK_SLOT is available for import."
# (Add your import logic here)
break # Break out of the loop if a free slot is found
else
echo "Error: Disk already exists in slot $DISK_SLOT. Checking next slot."
fi
else
echo "Slot $DISK_SLOT is already in use. Checking next slot."
fi
done
# If no available slot was found
if [ "$DISK_SLOT" -eq 20 ]; then
echo "Error: No available SCSI slots to attach the disk."
exit 1
fi
fi
# Import the disk to Proxmox in QCOW2 format
echo "Importing disk in QCOW2 format..."
qm importdisk $VMID $SOURCE_DISK_PATH $STORAGE_TARGET --format qcow2
check_error "Failed to import disk for VM $VMID."
# Create the disk path if it doesn't exist
mkdir -p "$DISK_PATH"
# Wait a moment to ensure the import completes
sleep 1 # Optional: adjust as necessary
# List existing disk files to determine the highest index
echo "Listing existing disk files in $DISK_PATH:"
EXISTING_DISKS=$(ls "$DISK_PATH" | grep "vm-$VMID-disk")
# Detect the highest existing index from the existing disks
echo "Detecting existing disk indices..."
EXISTING_INDICES=$(echo "$EXISTING_DISKS" | sed 's/.*-disk-\([0-9]\+\)\.qcow2/\1/' | sort -n)
# Determine the next index for the new disk
if [ -z "$EXISTING_INDICES" ]; then
NEXT_INDEX=0
else
NEXT_INDEX=$(echo "$EXISTING_INDICES" | tail -n 1)
NEXT_INDEX=$((NEXT_INDEX + 1))
fi
# Determine the old disk file name based on the highest existing index
OLD_DISK_FILE="vm-${VMID}-disk-$((NEXT_INDEX - 1)).qcow2"
# Check if the expected old disk file exists
if [ ! -f "$DISK_PATH/$OLD_DISK_FILE" ]; then
echo "Error: The expected old disk file '$OLD_DISK_FILE' was not found."
exit 1
fi
# Rename the newly imported disk to the specified label
NEW_DISK_FILE="${DISK_LABEL}.qcow2"
# Move the imported disk to the specified label in the correct format
echo "Renaming disk from '$OLD_DISK_FILE' to '$NEW_DISK_FILE' in storage target '$STORAGE_TARGET'."
mv "$DISK_PATH/$OLD_DISK_FILE" "$DISK_PATH/$NEW_DISK_FILE"
check_error "Failed to rename disk to '$NEW_DISK_FILE'."
# Update the VM configuration file to reflect the new disk file
CONFIG_FILE="/etc/pve/qemu-server/$VMID.conf"
echo "Updating VM configuration file: $CONFIG_FILE"
sed -i "s|$OLD_DISK_FILE|$NEW_DISK_FILE|g" "$CONFIG_FILE"
check_error "Failed to update VM configuration file."
# Attach the newly imported disk to the VM
echo "Attaching the disk to VM $VMID..."
# Attach the disk to the determined slot
if [ ! -z "$DISK_SLOT" ]; then
qm set $VMID --scsi"$SLOT" "$STORAGE_TARGET:$VMID/$NEW_DISK_FILE"
check_error "Failed to attach the disk to VM $VMID in slot $SLOT."
echo "Disk attached to VM $VMID in SCSI slot $SLOT."
else
# If no specific slot was provided, attach to the first available slot
for ((SLOT = 0; SLOT <= 20; SLOT++)); do
if ! grep -q "scsi$SLOT" "$CONFIG_FILE"; then
qm set $VMID --scsi"$SLOT" "$STORAGE_TARGET:$VMID/$NEW_DISK_FILE"
check_error "Failed to attach the disk to VM $VMID in slot $SLOT."
echo "Disk attached to VM $VMID in SCSI slot $SLOT."
break
fi
done
fi
echo "Disk import and attachment completed successfully."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment