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/