File: zfs_script

package info (click to toggle)
burp 3.1.4-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,684 kB
  • sloc: ansic: 50,989; sh: 3,612; cpp: 2,859; makefile: 868
file content (148 lines) | stat: -rwxr-xr-x 4,117 bytes parent folder | download | duplicates (7)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env bash
#
# ZFS backup script.
#
# Creates temporary ZFS snapshots, and 'zfs sends' them (or differences
# between them and previous snapshots) down fifo nodes in
# /etc/burp/fifos.
#
# On success, the ZFS script renames the temporary snapshot
# to a more permanent name so that the snapshots can be tracked consistently.
#
# To use, put something like this in your burp.conf.
# You can add multiple pools.
#
# backup_script=/etc/burp/zfs_script
# backup_script_arg=7
# backup_script_arg=rpool/export/home@burp
# backup_script_arg=rpool/ROOT/s10x_u9wos_14a/var@burp
# backup_script_post_run_on_fail=1
#
# A snapshot numbered between 1 to $MAX_SNAPS is created on a backup. The
# number is incremented for each backup. Number 1 is always a full ZFS snapshot.
# The rest are incrementals based on the previous number. After $MAX_SNAPS,
# the sequence starts from 1 again.
#
# You will want to configure the burp server to keep enough backups so that
# a ZFS 'full' snapshot is always available. For example, if you set $MAX_SNAPS
# to 7, you will want to keep at least 14 backups on the server to guarantee
# that you can always restore at least 7 backups into the past.
#
# To do a restore, you will need to do this (for example), starting from number
# 1:
# mkfifo /etc/burp/fifos/rpool/export/home@burp<number>
# cat /etc/burp/fifos/rpool/export/home@burp<number> | zfs recv <zfs recv args>
#
# Then repeat, each time incrementing the number until you reach the backup
# that you want to end up on.

if [ $# -lt 7 ] ; then
	echo "$0: not enough arguments" 1>&2
	exit 1
fi

MODE="$1" ; shift
FAILED="$1" ; shift; shift; shift; shift
MAX_SNAPS="$1" ; shift

if [ "$MODE" = "pre" ] ; then
	declare -a arr=($@)

	# Set up the fifo directory 
	PIPE_DIR=/etc/burp/fifos
	rm -rf "$PIPE_DIR" || exit 1
	mkdir -p "$PIPE_DIR" || exit 1

	# Create all the snapshots that we will need.
	a=0
	while [ $a -lt $# ] ; do
		SNAPSHOT="${arr[$a]}"
		SNAPSHOT_TMP="$SNAPSHOT"tmp

		# Find out how many snapshots already exist.
		inc=1
		while [ "$inc" -le $MAX_SNAPS ] ; do
		  /usr/sbin/zfs list "$SNAPSHOT$inc" >/dev/null 2>&1 || break
		  inc=$((inc+1))
		done

		if [ "$inc" -gt $MAX_SNAPS ] ; then
		  # Had enough snapshots now. Start from 1 again.
		  inc=1
		fi

		# Destroy all the unneeded snapshots
		i=$inc
		while [ "$i" -le $MAX_SNAPS ] ; do
		  /usr/sbin/zfs destroy "$SNAPSHOT$i" >/dev/null 2>&1
		  /usr/sbin/zfs destroy "$SNAPSHOT_TMP$i" >/dev/null 2>&1
		  i=$((i+1))
		done

		# Create the new snapshot.
		/usr/sbin/zfs snapshot -r "$SNAPSHOT_TMP$inc" || exit 1

		# Create a pipe.
		ZFS_PIPE=$PIPE_DIR/$SNAPSHOT$inc
		mkdir -p "${ZFS_PIPE%/*}"
		mkfifo "$ZFS_PIPE" || exit 1
		chmod 777 "$ZFS_PIPE" || exit 1

		a=$((a+1))
	done

	# Need to exec here, otherwise burp will wait forever for this script to
	# return.
	exec > /dev/null 2>&1

	# Now, go through the list and do zfs sends for all the new snapshots.
	a=0
	while [ $a -lt $# ] ; do
		SNAPSHOT="${arr[$a]}"
		SNAPSHOT_TMP="${arr[$a]}tmp"

		# Figure out the most recent snapshot again.
		inc=1
		while [ "$inc" -le $MAX_SNAPS ] ; do
		  /usr/sbin/zfs list "$SNAPSHOT$inc" >/dev/null 2>&1 || break
		  inc=$((inc+1))
		done

		ZFS_PIPE=$PIPE_DIR/$SNAPSHOT$inc

		if [ "$inc" = 1 ] ; then
		  # First in the chain. Just do the full zfs send.
		  /usr/sbin/zfs send "$SNAPSHOT_TMP$inc" > "$ZFS_PIPE" &
		else
		  # Not the first in the chain. Do an incremental zfs send.
		  /usr/sbin/zfs send -i "$SNAPSHOT$((inc-1))" "$SNAPSHOT_TMP$inc" > "$ZFS_PIPE" &
		fi

		a=$((a+1))
	done

	exit 0
elif [ "$MODE" = "post" ] ; then
 	while [ "$#" -gt 0 ] ; do
	  SNAPSHOT=$1 ; shift
	  SNAPSHOT_TMP="$SNAPSHOT"tmp
	  i=1
	  if [ "$FAILED" = "1" ] ; then
	    while [ "$i" -le $MAX_SNAPS ] ; do
	      /usr/sbin/zfs destroy "$SNAPSHOT_TMP$i" >/dev/null 2>&1 
	      i=$((i+1))
	    done
	  else
	    while [ "$i" -le $MAX_SNAPS ] ; do
	      /usr/sbin/zfs list "$SNAPSHOT_TMP$i" >/dev/null 2>&1 && \
			/usr/sbin/zfs rename "$SNAPSHOT_TMP$i" "$SNAPSHOT$i"
	      i=$((i+1))
	    done
	  fi
	done

	exit 0
else
	echo "$0: unknown mode: $MODE" 1>&2
	exit 1
fi