Skip to content

Commit 26d9dd6

Browse files
committed
Implement snapshot replication.
1 parent d5cb31a commit 26d9dd6

File tree

2 files changed

+121
-4
lines changed

2 files changed

+121
-4
lines changed

src/zfs-auto-snapshot.8

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,17 @@ PRE is 'zfs\-auto\-snap' by default.
4646
\fB\-q\fR, \fB\-\-quiet\fR
4747
Suppress warnings and notices at the console.
4848
.TP
49-
\fB\-\-send\-full\fR=\fIF\fR
50-
Send zfs full backup. Unimplemented.
49+
\fB\-\-send\-full\fR=[\fIremote host\fR]:[\fIremote pool\fR]
50+
Send zfs full backup to remote hostname (or IP address) and put it in remote pool.
5151
.TP
52-
\fB\-\-send\-incr\fR=\fIF\fR
53-
Send zfs incremental backup. Unimplemented.
52+
\fB\-\-send\-incr\fR=[\fIremote host\fR]:[\fIremote pool\fR]
53+
Send zfs incremental backup to remote hostname (or IP address) and put it in remote pool.
54+
.TP
55+
\fB\-\-send\-opts\fR=\fIOPTS\fR
56+
Option(s) passed to 'zfs send'.
57+
.TP
58+
\fB\-\-recv\-opts\fR=\fIOPTS\fR
59+
Option(s) passed to 'zfs receive'.
5460
.TP
5561
\fB\-\-sep\fR=\fICHAR\fR
5662
Use CHAR to separate date stamps in snapshot names.

src/zfs-auto-snapshot.sh

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ opt_keep=''
3434
opt_label=''
3535
opt_prefix='zfs-auto-snap'
3636
opt_recursive=''
37+
opt_send_type=''
38+
opt_send_host=''
39+
opt_recv_pool=''
40+
opt_send_opts=''
41+
opt_recv_opts=''
3742
opt_sep='_'
3843
opt_setauto=''
3944
opt_syslog=''
@@ -68,6 +73,8 @@ print_usage ()
6873
-q, --quiet Suppress warnings and notices at the console.
6974
--send-full=F Send zfs full backup. Unimplemented.
7075
--send-incr=F Send zfs incremental backup. Unimplemented.
76+
--send-opts=F Option(s) passed to 'zfs send'.
77+
--recv-opts=F Option(s) passed to 'zfs receive'.
7178
--sep=CHAR Use CHAR to separate date stamps in snapshot names.
7279
-g, --syslog Write messages into the system log.
7380
-r, --recursive Snapshot named filesystem and all descendants.
@@ -159,6 +166,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
159166
# global WARNING_COUNT
160167
# global SNAPSHOTS_OLD
161168

169+
SNAPS_DONE=''
170+
162171
for ii in $TARGETS
163172
do
164173
if [ -n "$opt_do_snapshots" ]
@@ -170,6 +179,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
170179
if [ $RUNSNAP -eq 1 ] && do_run "zfs snapshot $PROPS $FLAGS '$ii@$NAME'"
171180
then
172181
[ "$opt_post_snapshot" != "" ] && do_run "$opt_post_snapshot $ii $NAME"
182+
[ -n "$opt_send_host" ] && SNAPS_DONE="$SNAPS_DONE
183+
$ii@$NAME"
173184
SNAPSHOT_COUNT=$(( $SNAPSHOT_COUNT + 1 ))
174185
else
175186
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
@@ -203,6 +214,79 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
203214
done
204215
}
205216

217+
do_send () # snapname, oldglob
218+
{
219+
local NAME="$1"
220+
local GLOB="$2"
221+
local remote="ssh $opt_send_host zfs receive $opt_recv_opts $opt_recv_pool"
222+
local ii
223+
local jj
224+
225+
# STEP 1: Go throug all snapshots we've created
226+
for ii in $SNAPS_DONE
227+
do
228+
opts=''
229+
SNAPS_SEND=''
230+
231+
dset=${ii%@*}
232+
233+
# STEP 2: Go through ALL snapshots that exist, look for exact
234+
# match on dataset/volume (with snapshot matching 'GLOB').
235+
for jj in $SNAPSHOTS_OLD
236+
do
237+
# Check whether this is an old snapshot of the filesystem.
238+
if [ -z "${jj#$dset@$GLOB}" ]; then
239+
# We want the FIRST one (which is the last in time
240+
# before the one we just created in do_snapshot()).
241+
# Also, here we just need the snapshot name.
242+
last_snap="${jj#*@}"
243+
break
244+
fi
245+
done
246+
247+
# NOTE: If we don't have any previous snapshots (for example, we've
248+
# just created the first one) we can end up with last_snap=''
249+
# here.
250+
# If we're called with '--send-incr' we have to options:
251+
# 1: We change from incremental to full.
252+
# 2: We accept that the user have said INCR, and stick with
253+
# it.
254+
if [ "$opt_send_type" = "incr" -a -z "$last_snap" ]; then
255+
if [ -n "$opt_verbose" ]; then
256+
echo "WARNING: No previous snapshots exist but we where called"
257+
echo " with --send-incr. Can not continue."
258+
echo " Please rerun with --send-full."
259+
fi
260+
return 1
261+
fi
262+
263+
if [ -n "$opt_recursive" -a -n "$last_snap" ]; then
264+
# STEP 3: Again, go through ALL snapshots that exists, but this
265+
# time only look for the snapshots that 'starts with'
266+
# the dataset/volume in question AND 'ends with'
267+
# the exact snapshot name/date in step 2.
268+
for jj in $SNAPSHOTS_OLD
269+
do
270+
if echo "$jj" | grep -qE "^$dset.*@$last_snap"; then
271+
SNAPS_SEND="$SNAPS_SEND
272+
$jj"
273+
fi
274+
done
275+
else
276+
SNAPS_SEND="$ii"
277+
fi
278+
279+
# STEP 4: Go through all snapshots that is to be transfered and send them.
280+
for jj in $SNAPS_SEND
281+
do
282+
if [ "$opt_send_type" = "incr" ]; then
283+
do_run "zfs send $opt_send_opts -i $jj $ii | $remote"
284+
else
285+
do_run "zfs send $opt_send_opts -R $jj | $remote"
286+
fi
287+
done
288+
done
289+
}
206290

207291
# main ()
208292
# {
@@ -212,6 +296,7 @@ GETOPT=$(getopt \
212296
--longoptions=event:,keep:,label:,prefix:,sep: \
213297
--longoptions=debug,help,quiet,syslog,verbose \
214298
--longoptions=pre-snapshot:,post-snapshot:,destroy-only \
299+
--longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
215300
--options=dnshe:l:k:p:rs:qgv \
216301
-- "$@" ) \
217302
|| exit 128
@@ -296,6 +381,30 @@ do
296381
opt_recursive='1'
297382
shift 1
298383
;;
384+
(--send-full)
385+
opt_send_type='full'
386+
387+
opt_send_host=$(echo "$2" | sed 's,:.*,,')
388+
opt_recv_pool=$(echo "$2" | sed 's,.*:,,')
389+
390+
opt_send_opts="$opt_send_opts -R"
391+
shift 2
392+
;;
393+
(--send-incr)
394+
opt_send_type='incr'
395+
396+
opt_send_host=$(echo "$2" | sed 's,:.*,,')
397+
opt_recv_pool=$(echo "$2" | sed 's,.*:,,')
398+
shift 2
399+
;;
400+
(--send-opts)
401+
opt_send_opts="$2"
402+
shift 2
403+
;;
404+
(--recv-opts)
405+
opt_recv_opts="$2"
406+
shift 2
407+
;;
299408
(--sep)
300409
case "$2" in
301410
([[:alnum:]_.:\ -])
@@ -567,6 +676,8 @@ test -n "$opt_dry_run" \
567676
do_snapshots "$SNAPPROP" "" "$SNAPNAME" "$SNAPGLOB" "$TARGETS_REGULAR"
568677
do_snapshots "$SNAPPROP" "-r" "$SNAPNAME" "$SNAPGLOB" "$TARGETS_RECURSIVE"
569678

679+
do_send "$SNAPNAME" "$SNAPGLOB"
680+
570681
print_log notice "@$SNAPNAME," \
571682
"$SNAPSHOT_COUNT created," \
572683
"$DESTRUCTION_COUNT destroyed," \

0 commit comments

Comments
 (0)