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 Data::Dumper; |
---|
10 |
|
---|
11 |
use vars qw/%conf $version_string |
---|
12 |
$PREFIX $CONF $LIST $FULL $SNAP $ZFS $BASE $RESTORE $VERSION |
---|
13 |
$BUG_6343779/; |
---|
14 |
$version_string = '0.1'; |
---|
15 |
$PREFIX = q^__PREFIX__^; |
---|
16 |
$CONF = qq^$PREFIX/etc/zetaback_agent.conf^; |
---|
17 |
|
---|
18 |
=pod |
---|
19 |
|
---|
20 |
=head1 NAME |
---|
21 |
|
---|
22 |
zetaback_agent - client-side component of zetaback. |
---|
23 |
|
---|
24 |
=head1 SYNOPSIS |
---|
25 |
|
---|
26 |
zetaback_agent -v |
---|
27 |
|
---|
28 |
zetaback_agent -l [-c conf] |
---|
29 |
|
---|
30 |
zetaback_agent -r [-b <timestamp>] [-c conf] [-z zfs] |
---|
31 |
|
---|
32 |
zetaback -f <timestamp> [-c conf] [-z zfs] |
---|
33 |
|
---|
34 |
zetaback -i <timestamp> [-c conf] [-z zfs] |
---|
35 |
|
---|
36 |
zetaback -d <snap> -z <zfs> [-c conf] |
---|
37 |
|
---|
38 |
=cut |
---|
39 |
|
---|
40 |
GetOptions( |
---|
41 |
"c=s" => \$CONF, |
---|
42 |
"l" => \$LIST, |
---|
43 |
"r" => \$RESTORE, |
---|
44 |
"z=s" => \$ZFS, |
---|
45 |
"d=s" => \$SNAP, |
---|
46 |
"f=s" => \$FULL, |
---|
47 |
"i=s" => \$BASE, |
---|
48 |
"b=s" => \$BUG_6343779, |
---|
49 |
"v" => \$VERSION, |
---|
50 |
); |
---|
51 |
|
---|
52 |
=pod |
---|
53 |
|
---|
54 |
=head1 DESCRIPTION |
---|
55 |
|
---|
56 |
B<zetaback_agent> handles requests from zetaback and performs the requested |
---|
57 |
operations on a host. Normally B<zetaback_agent> is only called by |
---|
58 |
zetaback and should never need to be invoked directly. |
---|
59 |
|
---|
60 |
=head1 OPTIONS |
---|
61 |
|
---|
62 |
The following options are available: |
---|
63 |
|
---|
64 |
=over |
---|
65 |
|
---|
66 |
=item -c <conf> |
---|
67 |
|
---|
68 |
Use the specified file as the configuration file. The default file, if |
---|
69 |
none is specified is /etc/zetaback_agent.conf. The prefix of this file |
---|
70 |
may also be specified in the Makefile. |
---|
71 |
|
---|
72 |
=item -d <snap> |
---|
73 |
|
---|
74 |
Delete the specified snapshot. Requires the use of -z to specify the |
---|
75 |
ZFS filesystem. |
---|
76 |
|
---|
77 |
=item -f <timestamp> |
---|
78 |
|
---|
79 |
Perform a full backup. The name of the backup will include <timestamp>, |
---|
80 |
which is provided by the backup server. |
---|
81 |
|
---|
82 |
=item -i <timestamp> |
---|
83 |
|
---|
84 |
Perform an incremental backup. The name of the backup will include |
---|
85 |
<timestamp>, which is provided by the backup server. |
---|
86 |
|
---|
87 |
=item -l |
---|
88 |
|
---|
89 |
List ZFS filesystems. |
---|
90 |
|
---|
91 |
=item -r |
---|
92 |
|
---|
93 |
Perform a restore. |
---|
94 |
|
---|
95 |
=item -b |
---|
96 |
|
---|
97 |
When performing a restore, if -b is specified, it informs the agent that |
---|
98 |
the receive command is an incremental based of the full snapshot with the |
---|
99 |
timestamp specified. The agent will unmount and rollback the filesystem |
---|
100 |
prior to applying the incremental in order to work around bug 6343779. |
---|
101 |
|
---|
102 |
=item -v |
---|
103 |
|
---|
104 |
Print the version number and exit. |
---|
105 |
|
---|
106 |
=item -z |
---|
107 |
|
---|
108 |
Specify a ZFS filesystem to backup, restore, or delete. |
---|
109 |
|
---|
110 |
=cut |
---|
111 |
|
---|
112 |
if($VERSION) { |
---|
113 |
print "zetaback_agent: $version_string\n"; |
---|
114 |
exit 0; |
---|
115 |
} |
---|
116 |
|
---|
117 |
=pod |
---|
118 |
|
---|
119 |
=head1 CONFIGURATION |
---|
120 |
|
---|
121 |
The zetaback_agent configuration file contains a pattern list of ZFS |
---|
122 |
filesystems to be backed up. The pattern list is a Perl-compatible |
---|
123 |
regular expression (PCRE). Only one 'pattern=' line is permitted. |
---|
124 |
|
---|
125 |
=head1 CONFIGURATION EXAMPLES |
---|
126 |
|
---|
127 |
=head2 All ZFS filesystems |
---|
128 |
|
---|
129 |
This pattern matches all ZFS filesystems. |
---|
130 |
|
---|
131 |
pattern=. |
---|
132 |
|
---|
133 |
=head2 Substring match |
---|
134 |
|
---|
135 |
This will match anywhere in the name of the ZFS filesystem. This is |
---|
136 |
helpful for catching all ZFS filesystems in a particular zpool, while |
---|
137 |
excluding any others. |
---|
138 |
|
---|
139 |
pattern=zones |
---|
140 |
|
---|
141 |
=head2 Left-anchored names |
---|
142 |
|
---|
143 |
This pattern matches all ZFS filesystems whose names begin with 'www'. |
---|
144 |
|
---|
145 |
pattern=^www |
---|
146 |
|
---|
147 |
=head2 Specific ZFS filesystems |
---|
148 |
|
---|
149 |
This pattern matches specific ZFS filesystems. |
---|
150 |
|
---|
151 |
pattern=(?:data|mirrors|www) |
---|
152 |
|
---|
153 |
=cut |
---|
154 |
|
---|
155 |
# Read our config in |
---|
156 |
$conf{pattern} = '.'; |
---|
157 |
open(CONF, "<$CONF"); |
---|
158 |
while(<CONF>) { /^\s*([^#](?:\S*)?)\s*=\s*(\S+)/ && ($conf{lc($1)} = $2); } |
---|
159 |
close(CONF); |
---|
160 |
|
---|
161 |
sub zfs_agent_remove_snap { |
---|
162 |
my $target = $ZFS . '@'; |
---|
163 |
die "zfs_agent_remove_snap: insufficient args\n" unless($ZFS && $SNAP); |
---|
164 |
if($SNAP eq '__zb_incr' or |
---|
165 |
$SNAP =~ /__zb_full_\d+/) { |
---|
166 |
$target .= $SNAP; |
---|
167 |
} |
---|
168 |
else { |
---|
169 |
die "zfs_agent_remove_snap: illegal snap: $SNAP\n"; |
---|
170 |
} |
---|
171 |
`/usr/sbin/zfs destroy $target`; |
---|
172 |
} |
---|
173 |
|
---|
174 |
sub zfs_agent_perform_full { |
---|
175 |
my $target = $ZFS . '@__zb_full_' . $FULL; |
---|
176 |
unless($ZFS && $FULL =~ /^\d+$/) { |
---|
177 |
die "zfs_agent_perform_full: bad fs or snap name\n" |
---|
178 |
} |
---|
179 |
`/usr/sbin/zfs snapshot $target`; |
---|
180 |
my @cmd = ("/usr/sbin/zfs", "send", $target); |
---|
181 |
exec { $cmd[0] } @cmd; |
---|
182 |
exit; |
---|
183 |
} |
---|
184 |
|
---|
185 |
sub zfs_agent_perform_incremental { |
---|
186 |
my $target = $ZFS . '@__zb_incr'; |
---|
187 |
my $base = $ZFS . '@__zb_full_' . $BASE; |
---|
188 |
unless($ZFS && $BASE) { |
---|
189 |
die "zfs_agent_perform_incremental: bad args\n" |
---|
190 |
} |
---|
191 |
`/usr/sbin/zfs snapshot $target`; |
---|
192 |
my @cmd = ("/usr/sbin/zfs", "send", "-i", $base, $target); |
---|
193 |
exec { $cmd[0] } @cmd; |
---|
194 |
exit; |
---|
195 |
} |
---|
196 |
|
---|
197 |
sub zfs_agent_list { |
---|
198 |
my %zfs; |
---|
199 |
open(ZFSLIST, "/usr/sbin/zfs list -H |"); |
---|
200 |
while(<ZFSLIST>) { |
---|
201 |
chomp; |
---|
202 |
my @line = split /\t/; |
---|
203 |
(my $fs = $line[0]) =~ s/\@.+//; |
---|
204 |
if($fs =~ /$conf{pattern}/) { |
---|
205 |
if($line[0] =~ /(\S+)\@([^\@]+)$/) { |
---|
206 |
$zfs{$1} ||= []; |
---|
207 |
push @{$zfs{$1}}, $2; |
---|
208 |
} |
---|
209 |
else { |
---|
210 |
$zfs{$line[0]} ||= []; |
---|
211 |
} |
---|
212 |
} |
---|
213 |
} |
---|
214 |
close(ZFSLIST); |
---|
215 |
|
---|
216 |
foreach my $fs (sort keys %zfs) { |
---|
217 |
print "$fs [".join(',',@{$zfs{$fs}})."]\n"; |
---|
218 |
} |
---|
219 |
} |
---|
220 |
|
---|
221 |
sub zfs_agent_perform_restore { |
---|
222 |
unless($ZFS && $RESTORE) { |
---|
223 |
die "zfs_agent_perform_restore: bad state\n"; |
---|
224 |
} |
---|
225 |
if($BUG_6343779) { |
---|
226 |
# Optionally work around Solaris bug: 6343779 |
---|
227 |
my $base = $ZFS . '@__zb_full_' . $BUG_6343779; |
---|
228 |
`/usr/sbin/zfs unmount $ZFS`; |
---|
229 |
`/usr/sbin/zfs rollback $base`; |
---|
230 |
} |
---|
231 |
my @cmd = ("/usr/sbin/zfs", "recv", $ZFS); |
---|
232 |
exec { $cmd[0] } @cmd; |
---|
233 |
exit; |
---|
234 |
} |
---|
235 |
|
---|
236 |
if($LIST) { zfs_agent_list(); exit; } |
---|
237 |
if($ZFS && $SNAP) { zfs_agent_remove_snap(); exit; } |
---|
238 |
if($ZFS && $RESTORE) { zfs_agent_perform_restore(); exit; } |
---|
239 |
if($ZFS && $FULL) { zfs_agent_perform_full(); exit; } |
---|
240 |
if($ZFS && $BASE) { zfs_agent_perform_incremental(); exit; } |
---|
241 |
|
---|
242 |
=pod |
---|
243 |
|
---|
244 |
=head1 FILES |
---|
245 |
|
---|
246 |
=over |
---|
247 |
|
---|
248 |
=item /etc/zetaback_agent.conf |
---|
249 |
|
---|
250 |
The zetaback_agent configuration file. The location of the file can be |
---|
251 |
specified on the command line with the -c flag. |
---|
252 |
|
---|
253 |
=back |
---|
254 |
|
---|
255 |
=head1 SEE ALSO |
---|
256 |
|
---|
257 |
zetaback(1) |
---|
258 |
|
---|
259 |
=cut |
---|