#!/bin/bash
############## Clone VirtualBox Machine ##############
# Written By: Samy Antoun #
# #
# Usage: #
# ./clonevm.sh "Source Machine" "Clone Machine" #
# #
# Limitations: #
# 1. Clone only VM that has ONE Hard Drive (hda) #
# 2. Clone only VM that has NO Snapshots #
# 3. Clone only VM that is Powered Off #
# #
# ToDo: #
# 1. Check if the Hard Disk Partition has #
# sufficiant space for the cloned HD #
######################################################
################### Functions ########################
function ChkUtility {
res=`which $1 | grep "no $1"`
if [ "$res" != "" ]; then
echo "\"$1\" is missing";
exit 2;
fi
}
function GetValue {
Line=`VBoxManage -nologo showvminfo "$1" -machinereadable | grep "^$2="`;
Raw=`echo $Line | cut -d= -f2`;
Fixed=`echo $Raw | sed 's/"//g'`;
echo $Fixed;
}
function CheckUUID {
CheckID=`echo "$1" | sed -e "s/\w\{8\}-\w\{4\}-\w\{4\}-\w\{4\}-\w\{12\}/ok/"`;
if [ "$CheckID" != "ok" ]; then
echo "Source Disk \"$1\" UUID Not Valid";
exit 2;
fi
}
################## Sanity Check ######################
# Make Sure that we have the required software
ChkUtility "grep";
ChkUtility "cut";
ChkUtility "sed";
ChkUtility "uuidgen";
ChkUtility "VBoxManage";
# Command line Parameters must be 2
if [ $# != 2 ]; then
echo "Source VM Name Or Clone VM Name is Missing";
exit 2;
fi
# Get Command line Parameters
SrcVM=$1;
CloneVM=$2;
# Set Clone Machine Directory
MachinesDirLine=`VBoxManage -nologo list systemproperties | grep "Default machine folder:"`;
MachinesDirRaw=`echo $MachinesDirLine | cut -d: -f2`;
MachinesDir=`echo $MachinesDirRaw | sed -e "s/^ *//g"`;
CloneMachineDir=$MachinesDir/$CloneVM;
# Make Sure that the Source VM is Registered
res=`VBoxManage -nologo showvminfo "$SrcVM" | grep "[!]"`
if [ "$res" != "" ]; then
echo "Source VM \"$SrcVM\" Not Registered";
exit 2;
fi
# Make Sure that the Clone VM NOT Registered
res=`VBoxManage -nologo showvminfo "$CloneVM" | grep "[!]"`
if [ "$res" = "" ]; then
echo "Clone VM \"$CloneVM\" Already Registered";
exit 2;
fi
# Make Sure that the Clone VM Directory Doesn't Exsits
if [ -d "$CloneMachineDir" ]; then
echo "The Directory \"$CloneMachineDir\" Already Exists";
exit 2;
fi
# Make Sure that the Source Disk UUID is Valid
SrcDiskID=`GetValue "$SrcVM" "HdaImageUUID"`;
CheckDiskID=`CheckUUID "$SrcDiskID"`;
# Make Sure that the Source Machine UUID is Valid
SrcVMid=`GetValue "$SrcVM" "UUID"`;
CheckDiskID=`CheckUUID "$SrcVMid"`;
# Make Sure that the Source Machine Config File Exists
SrcVMcfg=`GetValue "$SrcVM" "CfgFile"`;
if [ ! -f "$SrcVMcfg" ]; then
echo "Source Config File \"$SrcVMcfg\" Doesn't Exist";
exit 2;
fi
# Make Sure that the Source Machine Dosen't have a Snapshot
res=`GetValue "$SrcVM" "SnapshotName"`;
if [ "$res" != "" ]; then
echo "Source Machine has a Snapshot";
exit 2;
fi
# Make Sure that the Source Machine NOT Running
res=`GetValue "$SrcVM" "VMState"`;
if [ "$res" != "poweroff" ]; then
echo "Source Machine is NOT Powered Off";
exit 2;
fi
# Make Sure that the Source Machine has Only ONE Hard Disk (hda)
res=`VBoxManage list hdds | grep -c "$SrcVMid"`;
if [ "$res" != "1" ]; then
echo "Source Machine have $res Hard Disk(s), It Must has only ONE Hard Disk";
exit 2;
else
res=`sed -n '/<HardDiskAttachment /p' "$SrcVMcfg" | grep "bus=\"SATA\""`;
if [ "$res" != "" ]; then
echo "Source Machine Hard Disk Type is \"SATA\"";
exit 2;
fi
if [[ `GetValue "$SrcVM" "hda"` = "none" ]] || [[ `GetValue "$SrcVM" "hdb"` != "none" ]] || [[ `GetValue "$SrcVM" "hdd"` != "none" ]]; then
echo "Source Machine Hard Disk is NOT hda";
exit 2;
fi
fi
################# Main Functions #####################
# Clone Disk
SrcDiskVDI=`GetValue "$SrcVM" "hda"`;
echo "Cloning Disk ...";
VBoxManage -nologo clonevdi "$SrcDiskID" "$CloneVM.vdi";
echo -e "Source Disk\nUUID: $SrcDiskID\nvdi: $SrcDiskVDI\nHas been Cloned to\n$CloneMachineDir/$CloneVM.vdi\n";
# Create Clone Machine Directory and Copy Machine Config File
mkdir "$CloneMachineDir";
echo -e "Created Clone Machine Directory\n$CloneMachineDir\n";
cp -f "$SrcVMcfg" "$CloneMachineDir/$CloneVM.xml";
echo -e "Copied Source Machine Config File \n$SrcVMcfg\nto\n$CloneMachineDir/$CloneVM.xml\n";
# Create a new Machine UUID and replace the original
sed -i "s/<Machine uuid=\"{$SrcVMid}\" name=\"$SrcVM\"/<Machine uuid=\"{`uuidgen`}\" name=\"$CloneVM\"/" "$CloneMachineDir/$CloneVM.xml";
echo -e "Clone Machine UUID has been Updated\n";
# Remove Hard Disk Description from xml file
sed -i 's/<HardDiskAttachment .*\/>//' "$CloneMachineDir/$CloneVM.xml";
echo -e "Hard Disk Description has been Removed from \"$CloneMachineDir/$CloneVM.xml\"\n";
# Register the New Machine
VBoxManage -nologo registervm "$CloneMachineDir/$CloneVM.xml";
echo -e "Clone Machine has been Registered\n";
# Register the New Disk
VBoxManage -nologo modifyvm "$CloneVM" -hda "$CloneVM.vdi";
echo -e "Clone Machine Hard Disk has been Registered\n";
######################## Done ########################
echo -e "*** DONE ***\n*** The Clone Machine \"$CloneVM\" Created Succesfully ***";