Imported Upstream version 3.3.3
[debian/amanda] / installcheck / Amanda_Taper_Scan_oldest.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 => 27;
21 use File::Path;
22 use Data::Dumper;
23 use strict;
24 use warnings;
25
26 use lib "@amperldir@";
27 use Installcheck;
28 use Installcheck::Config;
29 use Installcheck::Changer;
30 use Amanda::Device qw( :constants );
31 use Amanda::Debug;
32 use Amanda::MainLoop;
33 use Amanda::Config qw( :init :getconf config_dir_relative );
34 use Amanda::Changer;
35 use Amanda::Taper::Scan;
36
37 # set up debugging so debug output doesn't interfere with test results
38 Amanda::Debug::dbopen("installcheck");
39 Installcheck::log_test_output();
40
41 # and disable Debug's die() and warn() overrides
42 Amanda::Debug::disable_die_override();
43
44 my $taperoot = "$Installcheck::TMP/Amanda_Taper_Scan_oldest";
45 my $tapelist_filename = "$Installcheck::TMP/tapelist";
46 `cat /dev/null > $Installcheck::TMP/tapelist`;
47 my $tapelist = Amanda::Tapelist->new($tapelist_filename);
48
49 # vtape support
50 my %slot_label;
51
52 sub reset_taperoot {
53     my ($nslots) = @_;
54
55     if (-d $taperoot) {
56         rmtree($taperoot);
57     }
58     mkpath($taperoot);
59
60     for my $slot (1 .. $nslots) {
61         mkdir("$taperoot/slot$slot")
62             or die("Could not mkdir: $!");
63     }
64
65     # clear out the tapefile
66     open(my $fh, ">", $tapelist_filename) or die("opening tapelist_filename: $!");
67     %slot_label = ();
68 }
69
70 sub label_slot {
71     my ($slot, $label, $stamp, $reuse, $update_tapelist) = @_;
72
73     my $drivedir = "$taperoot/tmp";
74     -d $drivedir and rmtree($drivedir);
75     mkpath($drivedir);
76     symlink("$taperoot/slot$slot", "$drivedir/data");
77
78     my $dev = Amanda::Device->new("file:$drivedir");
79     die $dev->error_or_status() unless $dev->status == $DEVICE_STATUS_SUCCESS;
80
81     if (defined $label){
82         if (!$dev->start($ACCESS_WRITE, $label, $stamp)) {
83             die $dev->error_or_status();
84         }
85     } else {
86         $dev->erase();
87     }
88
89     rmtree($drivedir);
90
91     if ($update_tapelist) {
92         if (exists $slot_label{$slot}) {
93             $tapelist->remove_tapelabel($slot_label{$slot});
94             delete $slot_label{$slot};
95         }
96         # tapelist uses '0' for new tapes; devices use 'X'..
97         $stamp = '0' if ($stamp eq 'X');
98         $reuse = $reuse ne 'no-reuse';
99         $tapelist->remove_tapelabel($label);
100         $tapelist->add_tapelabel($stamp, $label, "", $reuse);
101         $tapelist->write();
102         $slot_label{$slot} = $label;
103         #open(my $fh, ">>", $tapelist_filename) or die("opening tapelist_filename: $!");
104         #print $fh "$stamp $label $reuse\n";
105         #close($fh);
106     }
107 }
108
109 # run the mainloop around a scan
110 sub run_scan {
111     my ($ts) = @_;
112     my ($error, $res, $label, $mode);
113
114     my $result_cb = make_cb(result_cb => sub {
115         ($error, $res, $label, $mode) = @_;
116
117         $error = "$error" if defined $error;
118         if ($res) {
119             $res->release(finished_cb => sub {
120                 Amanda::MainLoop::quit();
121             });
122         } else {
123             Amanda::MainLoop::quit();
124         }
125     });
126
127     $ts->scan(result_cb => $result_cb);
128     Amanda::MainLoop::run();
129     return $error, $label, $mode;
130 }
131
132 # set the current slot on the changer
133 sub set_current_slot {
134     my ($slot) = @_;
135
136     unlink("$taperoot/data");
137     symlink("slot$slot", "$taperoot/data");
138 }
139
140 # set up and load a config
141 my $testconf = Installcheck::Config->new();
142 $testconf->add_param("tapelist", "\"$tapelist\"");
143 $testconf->add_param("labelstr", "\"TEST-[0-9]+\"");
144 $testconf->write();
145 my $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
146 if ($cfg_result != $CFGERR_OK) {
147     my ($level, @errors) = Amanda::Config::config_errors();
148     die(join "\n", @errors);
149 }
150
151 reset_taperoot(6);
152 $tapelist->clear_tapelist();
153 $tapelist->write();
154 label_slot(1, "TEST-10", "20090424173011", "reuse", 1);
155 label_slot(2, "TEST-20", "20090424173022", "reuse", 1);
156 label_slot(3, "TEST-30", "20090424173033", "reuse", 1);
157
158 my $chg;
159 my $taperscan;
160 my @results;
161
162 # set up a oldest taperscan
163 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
164 $taperscan = Amanda::Taper::Scan->new(
165     tapelist  => $tapelist,
166     algorithm => "oldest",
167     tapecycle => 4,
168     changer => $chg);
169 @results = run_scan($taperscan);
170 is_deeply([ @results ],
171           [ "No acceptable volumes found", undef, undef ],
172           "no reusable tapes -> error")
173           or diag(Dumper(\@results));
174 $taperscan->quit();
175
176 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
177 $taperscan = Amanda::Taper::Scan->new(
178     tapelist  => $tapelist,
179     algorithm => "oldest",
180     tapecycle => 3,
181     changer => $chg);
182 @results = run_scan($taperscan);
183 is_deeply([ @results ],
184           [ undef, "TEST-10", $ACCESS_WRITE ],
185           "finds the best reusable tape")
186           or diag(Dumper(\@results));
187 $taperscan->quit();
188
189 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
190 set_current_slot(2);
191 $taperscan = Amanda::Taper::Scan->new(
192     tapelist  => $tapelist,
193     algorithm => "oldest",
194     tapecycle => 1,
195     changer => $chg);
196 @results = run_scan($taperscan);
197 is_deeply([ @results ],
198           [ undef, "TEST-10", $ACCESS_WRITE ],
199           "finds the first reusable tape")
200           or diag(Dumper(\@results));
201 $taperscan->quit();
202
203 label_slot(4, "TEST-40", "20090424173030", "reuse", 1);
204 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
205 $taperscan = Amanda::Taper::Scan->new(
206     tapelist  => $tapelist,
207     algorithm => "oldest",
208     tapecycle => 1,
209     changer => $chg);
210 @results = run_scan($taperscan);
211 is_deeply([ @results ],
212           [ undef, "TEST-10", $ACCESS_WRITE ],
213           "finds the first reusable tape")
214           or diag(Dumper(\@results));
215 $taperscan->quit();
216
217 label_slot(4, "TEST-40", "X", "reuse", 1);
218 label_slot(5, "TEST-35", "X", "reuse", 1);
219 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
220 $taperscan = Amanda::Taper::Scan->new(
221     tapelist  => $tapelist,
222     algorithm => "oldest",
223     tapecycle => 2,
224     changer => $chg);
225 @results = run_scan($taperscan);
226 is_deeply([ @results ],
227           [ undef, "TEST-35", $ACCESS_WRITE ],
228           "finds the first reusable tape")
229           or diag(Dumper(\@results));
230 $taperscan->quit();
231
232 $chg = Amanda::Changer->new("chg-disk:$taperoot",
233                         tapelist => $tapelist,
234                         autolabel => { 'template'     => "TEST-%0",
235                                        'empty'        => 1,
236                                        'volume_error' => 1});
237 $taperscan = Amanda::Taper::Scan->new(
238     tapelist  => $tapelist,
239     algorithm => "oldest",
240     tapecycle => 2,
241     changer => $chg);
242 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
243 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
244 @results = run_scan($taperscan);
245 is_deeply([ @results ],
246           [ undef, "TEST-50", $ACCESS_WRITE ],
247           "labels new tapes in blank slots")
248           or diag(Dumper(\@results));
249 $taperscan->quit();
250
251 $chg = Amanda::Changer->new("chg-disk:$taperoot",
252                         tapelist => $tapelist);
253 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
254 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
255 # simulate "amlabel"
256 label_slot(1, "TEST-60", "X", "reuse", 1);
257 $taperscan = Amanda::Taper::Scan->new(
258     tapelist  => $tapelist,
259     algorithm => "oldest",
260     tapecycle => 2,
261     changer => $chg);
262 set_current_slot(2);
263 @results = run_scan($taperscan);
264 is_deeply([ @results ],
265           [ undef, "TEST-35", $ACCESS_WRITE ],
266           "scans for volumes, even with a newly labeled volume available")
267           or diag(Dumper(\@results));
268 $taperscan->quit();
269
270 # test new_labeled with autolabel
271 reset_taperoot(5);
272 $tapelist->clear_tapelist();
273 $tapelist->write();
274 label_slot(1, "TEST-10", "20090424173011", "reuse", 1);
275 label_slot(2, "TEST-20", "20090424173033", "reuse", 1);
276 label_slot(4, "TEST-30", "20090424173022", "reuse", 1);
277 label_slot(3, "TEST-15", "X", "reuse", 1);
278 label_slot(5, "TEST-25", "X", "reuse", 1);
279 set_current_slot(2);
280
281 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist,
282                              autolabel => { 'template'     => "TEST-%0",
283                                             'empty'        => 1,
284                                             'volume_error' => 1});
285 set_current_slot(1);
286
287 $taperscan = Amanda::Taper::Scan->new(
288     tapelist  => $tapelist,
289     algorithm => "oldest",
290     tapecycle => 1,
291     changer => $chg);
292 $taperscan->{'scan_conf'}->{'new_labeled'} = 'soon';
293 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
294 @results = run_scan($taperscan);
295 is_deeply([ @results ],
296           [ undef, "TEST-25", $ACCESS_WRITE ],
297           "autolabel soon")
298           or diag(Dumper(\@results));
299
300 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
301 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
302 @results = run_scan($taperscan);
303 is_deeply([ @results ],
304           [ undef, "TEST-25", $ACCESS_WRITE ],
305           "autolabel order")
306           or diag(Dumper(\@results));
307
308 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
309 $taperscan->{'scan_conf'}->{'new_volume'} = 'last';
310 @results = run_scan($taperscan);
311 is_deeply([ @results ],
312           [ undef, "TEST-10", $ACCESS_WRITE ],
313           "autolabel last")
314           or diag(Dumper(\@results));
315 $taperscan->quit();
316
317 # test new_labeled with autolabel
318 reset_taperoot(5);
319 $tapelist->clear_tapelist();
320 $tapelist->write();
321 label_slot(1, "TEST-10", "20090424173011", "reuse", 1);
322 label_slot(2, "TEST-20", "20090424173033", "reuse", 1);
323 label_slot(4, "TEST-30", "20090424173022", "reuse", 1);
324 label_slot(3, "TEST-15", "X", "reuse", 1);
325 set_current_slot(2);
326
327 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist,
328                              autolabel => { 'template'     => "TEST-%0",
329                                             'empty'        => 1,
330                                             'volume_error' => 1});
331 set_current_slot(1);
332
333 $taperscan = Amanda::Taper::Scan->new(
334     tapelist  => $tapelist,
335     algorithm => "oldest",
336     tapecycle => 1,
337     changer => $chg);
338 $taperscan->{'scan_conf'}->{'new_labeled'} = 'soon';
339 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
340 @results = run_scan($taperscan);
341 is_deeply([ @results ],
342           [ undef, "TEST-15", $ACCESS_WRITE ],
343           "autolabel soon")
344           or diag(Dumper(\@results));
345
346 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
347 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
348 @results = run_scan($taperscan);
349 is_deeply([ @results ],
350           [ undef, "TEST-40", $ACCESS_WRITE ],
351           "autolabel order")
352           or diag(Dumper(\@results));
353
354 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
355 $taperscan->{'scan_conf'}->{'new_volume'} = 'last';
356 @results = run_scan($taperscan);
357 is_deeply([ @results ],
358           [ undef, "TEST-10", $ACCESS_WRITE ],
359           "autolabel last")
360           or diag(Dumper(\@results));
361
362 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
363 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
364 @results = run_scan($taperscan);
365 is_deeply([ @results ],
366           [ undef, "TEST-40", $ACCESS_WRITE ],
367           "autolabel last")
368           or diag(Dumper(\@results));
369
370 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
371 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
372 @results = run_scan($taperscan);
373 is_deeply([ @results ],
374           [ undef, "TEST-40", $ACCESS_WRITE ],
375           "autolabel last")
376           or diag(Dumper(\@results));
377 $taperscan->quit();
378
379 # test new_labeled with autolabel
380 reset_taperoot(5);
381 $tapelist->clear_tapelist();
382 $tapelist->write();
383 label_slot(1, "TEST-10", "20090424173011", "reuse", 1);
384 label_slot(2, "TEST-20", "20090424173022", "reuse", 1);
385 label_slot(4, "TEST-30", "20090424173033", "reuse", 1);
386 label_slot(3, "TEST-15", "X", "reuse", 1);
387 set_current_slot(2);
388
389 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist,
390                              autolabel => { 'template'     => "TEST-%0",
391                                             'empty'        => 1,
392                                             'volume_error' => 1});
393 set_current_slot(1);
394
395 $taperscan = Amanda::Taper::Scan->new(
396     tapelist  => $tapelist,
397     algorithm => "oldest",
398     tapecycle => 1,
399     changer => $chg);
400 $taperscan->{'scan_conf'}->{'new_labeled'} = 'soon';
401 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
402 @results = run_scan($taperscan);
403 is_deeply([ @results ],
404           [ undef, "TEST-15", $ACCESS_WRITE ],
405           "autolabel soon")
406           or diag(Dumper(\@results));
407
408 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
409 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
410 @results = run_scan($taperscan);
411 is_deeply([ @results ],
412           [ undef, "TEST-40", $ACCESS_WRITE ],
413           "autolabel order")
414           or diag(Dumper(\@results));
415
416 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
417 $taperscan->{'scan_conf'}->{'new_volume'} = 'last';
418 @results = run_scan($taperscan);
419 is_deeply([ @results ],
420           [ undef, "TEST-10", $ACCESS_WRITE ],
421           "autolabel last")
422           or diag(Dumper(\@results));
423
424 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
425 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
426 @results = run_scan($taperscan);
427 is_deeply([ @results ],
428           [ undef, "TEST-40", $ACCESS_WRITE ],
429           "autolabel last")
430           or diag(Dumper(\@results));
431
432 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
433 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
434 @results = run_scan($taperscan);
435 is_deeply([ @results ],
436           [ undef, "TEST-40", $ACCESS_WRITE ],
437           "autolabel last")
438           or diag(Dumper(\@results));
439 $taperscan->quit();
440
441 # test new_volume with autolabel
442 reset_taperoot(5);
443 $tapelist->clear_tapelist();
444 $tapelist->write();
445 label_slot(1, "TEST-10", "20090424173011", "reuse", 1);
446 label_slot(2, "TEST-20", "20090424173033", "reuse", 1);
447 label_slot(4, "TEST-30", "20090424173022", "reuse", 1);
448 set_current_slot(2);
449
450 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist,
451                              autolabel => { 'template'     => "TEST-%0",
452                                             'empty'        => 1,
453                                             'volume_error' => 1});
454 set_current_slot(1);
455
456 $taperscan = Amanda::Taper::Scan->new(
457     tapelist  => $tapelist,
458     algorithm => "oldest",
459     tapecycle => 1,
460     changer => $chg);
461 $taperscan->{'scan_conf'}->{'new_labeled'} = 'soon';
462 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
463 @results = run_scan($taperscan);
464 is_deeply([ @results ],
465           [ undef, "TEST-40", $ACCESS_WRITE ],
466           "autolabel soon")
467           or diag(Dumper(\@results));
468
469 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
470 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
471 @results = run_scan($taperscan);
472 is_deeply([ @results ],
473           [ undef, "TEST-40", $ACCESS_WRITE ],
474           "autolabel order")
475           or diag(Dumper(\@results));
476
477 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
478 $taperscan->{'scan_conf'}->{'new_volume'} = 'last';
479 @results = run_scan($taperscan);
480 is_deeply([ @results ],
481           [ undef, "TEST-10", $ACCESS_WRITE ],
482           "autolabel last")
483           or diag(Dumper(\@results));
484 $taperscan->quit();
485
486 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist,
487                              autolabel => { 'template'     => "TEST-%0",
488                                             'empty'        => 1,
489                                             'volume_error' => 1});
490 $taperscan = Amanda::Taper::Scan->new(
491     tapelist  => $tapelist,
492     algorithm => "oldest",
493     tapecycle => 4,
494     changer => $chg);
495 $taperscan->{'scan_conf'}->{'new_labeled'} = 'soon';
496 $taperscan->{'scan_conf'}->{'new_volume'} = 'soon';
497 @results = run_scan($taperscan);
498 is_deeply([ @results ],
499           [ undef, "TEST-40", $ACCESS_WRITE ],
500           "autolabel soon")
501           or diag(Dumper(\@results));
502
503 $taperscan->{'scan_conf'}->{'new_labeled'} = 'order';
504 $taperscan->{'scan_conf'}->{'new_volume'} = 'order';
505 @results = run_scan($taperscan);
506 is_deeply([ @results ],
507           [ undef, "TEST-40", $ACCESS_WRITE ],
508           "autolabel order")
509           or diag(Dumper(\@results));
510
511 $taperscan->{'scan_conf'}->{'new_labeled'} = 'last';
512 $taperscan->{'scan_conf'}->{'new_volume'} = 'last';
513 @results = run_scan($taperscan);
514 is_deeply([ @results ],
515           [ undef, "TEST-40", $ACCESS_WRITE ],
516           "autolabel last")
517           or diag(Dumper(\@results));
518 $taperscan->quit();
519
520 # test skipping no-reuse tapes
521 reset_taperoot(5);
522 $tapelist->clear_tapelist();
523 $tapelist->write();
524 label_slot(1, "TEST-1", "20090424173001", "no-reuse", 1);
525 label_slot(2, "TEST-2", "20090424173002", "reuse", 1);
526 label_slot(3, "TEST-3", "20090424173003", "reuse", 1);
527 label_slot(4, "TEST-4", "20090424173004", "reuse", 1);
528
529 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
530 set_current_slot(1);
531
532 $taperscan = Amanda::Taper::Scan->new(
533     tapelist  => $tapelist,
534     algorithm => "oldest",
535     tapecycle => 2,
536     tapecycle => 1,
537     changer => $chg);
538 @results = run_scan($taperscan);
539 is_deeply([ @results ],
540           [ undef, "TEST-2", $ACCESS_WRITE ],
541           "skips a no-reuse volume")
542           or diag(Dumper(\@results));
543 $taperscan->quit();
544
545 rmtree($taperoot);
546 unlink($tapelist);