Skip to content

Commit 6bb45fa

Browse files
committed
Implement snapshot replication.
1 parent d5cb31a commit 6bb45fa

File tree

2 files changed

+120
-4
lines changed

2 files changed

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

207290
# main ()
208291
# {
@@ -212,6 +295,7 @@ GETOPT=$(getopt \
212295
--longoptions=event:,keep:,label:,prefix:,sep: \
213296
--longoptions=debug,help,quiet,syslog,verbose \
214297
--longoptions=pre-snapshot:,post-snapshot:,destroy-only \
298+
--longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
215299
--options=dnshe:l:k:p:rs:qgv \
216300
-- "$@" ) \
217301
|| exit 128
@@ -296,6 +380,30 @@ do
296380
opt_recursive='1'
297381
shift 1
298382
;;
383+
(--send-full)
384+
opt_send_type='full'
385+
386+
opt_send_host=$(echo "$2" | sed 's,:.*,,')
387+
opt_recv_pool=$(echo "$2" | sed 's,.*:,,')
388+
389+
opt_send_opts="$opt_send_opts -R"
390+
shift 2
391+
;;
392+
(--send-incr)
393+
opt_send_type='incr'
394+
395+
opt_send_host=$(echo "$2" | sed 's,:.*,,')
396+
opt_recv_pool=$(echo "$2" | sed 's,.*:,,')
397+
shift 2
398+
;;
399+
(--send-opts)
400+
opt_send_opts="$2"
401+
shift 2
402+
;;
403+
(--recv-opts)
404+
opt_recv_opts="$2"
405+
shift 2
406+
;;
299407
(--sep)
300408
case "$2" in
301409
([[:alnum:]_.:\ -])
@@ -567,6 +675,8 @@ test -n "$opt_dry_run" \
567675
do_snapshots "$SNAPPROP" "" "$SNAPNAME" "$SNAPGLOB" "$TARGETS_REGULAR"
568676
do_snapshots "$SNAPPROP" "-r" "$SNAPNAME" "$SNAPGLOB" "$TARGETS_RECURSIVE"
569677

678+
do_send "$SNAPNAME" "$SNAPGLOB"
679+
570680
print_log notice "@$SNAPNAME," \
571681
"$SNAPSHOT_COUNT created," \
572682
"$DESTRUCTION_COUNT destroyed," \

0 commit comments

Comments
 (0)