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 chomp ($tapeDevice = `$sbindir/amgetconf tapedev 2>&1`);
67 die "tapedev not found in amanda.conf"
68 if !$tapeDevice or $tapeDevice eq "" or
69 $tapeDevice =~ m/no such parameter/;
70 chomp ($changerDevice = `$sbindir/amgetconf changerdev 2>&1`);
72 die "changerdev not found in amanda.conf"
73 if !$changerDevice or $changerDevice eq "" or
74 $changerDevice =~ m/no such parameter/;
77 # Initialise a few global variables
86 @dow = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
87 @moy = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
88 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
95 # Get the local time for the value.
98 @t = localtime (time ());
104 $r = sprintf "%s %s %2d %2d:%02d:%02d %4d",
115 print LOG &do_time(), ": enter: getCurrentTape\n";
118 # Determines the slot number for the tape that is currently in the
119 # drive. getTapeParams and getTapeStatus should have been called.
120 # If there is no tape in the drive, no current tape, 0 is returned.
125 if ( !$drives[0] ) { # drive empty
127 } elsif ( $nr_tapes == 1 ) { # one tape -> comes from slot max_slot
129 } else { # find first empty slot
131 while ( $i < $#slots and $slots[$i] ) {
137 print LOG &do_time(), ": leave: getCurrentTape: $i\n";
142 print LOG &do_time(), ": enter: getTapeStatus\n";
145 # Sets $nr_tapes, @slots, @drives, $current_tape
148 my($type,$num,$status);
150 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice status\n";
151 if ( !(open(FH,"@CHIO@ -f $changerDevice status|")) ) {
152 print "$progname: '@CHIO@ -f $changerDevice status' failed, $!\n";
157 # This routine requires the format of the output of 'chio status' to
161 # slot 1: <ACCESS,FULL>
162 # slot 2: <ACCESS,FULL>
164 # drive 0: <ACCESS,FULL>
170 while( defined ($line = <FH>) ) {
172 print LOG &do_time(), ": $line\n";
173 next unless $line =~ m/(\w+)\s+(\d+):\s*<([^>]+)>/;
174 ($type,$num,$status) = ($1,$2,$3);
175 if ( $type =~ m/slot/i ) {
176 $slots[$num] = ( $status =~ m/full/i ) ? 1 : 0;
177 if ($slots[ $num ]) { $nr_tapes++ }
178 } elsif ( $type =~ m/drive/i ) {
180 if ( $status =~ m/full/i ) {
185 # ignore 'picker', empty ones, etc...
190 if ( $nr_tapes == 0 ) {
191 print "$progname: No tapes in changer!\n";
195 $currentTape = &getCurrentTape();
197 print LOG &do_time(), ": leave: getTapeStatus: $nr_tapes\n";
202 print LOG &do_time(), ": enter: getTapeParams\n";
205 # Requests information on the number of slots, pickers and drives
209 my($max_slot,$max_drive,$max_picker);
211 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice params\n";
212 if ( !open(FH,"@CHIO@ -f $changerDevice params|") ) {
213 print "$progname: '@CHIO@ -f $changerDevice params' failed, $!\n";
218 # the format of the output of 'chio params' should be
219 # /dev/ch0: 8 slots, 1 drive, 1 picker
220 # /dev/ch0: current picker: 0
227 while( defined ($line = <FH>) ) {
229 print LOG &do_time(), ": $line\n";
230 $max_slot = $1 if $line =~ m/(\d+) slot/i;
231 $max_drive = $1 if $line =~ m/(\d+) drive/i;
232 $max_picker = $1 if $line =~ m/(\d+) picker/i;
236 if ( $max_drive == 0 or $max_picker == -1 ) {
237 print "$progname: No drive or picker ? ($max_drive/$max_picker)\n";
241 print LOG &do_time(), ": leave: getTapeParams: $max_slot, $max_drive, $max_picker\n";
242 return ($max_slot, $max_drive, $max_picker);
249 # Check a few parameters to avoid the most serious problems
253 if $currentTape == $tape;
255 if( $slots[$tape-1] == 0 ) {
256 print "<none> $progname: no tape in slot requested\n";
259 if( $tape > $max_slot ) {
260 print $tape," $progname: requested a tape > $max_slot\n";
264 print $tape," $progname: requested a tape < 1\n";
272 print LOG &do_time(), ": enter: Load: $tape\n";
275 # Load tape $tape into drive 0
278 print LOG &do_time(), ": running: @CHIO@ -f $changerDevice move slot ", $tape - 1, " drive 0\n";
279 if ( system("@CHIO@ -f $changerDevice move slot ".($tape-1)." drive 0") ) {
280 print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape into drive 0\n";
284 # wait for tape to load
286 while ( $count > 0 &&
287 system("$MT $MTF $tapeDevice status > /dev/null 2>&1" ) ) {
288 print LOG &do_time(), ": waiting for tape to load\n";
293 print LOG &do_time(), ": leave: Load\n";
298 print LOG &do_time(), ": enter: Unload: $tape\n";
301 # Unload the tape from drive 0 and put it into the slot specified by
306 # Ecrix AutoPAK devices (based on the Spectra Logics 215 changer)
307 # can lock up if you try to move a tape from a drive to an open slot
308 # without first rewinding and ejecting the tape. This appears to
309 # occur when the operation times out and the ch driver sends a device
310 # or bus reset. Ecrix claims this is about to be fixed with a new
311 # firmware rev but for now it's safest to just explicitly eject
312 # the tape before moving the cartridge.
314 if ( system ("$MT $MTF $tapeDevice offline") ) {
315 print "$progname: Warning, failed to eject the tape with '$MT $MTF $tapeDevice offline'\n";
316 # NB: not fatal; let chio try it's thing
319 if ( system("@CHIO@ -f $changerDevice move drive 0 slot ".($tape-1)." ") ) {
320 print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape from drive 0\n";
323 print LOG &do_time(), ": leave: Unload\n";
328 print LOG &do_time(), ": enter: changeTape: $tape\n";
331 # Unload current tape and load a new tape from slot $tape.
334 if ($tape != $currentTape) {
338 if( $currentTape != 0 ) {
339 &Unload($currentTape);
342 $currentTape = $tape;
344 print LOG &do_time(), ": leave: changeTape\n";
356 ($max_slot, $max_drive) = &getTapeParams();
358 $opt_slot = 0; # perl -w fodder
359 $opt_info = 0; # perl -w fodder
360 $opt_reset = 0; # perl -w fodder
361 $opt_eject = 0; # perl -w fodder
363 GetOptions("slot=s", "info", "reset", "eject");
365 $nr_tapes = &getTapeStatus();
368 # Before we do anything with the tape changer we'll have to rewind the tape
371 if (-x "$sbindir/ammt") {
374 } elsif (-x "@MT@") {
376 $MTF="@MT_FILE_FLAG@";
378 print LOG &do_time(), ": mt program not found\n";
379 print "<none> mt program not found\n";
382 print LOG &do_time(), ": MT -> $MT $MTF\n";
384 system ("$MT $MTF $tapeDevice rewind")
385 unless $currentTape == 0;
389 if ( $opt_slot =~ /first/ ) {
391 print LOG &do_time(), ": $currentTape $tapeDevice\n";
392 print "$currentTape $tapeDevice\n";
394 if ( $opt_slot =~ /last/ ) {
395 &changeTape($max_slot);
396 print LOG &do_time(), ": $currentTape $tapeDevice\n";
397 print "$currentTape $tapeDevice\n";
399 if ( $opt_slot =~ /current/ ) {
400 &changeTape($currentTape);
401 print LOG &do_time(), ": $currentTape $tapeDevice\n";
402 print "$currentTape $tapeDevice\n";
404 if ( $opt_slot =~ /next/ ) {
405 $tape = $currentTape+1;
406 if ( $tape > $max_slot ) {
409 while ( $slots[$tape-1] == 0 ) { # there is at least 1
410 if ( ++$tape > $max_slot ) {
415 print LOG &do_time(), ": $currentTape $tapeDevice\n";
416 print "$currentTape $tapeDevice\n";
418 if ( $opt_slot =~ /prev/ ) {
419 $tape = $currentTape-1;
423 while ( $slots[$tape-1] == 0 ) { # there is at least 1
429 print LOG &do_time(), ": $currentTape $tapeDevice\n";
430 print "$currentTape $tapeDevice\n";
432 if ( $opt_slot =~ /^\d+$/ ) {
433 &changeTape($opt_slot);
434 print LOG &do_time(), ": $currentTape $tapeDevice\n";
435 print "$currentTape $tapeDevice\n";
437 if ( $opt_slot =~ /advance/ ) {
438 $tape=$currentTape+1;
439 if ( $tape > $max_slot ) {
442 if ( $currentTape ) {
443 &Unload($currentTape);
445 print LOG &do_time(), ": $currentTape $tapeDevice\n";
446 print "$currentTape , /dev/null\n";
453 if ( $currentTape == 0 ) {
454 &Load(1); # load random tape
458 print LOG &do_time(), ": $currentTape $max_slot 1\n";
459 print "$currentTape $max_slot 1\n";
465 print LOG &do_time(), ": $currentTape $tapeDevice\n";
466 print "$currentTape $tapeDevice\n";
471 if ( $currentTape ) {
472 &Unload($currentTape);
473 print "0 $tapeDevice\n";
476 print "$progname: drive was not loaded\n";
481 print "$progname: No command was received. Exiting.\n";