diff options
Diffstat (limited to 'share/hydractl/sync-guestfs')
-rwxr-xr-x | share/hydractl/sync-guestfs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/share/hydractl/sync-guestfs b/share/hydractl/sync-guestfs new file mode 100755 index 0000000..96e74cd --- /dev/null +++ b/share/hydractl/sync-guestfs @@ -0,0 +1,112 @@ +#!/bin/bash +# +# sync-guestfs: sync a tree containing virtual machine guest images +# + +# Load +source $APP_BASE/lib/hydra/functions || exit 1 +hydra_config_load + +# Parameters +BASENAME="$0" +ORIG="$1" +DEST="$2" +TMP="/tmp" +RSYNC="ionice -c 3 nice -n 19 rsync -av --delete --progress" + +# Dependencies +hydra_install_package rsync +hydra_install_package libguestfs-tools + +# Syntax +if [ -z "$DEST" ]; then + echo "usage: $BASENAME <orig-folder> <dest-folder>" + exit 1 +elif [ ! -d "$ORIG" ]; then + echo "folder $DEST does not exist." + exit 1 +fi + +# Sudo +if [ "$USER" != 'root' ]; then + export SUDO="sudo" +fi + +# Ensure the dest folder exist +if [ ! -d "$DEST" ]; then + $SUDO mkdir -p $DEST + + OWNER="$(stat -c %U $ORIG)" + GROUP="$(stat -c %G $ORIG)" + + # With the right permissions + $SUDO chown $OWNER.$GROUP $DEST +fi + +# First sync the folder structure +$SUDO $RSYNC --exclude='*.img' $ORIG/ $DEST/ + +# Temporary folders +ORIG_MOUNT="`mktemp -d $TMP/sync-guestfs-orig.XXXXXXXXXX`" +DEST_MOUNT="`mktemp -d $TMP/sync-guestfs-dest.XXXXXXXXXX`" + +# Main loop +( + cd $ORIG + find -name '*.img' | sort | sed -e 's|^./||' | while read image; do + if [ ! -e "$DEST/$image" ]; then + # Make the first copy + # See https://gergap.wordpress.com/2013/08/10/rsync-and-sparse-files/ + # https://stackoverflow.com/questions/19821186/rsync-sparse-does-transfer-whole-data#19827546 + echo "Making the first copy of $image to $DEST, which might take a while..." + $SUDO $RSYNC --sparse $image $DEST/$image + else + echo "Destination $DEST/$image exists, syncing..." + $SUDO $RSYNC --inplace $image $DEST/$image + + # + # Sync using libguestfs-tools: mount existing + # images and use rsync to copy the differences. + # + ## Mount and sync + #$SUDO guestmount -a $image -i --ro $ORIG_MOUNT/ && \ + #$SUDO guestmount -a $DEST/$image -i $DEST_MOUNT/ && \ + #time $SUDO $RSYNC $ORIG_MOUNT/ $DEST_MOUNT/ || \ + #echo "Failed to sync $image with $DEST/$image." + # + ## Umount orig image + #if mount | grep -q "$ORIG_MOUNT"; then + # $SUDO guestunmount $ORIG_MOUNT + #fi + # + ## Umount dest image + #if mount | grep -q "$DEST_MOUNT"; then + # $SUDO guestunmount $DEST_MOUNT + #fi + # + #echo "Optimizing $DEST/$image size..." + #time $SUDO ionice -c 3 nice -n 19 virt-sparsify --in-place $DEST/$image + #time $SUDO ionice -c 3 nice -n 19 virt-sparsify --tmp $TMP --compress $DEST/$image $DEST/$image.new && \ + # $SUDO mv $DEST/$image.new $DEST/$image + fi + done +) + +# Remove images that does not exist anymore in the origin +( + cd $DEST + find -name '*.img' | sort | sed -e 's|^./||' | while read image; do + if [ ! -e "$ORIG/$image" ]; then + echo "Removing old $DEST/$image..." + $SUDO rm -f $image + fi + done + + # Sync again to prune any dangling folder structure + echo "Cleaning up..." + $SUDO $RSYNC --exclude='*.img' $ORIG/ $DEST/ +) + +# Teardown +$SUDO rmdir $ORIG_MOUNT +$SUDO rmdir $DEST_MOUNT |