Imported Upstream version 3.3.3
[debian/amanda] / installcheck / amvault.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 strict;
22 use warnings;
23
24 use lib "@amperldir@";
25 use File::Path;
26 use Data::Dumper;
27 use Installcheck;
28 use Installcheck::Dumpcache;
29 use Installcheck::Config;
30 use Installcheck::Mock;
31 use Installcheck::Run qw(run run_err run_get $diskname);
32 use Amanda::DB::Catalog;
33 use Amanda::Paths;
34 use Amanda::Config qw( :init );
35 use Amanda::Changer;
36 use Amanda::Debug;
37
38 Amanda::Debug::dbopen("installcheck");
39
40 my $vtape_root = "$Installcheck::TMP/tertiary";
41 sub setup_chg_disk {
42     rmtree $vtape_root if -d $vtape_root;
43     mkpath "$vtape_root/slot1";
44     return "chg-disk:$vtape_root";
45 }
46
47 # set up a basic dump
48 Installcheck::Dumpcache::load("basic");
49
50 config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
51 my ($cfgerr_level, @cfgerr_errors) = config_errors();
52 if ($cfgerr_level >= $CFGERR_WARNINGS) {
53     config_print_errors();
54     die "config errors";
55 }
56
57 # and then set up a new vtape to vault onto
58 my $tertiary_chg = setup_chg_disk();
59
60 # try a few failures first
61 like(run_err("$sbindir/amvault",
62                 '--autolabel=any',
63                 '--label-template', "TESTCONF%%",
64                 '--src-timestamp', 'latest',
65                 '--dst-changer', $tertiary_chg,
66                 'TESTCONF', 'someotherhost'),
67     qr/No dumps to vault/,
68     "amvault with a non-matching dumpspec dumps nothing")
69     or diag($Installcheck::Run::stderr);
70
71 like(run_err("$sbindir/amvault",
72                 '--autolabel=any',
73                 '--label-template', "TESTCONF%%",
74                 '--src-timestamp', 'latest',
75                 '--fulls-only',
76                 '--dst-changer', $tertiary_chg,
77                 'TESTCONF', '*', '*', '*', '1-3'),
78     qr/No dumps to vault/,
79     "amvault with --fulls-only but specifying non-full dumpspecs dumps nothing")
80     or diag($Installcheck::Run::stderr);
81
82 like(run_err("$sbindir/amvault",
83                 '--autolabel=any',
84                 '--label-template', "TESTCONF%%",
85                 '--dst-changer', $tertiary_chg,
86                 'TESTCONF'),
87     qr/specify something to select/,
88     "amvault without any limiting factors is an error"),
89     or diag($Installcheck::Run::stderr);
90
91 # now a successful vaulting
92 ok(run("$sbindir/amvault",
93                 '--autolabel=any',
94                 '--label-template', "TESTCONF%%",
95                 '--src-timestamp', 'latest',
96                 '--dst-changer', $tertiary_chg,
97                 'TESTCONF'),
98     "amvault runs!")
99     or diag($Installcheck::Run::stderr);
100 my @tert_files = glob("$vtape_root/slot1/0*");
101 ok(@tert_files > 0,
102     "..and files appear on the tertiary volume!");
103
104 my @dumps = Amanda::DB::Catalog::sort_dumps([ 'write_timestamp' ],
105         Amanda::DB::Catalog::get_dumps());
106
107 is(scalar @dumps, 2,
108     "now there are two dumps in the catalog");
109
110 sub summarize {
111     my ($dump) = @_;
112     return {
113         map { $_ => $dump->{$_} }
114             qw(diskname hostname level dump_timestamp kb orig_kb)
115     };
116 }
117 is_deeply(summarize($dumps[1]), summarize($dumps[0]),
118     "and they match in all the right ways")
119     or diag(Dumper(@dumps));
120
121 # clean up the tertiary vtapes before moving on
122 rmtree $vtape_root;
123 Installcheck::Run::cleanup();
124
125 # try the multi dump, to get a better idea of the filtering possibilities
126 Installcheck::Dumpcache::load("multi");
127 config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
128 ($cfgerr_level, @cfgerr_errors) = config_errors();
129 if ($cfgerr_level >= $CFGERR_WARNINGS) {
130     config_print_errors();
131     die "config errors";
132 }
133
134 sub get_dry_run {
135     my $stdout = run_get(@_);
136     if (!$stdout) {
137         diag($Installcheck::Run::stderr);
138         return 'run-failed';
139     }
140
141     my @rv;
142     for my $line (split /\n/, $stdout) {
143         next if ($line =~ /^Total Size:/);
144         my ($tape, $file, $host, $disk, $datestamp, $level) =
145             ($line =~ /^(\S+) (\d*) (\S+) (.+) (\d+) (\d+)$/);
146         $tape = 'holding' if $file eq '';
147         push @rv, [$tape, $file, $host, $disk,   $level]; # note: no datestamp
148     }
149     return @rv;
150 }
151
152 is_deeply([ get_dry_run("$sbindir/amvault",
153                 '--dry-run',
154                 '--autolabel=any',
155                 '--label-template', "TESTCONF%%",
156                 '--fulls-only',
157                 '--dst-changer', $tertiary_chg,
158                 'TESTCONF') ], [
159     [ "TESTCONF01", "1", "localhost", "$diskname/dir", "0" ],
160     [ "TESTCONF01", "2", "localhost", "$diskname",     "0" ],
161     [ "TESTCONF02", "2", "localhost", "$diskname",     "0" ]
162     ], "amvault with --fulls-only only dumps fulls");
163
164 is_deeply([ get_dry_run("$sbindir/amvault",
165                 '--dry-run',
166                 '--autolabel=any',
167                 '--label-template', "TESTCONF%%",
168                 '--dst-changer', $tertiary_chg,
169                 'TESTCONF', "localhost", "$diskname/dir") ], [
170     [ "holding", "",     "localhost", "$diskname/dir",     "1" ],
171     [ "TESTCONF01", "1", "localhost", "$diskname/dir",     "0" ],
172     [ "TESTCONF02", "1", "localhost", "$diskname/dir",     "1" ]
173     ], "amvault with a disk expression dumps only that disk");
174
175 # Test NDMP-to-NDMP vaulting.  This will test all manner of goodness:
176 #  - specifying a named changer on the amvault command line
177 #  - exporting
178 #  - directtcp vaulting (well, not really, since we don't support connecting yet)
179 SKIP: {
180     skip "not built with ndmp and server", 2 unless
181         Amanda::Util::built_with_component("ndmp") and Amanda::Util::built_with_component("server");
182
183     Installcheck::Dumpcache::load("ndmp");
184
185     my $ndmp = Installcheck::Mock::NdmpServer->new(no_reset => 1);
186     $ndmp->edit_config();
187
188     # append a tertiary changer to the config file - it's just too hard to
189     # specify a full ndmp changer on the command line
190
191     my $ndmp_port = $ndmp->{'port'};
192     my $chg_dir = "$Installcheck::TMP/vtapes/ndmjob-tert";
193     my $chg_spec = "chg-ndmp:127.0.0.1:$ndmp_port\@$chg_dir";
194     my $drive_root = "ndmp:127.0.0.1:$ndmp_port\@$chg_dir";
195
196     -d $chg_dir && rmtree($chg_dir);
197     mkpath($chg_dir);
198
199     my $amanda_conf_filename = "$CONFIG_DIR/TESTCONF/amanda.conf";
200     open(my $fh, ">>", $amanda_conf_filename);
201     print $fh <<EOF;
202 define changer "tertiary" {
203     tpchanger "$chg_spec"
204     property        "tape-device" "0=$drive_root/drive0"
205     property append "tape-device" "1=$drive_root/drive1"
206     changerfile "$chg_dir-changerfile"
207 }
208 EOF
209
210     $tertiary_chg = "tertiary";
211     ok(run("$sbindir/amvault",
212                     '--export',
213                     '--autolabel=any',
214                     '--label-template', "TESTCONF%%",
215                     '--src-timestamp', 'latest',
216                     '--dst-changer', $tertiary_chg,
217                     'TESTCONF'),
218         "amvault runs with an NDMP device as secondary and tertiary, with --export")
219         or diag($Installcheck::Run::stderr);
220
221     config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
222     ($cfgerr_level, @cfgerr_errors) = config_errors();
223     if ($cfgerr_level >= $CFGERR_WARNINGS) {
224         config_print_errors();
225         die "config errors";
226     }
227
228     # query the tertiary changer to see where that dump ended up
229     my $chg = Amanda::Changer->new($tertiary_chg);
230     my $inventory;
231     my $inventory_cb = sub {
232         my ($err, $inv) = @_;
233         die "$err" if $err;
234
235         $inventory = $inv;
236         Amanda::MainLoop::quit();
237     };
238     Amanda::MainLoop::call_later(sub { $chg->inventory(inventory_cb => $inventory_cb); });
239     Amanda::MainLoop::run();
240     $chg->quit();
241
242     # find TESTCONF02 in the inventory, and check that it is in an i/e slot
243     my $notfound = "tertiary volume not found";
244     for my $i (@$inventory) {
245         if ($i->{'label'} && $i->{'label'} eq 'TESTCONF02') {
246             if ($i->{'import_export'}) {
247                 $notfound = undef;
248             } else {
249                 $notfound = "tertiary volume not properly exported";
250             }
251             #last;
252         }
253     }
254
255     ok(!$notfound, "tertiary volume exists and was properly exported");
256     if ($notfound) {
257         diag($notfound);
258         diag("amvault stderr:");
259         diag($Installcheck::Run::stderr);
260     }
261
262 }
263
264 # clean up
265 Installcheck::Run::cleanup();