Exabyte-mount

Overview
The exabyte-mount family of BASH scripts was written by Andrew Deason in early 2006 as a set of glue scripts for interfacing the OpenAFS backup system to the Exabyte EXB-480 Tape Drive. They mostly just call the mtx and mt programs to load the appropriate tapes, and are partially based off of chg-zd-mtx.

The "family" consists of four files, which are, as of the time of this writing, located in  on emperor. They are:
 * exabyte-mount -- Loads the requested tape
 * exabyte-unmount -- Unloads and stores the current tape
 * exabyte-functions.sh -- Functions used by both of the above scripts
 * exabyte-barcodes.map -- Maps AFS tape names to barcode IDs and vice-vers

Most of the information about how automated backup scripts work for OpenAFS can be located in the OpenAFS IBM documentation.

Exit status
Both the mount or unmount script can exit with one of three exit statuses. An exit status of 0 indicates the tape was successfully loaded, and that the backup system should continue and try to use it. An exit status of 1 indicates a failure to find the correct tape, and makes the backup system abort the attempted backup. An exit status of 2 stops the backup program, and on the butc terminal, prompts the operator to load a tape manually. These three statuses are represented by $EX_SUCCESS, $EX_FAIL, and $EX_PROMPT in the scripts, respectively.

exabyte-mount
exabyte-mount is called with five arguments:
 * 1) The absolute path to the tape device (e.g. /dev/st1)
 * 2) The tape operation to be performed (usually dump, though there are a few others)
 * 3) The number of times OpenAFS has tried to open the tape file; if it fails, it runs this script again with this number incremented once
 * 4) The tape name (or "none", if OpenAFS does not know)
 * 5) The tape ID, which is really the backup ID, since it is the same when a backup spans multiple tapes. Currently unused by exabyte-mount.

From the path to the tape device, exabyte-mount grabs which Device Element we are dealing with (to use with mtx), and determines whether that drive is empty, full with the correct drive, or full with the incorrect drive via output from mtx status. The correct tape is found by using the "tape name" to get the barcode ID from exabyte-barcodes.map. The slot or drive of that correct tape is then found using output from mtx status, and the correct tape is loaded into the appropriate drive with mtx load.

If OpenAFS has attempted to mount the tape more than $MAX_ATTEMPTS times (as defined in exabyte-functions.sh), then the script fails with an error message, and gives exit status $EX_FAIL.

Mount Operations
There are a few special cases when the "tape operation" (argument 2) is not "dump". If it is "appenddump", it indicates that we are trying to find a tape to append to, instead of a normal dump. In this case, before any loading is attempted, exabyte-mount translates the tape name into the name of the tape that should be appended to. As of the time of this writing, the only time this happens is when incremental "web" dumps are appended to the "user" incrementals, so when "appenddump" is given, it translates a "web" tape name to a "user" one.

If the operation is "labeltape", "scantape", or "readlabel", exabyte-mount forces the tape to be manually loaded, since these operations are not the kind that are normally automated. If there is a tape already in the requested slot, then it just uses that and returns successfully. If not, it returns $EX_PROMPT. If this were not done, these operations would always load the first unused tape, since the tape name passed would always be "none", since the backup system never knows the name of the tape for these operations.

exabyte-unmount
exabyte-unmount is only called with two arguments:
 * 1) The absolute path to the tape device (e.g. /dev/st1)
 * 2) The tape operation to be performed (always "unmount")

These function exactly the same as with exabyte-mount, except that there are no special cases for the tape operation, since it's always the same (and thus, ignored by the script). exabyte-unmount merely determines from which slot the loaded tape originated, and returns it there by issuing an mtx unload after mt offline.

exabyte-barcodes.map
This is a tab-delimited text file, with the following format: NAME:none      VTAG:00012345 NAME:none      VTAG:00012346 NAME:tape.name.1    VTAG:00012344   TAPEID:1146988804 First is the tape name, then the barcode ID, and then the "tape id" given by OpenAFS. The column prefixes with colons just make it easier to grep for things in the scripts. The third column is optional, and actually is not used at this point in time, although it possibly could be used in the future.

There are usually many entries at the beginning the of file with the name "none", which are the tapes that have not been used yet. The scripts use those tapes when a tape name given to them cannot be found, and then their actual name is given to the tape by erasing the original "none" record, and writing a new record with the name at the bottom of the file. So, to add or remove tapes from being reserved to OpenAFS backups, adding or removing tape entries from the beginning, with the "none" name is probably the best. The first "none" tapes used are the ones closest to the top of the file.

exabyte-functions.sh
This file contains numerous functions (mostly for finding tape slots/names/etc.) used by the above two scripts, as well as some constants. In case anybody needs to ever fix or otherwise alter these scripts, developer documentation for them is provided here:

Constants

 * CHANGER -- The SCSI device for the tape changer, used by mtx
 * MTX -- The absolute path to the mtx binary
 * MT -- The absolute path to the mt binary
 * MAX_WAIT -- The maximum amount of seconds to wait for the tape drive to become ready before returning
 * MAX_ATTEMPTS -- The maximum number of tries the OpenAFS backup system can try to run the exabyte-mount script before it reporting a failure
 * EX_SUCCESS -- The exit code for success
 * EX_FAIL -- The exit code for a failure
 * EX_PROMPT -- The exit code to prompt the operator for a tape
 * EXABYTE_MOUNT -- The absolute path to the exabyte-mount script
 * EXABYTE_UNMOUNT -- The absolute path to the exabyte-unmount script
 * BARCODE_LOCKFILE -- The absolute path to the exabyte-barcodes.map lock file
 * BARCODE_NAME_MAP -- The absolute path to exabyte-barcodes.map
 * mtx_status -- The output of mtx status, so the command only needs to be run once

Functions
Since these are BASH functions, things that are traditionally returned are echo'd instead, so you can easily store the result to a variable, such as: ret=`myfunc $arg` So these functions cannot usually use 'echo' or 'print' to debug, unless it is redirected to stderr or to a file.
 * echo2 -- A wrapper for echo for informational/debug messages, currently just prints the given string to stderr so it is displayed by butc
 * usage -- Displays usage
 * dev_to_drive -- Given a tape device as an argument, echos the index of that drive (i.e. the Data Transfer Element numer)
 * drive_to_dev -- Does the reverse of the above function
 * get_slot_in_drive -- Given a tape drive index number, echos the slot number of the tape currently in that drive
 * get_dev_from_slot -- Given a tape slot number, echos the the tape device that has the tape that's usually stored in that slot, or "none" if the tape is not in a drive
 * find_tape_slot -- Given a tape name and ID, echos the slot number of that tape. This is called recursively if the tape name was not found, and a third argument is given to indicate the tape's "real name". This is so when find_tape_slot finds a tape with the name "none" (which it does when it cannot find a tape with the specified name), it also labels the tape to that name in exabyte-barcodes.map so it can be used in the future.
 * volumetag_to_slot -- Given a barcode ID, echos the slot number associated with that ID. If none is found, echos "-1".
 * lock_barcode_map -- Creates a lockfile for the barcode map (after waiting for the lockfile to not exist, or for its creator process to die), so two instances do not try to edit the map at the same time
 * unlock_barcode_map -- Deletes the barcode lockfile if the PID in it is the same as this script's (which, theoretically, it always should be...)
 * append_tape_name -- Translates a tape name to the tape name of the tape to append to, in the case of an "appenddump" tape operation in exabyte-mount, as outlined above.