Add proxmox_converter.sh
This commit is contained in:
parent
6277e110c0
commit
df6107946b
1 changed files with 225 additions and 0 deletions
225
proxmox_converter.sh
Normal file
225
proxmox_converter.sh
Normal file
|
@ -0,0 +1,225 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Proxmox Image Converter
|
||||
# This script converts various virtual machine image formats to Proxmox-compatible format
|
||||
# Supported formats: VMDK, VHD, VHDX, QED, QCOW2, RAW
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color codes for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Required tools
|
||||
REQUIRED_TOOLS=("qemu-img" "md5sum" "awk" "grep" "basename" "dirname")
|
||||
|
||||
# Log file
|
||||
LOG_FILE="/var/log/proxmox_converter.log"
|
||||
TEMP_DIR="/tmp/proxmox_convert"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
local level=$1
|
||||
local message=$2
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo -e "${timestamp} [${level}] ${message}" >> "${LOG_FILE}"
|
||||
|
||||
case ${level} in
|
||||
"ERROR")
|
||||
echo -e "${RED}ERROR: ${message}${NC}" >&2
|
||||
;;
|
||||
"WARNING")
|
||||
echo -e "${YELLOW}WARNING: ${message}${NC}"
|
||||
;;
|
||||
"INFO")
|
||||
echo -e "${GREEN}INFO: ${message}${NC}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to check required tools
|
||||
check_requirements() {
|
||||
local missing_tools=()
|
||||
|
||||
for tool in "${REQUIRED_TOOLS[@]}"; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
missing_tools+=("$tool")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_tools[@]} -ne 0 ]; then
|
||||
log_message "ERROR" "Missing required tools: ${missing_tools[*]}"
|
||||
log_message "ERROR" "Please install them using: apt-get install qemu-utils coreutils grep"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to verify disk image integrity
|
||||
verify_image() {
|
||||
local image_path=$1
|
||||
local checksum_before=$2
|
||||
|
||||
if [ ! -f "$image_path" ]; then
|
||||
log_message "ERROR" "Image file not found: $image_path"
|
||||
return 1
|
||||
}
|
||||
|
||||
local checksum_after=$(md5sum "$image_path" | awk '{print $1}')
|
||||
|
||||
if [ "$checksum_before" != "$checksum_after" ]; then
|
||||
log_message "ERROR" "Image verification failed! Checksums don't match"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_message "INFO" "Image verification successful"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to detect image format
|
||||
detect_format() {
|
||||
local image_path=$1
|
||||
|
||||
if [ ! -f "$image_path" ]; then
|
||||
log_message "ERROR" "Image file not found: $image_path"
|
||||
return 1
|
||||
}
|
||||
|
||||
local format=$(qemu-img info "$image_path" | grep "file format" | awk '{print $3}')
|
||||
|
||||
if [ -z "$format" ]; then
|
||||
log_message "ERROR" "Unable to detect image format"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$format"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to convert image to QCOW2
|
||||
convert_to_qcow2() {
|
||||
local input_path=$1
|
||||
local output_path=$2
|
||||
local format=$3
|
||||
|
||||
# Calculate checksum before conversion
|
||||
local checksum_before=$(md5sum "$input_path" | awk '{print $1}')
|
||||
|
||||
# Create temp directory if it doesn't exist
|
||||
mkdir -p "$TEMP_DIR"
|
||||
|
||||
# Convert image
|
||||
log_message "INFO" "Converting $input_path to QCOW2 format..."
|
||||
if ! qemu-img convert -f "$format" -O qcow2 "$input_path" "${TEMP_DIR}/temp.qcow2"; then
|
||||
log_message "ERROR" "Conversion failed"
|
||||
rm -f "${TEMP_DIR}/temp.qcow2"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verify source image hasn't been modified
|
||||
if ! verify_image "$input_path" "$checksum_before"; then
|
||||
log_message "ERROR" "Source image was modified during conversion"
|
||||
rm -f "${TEMP_DIR}/temp.qcow2"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Move converted image to final destination
|
||||
mv "${TEMP_DIR}/temp.qcow2" "$output_path"
|
||||
|
||||
log_message "INFO" "Conversion completed successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to import image to Proxmox
|
||||
import_to_proxmox() {
|
||||
local image_path=$1
|
||||
local vm_id=$2
|
||||
local storage=$3
|
||||
|
||||
# Verify VM ID is valid
|
||||
if ! [[ "$vm_id" =~ ^[0-9]+$ ]]; then
|
||||
log_message "ERROR" "Invalid VM ID: $vm_id"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if VM ID already exists
|
||||
if qm status "$vm_id" >/dev/null 2>&1; then
|
||||
log_message "ERROR" "VM ID $vm_id already exists"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if storage exists
|
||||
if ! pvesm status | grep -q "^$storage"; then
|
||||
log_message "ERROR" "Storage $storage not found"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Import disk
|
||||
log_message "INFO" "Importing disk to Proxmox..."
|
||||
if ! qm importdisk "$vm_id" "$image_path" "$storage"; then
|
||||
log_message "ERROR" "Failed to import disk"
|
||||
return 1
|
||||
}
|
||||
|
||||
log_message "INFO" "Disk imported successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
local input_path=$1
|
||||
local vm_id=$2
|
||||
local storage=$3
|
||||
|
||||
# Check requirements
|
||||
check_requirements
|
||||
|
||||
# Create log directory if it doesn't exist
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
|
||||
# Detect input format
|
||||
local format
|
||||
format=$(detect_format "$input_path")
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate output path
|
||||
local filename=$(basename "$input_path")
|
||||
local output_path="${TEMP_DIR}/${filename%.*}.qcow2"
|
||||
|
||||
# Convert image if not already in QCOW2 format
|
||||
if [ "$format" != "qcow2" ]; then
|
||||
if ! convert_to_qcow2 "$input_path" "$output_path" "$format"; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
cp "$input_path" "$output_path"
|
||||
fi
|
||||
|
||||
# Import to Proxmox
|
||||
if ! import_to_proxmox "$output_path" "$vm_id" "$storage"; then
|
||||
rm -f "$output_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
rm -f "$output_path"
|
||||
log_message "INFO" "Image conversion and import completed successfully"
|
||||
}
|
||||
|
||||
# Script usage
|
||||
usage() {
|
||||
echo "Usage: $0 <input_image_path> <vm_id> <storage>"
|
||||
echo "Example: $0 /path/to/windows.vmdk 100 local-lvm"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check arguments
|
||||
if [ $# -ne 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# Run main function
|
||||
main "$1" "$2" "$3"
|
Loading…
Reference in a new issue