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 => 9;
26 use lib "@amperldir@";
28 use Installcheck::Config;
29 use Installcheck::Changer;
30 use Amanda::Device qw( :constants );
33 use Amanda::Config qw( :init :getconf config_dir_relative );
35 use Amanda::Taper::Scan;
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();
44 my $taperoot = "$Installcheck::TMP/Amanda_Taper_Scan_traditional";
45 my $tapelist_filename = "$Installcheck::TMP/tapelist";
46 my $tapelist = Amanda::Tapelist->new($tapelist_filename);
58 for my $slot (1 .. $nslots) {
59 mkdir("$taperoot/slot$slot")
60 or die("Could not mkdir: $!");
63 # clear out the tapefile
64 open(my $fh, ">", $tapelist_filename) or die("opening tapelist_filename: $!");
68 my ($slot, $label, $stamp, $reuse, $update_tapelist) = @_;
70 my $drivedir = "$taperoot/tmp";
71 -d $drivedir and rmtree($drivedir);
73 symlink("$taperoot/slot$slot", "$drivedir/data");
75 my $dev = Amanda::Device->new("file:$drivedir");
76 die $dev->error_or_status() unless $dev->status == $DEVICE_STATUS_SUCCESS;
79 if (!$dev->start($ACCESS_WRITE, $label, $stamp)) {
80 die $dev->error_or_status();
88 if ($update_tapelist) {
89 # tapelist uses '0' for new tapes; devices use 'X'..
90 $stamp = '0' if ($stamp eq 'X');
91 open(my $fh, ">>", $tapelist_filename) or die("opening tapelist_filename: $!");
92 print $fh "$stamp $label $reuse\n";
97 # run the mainloop around a scan
100 my ($error, $res, $label, $mode);
102 my $result_cb = make_cb(result_cb => sub {
103 ($error, $res, $label, $mode) = @_;
106 $res->release(finished_cb => sub {
107 Amanda::MainLoop::quit();
110 Amanda::MainLoop::quit();
114 $ts->scan(result_cb => $result_cb);
115 Amanda::MainLoop::run();
116 return $error, $label, $mode;
119 # set the current slot on the changer
120 sub set_current_slot {
123 unlink("$taperoot/data");
124 symlink("slot$slot", "$taperoot/data");
127 # set up and load a config
128 my $testconf = Installcheck::Config->new();
129 $testconf->add_param("tapelist", "\"$tapelist\"");
130 $testconf->add_param("labelstr", "\"TEST-[0-9]+\"");
132 my $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
133 if ($cfg_result != $CFGERR_OK) {
134 my ($level, @errors) = Amanda::Config::config_errors();
135 die(join "\n", @errors);
139 label_slot(1, "TEST-1", "20090424173001", "reuse", 1);
140 label_slot(2, "TEST-2", "20090424173002", "reuse", 1);
141 label_slot(3, "TEST-3", "20090424173003", "reuse", 1);
147 # set up a traditional taperscan
148 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
149 $taperscan = Amanda::Taper::Scan->new(
150 tapelist => $tapelist,
151 algorithm => "traditional",
154 @results = run_scan($taperscan);
155 is_deeply([ @results ],
156 [ "No acceptable volumes found", undef, undef ],
157 "no reusable tapes -> error")
158 or diag(Dumper(\@results));
161 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
162 $taperscan = Amanda::Taper::Scan->new(
163 tapelist => $tapelist,
164 algorithm => "traditional",
167 @results = run_scan($taperscan);
168 is_deeply([ @results ],
169 [ undef, "TEST-1", $ACCESS_WRITE ],
170 "finds the best reusable tape")
171 or diag(Dumper(\@results));
174 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
175 $chg->{'support_fast_search'} = 0; # no fast search -> skip stage 1
176 set_current_slot(2); # slot 2 is acceptable, so it should be returned
177 $taperscan = Amanda::Taper::Scan->new(
178 tapelist => $tapelist,
179 algorithm => "traditional",
182 @results = run_scan($taperscan);
183 is_deeply([ @results ],
184 [ undef, "TEST-2", $ACCESS_WRITE ],
185 "finds the first reusable tape when fast_search is false")
186 or diag(Dumper(\@results));
189 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
190 $chg->{'support_fast_search'} = 1;
192 label_slot(1); # remove TEST-1
193 label_slot(4, "TEST-4", "20090424183004", "reuse", 1);
195 $taperscan = Amanda::Taper::Scan->new(
196 tapelist => $tapelist,
197 algorithm => "traditional",
200 @results = run_scan($taperscan);
201 is_deeply([ @results ],
202 [ undef, "TEST-2", $ACCESS_WRITE ],
203 "uses the first usable tape it finds when oldest is missing")
204 or diag(Dumper(\@results));
207 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
210 $taperscan = Amanda::Taper::Scan->new(
211 tapelist => $tapelist,
212 algorithm => "traditional",
215 @results = run_scan($taperscan);
216 is_deeply([ @results ],
217 [ undef, "TEST-3", $ACCESS_WRITE ],
218 "starts sequential scan at 'current'")
219 or diag(Dumper(\@results));
222 $chg = Amanda::Changer->new("chg-disk:$taperoot",
223 tapelist => $tapelist,
224 autolabel => { 'template' => "TEST-%",
226 'volume_error' => 1});
227 $taperscan = Amanda::Taper::Scan->new(
228 tapelist => $tapelist,
229 algorithm => "traditional",
233 @results = run_scan($taperscan);
234 is_deeply([ @results ],
235 [ undef, "TEST-5", $ACCESS_WRITE ],
236 "labels new tapes in blank slots")
237 or diag(Dumper(\@results));
240 $chg = Amanda::Changer->new("chg-disk:$taperoot",
241 tapelist => $tapelist,
243 $taperscan = Amanda::Taper::Scan->new(
244 tapelist => $tapelist,
245 algorithm => "traditional",
249 @results = run_scan($taperscan);
250 is_deeply([ @results ],
251 [ undef, "TEST-2", $ACCESS_WRITE ],
252 "handles an invalid current slot by going to the next")
253 or diag(Dumper(\@results));
256 $chg = Amanda::Changer->new("chg-disk:$taperoot",
257 tapelist => $tapelist);
259 label_slot(1, "TEST-6", "X", "reuse", 1);
260 $taperscan = Amanda::Taper::Scan->new(
261 tapelist => $tapelist,
262 algorithm => "traditional",
266 @results = run_scan($taperscan);
267 is_deeply([ @results ],
268 [ undef, "TEST-2", $ACCESS_WRITE ],
269 "scans for volumes, even with a newly labeled volume available")
270 or diag(Dumper(\@results));
272 # test skipping no-reuse tapes
274 label_slot(1, "TEST-1", "20090424173001", "no-reuse", 1);
275 label_slot(2, "TEST-2", "20090424173002", "reuse", 1);
276 label_slot(3, "TEST-3", "20090424173003", "reuse", 1);
277 label_slot(4, "TEST-4", "20090424173004", "reuse", 1);
280 $chg = Amanda::Changer->new("chg-disk:$taperoot", tapelist => $tapelist);
283 $taperscan = Amanda::Taper::Scan->new(
284 tapelist => $tapelist,
285 algorithm => "traditional",
288 @results = run_scan($taperscan);
289 is_deeply([ @results ],
290 [ undef, "TEST-2", $ACCESS_WRITE ],
291 "skips a no-reuse volume")
292 or diag(Dumper(\@results));