Files
programming/bash/vmclone.sh

112 lines
3.2 KiB
Bash
Raw Normal View History

2026-03-12 21:51:59 +01:00
#!/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