root/zetaback_agent.in

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

Make the default config file location clearer

  • 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 /usr/local/etc/zetaback_agent.conf.  The prefix of this
72 file may also be specified as an argument to the configure script.
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 =back
113
114 =cut
115
116 if($VERSION) {
117   print "zetaback_agent: $version_string\n";
118   exit 0;
119 }
120
121 =pod
122
123 =head1 CONFIGURATION
124
125 The zetaback_agent configuration file contains a pattern list of ZFS
126 filesystems to be backed up.  The pattern list is a Perl-compatible
127 regular expression (PCRE).  Only one 'pattern=' line is permitted.
128
129 The pattern acts as a filter to reduce the list of filesystems to
130 be backed up.  Further excludes from this list are possible by setting
131 a user property on any filesystem that should not be backed up, even
132 if it matches the pattern:
133
134   zfs set com.omniti.labs.zetaback:exclude=on pool/fs
135
136 User properties are available on Solaris 10 8/07 and newer, and on
137 Solaris Express build 48 and newer.
138
139 Once a pattern and/or exclude properties have been configured on a host,
140 the list of remaining filesystems can be validated by invoking
141 zetaback_agent with the -l option.
142
143 =head1 CONFIGURATION EXAMPLES
144
145 =head2 All ZFS filesystems
146
147 This pattern matches all ZFS filesystems.
148
149   pattern=.
150
151 =head2 Substring match
152
153 This will match anywhere in the name of the ZFS filesystem.  This is
154 helpful for catching all ZFS filesystems in a particular zpool, while
155 excluding any others.
156
157   pattern=zones
158
159 =head2 Left-anchored names
160
161 This pattern matches all ZFS filesystems whose names begin with 'www'.
162
163   pattern=^www
164
165 =head2 Specific ZFS filesystems
166
167 This pattern matches specific ZFS filesystems.
168
169   pattern=(?:data|mirrors|www)
170
171 =head2 Combining with property-based exclude
172
173 All filesystems in pool 'zones' except 'foo'
174
175   pattern=^zones
176
177   (At a root shell or with pfexec/sudo):
178   zfs set com.omniti.labs.zetaback:exclude=on zones/foo
179
180 =cut
181
182 # Read our config in
183 $conf{pattern} = '.';
184 open(CONF, "<$CONF");
185 while(<CONF>) { /^\s*([^#](?:\S*)?)\s*=\s*(\S+)/ && ($conf{lc($1)} = $2); }
186 close(CONF);
187
188 sub zfs_agent_remove_snap {
189   my $target = $ZFS . '@';
190   die "zfs_agent_remove_snap: insufficient args\n" unless($ZFS && $SNAP);
191   if($SNAP eq '__zb_incr' or
192      $SNAP =~ /__zb_full_\d+/) {
193     $target .= $SNAP;
194   }
195   else {
196     die "zfs_agent_remove_snap: illegal snap: $SNAP\n";
197   }
198   `__ZFS__ destroy $target`;
199 }
200
201 sub zfs_agent_perform_full {
202   my $target = $ZFS . '@__zb_full_' . $FULL;
203   unless($ZFS && $FULL =~ /^\d+$/) {
204     die "zfs_agent_perform_full: bad fs or snap name\n"
205   }
206   `__ZFS__ snapshot $target`;
207   my @cmd = ("__ZFS__", "send", $target);
208   if($NEEDSFD) {
209     fifo_exec(@cmd);
210   } else {
211     exec { $cmd[0] } @cmd;
212   }
213   exit;
214 }
215
216 sub zfs_agent_perform_incremental {
217   my $target = $ZFS . '@__zb_incr';
218   my $base = $ZFS . '@__zb_full_' . $BASE;
219   unless($ZFS && $BASE) {
220     die "zfs_agent_perform_incremental: bad args\n"
221   }
222   `__ZFS__ snapshot $target`;
223   my @cmd = ("__ZFS__", "send", "-i", $base, $target);
224   if($NEEDSFD) {
225     fifo_exec(@cmd);
226   } else {
227     exec { $cmd[0] } @cmd;
228   }
229   exit;
230 }
231
232 sub zfs_agent_list {
233   my %zfs;
234   open(ZFSLIST, "__ZFS__ list -H -t snapshot,filesystem |");
235   while(<ZFSLIST>) {
236     chomp;
237     my @line = split /\t/;
238     (my $fs = $line[0]) =~ s/\@.+//;
239     my $excl = (split(/\s+/,`__ZFS__ get -H com.omniti.labs.zetaback:exclude $fs`))[2];
240     if(($excl ne "on") && ($fs =~ /$conf{pattern}/)) {
241       if($line[0] =~ /(\S+)\@([^\@]+)$/) {
242         $zfs{$1} ||= [];
243         push @{$zfs{$1}}, $2;
244       }
245       else {
246         $zfs{$line[0]} ||= [];
247       }
248     }
249   }
250   close(ZFSLIST);
251
252   foreach my $fs (sort keys %zfs) {
253     print "$fs [".join(',',@{$zfs{$fs}})."]\n";
254   }
255 }
256
257 sub zfs_agent_perform_restore {
258   unless($ZFS && $RESTORE) {
259     die "zfs_agent_perform_restore: bad state\n";
260   }
261   if($BUG_6343779) {
262     # Optionally work around Solaris bug: 6343779
263     my $base = $ZFS . '@__zb_full_' . $BUG_6343779;
264     `__ZFS__ unmount $ZFS`;
265     `__ZFS__ rollback $base`;
266   }
267   my @cmd = ("__ZFS__", "recv", $ZFS);
268   exec { $cmd[0] } @cmd;
269   exit;
270 }
271
272 sub fifo_exec {
273   my @cmd = @_;
274   my $rv = -1;
275   my $fifo = "zetaback_${$}_${FULL}${BASE}.fifo";
276   mkfifo($fifo, 0600) || die "Could not create fifo: $!";
277   my $pid = fork();
278   if($pid == 0) {
279     close(STDOUT);
280     open(STDOUT, ">$fifo") || die "Could not open fifo: $!";
281     exec { $cmd[0] } @cmd;
282     exit;
283   }
284   open(FIFO, "<$fifo");
285   unlink($fifo);
286   my $buf;
287   while(my $len = sysread(FIFO, $buf, 1024*64)) {
288     syswrite(STDOUT, $buf, $len);
289   }
290   waitpid($pid, 0);
291 }
292
293 if($LIST) { zfs_agent_list(); exit; }
294 if($ZFS && $SNAP) { zfs_agent_remove_snap(); exit; }
295 if($ZFS && $RESTORE) { zfs_agent_perform_restore(); exit; }
296 if($ZFS && $FULL) { zfs_agent_perform_full(); exit; }
297 if($ZFS && $BASE) { zfs_agent_perform_incremental(); exit; }
298
299 =pod
300
301 =head1 FILES
302
303 =over
304
305 =item /usr/local/etc/zetaback_agent.conf
306
307 The zetaback_agent configuration file.  The location of the file can be
308 specified on the command line with the -c flag.  The prefix of this
309 file may also be specified as an argument to the configure script.
310
311 =back
312
313 =head1 SEE ALSO
314
315 zetaback(1)
316
317 =cut
Note: See TracBrowser for help on using the browser.