root/zetaback_agent.in

Revision d5b7a9676dc8d9c9ccc6ff240fb77b72bfbddf1a, 6.7 kB (checked in by Eric Sproul <esproul@omniti.com>, 6 years ago)

Document property-based excludes. Closes #26

  • Property mode set to 100755
Line 
1 #!/usr/bin/perl
2
3 # Copyright (c) 2007 OmniTI Computer Consulting, Inc. All rights reserved.
4 # For information on licensing see:
5 #   https://labs.omniti.com/zetaback/trunk/LICENSE
6
7 use strict;
8 use Getopt::Long;
9 use POSIX qw/mkfifo/;
10 use Data::Dumper;
11
12 use vars qw/%conf $version_string
13             $PREFIX $CONF $LIST $FULL $SNAP $ZFS $BASE $RESTORE $VERSION
14             $BUG_6343779 $NEEDSFD/;
15 $version_string = '0.1';
16 $PREFIX = q^__PREFIX__^;
17 $CONF = qq^$PREFIX/etc/zetaback_agent.conf^;
18 $NEEDSFD = ($^O eq 'darwin') ? 1 : 0;
19
20 =pod
21
22 =head1 NAME
23
24 zetaback_agent - client-side component of zetaback.
25
26 =head1 SYNOPSIS
27
28   zetaback_agent -v
29
30   zetaback_agent -l [-c conf]
31
32   zetaback_agent -r [-b <timestamp>] [-c conf] [-z zfs]
33
34   zetaback -f <timestamp> [-c conf] [-z zfs]
35
36   zetaback -i <timestamp> [-c conf] [-z zfs]
37
38   zetaback -d <snap> -z <zfs> [-c conf]
39
40 =cut
41
42 GetOptions(
43   "c=s" => \$CONF,
44   "l"   => \$LIST,
45   "r"   => \$RESTORE,
46   "z=s" => \$ZFS,
47   "d=s" => \$SNAP,
48   "f=s" => \$FULL,
49   "i=s" => \$BASE,
50   "b=s" => \$BUG_6343779,
51   "v"   => \$VERSION,
52 );
53
54 =pod
55
56 =head1 DESCRIPTION
57
58 B<zetaback_agent> handles requests from zetaback and performs the requested
59 operations on a host.  Normally B<zetaback_agent> is only called by
60 zetaback and should never need to be invoked directly.
61
62 =head1 OPTIONS
63
64 The following options are available:
65
66 =over
67
68 =item -c <conf>
69
70 Use the specified file as the configuration file.  The default file, if
71 none is specified is /etc/zetaback_agent.conf.  The prefix of this file
72 may also be specified in the Makefile.
73
74 =item -d <snap>
75
76 Delete the specified snapshot.  Requires the use of -z to specify the
77 ZFS filesystem.
78
79 =item -f <timestamp>
80
81 Perform a full backup.  The name of the backup will include <timestamp>,
82 which is provided by the backup server.
83
84 =item -i <timestamp>
85
86 Perform an incremental backup.  The name of the backup will include
87 <timestamp>, which is provided by the backup server.
88
89 =item -l
90
91 List ZFS filesystems.
92
93 =item -r
94
95 Perform a restore.
96
97 =item -b
98
99 When performing a restore, if -b is specified, it informs the agent that
100 the receive command is an incremental based of the full snapshot with the
101 timestamp specified.  The agent will unmount and rollback the filesystem
102 prior to applying the incremental in order to work around bug 6343779.
103
104 =item -v
105
106 Print the version number and exit.
107
108 =item -z
109
110 Specify a ZFS filesystem to backup, restore, or delete.
111
112 =cut
113
114 if($VERSION) {
115   print "zetaback_agent: $version_string\n";
116   exit 0;
117 }
118
119 =pod
120
121 =head1 CONFIGURATION
122
123 The zetaback_agent configuration file contains a pattern list of ZFS
124 filesystems to be backed up.  The pattern list is a Perl-compatible
125 regular expression (PCRE).  Only one 'pattern=' line is permitted.
126
127 The pattern acts as a filter to reduce the list of filesystems to
128 be backed up.  Further excludes from this list are possible by setting
129 a user property on any filesystem that should not be backed up, even
130 if it matches the pattern:
131
132   zfs set com.omniti.labs.zetaback:exclude=on <zfs>
133
134 =head1 CONFIGURATION EXAMPLES
135
136 =head2 All ZFS filesystems
137
138 This pattern matches all ZFS filesystems.
139
140   pattern=.
141
142 =head2 Substring match
143
144 This will match anywhere in the name of the ZFS filesystem.  This is
145 helpful for catching all ZFS filesystems in a particular zpool, while
146 excluding any others.
147
148   pattern=zones
149
150 =head2 Left-anchored names
151
152 This pattern matches all ZFS filesystems whose names begin with 'www'.
153
154   pattern=^www
155
156 =head2 Specific ZFS filesystems
157
158 This pattern matches specific ZFS filesystems.
159
160   pattern=(?:data|mirrors|www)
161
162 =head2 Combining with property-based exclude
163
164 All filesystems in pool 'zones' except 'foo'
165
166   pattern=^zones
167  
168   (At a root shell or with pfexec/sudo):
169   zfs set com.omniti.labs.zetaback:exclude=on zones/foo
170
171 =cut
172
173 # Read our config in
174 $conf{pattern} = '.';
175 open(CONF, "<$CONF");
176 while(<CONF>) { /^\s*([^#](?:\S*)?)\s*=\s*(\S+)/ && ($conf{lc($1)} = $2); }
177 close(CONF);
178
179 sub zfs_agent_remove_snap {
180   my $target = $ZFS . '@';
181   die "zfs_agent_remove_snap: insufficient args\n" unless($ZFS && $SNAP);
182   if($SNAP eq '__zb_incr' or
183      $SNAP =~ /__zb_full_\d+/) {
184     $target .= $SNAP;
185   }
186   else {
187     die "zfs_agent_remove_snap: illegal snap: $SNAP\n";
188   }
189   `__ZFS__ destroy $target`;
190 }
191
192 sub zfs_agent_perform_full {
193   my $target = $ZFS . '@__zb_full_' . $FULL;
194   unless($ZFS && $FULL =~ /^\d+$/) {
195     die "zfs_agent_perform_full: bad fs or snap name\n"
196   }
197   `__ZFS__ snapshot $target`;
198   my @cmd = ("__ZFS__", "send", $target);
199   if($NEEDSFD) {
200     fifo_exec(@cmd);
201   } else {
202     exec { $cmd[0] } @cmd;
203   }
204   exit;
205 }
206
207 sub zfs_agent_perform_incremental {
208   my $target = $ZFS . '@__zb_incr';
209   my $base = $ZFS . '@__zb_full_' . $BASE;
210   unless($ZFS && $BASE) {
211     die "zfs_agent_perform_incremental: bad args\n"
212   }
213   `__ZFS__ snapshot $target`;
214   my @cmd = ("__ZFS__", "send", "-i", $base, $target);
215   if($NEEDSFD) {
216     fifo_exec(@cmd);
217   } else {
218     exec { $cmd[0] } @cmd;
219   }
220   exit;
221 }
222
223 sub zfs_agent_list {
224   my %zfs;
225   open(ZFSLIST, "__ZFS__ list -H -t snapshot,filesystem |");
226   while(<ZFSLIST>) {
227     chomp;
228     my @line = split /\t/;
229     (my $fs = $line[0]) =~ s/\@.+//;
230     my $excl = (split(/\s+/,`__ZFS__ get -H com.omniti.labs.zetaback:exclude $fs`))[2];
231     if(($excl ne "on") && ($fs =~ /$conf{pattern}/)) {
232       if($line[0] =~ /(\S+)\@([^\@]+)$/) {
233         $zfs{$1} ||= [];
234         push @{$zfs{$1}}, $2;
235       }
236       else {
237         $zfs{$line[0]} ||= [];
238       }
239     }
240   }
241   close(ZFSLIST);
242
243   foreach my $fs (sort keys %zfs) {
244     print "$fs [".join(',',@{$zfs{$fs}})."]\n";
245   }
246 }
247
248 sub zfs_agent_perform_restore {
249   unless($ZFS && $RESTORE) {
250     die "zfs_agent_perform_restore: bad state\n";
251   }
252   if($BUG_6343779) {
253     # Optionally work around Solaris bug: 6343779
254     my $base = $ZFS . '@__zb_full_' . $BUG_6343779;
255     `__ZFS__ unmount $ZFS`;
256     `__ZFS__ rollback $base`;
257   }
258   my @cmd = ("__ZFS__", "recv", $ZFS);
259   exec { $cmd[0] } @cmd;
260   exit;
261 }
262
263 sub fifo_exec {
264   my @cmd = @_;
265   my $rv = -1;
266   my $fifo = "zetaback_${$}_${FULL}${BASE}.fifo";
267   mkfifo($fifo, 0600) || die "Could not create fifo: $!";
268   my $pid = fork();
269   if($pid == 0) {
270     close(STDOUT);
271     open(STDOUT, ">$fifo") || die "Could not open fifo: $!";
272     exec { $cmd[0] } @cmd;
273     exit;
274   }
275   open(FIFO, "<$fifo");
276   unlink($fifo);
277   my $buf;
278   while(my $len = sysread(FIFO, $buf, 1024*64)) {
279     syswrite(STDOUT, $buf, $len);
280   }
281   waitpid($pid, 0);
282 }
283
284 if($LIST) { zfs_agent_list(); exit; }
285 if($ZFS && $SNAP) { zfs_agent_remove_snap(); exit; }
286 if($ZFS && $RESTORE) { zfs_agent_perform_restore(); exit; }
287 if($ZFS && $FULL) { zfs_agent_perform_full(); exit; }
288 if($ZFS && $BASE) { zfs_agent_perform_incremental(); exit; }
289
290 =pod
291
292 =head1 FILES
293
294 =over
295
296 =item /etc/zetaback_agent.conf
297
298 The zetaback_agent configuration file.  The location of the file can be
299 specified on the command line with the -c flag.
300
301 =back
302
303 =head1 SEE ALSO
304
305 zetaback(1)
306
307 =cut
Note: See TracBrowser for help on using the browser.