SUMMARY: Looking for jukebox backup script

From: Chris Jankowski - mailing lists <chrisj_at_lagoon.meo.dec.com>
Date: Fri, 20 Nov 1998 23:34:59 -0900

I owe the list a summary.
Terribly late, but here it is.
My apologies for the delay.

-------------------------------------------------------------------------------
Original question (short):
==========================

I am looking for a set of scripts that would let me to fully
utilise the features offered by the DLT TL891/TL892 tape mini
library.

-------------------------------------------------------------------------------
Short summary:
==============

Nearly all respondents pointed me to Networker, and a few to Amanda.

I am quite familiar with Networker and I looked at Amanda.
Both are relatively complex, binary products. I asked for a simple script.
I certainly should have been more clear and specifically to have excluded
binary products.

Some respondents expressed their surprise at why a Compaq's consultant
would not use Networker. I understand the concerns, however, I worked
for a customer at this time, and my customer had good reasons not to
use Networker. The customer is always right.
For those of you interested I summarize below the customer's reasons
for not using Networker.

In the end I developed a simple script.
It is far from perfect, but it took only 8 hours to develop
and debug, and fulfilled my customer's requirement.

Below you will find:
        - full question
        - my customer's reasons for not using Networker on this occasion
        - short discussion of the developed scripts
        - scripts themselves

Thanks again to all respondents and regards,

Chris

 +-+-+-+-+-+-+-+ Chris Jankowski - Open Systems Cons.- chris_at_lagoon.meo.dec.com
 |d|i|g|i|t|a|l| Digital Equipment Corporation (Australia) tel.+61 3 92753622
 +-+-+-+-+-+-+-+ 564 St. Kilda Rd, Melbourne 3004, AUSTRALIA fax +61 3 92753453

Entities should not be multiplied needlessly. - William of Ockham, razor of

-------------------------------------------------------------------------------
Original question (long):
=========================

I am looking for a set of scripts that would let me to fully
utilise the features offered by the DLT TL891/TL892 tape mini
library.

I would imagine that it would use the robot(1) utility delivered with the
library to manipulate the jukebox.

Ideally the scripts would:
        - select the tapes for tonights backup by looking up a prepared
          file of a certain format.
          Select means here - select by bar code on the tape label.
        - check if correct tapes for a this backup are in the magazine.
        - load them into tape unit(s).
        - call backup scripts that do the actual backup.
        - handle errors.
        - keep logs, do notifications and such.
        - handle signals gracefully.
        - be well documented so they can be easily understood and
          modified maintained as needed.

I am sure that somebody who spent all this time writing and debugging
such a set of scripts will be willing to share the fruits of their labour.

Your contributions, pointers, ideas, etc. are welcome.

-------------------------------------------------------------------------------
Why not Networker this time?
============================

There were several reasons, which in combination made Networker less
attractive.

1. Cost
The system was a cluster with two 8400.
The Networker licences for 8400 cluster cost much more than a day
of consultant's work.

2. Complexity
The customer is a software house that does some basic administration
of their client systems. They are good developers, but do not wish
to have to maintain skills of managing a complex product if it can be
avoided.
Networker in a cluster and with tape libraries can be quite complex.

3. Integration with the application
Their application is a database that has to be stopped before the backup
and restarted thereafter. Operations are 24/365.
Networker does not have an easy, straight out of the box way of
doing this as far as I know. On the other hand this is trivial
to do in a simple backup script using AdvFS cloning.
Downtime is limited to 15 seconds roughly and execution is synchronous.

4. Limited wide area network bandwidth.
The computer site is 2,000km from the place, where the administrators
are. The network link is only 64kb/s. X through narrow links is slow.
Networker requires X or arcane command line commands to manage.
The backup is over dial up. X does not work all that well through
dial up.

-------------------------------------------------------------------------------
Description of the scripts.
===========================

The script uses Media Robot Utility that comes with every tape library.
It also relies on the ability of the tape library to read a bar code
label on the tape.

The idea is that there will be a maintained file that constitutes
a schedule file. The file contains entries that match date to a
bar code label.

When the script is run (presumably from cron) it will find a
bar code tape label matching the today's date in the file.
This is the tape(s), which is to be used for backup.

The tape is located, and if found loaded, and a typical (not included here)
backup script is called to do the real work on the tape that already has
been loaded for it.

When the backup script exits, the main script unloads the tape and exits.

All actions are logged.

Limitations and bugs:

1. Handles only one tape drive in one jukebox at present.
2. Backup script must be self contained and have proper tape unit and actions
   encoded in it. No information is passed between the scripts at present.
3. There are certain limits to the format of tape label.
4. There is no signal handler yet.
5. The version published below is one of the earlier ones and still has some
   bugs that have been removed later, but I no longer have the latest version.

------------------------------------------------------------------------------
Scripts.
========

----------------------------------------------------------------------------

#
# Schedule file for backups.
# --------------------------
#
# Anything from a # charecter in a line up to the end of the line
# will be ignored.
#
# Valid lines consist of two fields separated by a single space.
#
# The first field is the date of the backup given as day/month
# where both day and month are exactly two digit numbers.
#
# Examples:
# 01/01
# 31/12
#
# The second field is the tape label as encoded on the bar code
# label on the tape.
#
# Example:
# PBI735
#
# Note:
# Tape labels should not have exactly the same format as date ie.
# tape labeled 01/01 will cause trouble, tape labeled A01/01 is OK.
#
#
09/09 PBI735
10/09 PBI736
11/09 PBI737
11/09 PBI738
13/09 PBI739

----------------------------------------------------------------------------

#!/bin/sh
#
# /usr/local/bin/squirrel.jukebox
#
# Script for backups for jukeboxes with bar code reader such as TL891.
#
# Description:
# ------------
#
#
# Limitations:
# ------------
# At present the script will only handle one tape drive in one jukebox.
# The backup script must be using a tape drive device coresponding to
# the drive number in the jukebox as referred to by robot(8).
# This is independently set in the scripts at the moment and not passed
# as arguments.
#
# Author: Chris Jankowski (Digital)
#
# Date last modified: 09/09/98
#
#
# set -x # uncomment this for debugging.
#


# Set and export search path for executables:
#
PATH=/sbin:/usr/sbin:/usr/bin:/usr/local/bin
export PATH


# Set pathnames for log files.
#
history_file="/usr/local/logs/squirrel_history"
status_file="/usr/local/logs/squirrel_status"
pid_file="/usr/local/logs/`basename $0`_pid"

# Store away own pid.
#
echo -n $$ > $pid_file


# Put the log file in a place where files are created every day
# and kept for a few weeks or months, and actually looked at! ...
#
logfile=/usr/local/logs/`basename $0`.`date "+%h%d"`.$$


# Backup script that does the real work.
backup_script=/usr/local/bin/squirrel.auslab.nrmt0h

# Set backup operators list for receipt of mail.
#
operators=""


# Start logging.
#
exec > $logfile 2>&1


# Record backup commencement date.
#
backupdate=`date`


date
echo "Script `basename $0` $* - entry point."
echo


# Set variable pointing to media changer device.
# robot(8) uses it.
#
MRU_ROBOT=/dev/mc16
export $MRU_ROBOT


# Drive number in the jukebox.
#
drive_number=0


# Print queue for printing of a log file.
#
printqueue=''

# Schedule file - keeps date versus tape label entries.
#
schedule=/usr/local/bin/squirrel.schedule


# Exit value for the script.
#
exit_value=0


##########################
#
# get_tape_label
#
# Finds the label of the tape on which todays backup is to be done.
#
#
##########################

get_tape_label() {

        echo "Script $0:"
        echo "Function get_tape_label $*: Entry point:"
        echo

        if [ ! -f $schedule ]
        then
                echo `date`
                echo "Schedule file does not exist."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function get_tape_label $*: Abnormal completion:"
                echo "Function get_tape_label $*: Exit point:"
                echo
                exit 1
        fi


        # Get rid of comments, select lines with current date,
        # and put in a file.

        sed -e 's/\#.*//' -e '/^$/d' $schedule | grep `date +%d/%m` >${schedule}.tmp

        

        i=`cat ${schedule}.tmp | wc -l | awk '{ print $1 }'`
        case $i in
        0)
                echo `date`
                echo "No entry found for `date +%d/%m`."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function get_tape_label $*: Abnormal completion:"
                echo "Function get_tape_label $*: Exit point:"
                echo
                exit 1
                ;;
        1)
                echo `date`
                echo "One entry found for `date +%d/%m`."
                echo "Proceeding with the entry."
                echo
                ;;
        *)
                echo `date`
                echo "Warning:"
                echo "$i entries found for `date +%d/%m`."
                echo "Warning:"
                echo "One entry expected for `date +%d/%m`."
                echo "Proceeding with the first entry."
                echo
                ;;
        esac


        tape_label=`head -1 ${schedule}.tmp | awk '{ print $2 }'`

        rm ${schedule}.tmp

        if [ ${tape_label}X = X ]
        then
                echo `date`
                echo "Null tape label found for `date +%d/%m`."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function get_tape_label $*: Abnormal completion:"
                echo "Function get_tape_label $*: Exit point:"
                echo
                exit 1
        fi

        echo "Tape label: $tape_label found for date: `date +%d/%m`."
        echo

        echo "Script $0:"
        echo "Function get_tape_label $*: Normal completion:"
        echo "Function get_tape_label $*: Exit point:"
        echo
}


##########################
#
# locate_tape
#
# Locates the selected tape is in the magazine or a drive.
#
#
##########################

locate_tape() {

        date
        echo "Script $0:"
        echo "Function locate_tape $*: Entry point:"
        echo

        #
        # This syntax is needed to work around a bug in the read command.
        # It does not work in a pipe with variable in lower case ???
        #
        
        #
        # When robot cannot find the cartridge it outputs a message to stderr
        # and nothing goes to the temporary file.

        robot find cartridge $tape_label > ${schedule}.tmp
        exit_value=$?

        if [ ${exit_value}X != 0X ]
        then
                echo `date`
                echo "robot(8) exited with an error."
                echo "Tape labeled $tape_label cannot be found in the library."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function locate_tape $*: Abnormal completion:"
                echo "Function locate_tape $*: Exit point:"
                echo
                exit 1
        fi

        #
        # Tape is in the library somewhere.
        # But may be in a drive or in a slot.

        read location_type location_number media_label < ${schedule}.tmp

        rm ${schedule}.tmp

        case $location_type in
        DRIVE:)
                echo `date`
                echo "Tape labeled $tape_label is in drive $location_number."
                echo "It may be used or contain important data."
                echo "Too dangerous to proceed."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function get_tape_label $*: Abnormal completion:"
                echo "Function get_tape_label $*: Exit point:"
                echo
                exit 1
                ;;
        SLOT:)
                echo `date`
                echo "Tape labeled $tape_label is in slot $location_number."
                echo
                ;;
        *)
                echo `date`
                echo "Unknown location type: $location_type"
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function get_tape_label $*: Abnormal completion:"
                echo "Function get_tape_label $*: Exit point:"
                echo
                exit 1
                ;;
        esac


        echo "Script $0:"
        echo "Function locate_tape $*: Normal completion:"
        echo "Function locate_tape $*: Exit point:"
        echo
}


##########################
#
# load_tape.
#
# Load tape into the drive.
#
#
##########################

load_tape() {

        date
        echo "Script $0:"
        echo "Function load_tape $*: Entry point:"
        echo

        #
        # Check if our drive is empty.

        robot show drive $drive_number > ${schedule}.tmp
        read location_type location_number media_label < ${schedule}.tmp

        rm ${schedule}.tmp

        case $media_label in
        Empty)
                echo `date`
                echo "OK. Drive $drive_number is $media_label."
                echo
                ;;
        *)
                echo `date`
                echo "Drive $drive_number is/contains $media_label."
                echo "Drive not available."
                echo "Too dangerous to proceed."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function get_tape_label $*: Abnormal completion:"
                echo "Function get_tape_label $*: Exit point:"
                echo
                exit 1
                ;;
        esac


        #
        # Load the tape into the drive.

        robot load slot $location_number drive $drive_number
        exit_value=$?

        if [ ${exit_value}X != 0X ]
        then
                echo `date`
                echo "robot(8) exited with an error."
                echo "Tape labeled $tape_label cannot be loaded into the drive."
                echo "Exiting..."
                echo
                echo "Script $0:"
                echo "Function locate_tape $*: Abnormal completion:"
                echo "Function locate_tape $*: Exit point:"
                echo
                exit 1
        fi

        date
        echo "Tape labeled $tape_label loaded into drive $drive_number."
        echo

        echo "Script $0:"
        echo "Function load_tape $*: Normal completion:"
        echo "Function load_tape $*: Exit point:"
        echo
}


##########################
#
# unload_tape.
#
# Unload tape from the drive back into its slot.
#
#
##########################

unload_tape() {

        date
        echo "Script $0:"
        echo "Function unload_tape $*: Entry point:"
        echo

        #
        # Unload the tape from the drive.

        robot unload drive $drive_number slot $location_number
        exit_value=$?

        if [ ${exit_value}X != 0X ]
        then
                echo `date`
                echo "robot(8) exited with an error."
                echo "Tape labeled $tape_label cannot be unloaded from drive $drive_number into slot $location_number."
                echo "Falling through..."
                echo
                echo "Script $0:"
                echo "Function unload_tape $*: Abnormal completion:"
                echo "Function unload_tape $*: Exit point:"
                echo
                return 1
        fi

        date
        echo "Tape labeled $tape_label unloaded from drive $drive_number into slot $location_number."
        echo

        echo "Script $0:"
        echo "Function unload_tape $*: Normal completion:"
        echo "Function unload_tape $*: Exit point:"
        echo
}


##########################
#
# Work starts here.
#
##########################


echo "Last backup commenced on $backupdate - and is running or has been aborted" > $status_file
echo

echo "logfile=$logfile"
echo "history_file=$history_file"
echo "status_file=$status_file"
echo "pid_file=$pid_file"
echo

get_tape_label

locate_tape $tape_label

load_tape $location_number


# We have tape loaded. We can start backup now.

# $backup_script must use a tape drive device coresponding to
# drive number $drive_number in the jukebox as referred to by robot(8).
# This is independently set in the scripts at the moment and not passed
# as arguments.

echo "`date`: Starting backup script $backup_script."
echo


$backup_script

echo "`date`: Backup script $backup_script completed."
echo


unload_tape $location_number


echo "$0 started on $backupdate finished on `date`"
echo
echo "Script `basename $0` $* exiting with exit value: $exit_value"
echo

echo "$0 started on $backupdate finished on `date`" > $status_file
echo "$0 started on $backupdate finished on `date`" >> $history_file


# Send logfile by mail to operators

if [ ! X = X$operators ]
then
sed -e '
        /dump: Mapping (/d
        /dump: Dumping (/d
        /dump: Estimate /d
        /dump: Dump completed /d
' $logfile |tr -d '\007' | mailx -s "Backup log: $backupdate" $operators
fi


# Print log file

if [ ! X = X$printqueue ]
then
sed -e '
        /dump: Mapping (/d
        /dump: Dumping (/d
        /dump: Estimate /d
        /dump: Dump completed /d
' $logfile |tr -d '\007' | lpr -p -P$printqueue
fi

rm $pid_file

exit $exit_value
Received on Fri Nov 20 1998 - 12:38:55 NZDT

This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:38 NZDT