Add the git review file
[zfs-ubuntu/.git] / zfs-replicate
1 #!/bin/bash
2
3 : Usage: zfs-backup [filesystem] [destination_pool]
4
5 tmpdir="/export/home/tmp"
6
7 lockdir="/tmp/zfs-admin-lock"
8 if ! mkdir "$lockdir" >/dev/null 2>&1; then
9   echo >&2 "ZFS admin lock directory is present."
10   exit 1
11 fi
12
13 cleanup() { rm -rf "$lockdir"; }
14 trap cleanup EXIT
15
16 fs=$1
17 sourcepool=${1%%/*}
18 fsname=${1#*/}
19 destinationpool=$2
20
21 if ! zpool list -H "$sourcepool" >/dev/null 2>&1; then
22   echo >&2 "The source pool, '$sourcepool' doesn't seem to exist."
23   exit 1
24 fi
25
26 if ! zpool list -H "$destinationpool" >/dev/null 2>&1; then
27   echo >&2 "The destination pool, '$destinationpool' doesn't seem to exist."
28   exit 1
29 fi
30
31 if ! zfs list -H "$fs" >/dev/null 2>&1; then
32   echo >&2 "The source filesytem, '$fs' doesn't seem to exist."
33   exit 1
34 fi
35
36 printsnaps() {
37 sed 's,.*/,,' | awk '{print $1}' 
38 }
39
40 zfs list -rH -t snapshot $sourcepool/$fsname | printsnaps > /tmp/source-list
41 zfs list -rH -t snapshot $destinationpool/$fsname | printsnaps > /tmp/destination-list
42 diff -u /tmp/source-list /tmp/destination-list | grep -v '^+++' | awk '/^\+/ {print}' | sed "s,^\+,$destinationpool/," > /tmp/obsolete-snapshots
43 rm -f /tmp/source-list /tmp/destination-list
44
45 echo >&2 "Removing obsolete backups from the destination pool" 
46 for snapshot in $(cat /tmp/obsolete-snapshots); do
47   echo >&2 "Removing '$snapshot' from destination."
48   zfs destroy "$snapshot"
49 done
50
51 echo >&2 "Rolling back to the most recent snapshot on the destination." 
52 zfs rollback $(zfs list -rH -t snapshot $destinationpool/$fsname | awk '{snap=$1} END {print snap}')
53
54 echo >&2 "Calculating the most recent common snapshot between the two filesystems." 
55 common=""
56 if zfs list -H "$destinationpool/$fsname" >/dev/null 2>&1; then
57   for snap in $(zfs list -rH -t snapshot "$destinationpool/$fsname" |
58                   sed 's,.*@,,' | awk '{print$1}'); do
59     if zfs list -rH -t snapshot "$fs" | sed 's,.*@,,' | awk '{print$1}' | grep "^${snap}$" >/dev/null 2>&1; then
60       common=$snap
61     fi
62   done
63 fi
64
65 base=$common
66 foundcommon=false
67 if [ -z "$common" ]; then
68   foundcommon=true
69 fi
70
71 for snap in $(zfs list -rH -t snapshot "$fs" |
72                 sed 's,.*@,,' | awk '{print$1}'); do
73   if [ "$snap" = "$common" ]; then
74     foundcommon=true
75     continue
76   fi
77
78   if $foundcommon; then
79     if [ -z "$base" ]; then
80       echo >&2 "Sending '$1/$snap'"
81       zfs send "$1@$snap" > $tmpdir/zfs.part
82       mv $tmpdir/zfs.part $tmpdir/zfs.data
83       zfs recv "$destinationpool/$fsname" < $tmpdir/zfs.data
84       rm -f $tmpdir/zfs.data
85       zfs set readonly=on "$destinationpool"
86       zfs set atime=off "$destinationpool"
87       zfs set sharenfs=off "$destinationpool"
88       zfs set mountpoint=legacy "$destinationpool"
89       zfs unmount "$destinationpool/$fsname"
90       zfs rollback "$destinationpool/$fsname@$snap"
91     else
92       echo >&2 "Sending '$1@$base' -> '$1/$snap'"
93       zfs send -i "$1@$base" "$1@$snap" > $tmpdir/zfs.part
94       mv $tmpdir/zfs.part $tmpdir/zfs.data
95       zfs recv "$destinationpool/$fsname" < $tmpdir/zfs.data
96       rm -f $tmpdir/zfs.data
97       # zfs unmount "$destinationpool/$fsname"
98       # zfs rollback "$destinationpool/$fsname@$snap"
99     fi
100     base=$snap
101   fi
102 done
103
104 true