Second of which, why don't you match this patch relative to the latest
version of chg-zd-mtx, which fixes lots of the error handling. Your script
retains 90% of the bugs of the original version.

An updated version of the .sh.in file is at
        http://www.noc.isite.net/?Projects

On Fri, Feb 09, 2001 at 11:38:45AM -0500, Jason Hollinden wrote:
> Note: This has only been tested on an ADIC Scalar 100.  If you find
> something broken, or not clearly commented, tell me.  Also, this is my
> 1st public showing of any code, so please, be gentle... ;)
> 
> The attached file is a replacement for chg-zd-mtx.  I have added support
> for barcode readers, and also for libraries between 1-999 slots (I
> would so love to hear from someone that has a honking big library like
> that say it works).  All amanda utils can work with this for barcode
> database lookups (amcheck can load the appropriate tape all by itself,
> etc.)
> 
> The main thing to do it be sure to update the barcode database after any
> new tapes are added, or removed from cycle.  To do this, make a backup
> of the old barcodes file, then run 'amtape <conf> update'.  This will
> cycle through all your tape slots, and put them in your barcodes file
> like this:
> 
> <tape amlabel> <barcode>
> 
> Be sure to modify the top part of the script to fit your needs, and also 
> check out the comments on what 'mt status' should return for your tape
> device.
> 
> 
> Some changes to come:
> 
> - make it completely independent of what slot the tapes are in, since
>   certain loaders may unload to the wrong slot depending on circumstances.
> 
> - Better error handling, which right now is crappy to say the least.
> 
> - Anything brought ot my attention by you peoples
> 
> Enjoy...
> 
> --
>    Jason Hollinden
> 
>    SMG Systems Admin

> #!/bin/sh
> #
> # Exit Status:
> # 0 Alles Ok
> # 1 Illegal Request
> # 2 Fatal Error
> #
> # Contributed by Eric DOUTRELEAU <[EMAIL PROTECTED]>
> # This is supposed to work with Zubkoff/Dandelion version of mtx
> #
> # Modified by Joe Rhett <[EMAIL PROTECTED]>
> # to work with MTX 1.2.9 by Eric Lee Green http://mtx.sourceforge.net
> #
> # Modified by Jason Hollinden <[EMAIL PROTECTED]> on 6-Feb-2001
> # to work with MTX 1.2.10, up to 999 slots, and added barcode support.
> # NOTE:  Only tested the 2 additions with an ADIC Scalar 100.
> # All my additions have a '#### Comment' close by.
> 
> # You may need to customize these things
> MT=/bin/mt
> MTF=-f
> MTX=/sbin/mtx
> DD=/bin/dd
> firstslot=2
> lastslot=9
> #### Clean function just loads the tape, and may not necessarily eject it.
> #### If not, just issue an eject afterwards.
> cleanslot=31
> accessbeforeclean=119
> 
> #### If you have a barcode reader, set to 1.  Otherwise set to 0.
> havereader=1
> 
> #### Email of who should get severe library errors, and mailer to use.
> #### All other errors are in the $DBGFILE.
> [EMAIL PROTECTED]
> mailer=/bin/mail
> 
> #### Check the 'readyError' section if mt acts differently for you 
> #### as stated below.
> #### See the 'readstatus' section below if using a different drive than 0.
> 
> ########## No (hopefully) user-level customized required beyond this point.
> 
> 
> # try to hit all the possibilities here
> prefix=/opt/amanda
> exec_prefix=${prefix}
> sbindir=${exec_prefix}/sbin
> libexecdir=${exec_prefix}/libexec
>      
> PATH=$sbindir:$libexecdir:/usr/bin:/bin:/usr/sbin:/sbin:/usr/ucb:/usr/local/bin
> export PATH
>      
> if [ -d "/tmp/amanda" ]; then
>         DBGFILE=/tmp/amanda/changer.debug
> else
>         DBGFILE=/dev/null
> fi
>      
> USE_VERSION_SUFFIXES="no"
> if test "$USE_VERSION_SUFFIXES" = "yes"; then
>         SUF="-2.4.2b2"
> else
>         SUF=
> fi
>     
> myname=$0
> tape=`amgetconf$SUF tapedev`
> TAPE=`amgetconf$SUF changerdev`; export TAPE # for mtx command
> if [ "$tape" = "/dev/null" -o "$TAPE" = "/dev/null" ]; then
>         echo "Both tapedev and changerdev must be specified in config file";
>         exit 2;
> fi
> 
> changerfile=`amgetconf$SUF changerfile`
> 
> cleanfile=$changerfile-clean
> accessfile=$changerfile-access
> slotfile=$changerfile-slot
> labelfile=$changerfile-barcodes
> [ ! -f $cleanfile ] && echo 0 > $cleanfile
> [ ! -f $accessfile ] && echo 0 > $accessfile
> [ ! -f $slotfile ] && echo 0 > $slotfile
> [ ! -f $labelfile ] && echo 0 > $labelfile
> cleancount=`cat $cleanfile`
> accesscount=`cat $accessfile`
> 
> # Routines start here
> #### If using a different drive than /dev/nst0 (or whatever your OS 
> #### calls the 0'th drive) change the 'Data Transfer Element 0' (there 
> #### are 5 below) to 'Data Transfer Element #' where # = /dev/nst# 
> #### (or whatever for your OS).
> 
> readstatus() {
>       tmpslot=`$MTX status | grep "Data Transfer Element 0"`
> 
>       #### The horrid sed statement below returns the slot number.
>         #### The origional was in shell script, so I didn't want to change that, 
>         #### Which give the below puke for a number between 1-999.
>                       
>         usedslot=`echo $tmpslot |
>               sed -n 's/Data Transfer Element 0:Empty/-1/p;s/Data Transfer Element 
>0:Full (Storage Element \(\([1-9]\)\|\([1-9][0-9]\)\|\([1-9][0-9][0-9]\)\) 
>Loaded)\(.*\)/\1/p'`
>       barcode=`echo $tmpslot | 
>               sed -n 's/Data Transfer Element 0:Empty/-1/p;s/Data Transfer Element 
>0:Full (Storage Element \(.\) Loaded):VolumeTag = \(.*\)/\2/p'`
>         if [ "$usedslot" -eq "-1" ]; then
>                 echo '-1' > $slotfile
>         fi
>         echo "STATUS -> currently loaded slot = $usedslot" >> $DBGFILE
> }
>    
> 
> eject() {
>         readstatus
>         echo "EJECT -> ejecting tape from slot $usedslot" >> $DBGFILE
>         if [ $usedslot -gt 0 ]; then
>                 $MTX unload $usedslot 2>/dev/null
>                 echo "0 $tape"
>                 exit 0
>         else
>                 echo "0 Drive was not loaded"
>                 exit 1
>         fi
> }
> 
> reset() {
>         readstatus
>         if [ $usedslot -gt 0 ]; then
>                 echo "RESET -> ejecting tape from slot $usedslot" >> $DBGFILE
>                 $MTX unload $usedslot 2>/dev/null
>         fi
> 
>         echo "RESET -> loading tape from slot 1" >> $DBGFILE
>         result=`$MTX load 1 2>&1`
>         if [ $? -eq 0 ]; then
>                 echo "1 $tape"
>                 exit 0
>         else
>                 echo "1 $result"
>                 exit 1
>         fi
> }
> 
> loadslot() {
>         readstatus
> 
>         whichslot=$1
> 
>         echo "LOADSLOT -> load tape from slot $whichslot" >> $DBGFILE
>         case $whichslot in
>                 $[${whichslot}])
> 
>                       if [ $whichslot -gt $lastslot ] || [ $whichslot -lt $firstslot 
>]; then
>                               echo "0 Slot $whichslot is out of range ($firstslot - 
>$lastslot)"
>                               exit 1
>                               else
>                               loadslot=$whichslot
>                       fi
>                       ;;
>                 current)
>                         if [ $usedslot -lt 0 ]; then
>                                 loadslot=$firstslot
>                         else
>                                 echo "$usedslot $tape"
>                                 exit 0
>                         fi
>                         ;;
>                 next|advance)
>                         if [ $usedslot -lt 0 ]; then
>                                 loadslot=$firstslot
>                         else
>                                 loadslot=`expr $usedslot + 1`
>                                 if [ $loadslot -gt $lastslot ]; then
>                                         loadslot=$firstslot
>                                 fi
>                         fi
>                         ;;
>                 prev)
>                         loadslot=`expr $usedslot - 1`
>                         if [ $loadslot -lt $firstslot ]; then
>                                 loadslot=$lastslot
>                         fi
>                         ;;
>                 first)
>                         loadslot=$firstslot
>                         ;;
>                 last)
>                         loadslot=$lastslot
>                         ;;
>               clean)
>                       loadslot=$cleanslot
>                       ;;
>                 *)
>                         echo "0 illegal request"
>                         exit 1
>                         ;;
>         esac
>         
>         # Is this already the current slot?
>         if [ $loadslot = $usedslot ]; then
>                 echo "$usedslot $tape"
>                 exit 0
>         fi
>         
>         # Is this a cleaning request?
>         if [ $loadslot = $cleanslot ]; then
>                 expr $cleancount + 1 > $cleanfile
>                 echo 0 > $accessfile
>         else
>                 expr $accesscount + 1 > $accessfile
>                 if [ $accesscount -gt $accessbeforeclean ]; then
>                         $myname -slot clean >/dev/null
> 
>                         # Slot $cleanslot might contain an ordinary tape rather than 
>a cleaning
>                         # tape. A cleaning tape *MIGHT* auto-eject; an ordinary tape 
>does not.
>                         # We therefore have to read the status again to check what 
>actually happened.
>                         readstatus
>                 fi
>         fi
>         
>         # Unload any previous tape
>         if [ $usedslot -ne "-1" ]; then
>                 echo "         -> unload $usedslot" >> $DBGFILE
>                 result=`$MTX unload $usedslot 2>&1`
>                 status=$?
>                 echo "         -> status $status, result '$result'" >> $DBGFILE
>                 if [ $status -ne 0 ]; then
>                         echo "$loadslot $result"
>                         exit 2
>                 fi
>         fi
>                         
>         # Load the tape, finally!
>         echo "         -> loading tape from slot $loadslot" >> $DBGFILE
>         result=`$MTX load $loadslot 2>&1`
>         status=$?
>         echo "         -> status $status, result '$result'" >> $DBGFILE
>                         
>         # If there is an error, abort unless the slot is simply empty
>         if [ $status -ne 0 ]; then
>                 empty=`echo $result | grep "Empty"`
>                 if [ -z "$empty" ]; then
>                         echo "$loadslot $result"
>                         exit 2
>                 else
>                         loadslot next
>                 fi
>         else
>                 #### The origional test if the drive is offline.  This depends on 
>what
>                 #### 'mt -f <device> status returns different between being offline 
>and
>                 #### online.  Aparently some drives report an 'offline' when 
>offline, and
>                 #### it goes away when online.
>               #readyError="offline"
>                 #while [ -n "$readyError" ]; do
>                 #        readyStatus=`$MT $MTF $tape status 2>&1`
>                 #        readyError=`echo $readyStatus | grep "offline"`
>                 
>               #### ADIC doesn't report an 'offline', rather an 'ONLINE' when it's up.
>                 #### Don't assume the drive is ready until we get an ONLINE
>               readyError=""
>                 while [ -z "$readyError" ]; do
>                         readyStatus=`$MT $MTF $tape status 2>&1`
>                         readyError=`echo $readyStatus | grep "ONLINE"`
>                 done
>                 echo "         -> readyStatus = $readyStatus" >> $DBGFILE
>                         
>                 # Now rewind and check
>                 echo "         -> rewind $loadslot" >> $DBGFILE
>                 $MT $MTF $tape rewind
>                 echo "$loadslot" > $slotfile
>                 echo "$loadslot $tape"
>                 exit 0
>         fi
> }       
> 
> info() {
>         readstatus
>         echo "INFO -> current slot $usedslot, last slot $lastslot, can go backwards 
>1" >> $DBGFILE
>       #### Checks if you have a barcode reader or not.  If so, it passes the 4th 
>item in the echo
>       #### back to amtape signifying it can search based on barcodes.
>       if [ $havereader -eq 1 ]; then
>               if [ $usedslot -lt 0 ]; then
>                       #### added a variable to the end of the following 2 echos.  
>This indicates to amtape that 
>                       #### it can/cannot read barcodes.
>                       echo "0 $lastslot 1 1"
>               else
>                       echo "$usedslot $lastslot 1 1"
>               fi
>               exit 0
>       else
>                 if [ $usedslot -lt 0 ]; then
>                         echo "0 $lastslot 1"
>                 else
>                         echo "$usedslot $lastslot 1"
>                 fi
>                 exit 0
>       fi
>                                                                                      
>                                                                         
> }
> 
> #### Adds the amlabel and the barcode to the barcode file specified above.
> #### If the database is messed up, it kills amtape (rather abruptly) and 
> #### dumps a message into changer.debug on what to do, then sends an email
> #### of the changer.debug to the above set email addr.
> addlabel() {
>       readstatus
>       tapelabel=$1
>       labelfilesize=`ls -l $labelfile | awk '{print $5}'`
>       case $tapelabel in 
>       $tapelabel)
>               echo "LABEL -> Adding Barcode $barcode and amlabel $tapelabel for Slot 
>$usedslot into $labelfile" >> $DBGFILE
>               if [ $labelfilesize -eq 2 ]; then
>                       echo "$tapelabel $barcode" > $labelfile
>                       echo "0 $usedslot $tape"
>               else 
>                       included=`grep $tapelabel $labelfile | awk '{print $1}'`
>                       if [ -z $included ]; then
>                               echo "$tapelabel $barcode" >> $labelfile
>                               echo "0 $usedslot $tape"
>                       else
>                               oldbarcode=`grep $tapelabel $labelfile | awk '{print 
>$2}'`
>                               if [ $oldbarcode -eq $barcode ]; then
>                                       echo "      -> Barcode $barcode $oldbarcode 
>already synced for $tapelabel" >> $DBGFILE
>                                       echo "0 $usedslot $tape"
>                                       
>                               else
>                                       echo "      -> WARNING!!!  Label database 
>corrupted!!!" >> $DBGFILE
>                                       echo "      -> $tapelabel $oldbarcode 
>conflicts with new barcode $barcode" >> $DBGFILE
>                                       echo "      -> Remove file $labelfile and run 
>/usr/sbin/amtape <config> update" >> $DBGFILE
>                                       `cat $DBGFILE | $mailer -s "Error with barcode 
>reader on \`date\`" $email`
>                                       `killall amtape`
>                               fi
>                       fi
>               fi
>               ;;
>       esac
>       exit 0
> }
> 
> #### Looks for the amlabel in the barcode file.  If found, it locates the 
> #### slot it's in by looking for the barcode in the mtx output.  It then 
> #### loads that tape, and returns to amtape the device the tape is loaded in.  
> #### If the amlabel is not found, it kills amtape and dumps a message to 
> #### changer.debug on what to do, then sends an email of the changer.debug
> #### to the above set email addr.
> searchtape() {
>       # readstatus
>       tapelabel=$1
>       includedtag=`grep $tapelabel $labelfile | awk '{print $1}'`
>       includedbar=`grep $tapelabel $labelfile | awk '{print $2}'`
>       tmpincludedslot=`$MTX status | grep $includedbar`
>       #### The horrid sed statement below returns the slot number.
>       #### The origional was in shell script, so I didn't want to change that,
>       #### Which give the below puke for a number between 1-999.
>       includedslot=`echo $tmpincludedslot | sed -n 's/\(.*\)Storage Element 
>\(\([1-9]\)\|\([1-9][0-9]\)\|\([1-9][0-9][0-9]\)\):\(.*\)/\2/p;s/Data Transfer 
>Element 0:Full (Storage Element \(.\) Loaded)\(.*\)/\1/p'`
>         case $tapelabel in
>         $tapelabel)
>               if [ $tapelabel == $includedtag ]; then
>                       shift 
>                       loadslot $includedslot
>                       echo "$tape"
>               else
>                       echo "SEARCH -> WARNING!!!  $tapelabel not found in current 
>ADIC-barcodes database." >> $DBGFILE
>                       echo "       -> WARNING!!!  Check your typing, and/or update 
>the database." >> $DBGFILE
>                       `cat $DBGFILE | $mailer -s "Error with barcode reader on 
>\`date\`" $email`
>                       `killall amtape`
>               fi
>               exit 0
>       esac
> }
> 
> # Program invocation begins here
> echo "`date` Invoked with args '$@'" >> $DBGFILE
> while [ $# -ge 1 ];do
>         case $1 in
>                 -slot)
>                         shift
>                         loadslot $*
>                         ;;
>                 -info)
>                         shift
>                         info
>                         ;;
>                 -reset)
>                         shift
>                         reset
>                         ;;
>                 -eject)
>                         shift
>                         eject
>                         ;;
> #### Added the below flags, for barcode support
>               -label) 
>                       shift
>                       addlabel $*
>                       ;;
>               -search)
>                       shift
>                       searchtape $*
>                       ;;
>               -clean)
>                       shift
>                       loadslot $cleanslot
>                       ;;
>                 *)
>                         echo "Unknown option $1"
>                         exit 2
>                         ;;
>         esac            
> done


-- 
Joe Rhett                                         Chief Technology Officer
[EMAIL PROTECTED]                                      ISite Services, Inc.

PGP keys and contact information:          http://www.noc.isite.net/Staff/

Reply via email to