3 # Catch for sh/csh on systems without #! ability.
4 eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}'
5 & eval 'exec @PERL@ -S $0 $argv:q'
9 # This changer script controls tape libraries on operating systems that have a
11 # DSL 7000 on FreeBSD is an example
13 # The changer being used is a n tape juke, that can be used with 1, n-1 or n
14 # tapes in the juke. The special slot is slot n. The script does not
15 # make assumptions about the number of slots, except that the special slot
16 # is the highest number. The slot is special in the sense that it contains the
17 # the only tape if the juke contains 1 tape and contains no tape if the juke
18 # contains n-1 tapes. See getCurrentTape.
20 # Furthermore, the script uses drive 0 and assumes that the device is able to
21 # figure itself how to move a type from slot m to drive 0 if asked to do so and
22 # multiple pickers are present.
24 # The numbering of the slots is by the way from 1 to n with slots. The chio
25 # program returns the slot numbers numbered from 0 to n-1 however.
27 # This script is built up out of bits and pieces of the other scripts
28 # and no credits are claimed. Most notably the chg-rth.pl script was used. That
29 # script was written by Erik Frederick, <edf@tyrell.mc.duke.edu>.
31 # Permission to freely use and distribute is granted (by me and was granted by
32 # the original authors).
34 # Nick Hibma - nick.hibma@jrc.it
39 ($progname = $0) =~ s#/.*/##;
46 if (-d "@AMANDA_DBGDIR@") {
47 $logfile = "@AMANDA_DBGDIR@/changer.debug";
49 $logfile = "/dev/null";
51 die "$progname: cannot open $logfile: $ERRNO\n"
52 unless (open (LOG, ">> $logfile"));
55 # get the information from the configuration file
59 $prefix=$prefix; # avoid warnings about possible typo
60 $exec_prefix="@exec_prefix@";
61 $exec_prefix=$exec_prefix; # Ditto
63 if ( "@USE_VERSION_SUFFIXES@" eq "yes" ) {
69 chomp ($tapeDevice = `$sbindir/amgetconf$SUF tapedev 2>&1`);
70 die "tapedev not found in amanda.conf"
71 if !$tapeDevice or $tapeDevice =~ m/BUGGY/;
72 chomp ($changerDevice = `$sbindir/amgetconf$SUF changerdev 2>&1`);
74 die "changerdev not found in amanda.conf"
75 if !$changerDevice or $changerDevice =~ m/BUGGY/;
78 # Initialise a few global variables
87 @dow = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
88 @moy = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
89 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
96 # Get the local time for the value.
99 @t = localtime (time ());
105 $r = sprintf "%s %s %2d %2d:%02d:%02d %4d",
116 print LOG &do_time(), ": enter: getCurrentTape\n";
119 # Determines the slot number for the tape that is currently in the
120 # drive. getTapeParams and getTapeStatus should have been called.
121 # If there is no tape in the drive, no current tape, 0 is returned.
126 if ( !$drives[0] ) { # drive empty
128 } elsif ( $nr_tapes == 1 ) { # one tape -> comes from slot max_slot
130 } else { # find first empty slot
132 while ( $i < $#slots and $slots[$i] ) {
138 print LOG &do_time(), ": leave: getCurrentTape: $i\n";
143 print LOG &do_time(), ": enter: getTapeStatus\n";
146 # Sets $nr_tapes, @slots, @drives, $current_tape
149 my($type,$num,$status);
151 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice status\n";
152 if ( !(open(FH,"@CHIO@ -f $changerDevice status|")) ) {
153 print "$progname: '@CHIO@ -f $changerDevice status' failed, $!\n";
158 # This routine requires the format of the output of 'chio status' to
162 # slot 1: <ACCESS,FULL>
163 # slot 2: <ACCESS,FULL>
165 # drive 0: <ACCESS,FULL>
171 while( defined ($line = <FH>) ) {
173 print LOG &do_time(), ": $line\n";
174 next unless $line =~ m/(\w+)\s+(\d+):\s*<([^>]+)>/;
175 ($type,$num,$status) = ($1,$2,$3);
176 if ( $type =~ m/slot/i ) {
177 $slots[$num] = ( $status =~ m/full/i ) ? 1 : 0;
178 if ($slots[ $num ]) { $nr_tapes++ }
179 } elsif ( $type =~ m/drive/i ) {
181 if ( $status =~ m/full/i ) {
186 # ignore 'picker', empty ones, etc...
191 if ( $nr_tapes == 0 ) {
192 print "$progname: No tapes in changer!\n";
196 $currentTape = &getCurrentTape();
198 print LOG &do_time(), ": leave: getTapeStatus: $nr_tapes\n";
203 print LOG &do_time(), ": enter: getTapeParams\n";
206 # Requests information on the number of slots, pickers and drives
210 my($max_slot,$max_drive,$max_picker);
212 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice params\n";
213 if ( !open(FH,"@CHIO@ -f $changerDevice params|") ) {
214 print "$progname: '@CHIO@ -f $changerDevice params' failed, $!\n";
219 # the format of the output of 'chio params' should be
220 # /dev/ch0: 8 slots, 1 drive, 1 picker
221 # /dev/ch0: current picker: 0
228 while( defined ($line = <FH>) ) {
230 print LOG &do_time(), ": $line\n";
231 $max_slot = $1 if $line =~ m/(\d+) slot/i;
232 $max_drive = $1 if $line =~ m/(\d+) drive/i;
233 $max_picker = $1 if $line =~ m/(\d+) picker/i;
237 if ( $max_drive == 0 or $max_picker == -1 ) {
238 print "$progname: No drive or picker ? ($max_drive/$max_picker)\n";
242 print LOG &do_time(), ": leave: getTapeParams: $max_slot, $max_drive, $max_picker\n";
243 return ($max_slot, $max_drive, $max_picker);
250 # Check a few parameters to avoid the most serious problems
254 if $currentTape == $tape;
256 if( $slots[$tape-1] == 0 ) {
257 print "<none> $progname: no tape in slot requested\n";
260 if( $tape > $max_slot ) {
261 print $tape," $progname: requested a tape > $max_slot\n";
265 print $tape," $progname: requested a tape < 1\n";
273 print LOG &do_time(), ": enter: Load: $tape\n";
276 # Load tape $tape into drive 0
279 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice move slot ", $tape - 1, " drive 0\n";
280 if ( system("@CHIO@ -f $changerDevice move slot ".($tape-1)." drive 0") ) {
281 print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape into drive 0\n";
284 print LOG &do_time(), ": leave: Load\n";
289 print LOG &do_time(), ": enter: Unload: $tape\n";
292 # Unload the tape from drive 0 and put it into the slot specified by
297 # Ecrix AutoPAK devices (based on the Spectra Logics 215 changer)
298 # can lock up if you try to move a tape from a drive to an open slot
299 # without first rewinding and ejecting the tape. This appears to
300 # occur when the operation times out and the ch driver sends a device
301 # or bus reset. Ecrix claims this is about to be fixed with a new
302 # firmware rev but for now it's safest to just explicitly eject
303 # the tape before moving the cartridge.
305 if ( system ("@MT@ @MT_FILE_FLAG@ $tapeDevice offline") ) {
306 print "$progname: Warning, failed to eject the tape with '@MT@ @MT_FILE_FLAG@ $tapeDevice offline'\n";
307 # NB: not fatal; let chio try it's thing
310 if ( system("@CHIO@ -f $changerDevice move drive 0 slot ".($tape-1)." ") ) {
311 print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape from drive 0\n";
314 print LOG &do_time(), ": leave: Unload\n";
319 print LOG &do_time(), ": enter: changeTape: $tape\n";
322 # Unload current tape and load a new tape from slot $tape.
325 if ($tape != $currentTape) {
329 if( $currentTape != 0 ) {
330 &Unload($currentTape);
333 $currentTape = $tape;
335 print LOG &do_time(), ": leave: changeTape\n";
347 ($max_slot, $max_drive) = &getTapeParams();
349 $opt_slot = 0; # perl -w fodder
350 $opt_info = 0; # perl -w fodder
351 $opt_reset = 0; # perl -w fodder
352 $opt_eject = 0; # perl -w fodder
354 GetOptions("slot=s", "info", "reset", "eject");
356 $nr_tapes = &getTapeStatus();
359 # Before we do anything with the tape changer we'll have to rewind the tape
362 if (-x "$sbindir/ammt$SUF") {
363 $MT="$sbindir/ammt$SUF";
365 } elsif (-x "@MT@") {
367 $MTF="@MT_FILE_FLAG@";
369 print LOG &do_time(), ": mt program not found\n";
370 print "<none> mt program not found\n";
373 print LOG &do_time(), "MT -> $MT $MTF\n";
375 system ("$MT $MTF $tapeDevice rewind")
376 unless $currentTape == 0;
380 if ( $opt_slot =~ /first/ ) {
382 print LOG &do_time(), ": $currentTape $tapeDevice\n";
383 print "$currentTape $tapeDevice\n";
385 if ( $opt_slot =~ /last/ ) {
386 &changeTape($max_slot);
387 print LOG &do_time(), ": $currentTape $tapeDevice\n";
388 print "$currentTape $tapeDevice\n";
390 if ( $opt_slot =~ /current/ ) {
391 &changeTape($currentTape);
392 print LOG &do_time(), ": $currentTape $tapeDevice\n";
393 print "$currentTape $tapeDevice\n";
395 if ( $opt_slot =~ /next/ ) {
396 $tape = $currentTape+1;
397 if ( $tape > $max_slot ) {
400 while ( $slots[$tape-1] == 0 ) { # there is at least 1
401 if ( ++$tape > $max_slot ) {
406 print LOG &do_time(), ": $currentTape $tapeDevice\n";
407 print "$currentTape $tapeDevice\n";
409 if ( $opt_slot =~ /prev/ ) {
410 $tape = $currentTape-1;
414 while ( $slots[$tape-1] == 0 ) { # there is at least 1
420 print LOG &do_time(), ": $currentTape $tapeDevice\n";
421 print "$currentTape $tapeDevice\n";
423 if ( $opt_slot =~ /^\d+$/ ) {
424 &changeTape($opt_slot);
425 print LOG &do_time(), ": $currentTape $tapeDevice\n";
426 print "$currentTape $tapeDevice\n";
428 if ( $opt_slot =~ /advance/ ) {
429 $tape=$currentTape+1;
430 if ( $tape > $max_slot ) {
433 if ( $currentTape ) {
434 &Unload($currentTape);
436 print LOG &do_time(), ": $currentTape $tapeDevice\n";
437 print "$currentTape , /dev/null\n";
444 if ( $currentTape == 0 ) {
445 &Load(1); # load random tape
449 print LOG &do_time(), ": $currentTape $max_slot 1\n";
450 print "$currentTape $max_slot 1\n";
456 print LOG &do_time(), ": $currentTape $tapeDevice\n";
457 print "$currentTape $tapeDevice\n";
462 if ( $currentTape ) {
463 &Unload($currentTape);
464 print "0 $tapeDevice\n";
467 print "$progname: drive was not loaded\n";
472 print "$progname: No command was received. Exiting.\n";