User Tools

Site Tools


sample_configs

This page is for people to post sample configurations for particularly tricky or usefull setups. This can include unusual hardware setups, or complicated schedules, for example.

In the Debian manner

  • Create a conf.d directory

mkdir /etc/bacula/conf.d

  • Create one file per job
# vi /etc/bacula/conf.d/test.conf
Job {
        Name = "Test"
        Enabled = no
        Client = backup-fd 
        FileSet = "FileSetTest"
        Schedule = "ScheduleTest"
        Write Bootstrap = "/var/bacula/Test.bsr"                         
        Full Backup Pool = FullTest 
        Incremental Backup Pool = IncrTest
        Differential Backup Pool = DiffTest
        Storage = DAT72
        Type = Backup
        Level = Incremental
        Pool = Default
        Priority = 10
        Messages = Standard
}

FileSet {
        Name = "FileSetTest"
        Include {
                Options {
                        signature = MD5
                }
                File = /home
        }

        Exclude {
                File = /proc
                File = /tmp
                File = /.journal
                File = /.fsck
        }
}

Schedule {
        Name = "ScheduleTest"
        Run = Full 1st sun at 23:05
        Run = Differential 2nd-5th sun at 23:05
        Run = Incremental mon-sat at 23:05
}

Pool {
        Name = FullTest
        Label Format = "FullTest"
        Pool Type = Backup
        Recycle = yes           # Bacula can automatically recycle Volumes
        AutoPrune = yes         # Prune expired volumes
        Volume Retention = 6 months
        Maximum Volume Jobs = 1
}

Pool {                                                                          
        Name = DiffTest
        Label Format = "DiffTest"
        Pool Type = Backup
        Recycle = yes
        AutoPrune = yes
        Volume Retention =  40 days                                             
        Maximum Volume Jobs = 1                                                 
}                                                                               
                                                                                
Pool {                                                                          
        Name = IncrTest 
        Label Format = "IncrTest"
        Pool Type = Backup
        Recycle = yes
        AutoPrune = yes
        Volume Retention =  10 days                                             
        Maximum Volume Jobs = 1                                                 
}
  • Include it in Bacula Director configuration file
# vi /etc/bacula/bacula-dir.conf
[snip]
  ...
  AutoPrune = yes                     # Prune expired volumes
  Volume Retention = 365 days         # one year
  MaximumVolumeBytes = 4700000000
}

#
# Restricted console used by tray-monitor to get the status of the director
#
Console {
  Name = backup-mon
  Password = "7f+4TYcZiZuSuPcAJQODTta55CL8lBPrj9MuYdyx6Y3u"
  CommandACL = status, .status
}

# Include below all yours jobs configuration files (remember add '@' at beginning)
@/etc/bacula/conf.d/test.conf

Sharing common configuration (a template approximation)

  • Create a file with Schedule declaration
# vi /etc/bacula/conf.d/schedule.conf
Run = Full on 1 at 23:05
Run = Differential thu at 23:05
Run = Incremental mon-fri at 3:05
  • Include it in Schedule Resource declaration for each job file
# vi /etc/bacula/conf.d/test.conf
[snip]

                File = /.journal
                File = /.fsck
        }
}

Schedule {
        Name = "ScheduleTest"
        @/etc/bacula/conf.d/schedule.conf
}

Pool {
        Name = FullTest
        ...

Put Pools, Clients and Storages Resources in separated files

To maintain Bacula Director configuration file as clean as possible and more readable, is a good idea put Pools, Clients and Storages Resources declarations in different files.

For example:

  • Put Pools declaration in a separated file
# vi /etc/bacula/conf.d/pools.conf
Pool {
        Name = AllIncrementals
        Label Format = "Incr"
        Pool Type = Backup
        Recycle = yes           # Bacula can automatically recycle Volumes
        AutoPrune = yes         # Prune expired volumes
        Storage = DDS-4
        Volume Retention = 2 months
}

Pool {
        Name = AllDifferentials
        Label Format = "Diff"
        Pool Type = Backup
        Recycle = yes           # Bacula can automatically recycle Volumes
        AutoPrune = yes         # Prune expired volumes
        Storage = DAT72
        Volume Retention = 2 months
}

AllInrementals pool is used to backup all Incrementals jobs in the same tape. Same idea with AllDifferentials pool.

Note: than don't exist “Maximum Volume Jobs” statement

  • Include it in Bacula Director configuration file
# vi /etc/bacula/bacula-dir.conf
[snip]
  ...
  Password = "7f+4TYcZiZuSuPcAJQODTta55CL8lBPrj9MuYdyx6Y3u"
  CommandACL = status, .status
}

# Include below all yours jobs configuration files (remember add '@' at beginning)
@/etc/bacula/conf.d/test.conf

# Pools definition files
@/etc/bacula/conf.d/pools.conf

A job file example than use those pools could be:

# vi /etc/bacula/conf.d/test.conf
Job {
        Name = "Test"
        Enabled = no
        Client = backup-fd 
        FileSet = "FileSetTest"
        Schedule = "ScheduleTest"
        Write Bootstrap = "/var/bacula/Test.bsr"                         
        Full Backup Pool = FullTest 
        Incremental Backup Pool = AllIncrementals
        Differential Backup Pool = AllDifferentials
        Storage = DAT72
        Type = Backup
        ...
  • Same way for Clients and Storage.

An Bacula Director configuration example could be:

# vi /etc/bacula/bacula-dir.conf
[snip]
  ...
  AutoPrune = yes                     # Prune expired volumes
  Volume Retention = 365 days         # one year
  MaximumVolumeBytes = 4700000000
}

#
# Restricted console used by tray-monitor to get the status of the director
#
Console {
  Name = backup-mon
  Password = "7f+4TYcZiZuSuPcAJQODTta55CL8lBPrj9MuYdyx6Y3u"
  CommandACL = status, .status
}

# Include below all yours jobs configuration files (remember add '@' at beginning)
@/etc/bacula/conf.d/test.conf
@/etc/bacula/conf.d/mails.conf
@/etc/bacula/conf.d/server2.conf
@/etc/bacula/conf.d/monitor.conf
@/etc/bacula/conf.d/debian.conf

# Clients definition files
@/etc/bacula/conf.d/clients.conf

# Storages definition file
@/etc/bacula/conf.d/storages.conf

# Pools definition files
@/etc/bacula/conf.d/pools.conf

Since Bacula 2.2.0 you can include the output of a command within a configuration file with the ”@|” syntax. Here's how you can use ”@|” to include all files within some directory without explicitly naming the files (this lets you, say, add new clients to a configuration without changing existing configuration files, just by adding a file for the new client, containing its Job, Client, and FileSet resources, to the included directory):

#
# Include subfiles associated with configuration of clients.
# They define the bulk of the Clients, Jobs, and FileSets.
# Remember to "reload" the Director after adding a client file.
#
@|"find /etc/bacula/clientdefs -name '*.conf' -type f -exec echo @{} \;"

Faking an auto-changer with one tape drive

After reading Total Automation of Bacula Tape Handling tip in the Bacula manual, I eventually managed to get it to work with the latest version of Bacula with a lot of script hacking.

Here's what I came up with…

  • Director config
Storage {
  Name = LTO-2
  Address = storage.host.name
  SDPort = 9103
  Password = "storage_password"
  Device = LTO-2
  Media Type = LTO-2
  Autochanger = yes
  Maximum Concurrent Jobs = 5
}
  • Storage Daemon Config
Autochanger {
  Name = LTO-2
  Device = LTO-2-Drive
  Changer Device = /dev/nst0
  Changer Command = "/usr/local/bin/bacula-changer.sh %o %a %S"
}

Device {
  Name = LTO-2-Drive
  Drive Index = 0
  Autochanger = yes
  Archive Device = /dev/nst0
  Maximum Changer Wait = 3d
  AutomaticMount = yes
  AlwaysOpen = yes
  Media Type = LTO-2
  RemovableMedia = yes
  Offline On Unmount = no
  Spool Directory = /home/bacula/spool
}
  • /usr/local/bin/bacula-changer.sh script
#!/bin/sh
#
# Bacula interface to mtx autoloader
#
# Created  OCT/31/03 by Alexander Kuehn, derived from Ludwig Jaffe's script
#
# *Heavily* hacked between 31/10/07 & 02/11/07 by Sean Cardus to make it work
# with the current Bacula version & our LTO tape drive.  This works for me,
# it might work for you too - But, don't blame me if it blows up :)
#
# John Murray added storagename feature on 6th Nov 2007 to cater for situation
# where more than one Storage resource exists - we need to supply the correct
# qualifier after 'status Storage'
#
# * Check that the bacula-sd process has permission to run this script, 
#   run bconsole and to write to the logfile specified below! *
#
#set -x
# these are the labels of the tapes in each virtual slot, not the slots!
labels="DC01 DC02 DC03 DC04 DC05 DC06 DC07 DC08 DC09 DC10"

# If more than one Storage resource exists, specify which to check status
# of (name is case-sensitive)
# e.g.
#   storagename="Tape"
storagename=""

# who to send a mail to?
recipient=operator@my.domain.name
logfile=/var/log/mtx.log

# Delay in seconds how often to check whether a new tape has been inserted
TAPEDELAY=10    # the default is every 10 seconds
echo `date` ":" $@ >>$logfile

# change this if mt is not in the path (use different quotes!)
mt=`which mt`
grep=`which grep`
#
# how to run the console application?
console="/usr/sbin/bconsole -c /etc/bacula/bconsole.conf"

command="$1"

#TAPEDRIVE0 holds the device/name of your 1st and only drive (Bacula supports only 1 drive currently)
#Read TAPEDRIVE from command line parameters
if [ -z "$2" ] ; then
  TAPEDRIVE0=/dev/nst0
else
  TAPEDRIVE0=$2
fi

#Read slot from command line parameters
if [ -z "$3" ] ; then
  slot=`expr 1`
else
  slot=`expr $3`
fi

if [ -z "$command" ] ; then
  echo ""
  echo "The mtx-changer script for Bacula"
  echo "---------------------------------"
  echo ""
  echo "usage: mtx-changer <command> <devicename of tapedrive> [slot]"
  echo "       mtx-changer"
  echo ""
  echo "Valid commands:"
  echo ""
  echo "unload          Unloads a tape into the slot"
  echo "                from where it was loaded."
  echo "load <slot>     Loads a tape from the slot <slot>"
  echo "list            Lists full storage slots"
  echo "loaded          Gives slot from where the tape was loaded."
  echo "                0 means the tape drive is empty."
  echo "slots           Gives Number of avialable slots." 
  echo "volumes         List avialable slots and the label of the." 
  echo "                tape in it (slot:volume)"
  echo "Example:"
  echo "  mtx-changer load /dev/nst0 1   loads a tape from slot1"
  echo "  mtx-changer %a %o %S   "
  echo ""
  exit 0
fi

case "$command" in
  unload)
    echo "mtx-changer: Unload request on $TAPEDRIVE0" >>$logfile

    DRIVESTATUS=`$mt -f $TAPEDRIVE0 status | grep ONLINE`
    echo "DriveStatus: $DRIVESTATUS" >>$logfile
    if [ -z $DRIVESTATUS ] ; then
      echo "Drive is OFFLINE" >>$logfile
    else
      echo "Drive is ONLINE" >>$logfile
      echo "Taking drive offline and ejecting..." >>$logfile
      mt -f $TAPEDRIVE0 rewoffl 2>/dev/null
    fi

    exit 0
    ;;

  load)
    echo "mtx-changer: load request on $TAPEDRIVE0" >>$logfile

    #Let's check if drive is loaded before we load it
    MOUNTED=`echo "status Storage=$storagename" | $console | $grep $TAPEDRIVE0 | $grep "is mounted with"`
    if [ -z "$MOUNTED" ] ; then
      echo "Drive is UNMOUNTED: $MOUNTED" >>$logfile
    else
      echo "Drive is MOUNTED: $MOUNTED" >>$logfile
      VOLUME=`echo "status Storage=$storagename" | $console | $grep -A2 $TAPEDRIVE0 | $grep "Volume:" | awk {'print $2'}`
      echo "Mounted Volume: $VOLUME" >>$logfile
      if [ $MOUNTED = $3 ] ; then
        echo "$3 is already mounted in $TAPEDRIVE0 as $VOLUME" >>$logfile
        exit
      else
        echo "$VOLUME is currently mounted in $TAPEDRIVE0, unmounting..." >>$logfile
        echo "unmount" | $console >/dev/null 2>/dev/null
      fi
    fi

    echo "Taking drive offline and ejecting..." >>$logfile
    mt -f $TAPEDRIVE0 rewoffl 2>/dev/null

    # extract label for the mail
    count=`expr 1`
    for label in $labels ; do
      if [ $slot -eq $count ] ; then volume=$label ; fi
      count=`expr $count + 1`
    done

    mail -s "Bacula needs volume $volume." $recipient <<END_OF_DATA
Please insert tape labelled $volume from slot $slot into $TAPEDRIVE0.
Kind regards,
Bacula.
END_OF_DATA

    sleep $TAPEDELAY

    # Wait for the tape to be inserted
    STATUS=`$mt -f $TAPEDRIVE0 status | $grep ONLINE`
    while [ -z "$STATUS" ] ; do
      sleep $TAPEDELAY
      STATUS=`$mt -f $TAPEDRIVE0 status | $grep ONLINE`
    done

    mail -s "Bacula says thank you." $recipient <<END_OF_DATA
Thank you for inserting the new tape! (I requested volume $volume from slot $slot.)
Kind regards,
Bacula.
END_OF_DATA

    echo "Successfully loaded a tape into drive $TAPEDRIVE0 (requested $volume from slot $slot)." >>$logfile
    echo "Loading finished." ; >>$logfile
    echo "$slot"
    exit 0
    ;;

  list)
    echo "mtx-changer: Requested list" >>$logfile
    count=`expr 1`
    for label in $labels ; do
      echo $count:$label 
      count=`expr $count + 1`
    done
    printf "\n"
    ;;

  loaded)
    echo "mtx-changer: tape loaded request on $TAPEDRIVE0" >>$logfile

    DRIVESTATUS=`mt -f $TAPEDRIVE0 status 2>/dev/null`
    MTRTN=$?
    if [ $MTRTN = "0" ] ; then
      echo "MT ran ok.  Return Code: $MTRTN" >>$logfile
      DRIVESTATUS=`mt -f $TAPEDRIVE0 status | grep "DR_OPEN"`
      if [ -z "$DRIVESTATUS"] ; then
        echo "MT says the drive has a tape" >>$logfile
        echo "0"
      else
        echo "MT says the drive is empty" >>$logfile
        echo "0"
      fi
    else
      echo "MT error, bacula might be using it! Return code: $MTRTN" >>$logfile

      MOUNTED=`echo "status Storage=$storagename" | $console | $grep $TAPEDRIVE0 | $grep "is mounted with"`
      if [ -z "$MOUNTED" ] ; then
        echo "Drive is UNMOUNTED: $MOUNTED">>$logfile
        echo "0"
      else
        echo "Drive is MOUNTED: $MOUNTED">>$logfile
        VOLUME=`echo "status Storage=$storagename" | $console | $grep -A2 $TAPEDRIVE0 | $grep "Volume:" | awk {'print $2'}`
        echo "Mounted Volume: $VOLUME" >>$logfile
        count=`expr 1`
        for label in $labels ; do
          if [ $VOLUME = $label ] ; then
            echo "$VOLUME = $label in slot $count" >>$logfile
            echo "$count"
          fi
          count=`expr $count + 1`
        done
      fi
    fi
    exit 0
    ;;

  slots)
    echo "mtx-changer: Request slots" >>$logfile
    count=`expr 0`
    for label in $labels ; do
      count=`expr $count + 1`
    done
    echo $count
    ;;

  volumes)
    echo "mtx-changer: Request volumes" >>$logfile
    count=`expr 1`
    for label in $labels ; do
      printf "$count:$label"
      count=`expr $count + 1`
    done
    printf "\n"
    ;;
esac

SD Configuration for Bacula with two one-drive auto changers

Autochanger {
  Name = Autochanger1
  Device = Drive-1
  Changer Command = "/etc/bacula/mtx-changer %c %o %S %a %d"
  Changer Device = /dev/sg0
}

Autochanger {
  Name = Autochanger2
  Device = Drive-2
  Changer Command = "/etc/bacula/mtx-changer %c %o %S %a %d"
  Changer Device = /dev/sg1
}

Device {
  Name = Drive-1                     #
  Drive Index = 0
  Media Type = LTO-2
  Archive Device = /dev/st0
  Changer Device = /dev/sg0
  AutomaticMount = yes;               # when device opened, read it
  AlwaysOpen = yes;
  RemovableMedia = yes;
  RandomAccess = no;
  AutoChanger = yes
  Label Media = no
  # Enable the Alert command only if you have the mtx package loaded
  Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
}

Device {
  Name = Drive-2                     #
  Drive Index = 0
  Media Type = LTO-2
  Archive Device = /dev/st1
  Changer Device = /dev/sg1
  AutomaticMount = yes;               # when device opened, read it
  AlwaysOpen = yes;
  RemovableMedia = yes;
  RandomAccess = no;
  AutoChanger = yes
  Label Media = no
  # Enable the Alert command only if you have the mtx package loaded
  Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
}

Dell ML6000 Configuration

Autochanger and device resources for an ML6000 with two LTO-3 drives (includes some commented-out default values):

Autochanger {
  Name = "ML6000 Library"
  Device = ML6000-LTO3-0, ML6000-LTO3-1
  Changer Device = /dev/sg3
  Changer Command = "/usr/local/bacula/sbin/mtx-changer %c %o %S %a %d"
                    # %c = changer device
                    # %o = command (unload|load|loaded|list|slots)
                    # %S = slot index (1-based)
                    # %a = archive device (i.e., /dev/sd* name for tape drive)
                    # %d = drive index (0-based)
}

Device {
  # The ML6000's first tape drive
  Name = ML6000-LTO3-0
  Archive Device = /dev/nst1
  Device Type = Tape
  Media Type = LTO3                     # If we were likely to ever have
                                        # multiple storage daemons
                                        # with LTO3 drives, we might
                                        # need to use media types like
                                        # "ML6000-LTO3" to distinguish
                                        # which library contained
                                        # which volumes.  But we're not.
  Autochanger = Yes
  # Changer Device = <inherited from Changer>
  Alert Command = "sh -c '/usr/local/bacula/sbin/tapeinfo -f /dev/sg1 | /bin/sed -n /TapeAlert/p'"
                                        # We use /dev/sg1 instead of
                                        # %c because we want the tape
                                        # drive's status, not the
                                        # changer's.  We use sed
                                        # instead of grep to avoid
                                        # logging non-zero exit
                                        # status reports from
                                        # grep when no strings
                                        # match its pattern.
  Drive Index = 0
  # Autoselect = yes                    # Since our backup host lacks
                                        # the I/O bandwidth for it to
                                        # worthwhile to write to two
                                        # drives simultaneously, it
                                        # might be worthwhile
                                        # manipulating this to either
                                        # reserve a drive for
                                        # restores, or to spread the
                                        # wear across the two drives.
  # Maximum Changer Wait = 300 seconds
  # Maximum Rewind Wait = 300 seconds
  # Maximum Open Wait = 300 seconds
  # Always Open = Yes
  # Volume Poll Interval = 0            # 0 means "don't poll".
  RemovableMedia = yes
  Random Access = no
  # Maximum block size = 64512        # Some sources suggest 128K or
                                      # 256K for better LTO3 throughput
  # Hardware End of Medium = Yes
  # Fast Forward Space File = Yes
  # Use MTIOCGET = Yes
  # BSF at EOM = No
  # Two EOM = No
  # Backward Space Record = Yes
  # Backward Space File = Yes
  # Forward Space Record = Yes
  # Forward Space File = Yes
  # Offline On Unmount = No
  # Maximum File Size = 1gb
  # Block Positioning = yes
  # Maximum Network Buffer Size = 32768  # The manual suggests it may be
                                         # worthwhile doubling this.
  Maximum Spool Size = 100gb
  Maximum Job Spool Size = 60gb
  Spool Directory = /backup/spool
  # Label media = No
  # Automatic mount = Yes
}

Device {
  # The ML6000's second tape drive
  Name = ML6000-LTO3-1
  Archive Device = /dev/nst2
  Device Type = Tape
  Media Type = LTO3
  Autochanger = Yes
  # Changer Device = <inherited from Changer>
  Alert Command = "sh -c '/usr/local/bacula/sbin/tapeinfo -f /dev/sg2 | /bin/sed -n /TapeAlert/p"
  Drive Index = 1
  RemovableMedia = yes
  Random Access = no

  Maximum Spool Size = 80gb
  Maximum Job Spool Size = 40gb
  Spool Directory = /backup/spool
}

(SUN) Storagetek SL-500 mtx-changer script

Inserted a new parameter in config file.

# If you vant Import/Export slots to show up in Bacula
io_slots_visible=1

  • mtx-changer.conf
# Bacula version 5.0.3
#
# This file is sourced by the mtx-changer script every time it runs.
#   You can put your site customization here, and when you do an
#   upgrade, the process should not modify this file.  Thus you
#   preserve your mtx-changer configuration.
#

# Set to 1 if you want to do offline before unload
offline=0

# Set to amount of time in seconds to wait after an offline
offline_sleep=0

# Set to amount of time in seconds to wait after a load
load_sleep=0

# Set to 1 to do an inventory before a status. Not normally needed. 
inventory=0

# If you have a VXA PacketLoader, it might display a different 
#  Storage Element line, so try setting the following to 1
vxa_packetloader=0

# If you vant Import/Export slots to show up in Bacula
io_slots_visible=1

# Set to 1 if you want debug info written to a log
debug_log=0


# mt status output
# SunOS     No Additional Sense
# FreeBSD   Current Driver State: at rest.
# Linux     ONLINE
#  Note Debian has a different mt than the standard Linux version. 
#    When no tape is in the drive it waits 2 minutes.  
#    When a tape is in the drive, it prints user unfriendly output.
#  Note, with Ubuntu Gusty (8.04), there are two versions of mt,
#    so we attempt to figure out which one.
#

OS=`uname`
case ${OS} in
  SunOS)
    ready="No Additional Sense"
    ;;
  FreeBSD)
    ready="Current Driver State: at rest."
    ;;
  Linux)
    ready="ONLINE"
    if test -f /etc/debian_version ; then
       mt --version|grep "mt-st" >/dev/null 2>&1
       if test $? -eq 1 ; then
          ready="drive status"
       fi
    fi
  ;;
esac
  • mtx-changer
#!/bin/sh
#
# Bacula interface to mtx autoloader
# Bacula version 5.0.3
#
#  If you set in your Device resource
#
#  Changer Command = "path-to-this-script/mtx-changer %c %o %S %a %d"
#    you will have the following input to this script:
#
#  So Bacula will always call with all the following arguments, even though
#    in come cases, not all are used.
#
#  mtx-changer "changer-device" "command" "slot" "archive-device" "drive-index"
#                  $1              $2       $3        $4               $5
#
#  for example:
#
#  mtx-changer /dev/sg0 load 1 /dev/nst0 0 (on a Linux system)
# 
#  will request to load the first cartidge into drive 0, where
#   the SCSI control channel is /dev/sg0, and the read/write device
#   is /dev/nst0.
#
#  The commands are:
#      Command            Function
#      unload             unload a given slot
#      load               load a given slot
#      loaded             which slot is loaded?
#      list               list Volume names (requires barcode reader)
#      slots              how many slots total?
#      listall            list all info
#      transfer
#
#  Slots are numbered from 1 ...
#  Drives are numbered from 0 ...
#
#
#  If you need to an offline, refer to the drive as $4
#    e.g.   mt -f $4 offline
#
#  Many changers need an offline after the unload. Also many
#   changers need a sleep 60 after the mtx load.
#
#  N.B. If you change the script, take care to return either 
#   the mtx exit code or a 0. If the script exits with a non-zero
#   exit code, Bacula will assume the request failed.
#

# source our conf file
if test ! -f /etc/bacula/mtx-changer.conf ; then
  echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
  echo "ERROR: /etc/bacula/mtx-changer.conf file not found!!!!"
  echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
  exit 1
fi
. /etc/bacula/mtx-changer.conf

MTX=/opt/csw/sbin/mtx

if test ${debug_log} -ne 0 ; then
  touch /var/bacula/working/mtx.log
fi
dbgfile="/var/bacula/working/mtx.log"
debug() {
    if test -f $dbgfile; then
        echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
    fi
}


#
# Create a temporary file
#
make_temp_file() {
  TMPFILE=`mktemp /var/bacula/working/mtx.XXXXXXXXXX`
  if test x${TMPFILE} = x; then
     TMPFILE="/var/bacula/working/mtx.$$"
     if test -f ${TMPFILE}; then
        echo "ERROR: Temp file security problem on: ${TMPFILE}"
        exit 1
     fi
  fi
}

#
# The purpose of this function to wait a maximum 
#   time for the drive. It will
#   return as soon as the drive is ready, or after
#   waiting a maximum of 300 seconds.
# Note, this is very system dependent, so if you are
#   not running on Linux, you will probably need to
#   re-write it, or at least change the grep target.
#   We've attempted to get the appropriate OS grep targets
#   in the code at the top of this script.
#
wait_for_drive() {
  i=0 
  while [ $i -le 300 ]; do  # Wait max 300 seconds
    if mt -f $1 status 2>&1 | grep "${ready}" >/dev/null 2>&1; then
      break
    fi
    debug "Device $1 - not ready, retrying..."
    sleep 1
    i=`expr $i + 1`
  done
}

# check parameter count on commandline
#
check_parm_count() {
    pCount=$1
    pCountNeed=$2
    if test $pCount -lt $pCountNeed; then
        echo "ERROR: usage: mtx-changer ctl-device command [slot archive-device drive-index]"
        echo "  Insufficient number of arguments given."
        if test $pCount -lt 2; then
            echo "  Mimimum usage is first two arguments ..."
        else
            echo "  Command expected $pCountNeed arguments"
        fi
        exit 1
    fi
}

# Check for special cases where only 2 arguments are needed, 
#  all others are a minimum of 5
#
case $2 in
    list|listall)
        check_parm_count $# 2
        ;;
    slots)
        check_parm_count $# 2
        ;;
    transfer)
        check_parm_count $# 4
        ;;
    *)
        check_parm_count $# 5
        ;;
esac


# Setup arguments
ctl=$1
cmd="$2"
slot=$3
device=$4
drive=$5

debug "Parms: $ctl $cmd $slot $device $drive"

case $cmd in 
   unload)
      debug "Doing mtx -f $ctl unload $slot $drive"

      if test ${offline} -eq 1 ; then
        mt -f $device offline
      fi
      if test ${offline_sleep} -ne 0 ; then
        sleep ${offline_sleep}
      fi
      ${MTX} -f $ctl unload $slot $drive
      ;;

   load)
      debug "Doing mtx -f $ctl load $slot $drive"
      ${MTX} -f $ctl load $slot $drive
      rtn=$?
      if test ${load_sleep} -ne 0 ; then
        sleep ${load_sleep}
      fi
      wait_for_drive $device
      exit $rtn
      ;;

   list) 
      debug "Doing mtx -f $ctl -- to list volumes"
      make_temp_file
      if test ${inventory} -ne 0 ; then
        ${MTX} -f $ctl inventory
      fi
      ${MTX} -f $ctl status >${TMPFILE}
      rtn=$?
      if test ${vxa_packetloader} -ne 0 ; then
        cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | sed "s/ Storage Element //" | sed "s/Full :VolumeTag=//"
      else
        if test ${io_slots_visible} -ne 0 ; then
          cat ${TMPFILE} | grep " Storage Element [0-9]*.*:Full.*" | sed "s/ *IMPORT\/EXPORT//" | awk "{print \$3 \$4}" | sed "s/Full.*:VolumeTag=//"
        else
        cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | awk "{print \$3 \$4}" | sed "s/Full.*:VolumeTag=//"
        fi
      fi
      cat ${TMPFILE} | grep "^Data Transfer Element [0-9]*:Full (Storage Element [0-9]" | awk '{printf "%s:%s\n",$7,$10}'
      rm -f ${TMPFILE} >/dev/null 2>&1
      exit $rtn
      ;;

   listall)
#  Drive content:         D:Drive num:F:Slot loaded:Volume Name
#  D:0:F:2:vol2        or D:Drive num:E
#  D:1:F:42:vol42   
#  D:3:E
# 
#  Slot content:
#  S:1:F:vol1             S:Slot num:F:Volume Name
#  S:2:E               or S:Slot num:E
#  S:3:F:vol4
# 
#  Import/Export tray slots:
#  I:10:F:vol10           I:Slot num:F:Volume Name
#  I:11:E              or I:Slot num:E
#  I:12:F:vol40
 
      debug "Doing mtx -f $ctl -- to list all"
      make_temp_file
      if test ${inventory} -ne 0 ; then
        ${MTX} -f $ctl inventory
      fi
      ${MTX} -f $ctl status >${TMPFILE}
      rtn=$?
      # can be converted to awk+sed+cut, see below
#      perl -ne '
#/Data Transfer Element (\d+):Empty/ && print "D:$1:E\n";
#/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "D:$1:F:$2:$4\n";
#/Storage Element (\d+):Empty/ && print "S:$1:E\n";
#/Storage Element (\d+):Full( :VolumeTag=(.+))?/ && print "S:$1:F:$3\n";
#/Storage Element (\d+) IMPORT.EXPORT:Empty/ && print "I:$1:E\n";
#/Storage Element (\d+) IMPORT.EXPORT:Full( :VolumeTag=(.+))?/ && print "I:$1:F:$3\n";' ${TMPFILE}
      # If perl isn't installed, you can use by those commands
cat ${TMPFILE} | grep "Data Transfer Element" | awk "{print \"D:\"\$4 \$7 \$9 \$10}" | sed "s/=/:/" | sed "s/Full/F:/" | sed "s/Empty/E/"
cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep -v "IMPORT/EXPORT" | awk "{print \"S:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/"
cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep "IMPORT/EXPORT" | awk "{print \"I:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" 

      rm -f ${TMPFILE} >/dev/null 2>&1
      exit $rtn
      ;;

   transfer)
      slotdest=$device
      debug "Doing transfer from $slot to $slotdest"
      ${MTX} -f $ctl transfer $slot $slotdest
      rtn=$?
      exit $rtn
      ;;

   loaded)
      debug "Doing mtx -f $ctl $drive -- to find what is loaded"
      make_temp_file
      ${MTX} -f $ctl status >${TMPFILE}
      rtn=$?
      cat ${TMPFILE} | grep "^Data Transfer Element $drive:Full" | awk "{print \$7}"
      cat ${TMPFILE} | grep "^Data Transfer Element $drive:Empty" | awk "{print 0}"
      rm -f ${TMPFILE} >/dev/null 2>&1
      exit $rtn
      ;;

   slots)
      debug "Doing mtx -f $ctl -- to get count of slots"
      ${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}"
      ;;
esac
sample_configs.txt · Last modified: 2013/11/15 19:22 by fs