1 # Copyright (c) 2010-2012 Zmanda, Inc. All Rights Reserved.
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.
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
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
17 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
20 use Test::More tests => 95;
26 use lib "@amperldir@";
27 use Installcheck::Config;
29 use Amanda::Device qw( :constants );
32 use Amanda::Config qw( :init :getconf config_dir_relative );
34 use Amanda::Recovery::Scan;
35 use Installcheck::Run qw(run run_get run_err vtape_dir);
37 # set up debugging so debug output doesn't interfere with test results
38 Amanda::Debug::dbopen("installcheck");
39 Installcheck::log_test_output();
41 # and disable Debug's die() and warn() overrides
42 Amanda::Debug::disable_die_override();
45 # Interactivity package
47 package Amanda::Interactivity::Installcheck;
49 @ISA = qw( Amanda::Interactivity );
54 return bless ($self, $class);
61 Amanda::Debug::debug("Change changer to multi-changer");
62 $params{'request_cb'}->(undef, "multi-changer");
66 # back to the perl tests..
70 my $testconf = Installcheck::Config->new();
72 my $taperoot_disk = "$Installcheck::TMP/Amanda_Recovery_Scan_Disk";
73 #create a disk changer with 3 slots
75 if (-d $taperoot_disk) {
76 rmtree($taperoot_disk);
78 mkpath($taperoot_disk);
80 for my $slot (1 .. 3) {
81 mkdir("$taperoot_disk/slot$slot")
82 or die("Could not mkdir: $!");
85 $testconf->add_changer("disk-changer", [
86 'tpchanger' => "\"chg-disk:$taperoot_disk\"",
90 my $taperoot_multi = "$Installcheck::TMP/Amanda_Recovery_Scan_Multi";
91 #create a multi changer
93 if (-d $taperoot_multi) {
94 rmtree($taperoot_multi);
96 mkpath($taperoot_multi);
99 for my $slot (1 .. 3) {
100 mkdir("$taperoot_multi/slot$slot")
101 or die("Could not mkdir: $!");
102 mkdir("$taperoot_multi/slot$slot/data")
103 or die("Could not mkdir: $!");
107 my $chg_name = "chg-multi:file:$taperoot_multi/slot{".join(',', @names)."}";
108 $testconf->add_changer("multi-changer", [
109 'tpchanger' => "\"$chg_name\"",
110 'changerfile' => "\"$Installcheck::TMP/Amanda_Recovery_Scan_Multi_status\"",
114 my $taperoot_compat = "$Installcheck::TMP/Amanda_Recovery_Scan_Compat";
115 my $changerfile = "$Installcheck::TMP/scan-changerfile";
117 #create a compat changer
119 if (-d $taperoot_compat) {
120 rmtree($taperoot_compat);
122 mkpath($taperoot_compat);
125 for my $slot (1 .. 3) {
126 mkdir("$taperoot_compat/slot$slot")
127 or die("Could not mkdir: $!");
128 #mkdir("$taperoot_compat/slot$slot/data")
129 # or die("Could not mkdir: $!");
133 open (CONF, ">$changerfile");
134 print CONF "firstslot=1\n";
135 print CONF "lastslot=3\n";
138 $testconf->add_changer("compat-changer", [
139 'tpchanger' => '"chg-disk"',
140 'tapedev' => "\"file:$taperoot_compat\"",
141 'changerfile' => "\"$changerfile\"",
145 my $taperoot_single = "$Installcheck::TMP/Amanda_Recovery_Scan_Single";
146 #create a single changer
148 if (-d $taperoot_single) {
149 rmtree($taperoot_single);
151 mkpath($taperoot_single);
152 mkdir("$taperoot_single/data");
154 $testconf->add_changer("single-changer", [
155 'tpchanger' => "\"chg-single:file:$taperoot_single\"",
161 Amanda::Config::config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
163 # sub to label a slot in a changer
165 my ($chg, $chg_name, $slot, $label, $finished_cb) = @_;
168 my $steps = define_steps
169 cb_ref => \$finished_cb;
172 $chg->load(slot => $slot, res_cb => $steps->{'res_cb'});
176 (my $err, $res) = @_;
179 $res->{'device'}->start($ACCESS_WRITE, $label, "20100201010203");
180 $res->set_label(label => $label, finished_cb => $steps->{'set_label_finished'});
183 step set_label_finished => sub {
187 $res->release(finished_cb => $steps->{'finished_cb'});
190 step finished_cb => sub {
193 pass("label slot $slot of $chg_name with label '$label'");
199 my ($chg, $chg_name, $slot, $label) = @_;
201 amlabel($chg, $chg_name, $slot, $label,
202 make_cb(finished_cb => sub { Amanda::MainLoop::quit(); }));
203 Amanda::MainLoop::run();
208 my ($chg, $chg_name, $finished_cb) = @_;
214 my $steps = define_steps
215 cb_ref => \$finished_cb,
216 finalize => sub { $scan->quit() };
219 $scan = Amanda::Recovery::Scan->new(chg => $chg);
220 $steps->{'find_04'}->();
223 step find_04 => sub {
224 $scan->find_volume(label => "TESTCONF04",
225 res_cb => $steps->{'res_cb_04'});
228 step res_cb_04 => sub {
229 my ($err, $res) = @_;
231 ok(!$res, "$chg_name didn't find TESTCONF04");
232 ok($err->notfound, "$chg_name: TESTCONF04 error is notfound");
234 $scan->find_volume(label => "TESTCONF02",
235 res_cb => $steps->{'res_cb_02'});
238 step res_cb_02 => sub {
239 (my $err, $res02) = @_;
241 ok(!$err, "$chg_name found TESTCONF02");
242 ok($res02, "$chg_name: TESTCONF02 give a reservation");
244 $scan->find_volume(label => "TESTCONF02",
245 res_cb => $steps->{'res_cb_02_volinuse'});
248 step res_cb_02_volinuse => sub {
249 my ($err, $res) = @_;
251 ok(!$res, "$chg_name doesn't reserve an already reserved slot");
252 if ($chg_name eq "compat-changer" ||
253 $chg_name eq "single-changer") {
254 ok($err->driveinuse, "$chg_name: TESTCONF02 is driveinuse") ||
255 diag("$chg_name:".Dumper($err));
257 ok($err->volinuse, "$chg_name: TESTCONF02 is volinuse") ||
258 diag("$chg_name:".Dumper($err));
261 $scan->find_volume(label => "TESTCONF03",
262 res_cb => $steps->{'res_cb_03'});
265 step res_cb_03 => sub {
266 (my $err, $res03) = @_;
268 if ($chg_name eq "compat-changer" ||
269 $chg_name eq "single-changer") {
270 ok($err, "$chg_name doesn't found TESTCONF03");
271 ok($err->driveinuse, "$chg_name TESTCONF03 is driveinuse") ||
273 ok(!$res03, "$chg_name: TESTCONF03 give no reservation");
275 ok(!$err, "$chg_name found TESTCONF03");
276 ok($res03, "$chg_name: TESTCONF03 give a reservation");
278 $scan->find_volume(label => "TESTCONF01",
279 res_cb => $steps->{'res_cb_01'});
282 step res_cb_01 => sub {
283 (my $err, $res01) = @_;
285 if ($chg_name eq "compat-changer" ||
286 $chg_name eq "single-changer") {
287 ok($err, "$chg_name doesn't found TESTCONF01");
288 ok($err->driveinuse, "$chg_name TESTCONF01 is driveinuse") ||
290 ok(!$res01, "$chg_name: TESTCONF01 give no reservation");
292 ok(!$err, "$chg_name found TESTCONF01");
293 ok($res01, "$chg_name: TESTCONF01 give a reservation");
295 $scan->find_volume(label => "TESTCONF05",
296 res_cb => $steps->{'res_cb_05'});
299 step res_cb_05 => sub {
300 my ($err, $res) = @_;
302 if ($chg_name eq "compat-changer" ||
303 $chg_name eq "single-changer") {
304 ok($err, "$chg_name doesn't found TESTCONF05");
305 ok($err->driveinuse, "$chg_name TESTCONF05 is driveinuse") ||
307 ok(!$res, "$chg_name: TESTCONF05 give no reservation");
309 ok(!$res, "$chg_name doesn't found TESTCONF05");
310 ok($err->notfound, "$chg_name: TESTCONF05 is notfound");
312 $scan->find_volume(label => "TESTCONF01",
313 res_cb => $steps->{'res_cb_01_volinuse'});
316 step res_cb_01_volinuse => sub {
317 my ($err, $res) = @_;
319 ok($err, "$chg_name doesn't found TESTCONF01");
320 if ($chg_name eq "compat-changer" ||
321 $chg_name eq "single-changer") {
322 ok($err->driveinuse, "$chg_name TESTCONF01 is driveinuse") ||
325 ok($err->volinuse, "$chg_name TESTCONF01 is volinuse") ||
328 ok(!$res, "$chg_name: TESTCONF01 give no reservation");
329 $steps->{'release01'}->();
332 step release01 => sub {
334 $res01->release(finished_cb => $steps->{'release02'});
336 $steps->{'release02'}->();
340 step release02 => sub {
341 $res02->release(finished_cb => $steps->{'release03'});
344 step release03 => sub {
346 $res03->release(finished_cb => $steps->{'done'});
348 $steps->{'done'}->();
353 pass("done with searching test on $chg_name");
358 foreach my $chg_name ("disk-changer", "multi-changer", "compat-changer",
360 # amlabel has to be done outside of Amanda::MainLoop
361 my $chg = Amanda::Changer->new($chg_name);
362 if ($chg_name eq "single-changer") {
363 amlabel_sync($chg, $chg_name, 1, 'TESTCONF02');
365 amlabel_sync($chg, $chg_name, 1, 'TESTCONF01');
366 amlabel_sync($chg, $chg_name, 2, 'TESTCONF02');
367 amlabel_sync($chg, $chg_name, 3, 'TESTCONF03');
370 test_searching($chg, $chg_name, \&Amanda::MainLoop::quit);
371 Amanda::MainLoop::run();
376 my ($chg_name, $finished_cb) = @_;
382 my $steps = define_steps
383 cb_ref => \$finished_cb,
384 finalize => sub { $scan->quit() };
387 $chg = Amanda::Changer->new($chg_name);
388 $scan = Amanda::Recovery::Scan->new(chg => $chg);
389 $scan->{'scan_conf'}->{'notfound'} = Amanda::Recovery::Scan::SCAN_POLL;
390 $scan->{'scan_conf'}->{'volinuse'} = Amanda::Recovery::Scan::SCAN_POLL;
391 $scan->{'scan_conf'}->{'poll_delay'} = 10; # 10 ms
393 $steps->{'find_04'}->();
396 step find_04 => sub {
397 Amanda::MainLoop::call_after(100, $steps->{'label_04'});
398 $scan->find_volume(label => "TESTCONF04",
399 res_cb => $steps->{'res_cb_04'});
400 pass("began searching for TESTCONF04");
403 step label_04 => sub {
404 # this needs to be run on a different process.
405 ok(run('amlabel', '-f', "-otpchanger=$chg_name", 'TESTCONF',
406 'TESTCONF04', 'slot', '3'),
407 "label slot 3 of $chg_name with label TESTCONF04");
408 # note: nothing to do in the amlabel callback
411 step res_cb_04 => sub {
412 (my $err, $res04) = @_;
414 ok(!$err, "$chg_name found TESTCONF04 after POLL");
415 ok($res04, "$chg_name: TESTCONF04 give a reservation after POLL");
417 $res04->release(finished_cb => $steps->{'done'});
421 pass("done with SCAN_POLL on $chg_name");
426 foreach my $chg_name ("disk-changer", "multi-changer") {
427 test_scan_poll($chg_name, \&Amanda::MainLoop::quit);
428 Amanda::MainLoop::run();
431 #test SCAN_ASK_POLL which change the changer.
432 #label TESTCONF05 in multi-changer
433 #start the scan on disk-changer
434 #interactivity module change changer to multi-changer
435 sub test_scan_ask_poll {
436 my ($finished_cb) = @_;
440 my $chg_name = "multi-changer";
441 my $chg = Amanda::Changer->new($chg_name);
442 amlabel_sync($chg, $chg_name, 2, 'TESTCONF05');
444 $chg = Amanda::Changer->new("disk-changer");
446 my $steps = define_steps
447 cb_ref => \$finished_cb,
448 finalize => sub { $scan->quit() };
451 my $interactivity = Amanda::Interactivity::Installcheck->new();
452 $scan = Amanda::Recovery::Scan->new(chg => $chg,
453 interactivity => $interactivity);
454 $scan->{'scan_conf'}->{'poll_delay'} = 10; # 10 ms
456 $steps->{'find_05'}->();
459 step find_05 => sub {
460 $scan->find_volume(label => "TESTCONF05",
461 res_cb => $steps->{'res_cb_05'});
464 step res_cb_05 => sub {
465 (my $err, $res05) = @_;
467 ok(!$err, "found TESTCONF05 on changer multi");
468 ok($res05, "TESTCONF05 give a reservation after interactivity");
469 is($res05->{'chg'}->{'chg_name'}, $chg_name,
470 "found TESTCONF05 on correct changer: $chg_name");
472 $res05->release(finished_cb => $steps->{'done'});
476 pass("done with SCAN_ASK_POLL");
480 test_scan_ask_poll(\&Amanda::MainLoop::quit);
481 Amanda::MainLoop::run();
483 rmtree($taperoot_disk);
484 rmtree($taperoot_multi);
485 rmtree($taperoot_compat);
486 rmtree($taperoot_single);
487 unlink($changerfile);