112 lines
3.2 KiB
Bash
112 lines
3.2 KiB
Bash
|
|
#!/usr/bin/bash
|
||
|
|
|
||
|
|
function usage {
|
||
|
|
echo "Usage: vmclone -s|--source <SOURCE_VM> -t|--target <TARGET_VM> -o|--scriptonly"
|
||
|
|
echo " o| --scriptonly, only clone script is generated, the clone command will not be executed"
|
||
|
|
}
|
||
|
|
|
||
|
|
########
|
||
|
|
# MAIN #
|
||
|
|
########
|
||
|
|
|
||
|
|
typeset SOURCE_VM
|
||
|
|
typeset TARGET_VM
|
||
|
|
typeset SCRIPTONLY
|
||
|
|
typeset CLONESCRIPT="/tmp/kvmclone.sh"
|
||
|
|
typeset -i DISK_COUNT_SOURCE
|
||
|
|
typeset -i I
|
||
|
|
typeset RC
|
||
|
|
typeset REPLACE
|
||
|
|
|
||
|
|
# parameter processing
|
||
|
|
while [ "$1" != "" ]; do
|
||
|
|
case $1 in
|
||
|
|
-s | --source ) shift
|
||
|
|
SOURCE_VM="$1"
|
||
|
|
;;
|
||
|
|
-t | --target ) shift
|
||
|
|
TARGET_VM="$1"
|
||
|
|
;;
|
||
|
|
-o | --scriptonly ) SCRIPTONLY=true
|
||
|
|
;;
|
||
|
|
-r | --replace ) REPLACE=true
|
||
|
|
;;
|
||
|
|
-h | --help ) usage
|
||
|
|
exit
|
||
|
|
;;
|
||
|
|
* ) usage
|
||
|
|
exit 1
|
||
|
|
esac
|
||
|
|
shift
|
||
|
|
done
|
||
|
|
|
||
|
|
|
||
|
|
if [ -z "$SOURCE_VM" ] || [ -z "$TARGET_VM" ]; then
|
||
|
|
usage
|
||
|
|
exit
|
||
|
|
fi
|
||
|
|
|
||
|
|
# check if source VM exists
|
||
|
|
I=$(virsh list --all | grep $SOURCE_VM | wc -l)
|
||
|
|
if (( I == 0 )); then
|
||
|
|
echo "Source VM ($SOURCE_VM) does not exists"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# check if source VM is shut off
|
||
|
|
RC=$(virsh domstate $SOURCE_VM)
|
||
|
|
if [ "$RC" != "shut off" ]; then
|
||
|
|
echo "Source VM ($SOURCE_VM) is $RC, please shut it down first"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# check if target VM exists
|
||
|
|
I=$(virsh list --all | grep $TARGET_VM | wc -l)
|
||
|
|
if (( I > 0 )); then
|
||
|
|
# -r|--replace option was used
|
||
|
|
if [ "$REPLACE" == true ] ; then
|
||
|
|
# destroy the VM and the underlayng storage
|
||
|
|
echo "Shutdown VM $TARGET_VM"
|
||
|
|
virsh destroy $TARGET_VM > /dev/null 2>&1
|
||
|
|
echo "Remove VM $TARGET_VM"
|
||
|
|
virsh undefine $TARGET_VM --remove-all-storage > /dev/null 2>&1
|
||
|
|
else
|
||
|
|
echo "Target VM ($TARGET_VM) already exists, use -r|--replace option to replace it"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# generate KVM clone shell
|
||
|
|
rm -rf $CLONESCRIPT
|
||
|
|
echo -e "#!/usr/bin/bash"'\n' >> $CLONESCRIPT
|
||
|
|
chmod +x $CLONESCRIPT
|
||
|
|
|
||
|
|
echo "virt-clone \\" >> $CLONESCRIPT
|
||
|
|
echo " --original $SOURCE_VM \\" >> $CLONESCRIPT
|
||
|
|
echo " --name $TARGET_VM \\" >> $CLONESCRIPT
|
||
|
|
|
||
|
|
DISK_COUNT_SOURCE=$(virsh domblklist ${SOURCE_VM} --details | grep -v cdrom | grep "file" | wc -l)
|
||
|
|
|
||
|
|
I=0
|
||
|
|
for DISK in $(virsh domblklist ${SOURCE_VM} --details | grep -v cdrom | grep "file" | awk -F " " '{ print $4}')
|
||
|
|
do
|
||
|
|
I=$((I+1))
|
||
|
|
NEWDISK=${DISK/$SOURCE_VM/$TARGET_VM}
|
||
|
|
if (( I < DISK_COUNT_SOURCE )); then
|
||
|
|
echo " --file $NEWDISK \\" >> $CLONESCRIPT
|
||
|
|
else
|
||
|
|
echo " --file $NEWDISK" >> $CLONESCRIPT
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
echo "KVM clone script [$SOURCE_VM -> $TARGET_VM] has been generated: $CLONESCRIPT"
|
||
|
|
|
||
|
|
if [ "$SCRIPTONLY" != true ] ; then
|
||
|
|
# recreate VM storage directories
|
||
|
|
cat $CLONESCRIPT | grep '\-\-file' | xargs -I{} echo {} | sed "s/--file//g" | sed 's/ //g' | xargs -I{} dirname {} | sort -u | xargs -I{} rm -rf {}
|
||
|
|
cat $CLONESCRIPT | grep '\-\-file' | xargs -I{} echo {} | sed "s/--file//g" | sed 's/ //g' | xargs -I{} dirname {} | sort -u | xargs -I{} mkdir -p {}
|
||
|
|
# Run generated KVM clone shell
|
||
|
|
echo "Executing $CLONESCRIPT.."
|
||
|
|
$CLONESCRIPT
|
||
|
|
fi
|