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#/.*/##;
44 delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'};
45 $ENV{'PATH'} = "/usr/bin:/usr/sbin:/sbin:/bin";
49 if (-d "@AMANDA_DBGDIR@") {
50 $logfile = "@AMANDA_DBGDIR@/changer.debug";
52 $logfile = "/dev/null";
54 die "$progname: cannot open $logfile: $ERRNO\n"
55 unless (open (LOG, ">> $logfile"));
58 # get the information from the configuration file
62 $prefix=$prefix; # avoid warnings about possible typo
63 $exec_prefix="@exec_prefix@";
64 $exec_prefix=$exec_prefix; # Ditto
66 if ( "@USE_VERSION_SUFFIXES@" eq "yes" ) {
72 chomp ($tapeDevice = `$sbindir/amgetconf$SUF tapedev 2>&1`);
73 die "tapedev not found in amanda.conf"
74 if !$tapeDevice or $tapeDevice eq "" or
75 $tapeDevice =~ m/no such parameter/;
76 chomp ($changerDevice = `$sbindir/amgetconf$SUF changerdev 2>&1`);
78 die "changerdev not found in amanda.conf"
79 if !$changerDevice or $changerDevice eq "" or
80 $changerDevice =~ m/no such parameter/;
83 # Initialise a few global variables
92 @dow = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
93 @moy = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
94 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
101 # Get the local time for the value.
104 @t = localtime (time ());
110 $r = sprintf "%s %s %2d %2d:%02d:%02d %4d",
121 print LOG &do_time(), ": enter: getCurrentTape\n";
124 # Determines the slot number for the tape that is currently in the
125 # drive. getTapeParams and getTapeStatus should have been called.
126 # If there is no tape in the drive, no current tape, 0 is returned.
131 if ( !$drives[0] ) { # drive empty
133 } elsif ( $nr_tapes == 1 ) { # one tape -> comes from slot max_slot
135 } else { # find first empty slot
137 while ( $i < $#slots and $slots[$i] ) {
143 print LOG &do_time(), ": leave: getCurrentTape: $i\n";
148 print LOG &do_time(), ": enter: getTapeStatus\n";
151 # Sets $nr_tapes, @slots, @drives, $current_tape
154 my($type,$num,$status);
156 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice status\n";
157 if ( !(open(FH,"@CHIO@ -f $changerDevice status|")) ) {
158 print "$progname: '@CHIO@ -f $changerDevice status' failed, $!\n";
163 # This routine requires the format of the output of 'chio status' to
167 # slot 1: <ACCESS,FULL>
168 # slot 2: <ACCESS,FULL>
170 # drive 0: <ACCESS,FULL>
176 while( defined ($line = <FH>) ) {
178 print LOG &do_time(), ": $line\n";
179 next unless $line =~ m/(\w+)\s+(\d+):\s*<([^>]+)>/;
180 ($type,$num,$status) = ($1,$2,$3);
181 if ( $type =~ m/slot/i ) {
182 $slots[$num] = ( $status =~ m/full/i ) ? 1 : 0;
183 if ($slots[ $num ]) { $nr_tapes++ }
184 } elsif ( $type =~ m/drive/i ) {
186 if ( $status =~ m/full/i ) {
191 # ignore 'picker', empty ones, etc...
196 if ( $nr_tapes == 0 ) {
197 print "$progname: No tapes in changer!\n";
201 $currentTape = &getCurrentTape();
203 print LOG &do_time(), ": leave: getTapeStatus: $nr_tapes\n";
208 print LOG &do_time(), ": enter: getTapeParams\n";
211 # Requests information on the number of slots, pickers and drives
215 my($max_slot,$max_drive,$max_picker);
217 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice params\n";
218 if ( !open(FH,"@CHIO@ -f $changerDevice params|") ) {
219 print "$progname: '@CHIO@ -f $changerDevice params' failed, $!\n";
224 # the format of the output of 'chio params' should be
225 # /dev/ch0: 8 slots, 1 drive, 1 picker
226 # /dev/ch0: current picker: 0
233 while( defined ($line = <FH>) ) {
235 print LOG &do_time(), ": $line\n";
236 $max_slot = $1 if $line =~ m/(\d+) slot/i;
237 $max_drive = $1 if $line =~ m/(\d+) drive/i;
238 $max_picker = $1 if $line =~ m/(\d+) picker/i;
242 if ( $max_drive == 0 or $max_picker == -1 ) {
243 print "$progname: No drive or picker ? ($max_drive/$max_picker)\n";
247 print LOG &do_time(), ": leave: getTapeParams: $max_slot, $max_drive, $max_picker\n";
248 return ($max_slot, $max_drive, $max_picker);
255 # Check a few parameters to avoid the most serious problems
259 if $currentTape == $tape;
261 if( $slots[$tape-1] == 0 ) {
262 print "<none> $progname: no tape in slot requested\n";
265 if( $tape > $max_slot ) {
266 print $tape," $progname: requested a tape > $max_slot\n";
270 print $tape," $progname: requested a tape < 1\n";
278 print LOG &do_time(), ": enter: Load: $tape\n";
281 # Load tape $tape into drive 0
284 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice move slot ", $tape - 1, " drive 0\n";
285 if ( system("@CHIO@ -f $changerDevice move slot ".($tape-1)." drive 0") ) {
286 print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape into drive 0\n";
290 # wait for tape to load
292 while ( $count > 0 &&
293 system("$MT $MTF $tapeDevice status > /dev/null 2>&1" ) ) {
294 print LOG &do_time(), ": waiting for tape to load\n";
299 print LOG &do_time(), ": leave: Load\n";
304 print LOG &do_time(), ": enter: Unload: $tape\n";
307 # Unload the tape from drive 0 and put it into the slot specified by
312 # Ecrix AutoPAK devices (based on the Spectra Logics 215 changer)
313 # can lock up if you try to move a tape from a drive to an open slot
314 # without first rewinding and ejecting the tape. This appears to
315 # occur when the operation times out and the ch driver sends a device
316 # or bus reset. Ecrix claims this is about to be fixed with a new
317 # firmware rev but for now it's safest to just explicitly eject
318 # the tape before moving the cartridge.
320 if ( system ("$MT $MTF $tapeDevice offline") ) {
321 print "$progname: Warning, failed to eject the tape with '$MT $MTF $tapeDevice offline'\n";
322 # NB: not fatal; let chio try it's thing
325 if ( system("@CHIO@ -f $changerDevice move drive 0 slot ".($tape-1)." ") ) {
326 print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape from drive 0\n";
329 print LOG &do_time(), ": leave: Unload\n";
334 print LOG &do_time(), ": enter: changeTape: $tape\n";
337 # Unload current tape and load a new tape from slot $tape.
340 if ($tape != $currentTape) {
344 if( $currentTape != 0 ) {
345 &Unload($currentTape);
348 $currentTape = $tape;
350 print LOG &do_time(), ": leave: changeTape\n";
362 ($max_slot, $max_drive) = &getTapeParams();
364 $opt_slot = 0; # perl -w fodder
365 $opt_info = 0; # perl -w fodder
366 $opt_reset = 0; # perl -w fodder
367 $opt_eject = 0; # perl -w fodder
369 GetOptions("slot=s", "info", "reset", "eject");
371 $nr_tapes = &getTapeStatus();
374 # Before we do anything with the tape changer we'll have to rewind the tape
377 if (-x "$sbindir/ammt$SUF") {
378 $MT="$sbindir/ammt$SUF";
380 } elsif (-x "@MT@") {
382 $MTF="@MT_FILE_FLAG@";
384 print LOG &do_time(), ": mt program not found\n";
385 print "<none> mt program not found\n";
388 print LOG &do_time(), ": MT -> $MT $MTF\n";
390 system ("$MT $MTF $tapeDevice rewind")
391 unless $currentTape == 0;
395 if ( $opt_slot =~ /first/ ) {
397 print LOG &do_time(), ": $currentTape $tapeDevice\n";
398 print "$currentTape $tapeDevice\n";
400 if ( $opt_slot =~ /last/ ) {
401 &changeTape($max_slot);
402 print LOG &do_time(), ": $currentTape $tapeDevice\n";
403 print "$currentTape $tapeDevice\n";
405 if ( $opt_slot =~ /current/ ) {
406 &changeTape($currentTape);
407 print LOG &do_time(), ": $currentTape $tapeDevice\n";
408 print "$currentTape $tapeDevice\n";
410 if ( $opt_slot =~ /next/ ) {
411 $tape = $currentTape+1;
412 if ( $tape > $max_slot ) {
415 while ( $slots[$tape-1] == 0 ) { # there is at least 1
416 if ( ++$tape > $max_slot ) {
421 print LOG &do_time(), ": $currentTape $tapeDevice\n";
422 print "$currentTape $tapeDevice\n";
424 if ( $opt_slot =~ /prev/ ) {
425 $tape = $currentTape-1;
429 while ( $slots[$tape-1] == 0 ) { # there is at least 1
435 print LOG &do_time(), ": $currentTape $tapeDevice\n";
436 print "$currentTape $tapeDevice\n";
438 if ( $opt_slot =~ /^\d+$/ ) {
439 &changeTape($opt_slot);
440 print LOG &do_time(), ": $currentTape $tapeDevice\n";
441 print "$currentTape $tapeDevice\n";
443 if ( $opt_slot =~ /advance/ ) {
444 $tape=$currentTape+1;
445 if ( $tape > $max_slot ) {
448 if ( $currentTape ) {
449 &Unload($currentTape);
451 print LOG &do_time(), ": $currentTape $tapeDevice\n";
452 print "$currentTape , /dev/null\n";
459 if ( $currentTape == 0 ) {
460 &Load(1); # load random tape
464 print LOG &do_time(), ": $currentTape $max_slot 1\n";
465 print "$currentTape $max_slot 1\n";
471 print LOG &do_time(), ": $currentTape $tapeDevice\n";
472 print "$currentTape $tapeDevice\n";
477 if ( $currentTape ) {
478 &Unload($currentTape);
479 print "0 $tapeDevice\n";
482 print "$progname: drive was not loaded\n";
487 print "$progname: No command was received. Exiting.\n";