Imported Upstream version 3.3.3
[debian/amanda] / installcheck / Amanda_Recovery_Planner.pl
1 # Copyright (c) 2010-2012 Zmanda Inc.  All Rights Reserved.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 # for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19
20 use Test::More tests => 11;
21 use File::Path;
22 use Data::Dumper;
23 use strict;
24 use warnings;
25
26 use lib "@amperldir@";
27 use Installcheck::Run;
28 use Installcheck::Catalogs;
29 use Amanda::Config qw( :init :getconf config_dir_relative );
30 use Amanda::Changer;
31 use Amanda::Debug;
32 use Amanda::DB::Catalog;
33 use Amanda::Recovery::Planner;
34 use Amanda::MainLoop;
35 use Amanda::Header;
36 use Amanda::Xfer qw( :constants );
37
38 # disable Debug's die() and warn() overrides
39 Amanda::Debug::disable_die_override();
40
41 # put the debug messages somewhere
42 Amanda::Debug::dbopen("installcheck");
43 Installcheck::log_test_output();
44
45 my $testconf;
46 $testconf = Installcheck::Run->setup();
47 $testconf->write();
48
49 # install the 'bigdb' catalog to test against
50 my $cat = Installcheck::Catalogs::load("bigdb");
51 $cat->install();
52
53 my $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
54 if ($cfg_result != $CFGERR_OK) {
55     my ($level, @errors) = Amanda::Config::config_errors();
56     die(join "\n", @errors);
57 }
58
59 ##
60 ## Tests!
61 ###
62
63 sub make_plan_sync {
64     my $plan;
65
66     Amanda::Recovery::Planner::make_plan(@_,
67         debug => 1,
68         plan_cb => sub {
69             (my $err, $plan) = @_;
70             die "$err" if $err;
71             Amanda::MainLoop::quit();
72         });
73
74     Amanda::MainLoop::run();
75     return $plan;
76 }
77
78 sub ds {
79     return Amanda::Cmdline::dumpspec_t->new($_[0], $_[1], $_[2], $_[3], undef);
80 }
81
82 sub is_plan {
83     my ($got, $exp, $msg) = @_;
84     my $got_dumps = $got->{'dumps'};
85
86     # make an "abbreviated" version of the plan for comparison with the
87     # expected
88     my @got_abbrev;
89     for my $d (@$got_dumps) {
90         my @parts;
91         push @got_abbrev, [
92             $d->{'hostname'},
93             $d->{'diskname'},
94             $d->{'dump_timestamp'},
95             "$d->{'level'}"+0, # strip bigints
96             \@parts ];
97
98         for my $p (@{$d->{'parts'}}) {
99             next unless defined $p;
100             if (exists $p->{'holding_file'}) {
101                 # extract the last two filename components, since the rest is variable
102                 my $hf = $p->{'holding_file'};
103                 $hf =~ s/^.*\/([^\/]*\/[^\/]*)$/$1/;
104                 push @parts, $hf;
105             } else {
106                 push @parts,
107                     $p->{'label'},
108                     "$p->{filenum}"+0; # strip bigints
109             }
110         }
111     }
112
113     is_deeply(\@got_abbrev, $exp, $msg)
114         or diag("got:\n" . Dumper(\@got_abbrev));
115 }
116
117 my $changer = undef; # not needed yet
118
119 is_plan(make_plan_sync(
120             dumpspec => ds("no-box-at-all"),
121             changer => $changer),
122     [ ],
123     "empty plan for nonexistent host");
124
125 is_plan(make_plan_sync(
126             dumpspec => ds("oldbox", "^/opt"),
127             changer => $changer),
128     [
129         [   "oldbox", "/opt", "20080414144444", 0, [
130                 '20080414144444/oldbox._opt',
131             ],
132         ],
133     ],
134     "simple plan for a dump on holding disk");
135
136 is_plan(make_plan_sync(
137             dumpspec => ds("somebox", "^/lib", "200801"),
138             changer => $changer),
139     [
140         [   "somebox", "/lib", "20080111000000", 0, [
141                 'Conf-001' => 1,
142             ],
143         ],
144     ],
145     "simple plan for just one dump");
146
147 is_plan(make_plan_sync(
148             dumpspec => ds("somebox", "^/usr/bin"),
149             changer => $changer),
150     [
151         [   'somebox', '/usr/bin', '20080313133333', 1, [
152                 'Conf-003' => 1,
153             ],
154         ],
155         [   'somebox', '/usr/bin', '20080515155555', 1, [
156                 'Conf-006' => 1,
157             ]
158         ],
159         [   'somebox', '/usr/bin', '20080616166666', 1, [
160                 'Conf-007' => 1,
161             ],
162         ],
163     ],
164     "plan for three dumps, in order by tape write time");
165
166 is_plan(make_plan_sync(
167             dumpspec => ds("otherbox", "^/lib"),
168             changer => $changer),
169     [
170         [   "otherbox", "/lib", "20080414144444", 1, [
171                 '20080414144444/otherbox._lib',
172             ],
173         ],
174         [   'otherbox', '/lib', '20080313133333', 0, [
175                 'Conf-003' => 14,
176             ],
177         ],
178         [   "otherbox", "/lib", "20080511151555", 0, [
179                 'Conf-006', 13,
180             ],
181         ],
182     ],
183     "plan for three dumps, one on holding disk; holding dumps prioritized first");
184
185 is_plan(make_plan_sync(
186             dumpspecs => [
187                 ds("somebox", "^/lib", "20080111"),
188                 ds("somebox", "^/lib", "20080222"),
189             ],
190             changer => $changer),
191     [
192         [   "somebox", "/lib", "20080111000000", 0, [
193                 'Conf-001' => 1,
194             ],
195         ],
196         [       'somebox', '/lib', '20080222222222', 0, [
197                 'Conf-002' => 1,
198                 'Conf-002' => 2,
199             ],
200         ],
201     ],
202     "plan for two dumps, one of them spanned, in order by tape write time");
203
204 is_plan(make_plan_sync(
205             dumpspec => ds("somebox", "^/lib", "200803"),
206             one_dump_per_part => 1,
207             changer => $changer),
208     [
209         [   "somebox", "/lib", "20080313133333", 0, [
210                 'Conf-003' => 2,
211             ],
212         ],
213         [   "somebox", "/lib", "20080313133333", 0, [
214                 'Conf-003' => 3,
215             ],
216         ],
217         [   "somebox", "/lib", "20080313133333", 0, [
218                 'Conf-003' => 4,
219             ],
220         ],
221         [   "somebox", "/lib", "20080313133333", 0, [
222                 'Conf-003' => 5,
223             ],
224         ],
225         [   "somebox", "/lib", "20080313133333", 0, [
226                 'Conf-003' => 6,
227             ],
228         ],
229         [   "somebox", "/lib", "20080313133333", 0, [
230                 'Conf-003' => 7,
231             ],
232         ],
233         [   "somebox", "/lib", "20080313133333", 0, [
234                 'Conf-003' => 8,
235             ],
236         ],
237         [   "somebox", "/lib", "20080313133333", 0, [
238                 'Conf-003' => 9,
239             ],
240         ],
241         [   "somebox", "/lib", "20080313133333", 0, [
242                 'Conf-003' => 10,
243             ],
244         ],
245         [   "somebox", "/lib", "20080313133333", 0, [
246                 'Conf-003' => 11,
247             ],
248         ],
249     ],
250     "plan for a multipart dump, one_dump_per_part");
251
252 is_plan(make_plan_sync(
253             dumpspec => ds("oldbox", "^/opt", "20080414144444"),
254             holding_file => $cat->holding_filename('oldbox_opt_20080414144444_holding')),
255     [
256         [   "oldbox", "/opt", "20080414144444", 0, [
257                 '20080414144444/oldbox._opt',
258             ],
259         ],
260     ],
261     "make_plan creates an appropriate plan for an explicit holding-disk recovery");
262
263 is_plan(make_plan_sync(
264             holding_file => $cat->holding_filename('oldbox_opt_20080414144444_holding')),
265     [
266         [   "oldbox", "/opt", "20080414144444", 0, [
267                 '20080414144444/oldbox._opt',
268             ],
269         ],
270     ],
271     "same, without a dumpspec");
272
273 is_plan(make_plan_sync(
274             dumpspec => ds("somebox", "/lib", "20080515155555"),
275             filelist => [
276                 'Conf-006' => [2, 3, 4, 5,       8, 9, 10, 11],
277                 #  (make_plan should fill in files 6 and 7)
278             ],
279             changer => $changer),
280     [
281         [   'somebox', '/lib', '20080515155555', 0, [
282                 'Conf-006' => 2,
283                 'Conf-006' => 3,
284                 'Conf-006' => 4,
285                 'Conf-006' => 5,
286                 'Conf-006' => 6,
287                 'Conf-006' => 7,
288                 'Conf-006' => 8,
289                 'Conf-006' => 9,
290                 'Conf-006' => 10,
291                 'Conf-006' => 11,
292             ],
293         ],
294     ],
295     "plan based on filelist, with a dumpspec");
296
297 is_plan(make_plan_sync(
298             filelist => [
299                 'Conf-006' => [2, 3, 4, 5,       8, 9, 10, 11],
300                 #  (make_plan should fill in files 6 and 7)
301             ],
302             changer => $changer),
303     [
304         [   'somebox', '/lib', '20080515155555', 0, [
305                 'Conf-006' => 2,
306                 'Conf-006' => 3,
307                 'Conf-006' => 4,
308                 'Conf-006' => 5,
309                 'Conf-006' => 6,
310                 'Conf-006' => 7,
311                 'Conf-006' => 8,
312                 'Conf-006' => 9,
313                 'Conf-006' => 10,
314                 'Conf-006' => 11,
315             ],
316         ],
317     ],
318     "plan based on filelist, without a dumpspec");