1 # Copyright (c) 2010-2012 Zmanda, Inc. All Rights Reserved.
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.
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
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
16 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
17 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19 use Test::More tests => 95;
25 use lib "@amperldir@";
26 use Installcheck::Config;
28 use Amanda::Device qw( :constants );
31 use Amanda::Config qw( :init :getconf config_dir_relative );
33 use Amanda::Recovery::Scan;
34 use Installcheck::Run qw(run run_get run_err vtape_dir);
36 # set up debugging so debug output doesn't interfere with test results
37 Amanda::Debug::dbopen("installcheck");
38 Installcheck::log_test_output();
40 # and disable Debug's die() and warn() overrides
41 Amanda::Debug::disable_die_override();
44 # Interactivity package
46 package Amanda::Interactivity::Installcheck;
48 @ISA = qw( Amanda::Interactivity );
53 return bless ($self, $class);
60 Amanda::Debug::debug("Change changer to multi-changer");
61 $params{'request_cb'}->(undef, "multi-changer");
65 # back to the perl tests..
69 my $testconf = Installcheck::Config->new();
71 my $taperoot_disk = "$Installcheck::TMP/Amanda_Recovery_Scan_Disk";
72 #create a disk changer with 3 slots
74 if (-d $taperoot_disk) {
75 rmtree($taperoot_disk);
77 mkpath($taperoot_disk);
79 for my $slot (1 .. 3) {
80 mkdir("$taperoot_disk/slot$slot")
81 or die("Could not mkdir: $!");
84 $testconf->add_changer("disk-changer", [
85 'tpchanger' => "\"chg-disk:$taperoot_disk\"",
89 my $taperoot_multi = "$Installcheck::TMP/Amanda_Recovery_Scan_Multi";
90 #create a multi changer
92 if (-d $taperoot_multi) {
93 rmtree($taperoot_multi);
95 mkpath($taperoot_multi);
98 for my $slot (1 .. 3) {
99 mkdir("$taperoot_multi/slot$slot")
100 or die("Could not mkdir: $!");
101 mkdir("$taperoot_multi/slot$slot/data")
102 or die("Could not mkdir: $!");
106 my $chg_name = "chg-multi:file:$taperoot_multi/slot{".join(',', @names)."}";
107 $testconf->add_changer("multi-changer", [
108 'tpchanger' => "\"$chg_name\"",
109 'changerfile' => "\"$Installcheck::TMP/Amanda_Recovery_Scan_Multi_status\"",
113 my $taperoot_compat = "$Installcheck::TMP/Amanda_Recovery_Scan_Compat";
114 my $changerfile = "$Installcheck::TMP/scan-changerfile";
116 #create a compat changer
118 if (-d $taperoot_compat) {
119 rmtree($taperoot_compat);
121 mkpath($taperoot_compat);
124 for my $slot (1 .. 3) {
125 mkdir("$taperoot_compat/slot$slot")
126 or die("Could not mkdir: $!");
127 #mkdir("$taperoot_compat/slot$slot/data")
128 # or die("Could not mkdir: $!");
132 open (CONF, ">$changerfile");
133 print CONF "firstslot=1\n";
134 print CONF "lastslot=3\n";
137 $testconf->add_changer("compat-changer", [
138 'tpchanger' => '"chg-disk"',
139 'tapedev' => "\"file:$taperoot_compat\"",
140 'changerfile' => "\"$changerfile\"",
144 my $taperoot_single = "$Installcheck::TMP/Amanda_Recovery_Scan_Single";
145 #create a single changer
147 if (-d $taperoot_single) {
148 rmtree($taperoot_single);
150 mkpath($taperoot_single);
151 mkdir("$taperoot_single/data");
153 $testconf->add_changer("single-changer", [
154 'tpchanger' => "\"chg-single:file:$taperoot_single\"",
160 Amanda::Config::config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
162 # sub to label a slot in a changer
164 my ($chg, $chg_name, $slot, $label, $finished_cb) = @_;
167 my $steps = define_steps
168 cb_ref => \$finished_cb;
171 $chg->load(slot => $slot, res_cb => $steps->{'res_cb'});
175 (my $err, $res) = @_;
178 $res->{'device'}->start($ACCESS_WRITE, $label, "20100201010203");
179 $res->set_label(label => $label, finished_cb => $steps->{'set_label_finished'});
182 step set_label_finished => sub {
186 $res->release(finished_cb => $steps->{'finished_cb'});
189 step finished_cb => sub {
192 pass("label slot $slot of $chg_name with label '$label'");
198 my ($chg, $chg_name, $slot, $label) = @_;
200 amlabel($chg, $chg_name, $slot, $label,
201 make_cb(finished_cb => sub { Amanda::MainLoop::quit(); }));
202 Amanda::MainLoop::run();
207 my ($chg, $chg_name, $finished_cb) = @_;
213 my $steps = define_steps
214 cb_ref => \$finished_cb,
215 finalize => sub { $scan->quit() };
218 $scan = Amanda::Recovery::Scan->new(chg => $chg);
219 $steps->{'find_04'}->();
222 step find_04 => sub {
223 $scan->find_volume(label => "TESTCONF04",
224 res_cb => $steps->{'res_cb_04'});
227 step res_cb_04 => sub {
228 my ($err, $res) = @_;
230 ok(!$res, "$chg_name didn't find TESTCONF04");
231 ok($err->notfound, "$chg_name: TESTCONF04 error is notfound");
233 $scan->find_volume(label => "TESTCONF02",
234 res_cb => $steps->{'res_cb_02'});
237 step res_cb_02 => sub {
238 (my $err, $res02) = @_;
240 ok(!$err, "$chg_name found TESTCONF02");
241 ok($res02, "$chg_name: TESTCONF02 give a reservation");
243 $scan->find_volume(label => "TESTCONF02",
244 res_cb => $steps->{'res_cb_02_volinuse'});
247 step res_cb_02_volinuse => sub {
248 my ($err, $res) = @_;
250 ok(!$res, "$chg_name doesn't reserve an already reserved slot");
251 if ($chg_name eq "compat-changer" ||
252 $chg_name eq "single-changer") {
253 ok($err->driveinuse, "$chg_name: TESTCONF02 is driveinuse") ||
254 diag("$chg_name:".Dumper($err));
256 ok($err->volinuse, "$chg_name: TESTCONF02 is volinuse") ||
257 diag("$chg_name:".Dumper($err));
260 $scan->find_volume(label => "TESTCONF03",
261 res_cb => $steps->{'res_cb_03'});
264 step res_cb_03 => sub {
265 (my $err, $res03) = @_;
267 if ($chg_name eq "compat-changer" ||
268 $chg_name eq "single-changer") {
269 ok($err, "$chg_name doesn't found TESTCONF03");
270 ok($err->driveinuse, "$chg_name TESTCONF03 is driveinuse") ||
272 ok(!$res03, "$chg_name: TESTCONF03 give no reservation");
274 ok(!$err, "$chg_name found TESTCONF03");
275 ok($res03, "$chg_name: TESTCONF03 give a reservation");
277 $scan->find_volume(label => "TESTCONF01",
278 res_cb => $steps->{'res_cb_01'});
281 step res_cb_01 => sub {
282 (my $err, $res01) = @_;
284 if ($chg_name eq "compat-changer" ||
285 $chg_name eq "single-changer") {
286 ok($err, "$chg_name doesn't found TESTCONF01");
287 ok($err->driveinuse, "$chg_name TESTCONF01 is driveinuse") ||
289 ok(!$res01, "$chg_name: TESTCONF01 give no reservation");
291 ok(!$err, "$chg_name found TESTCONF01");
292 ok($res01, "$chg_name: TESTCONF01 give a reservation");
294 $scan->find_volume(label => "TESTCONF05",
295 res_cb => $steps->{'res_cb_05'});
298 step res_cb_05 => sub {
299 my ($err, $res) = @_;
301 if ($chg_name eq "compat-changer" ||
302 $chg_name eq "single-changer") {
303 ok($err, "$chg_name doesn't found TESTCONF05");
304 ok($err->driveinuse, "$chg_name TESTCONF05 is driveinuse") ||
306 ok(!$res, "$chg_name: TESTCONF05 give no reservation");
308 ok(!$res, "$chg_name doesn't found TESTCONF05");
309 ok($err->notfound, "$chg_name: TESTCONF05 is notfound");
311 $scan->find_volume(label => "TESTCONF01",
312 res_cb => $steps->{'res_cb_01_volinuse'});
315 step res_cb_01_volinuse => sub {
316 my ($err, $res) = @_;
318 ok($err, "$chg_name doesn't found TESTCONF01");
319 if ($chg_name eq "compat-changer" ||
320 $chg_name eq "single-changer") {
321 ok($err->driveinuse, "$chg_name TESTCONF01 is driveinuse") ||
324 ok($err->volinuse, "$chg_name TESTCONF01 is volinuse") ||
327 ok(!$res, "$chg_name: TESTCONF01 give no reservation");
328 $steps->{'release01'}->();
331 step release01 => sub {
333 $res01->release(finished_cb => $steps->{'release02'});
335 $steps->{'release02'}->();
339 step release02 => sub {
340 $res02->release(finished_cb => $steps->{'release03'});
343 step release03 => sub {
345 $res03->release(finished_cb => $steps->{'done'});
347 $steps->{'done'}->();
352 pass("done with searching test on $chg_name");
357 foreach my $chg_name ("disk-changer", "multi-changer", "compat-changer",
359 # amlabel has to be done outside of Amanda::MainLoop
360 my $chg = Amanda::Changer->new($chg_name);
361 if ($chg_name eq "single-changer") {
362 amlabel_sync($chg, $chg_name, 1, 'TESTCONF02');
364 amlabel_sync($chg, $chg_name, 1, 'TESTCONF01');
365 amlabel_sync($chg, $chg_name, 2, 'TESTCONF02');
366 amlabel_sync($chg, $chg_name, 3, 'TESTCONF03');
369 test_searching($chg, $chg_name, \&Amanda::MainLoop::quit);
370 Amanda::MainLoop::run();
375 my ($chg_name, $finished_cb) = @_;
381 my $steps = define_steps
382 cb_ref => \$finished_cb,
383 finalize => sub { $scan->quit() };
386 $chg = Amanda::Changer->new($chg_name);
387 $scan = Amanda::Recovery::Scan->new(chg => $chg);
388 $scan->{'scan_conf'}->{'notfound'} = Amanda::Recovery::Scan::SCAN_POLL;
389 $scan->{'scan_conf'}->{'volinuse'} = Amanda::Recovery::Scan::SCAN_POLL;
390 $scan->{'scan_conf'}->{'poll_delay'} = 10; # 10 ms
392 $steps->{'find_04'}->();
395 step find_04 => sub {
396 Amanda::MainLoop::call_after(100, $steps->{'label_04'});
397 $scan->find_volume(label => "TESTCONF04",
398 res_cb => $steps->{'res_cb_04'});
399 pass("began searching for TESTCONF04");
402 step label_04 => sub {
403 # this needs to be run on a different process.
404 ok(run('amlabel', '-f', "-otpchanger=$chg_name", 'TESTCONF',
405 'TESTCONF04', 'slot', '3'),
406 "label slot 3 of $chg_name with label TESTCONF04");
407 # note: nothing to do in the amlabel callback
410 step res_cb_04 => sub {
411 (my $err, $res04) = @_;
413 ok(!$err, "$chg_name found TESTCONF04 after POLL");
414 ok($res04, "$chg_name: TESTCONF04 give a reservation after POLL");
416 $res04->release(finished_cb => $steps->{'done'});
420 pass("done with SCAN_POLL on $chg_name");
425 foreach my $chg_name ("disk-changer", "multi-changer") {
426 test_scan_poll($chg_name, \&Amanda::MainLoop::quit);
427 Amanda::MainLoop::run();
430 #test SCAN_ASK_POLL which change the changer.
431 #label TESTCONF05 in multi-changer
432 #start the scan on disk-changer
433 #interactivity module change changer to multi-changer
434 sub test_scan_ask_poll {
435 my ($finished_cb) = @_;
439 my $chg_name = "multi-changer";
440 my $chg = Amanda::Changer->new($chg_name);
441 amlabel_sync($chg, $chg_name, 2, 'TESTCONF05');
443 $chg = Amanda::Changer->new("disk-changer");
445 my $steps = define_steps
446 cb_ref => \$finished_cb,
447 finalize => sub { $scan->quit() };
450 my $interactivity = Amanda::Interactivity::Installcheck->new();
451 $scan = Amanda::Recovery::Scan->new(chg => $chg,
452 interactivity => $interactivity);
453 $scan->{'scan_conf'}->{'poll_delay'} = 10; # 10 ms
455 $steps->{'find_05'}->();
458 step find_05 => sub {
459 $scan->find_volume(label => "TESTCONF05",
460 res_cb => $steps->{'res_cb_05'});
463 step res_cb_05 => sub {
464 (my $err, $res05) = @_;
466 ok(!$err, "found TESTCONF05 on changer multi");
467 ok($res05, "TESTCONF05 give a reservation after interactivity");
468 is($res05->{'chg'}->{'chg_name'}, $chg_name,
469 "found TESTCONF05 on correct changer: $chg_name");
471 $res05->release(finished_cb => $steps->{'done'});
475 pass("done with SCAN_ASK_POLL");
479 test_scan_ask_poll(\&Amanda::MainLoop::quit);
480 Amanda::MainLoop::run();
482 rmtree($taperoot_disk);
483 rmtree($taperoot_multi);
484 rmtree($taperoot_compat);
485 rmtree($taperoot_single);
486 unlink($changerfile);