blob: dce2f2bbba601da56356715c4fc68126e8d8a73d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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..."
time $SUDO $RSYNC --sparse $image $DEST/$image
else
echo "Syncing $DEST/$image..."
time $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
|