In recent weeks, my team has had to virtualize many physical machines. These were mainly Windows client computers. As this was a recurring task, I created a script that simply pushes the existing hard disk into the vm using dd.
to get the running vms from our HV-Cluster i use a simple qm list (ssh auth is done via pubkey auth)
Output Example:
most of the script is there to make it look nice. the work is carried out by the following commands:
line 71:
dd if=/dev/$disk | ssh gandalfpve dd of=/tmp/transfer/$disk.raw status=progress
dd (disk dump) reads the data carrier bit by bit and through the pipe the output of dd is used as input for the following ssh. ssh establishes a connection to the hypervisor. On the HV, the bit stream sent to ssh is fed back into dd. The result is a file on the hypervisor which contains an image of the selected hard disk.
After the dump has been successfully stored on the Hypvervisor, all we have to do is import it
line 78 and 85
qmimportdisk="qm importdisk $vmid /tmp/transfer/$disk.raw gandalf-lvm"
ssh gandalfpve $importdisk
qm importdisk reads the file and saves it as a corresponding disk in the virtual machine (vmid). the last parameter is the location to use (gandalf-lvm). After this we have a Machine that runs in a Bluescreen. This is because Windows isnt good in moving to new Machines (VM). we must do the following:
This fixes the Bluescreen. if the machine does not boot then do also this:
here is the script:
# ******************************************************** #
# #
# #
# mvm.sh #
# #
# By: ♞ Raffael Willems <Raffael.Willems@im-c.de> #
# #
# Created: 2024/05/17 11:36:19 by ♞ Raffael Willems #
# Updated: 2024/05/17 12:30:40 by ♞ Raffael Willems #
# #
# ******************************************************** #
#!/bin/bash
# Global Vars
disk="no drive selected"
vmid=''
# Colors
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
PINK='\033[1;35m'
LIME_GREEN='\033[1;32m'
NC='\033[0m' # No Color
select_disk() {
# Runs lsblk and stores the output to a field
mapfile -t output_field < <(lsblk)
for i in "${!output_field[@]}"; do
echo "$i: ${output_field[i]}"
done
# Which Disk should be converted
read -p "Which Disk should be converted?:" userinput
# input validation
if [[ $userinput =~ ^[0-9]+$ && $userinput -ge 0 && $userinput -lt ${#output_field[@]} ]]; then
# Set a global var with the choosen output
disk=$(echo "${output_field[$userinput]}" | awk '{print $1}')
echo -e "${YELLOW}Chosen disk: $disk ${NC}"
else
echo -e "${YELLOW}Invalid choice. please enter a valid line number.${NC}"
fi
}
select_vm() {
# get VMList
mapfile -t output_field < <(ssh gandalfpve qm list)
for i in "${!output_field[@]}"; do
#echo ${output_field[i]} | awk '{print $1}'
echo "$i: ${output_field[i]}"
done
#Select Target VM
read -p "Select the target VM: " userinput
# input validation
if [[ $userinput =~ ^[0-9]+$ && $userinput -ge 0 && $userinput -lt ${#output_field[@]} ]]; then
# Set a global variable with the chosen output
vmid=$(echo "${output_field[$userinput]}" | awk '{print $1}')
echo -e "${YELLOW}Chosen VM: $vmid ${NC}"
else
echo -e "${YELLOW}Invalid choice. Please enter a valid line number.${NC}"
fi
}
copy_drive_to_raw() {
echo -e ${RED}"Are you shure you want to create a .RAW from this Device: $disk"${YELLOW}
lsblk | grep $disk
echo -e "\nPlease input 'yes' to continue..."
choice=""
read choice
if [ "$choice" == "yes" ]; then
echo -e "Saving $disk.raw on gandalfpve:/tmp/transfer/\n"
sudo dd if=/dev/$disk | ssh gandalfpve dd of=/tmp/transfer/$disk.raw status=progress
else
echo "canceled!"
fi
}
import_vm() {
qmimportdisk="qm importdisk $vmid /tmp/transfer/$disk.raw gandalf-lvm"
echo -e ${RED}"Are you shure you want to import the $disk into $vmid?\n"${YELLOW}
echo $qmimportdisk
echo "\nPlease input 'yes' to continue..."
choice=""
read choice
if [ "$choice" == "yes" ]; then
ssh gandalfpve $qmimportdisk
else
echo "canceled!"
fi
}
menu() {
clear
# Status
echo -e ${CYAN}"=== Migration Menu ==="
echo -e "Selected Drive:${NC}${YELLOW} $disk \n"${CYAN}
echo -e "Selected VID:${YELLOW} $vmid\n"
# Selections
echo -e ${PINK}"1. Select Drive to Migrate"
echo -e ${LIME_GREEN}"2. Migrate .raw to gandalfpve:/tmp/transfer/"gg
echo -e ${CYAN}"3. Select Virtual Machine"
echo -e ${PINK}"4. Import .raw into VM (gandalfpve)"
echo -e ${RED}"5. Exit\n"${CYAN}
echo -n "Enter your choice (1-4): "
read choice
}
while true; do
menu
case $choice in
1)
select_disk
;;
2)
copy_drive_to_raw
;;
3)
select_vm
;;
4)
import_vm
;;
5)
echo "Exiting. Goodbye!"
exit 0
;;
*)
echo "Invalid choice. Please enter a valid option."
;;
esac
echo -n "Press enter to continue..."
read
done