aboutsummaryrefslogtreecommitdiff
path: root/zfs-squash-datasets.sh
blob: 0e6d6023701903442697802f38fbc75279da9d6a (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
#!/bin/sh
# This script expects a source dataset and a target dataset as arguments.  It
# will then copy each snapshot of the source dataset into the target as a
# subfolder with the name of the dataset. This is being archived by cloning the
# source-dataset first into a sub-dataset of the source dataset named after the
# snapshot. From there rsync is used to copy files into the target location.
# After that finishes a snapshot will be created in the target with the original
# snapshot-name and a suffix, which is the last part of the source dataset.
#
# Known Bugs:
#
# * This script will immidiatly stop when any command returns an error and it
# will not clean up automatically the clones it created. But these clones are
# not promoted by the script and can be deleted without altering the source
# dataset and in order to re-execute the script after fixing the reason for the
# error.
#
# * There is currently no sanity checking. Please do not copy files from a
# dataset, which is a child of the source dataset.

#
# Example:
#
# 	./zfs-squash-datasets.sh  zpool/software zpool/projects
#
# would create a folder /zpool/projects/software within the dataset
# zpool/projects



set -o errexit

getMountPoint() {
	zfs get -H -o value mountpoint "$1" ||\
		(echo "mountpoint for dataset '$1' not found" ; exit 1)
}

listAllSnapshots() {
	zfs list -H -o name -tsnap -r "$1" ||\
		(echo "Could not find snapshots under $1" ; exit 2)
}

DATASET=$1
DATASET_NAME=`basename $DATASET`
DATASET_TARGET=$2
TARGET_PATH=`basename $DATASET_TARGET`

MP_TARGET=`getMountPoint $2`

test -d "$MP_TARGET" || (echo "failed to find mountpoint for $DATASET_TARGET: Its not $MP_TARGET" ; exit 3)

for i in `listAllSnapshots $DATASET`; do
	SNAPSHOT=`echo "$i" | cut -d@ -f2`

	CLONETMP="$DATASET/$SNAPSHOT"

	zfs clone "$i" "$CLONETMP" ||\
		(echo "Failed to create clone" ; exit 4)

	MP_CLONE=`getMountPoint $CLONETMP`

	test -d "$MP_CLONE" ||\
		(echo "$CLONETMP: clones mount point not found" ; exit 5)


	# copy all files to the target location
	(set -x ; rsync -ahox --info=progress2 --delete "$MP_CLONE/"  "$MP_TARGET/$TARGET_PATH" ||\
		(echo "rsync exit status was $?" ; exit 6)
	)
	
	(set -x ; zfs snap "$DATASET_TARGET@$SNAPSHOT-$DATASET_NAME" ||\
		(echo "failed to create a snapshot $DATASET_TARGET: $SNAPSHOT-$DATASET_NAME" ; exit 7)
	)

	# move clone out of the source dataset, so that we can resume
	# zfs promote "$CLONETMP" ||\
	# 	(echo "Failed to promote clone '$CLONETMP'" ; exit 8)
	zfs destroy "$CLONETMP" ||\
		(echo "Failed to destroy clone '$CLONETMP'" ; exit 8)

	# for better readability add two blank lines...
	echo
	echo
done
..