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