root/zetaback_agent.in

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

We don't get just the value back, so we need to extract it. Refs #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 =head1 CONFIGURATION EXAMPLES
128
129 =head2 All ZFS filesystems
130
131 This pattern matches all ZFS filesystems.
132
133   pattern=.
134
135 =head2 Substring match
136
137 This will match anywhere in the name of the ZFS filesystem.  This is
138 helpful for catching all ZFS filesystems in a particular zpool, while
139 excluding any others.
140
141   pattern=zones
142
143 =head2 Left-anchored names
144
145 This pattern matches all ZFS filesystems whose names begin with 'www'.
146
147   pattern=^www
148
149 =head2 Specific ZFS filesystems
150
151 This pattern matches specific ZFS filesystems.
152
153   pattern=(?:data|mirrors|www)
154
155 =cut
156
157 # Read our config in
158 $conf{pattern} = '.';
159 open(CONF, "<$CONF");
160 while(<CONF>) { /^\s*([^#](?:\S*)?)\s*=\s*(\S+)/ && ($conf{lc($1)} = $2); }
161 close(CONF);
162
163 sub zfs_agent_remove_snap {
164   my $target = $ZFS . '@';
165   die "zfs_agent_remove_snap: insufficient args\n" unless($ZFS && $SNAP);
166   if($SNAP eq '__zb_incr' or
167      $SNAP =~ /__zb_full_\d+/) {
168     $target .= $SNAP;
169   }
170   else {
171     die "zfs_agent_remove_snap: illegal snap: $SNAP\n";
172   }
173   `__ZFS__ destroy $target`;
174 }
175
176 sub zfs_agent_perform_full {
177   my $target = $ZFS . '@__zb_full_' . $FULL;
178   unless($ZFS && $FULL =~ /^\d+$/) {
179     die "zfs_agent_perform_full: bad fs or snap name\n"
180   }
181   `__ZFS__ snapshot $target`;
182   my @cmd = ("__ZFS__", "send", $target);
183   if($NEEDSFD) {
184     fifo_exec(@cmd);
185   } else {
186     exec { $cmd[0] } @cmd;
187   }
188   exit;
189 }
190
191 sub zfs_agent_perform_incremental {
192   my $target = $ZFS . '@__zb_incr';
193   my $base = $ZFS . '@__zb_full_' . $BASE;
194   unless($ZFS && $BASE) {
195     die "zfs_agent_perform_incremental: bad args\n"
196   }
197   `__ZFS__ snapshot $target`;
198   my @cmd = ("__ZFS__", "send", "-i", $base, $target);
199   if($NEEDSFD) {
200     fifo_exec(@cmd);
201   } else {
202     exec { $cmd[0] } @cmd;
203   }
204   exit;
205 }
206
207 sub zfs_agent_list {
208   my %zfs;
209   open(ZFSLIST, "__ZFS__ list -H -t snapshot,filesystem |");
210   while(<ZFSLIST>) {
211     chomp;
212     my @line = split /\t/;
213     (my $fs = $line[0]) =~ s/\@.+//;
214     my $excl = (split(/\s+/,`__ZFS__ get -H com.omniti.labs.zetaback:exclude $fs`))[2];
215     if(($excl ne "on") && ($fs =~ /$conf{pattern}/)) {
216       if($line[0] =~ /(\S+)\@([^\@]+)$/) {
217         $zfs{$1} ||= [];
218         push @{$zfs{$1}}, $2;
219       }
220       else {
221         $zfs{$line[0]} ||= [];
222       }
223     }
224   }
225   close(ZFSLIST);
226
227   foreach my $fs (sort keys %zfs) {
228     print "$fs [".join(',',@{$zfs{$fs}})."]\n";
229   }
230 }
231
232 sub zfs_agent_perform_restore {
233   unless($ZFS && $RESTORE) {
234     die "zfs_agent_perform_restore: bad state\n";
235   }
236   if($BUG_6343779) {
237     # Optionally work around Solaris bug: 6343779
238     my $base = $ZFS . '@__zb_full_' . $BUG_6343779;
239     `__ZFS__ unmount $ZFS`;
240     `__ZFS__ rollback $base`;
241   }
242   my @cmd = ("__ZFS__", "recv", $ZFS);
243   exec { $cmd[0] } @cmd;
244   exit;
245 }
246
247 sub fifo_exec {
248   my @cmd = @_;
249   my $rv = -1;
250   my $fifo = "zetaback_${$}_${FULL}${BASE}.fifo";
251   mkfifo($fifo, 0600) || die "Could not create fifo: $!";
252   my $pid = fork();
253   if($pid == 0) {
254     close(STDOUT);
255     open(STDOUT, ">$fifo") || die "Could not open fifo: $!";
256     exec { $cmd[0] } @cmd;
257     exit;
258   }
259   open(FIFO, "<$fifo");
260   unlink($fifo);
261   my $buf;
262   while(my $len = sysread(FIFO, $buf, 1024*64)) {
263     syswrite(STDOUT, $buf, $len);
264   }
265   waitpid($pid, 0);
266 }
267
268 if($LIST) { zfs_agent_list(); exit; }
269 if($ZFS && $SNAP) { zfs_agent_remove_snap(); exit; }
270 if($ZFS && $RESTORE) { zfs_agent_perform_restore(); exit; }
271 if($ZFS && $FULL) { zfs_agent_perform_full(); exit; }
272 if($ZFS && $BASE) { zfs_agent_perform_incremental(); exit; }
273
274 =pod
275
276 =head1 FILES
277
278 =over
279
280 =item /etc/zetaback_agent.conf
281
282 The zetaback_agent configuration file.  The location of the file can be
283 specified on the command line with the -c flag.
284
285 =back
286
287 =head1 SEE ALSO
288
289 zetaback(1)
290
291 =cut
Note: See TracBrowser for help on using the browser.