Last active
October 3, 2024 15:13
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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