3 # Bacula interface to virtual autoloader using disk storage
5 # Written by Kern Sibbald
7 # Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
9 # The main author of Bacula is Kern Sibbald, with contributions from
10 # many others, a complete list can be found in the file AUTHORS.
11 # This program is Free Software; you can redistribute it and/or
12 # modify it under the terms of version two of the GNU General Public
13 # License as published by the Free Software Foundation, which is
14 # listed in the file LICENSE.
16 # This program is distributed in the hope that it will be useful, but
17 # WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 # General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 # Bacula® is a registered trademark of Kern Sibbald.
27 # The licensor of Bacula is the Free Software Foundation Europe
28 # (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
29 # Switzerland, email:ftf@fsfeurope.org.
34 # If you set in your Device resource
36 # Changer Command = "path-to-this-script/disk-changer %c %o %S %a %d"
37 # you will have the following input to this script:
39 # So Bacula will always call with all the following arguments, even though
40 # in come cases, not all are used.
42 # disk-changer "changer-device" "command" "slot" "archive-device" "drive-index"
45 # By default the autochanger has 10 Volumes and 1 Drive.
47 # Note: For this script to work, you *must" specify
49 # in each of the Devices associated with your AutoChanger resource.
51 # changer-device is the name of a file that overrides the default
52 # volumes and drives. It may have:
53 # maxslot=n where n is one based (default 10)
54 # maxdrive=m where m is zero based (default 1 -- i.e. 2 drives)
56 # This code can also simulate barcodes. You simply put
57 # a list of the slots and barcodes in the "base" directory/barcodes.
58 # See below for the base directory definition. Example of a
60 # /var/bacula/barcodes
65 # archive-device is the name of the base directory where you want the
66 # Volumes stored appended with /drive0 for the first drive; /drive1
67 # for the second drive, ... For example, you might use
68 # /var/bacula/drive0 Note: you must not have a trailing slash, and
69 # the string (e.g. /drive0) must be unique, and it must not match
70 # any other part of the directory name. These restrictions could be
71 # easily removed by any clever script jockey.
73 # Full example: disk-changer /var/bacula/conf load 1 /var/bacula/drive0 0
75 # The Volumes will be created with names slot1, slot2, slot3, ... maxslot in the
76 # base directory. In the above example the base directory is /var/bacula.
77 # However, as with tapes, their Bacula Volume names will be stored inside the
78 # Volume label. In addition to the Volumes (e.g. /var/bacula/slot1,
79 # /var/bacula/slot3, ...) this script will create a /var/bacula/loadedn
80 # file to keep track of what Slot is loaded. You should not change this file.
89 # to turn on logging, uncomment the following line
90 #touch $wd/disk-changer.log
92 dbgfile="$wd/disk-changer.log"
94 if test -f $dbgfile; then
95 echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
101 # Create a temporary file
104 TMPFILE=`mktemp -t mtx.XXXXXXXXXX`
105 if test x${TMPFILE} = x; then
106 TMPFILE="$wd/disk-changer.$$"
107 if test -f ${TMPFILE}; then
108 echo "Temp file security problem on: ${TMPFILE}"
114 # check parameter count on commandline
119 if test $pCount -lt $pCountNeed; then
120 echo "usage: disk-changer ctl-device command [slot archive-device drive-index]"
121 echo " Insufficient number of arguments arguments given."
122 if test $pCount -lt 2; then
123 echo " Mimimum usage is first two arguments ..."
125 echo " Command expected $pCountNeed arguments"
132 # Strip off the final name in order to get the Directory ($dir)
133 # that we are dealing with.
136 bn=`basename $device`
137 dir=`echo "$device" | sed -e s%/$bn%%g`
138 if [ ! -d $dir ]; then
139 echo "ERROR: Autochanger directory \"$dir\" does not exist."
140 echo " You must create it."
163 # Check for special cases where only 2 arguments are needed,
164 # all others are a minimum of 5
168 check_parm_count $# 2
171 check_parm_count $# 2
174 check_parm_count $# 4
175 if [ $slot -gt $maxslot ]; then
176 echo "Slot ($slot) out of range (1-$maxslot)"
181 check_parm_count $# 5
182 if [ $drive -gt $maxdrive ]; then
183 echo "Drive ($drive) out of range (0-$maxdrive)"
186 if [ $slot -gt $maxslot ]; then
187 echo "Slot ($slot) out of range (1-$maxslot)"
195 debug "Parms: $ctl $cmd $slot $device $drive"
199 debug "Doing disk -f $ctl unload $slot $device $drive"
201 if [ -f $dir/loaded${drive} ]; then
202 ld=`cat $dir/loaded${drive}`
204 echo "Storage Element $slot is Already Full"
207 if [ $slot -eq $ld ]; then
208 echo "0" >$dir/loaded${drive}
209 unlink $device 2>/dev/null >/dev/null
212 echo "Storage Element $slot is Already Full"
218 debug "Doing disk $ctl load $slot $device $drive"
221 while [ $i -le $maxdrive ]; do
222 if [ -f $dir/loaded${i} ]; then
223 ld=`cat $dir/loaded${i}`
227 if [ $ld -eq $slot ]; then
228 echo "Drive ${i} Full (Storage element ${ld} loaded)"
233 # check if slot exists
234 if [ ! -f $dir/slot${slot} ] ; then
235 echo "source Element Address $slot is Empty"
238 if [ -f $dir/loaded${drive} ]; then
239 ld=`cat $dir/loaded${drive}`
243 if [ $ld -ne 0 ]; then
244 echo "Drive ${drive} Full (Storage element ${ld} loaded)"
247 echo "0" >$dir/loaded${drive}
248 unlink $device 2>/dev/null >/dev/null
250 ln -s $dir/slot${slot} $device
252 if [ $rtn -eq 0 ]; then
253 echo $slot >$dir/loaded${drive}
259 debug "Doing disk -f $ctl -- to list volumes"
261 if [ -f $dir/barcodes ]; then
265 while [ $i -le $maxslot ]; do
275 debug "Doing disk -f $ctl -- to list volumes"
277 if [ ! -f $dir/barcodes ]; then
281 # we print drive content seen by autochanger
282 # and we also remove loaded media from the barcode list
284 while [ $i -le $maxdrive ]; do
285 if [ -f $dir/loaded${i} ]; then
286 ld=`cat $dir/loaded${i}`
287 v=`awk -F: "/^$ld:/"' { print $2 }' $dir/barcodes`
289 echo "^$ld:" >> $TMPFILE
294 # Empty slots are not in barcodes file
295 # When we detect a gap, we print missing rows as empty
296 # At the end, we fill the gap between the last entry and maxslot
297 grep -v -f $TMPFILE $dir/barcodes | sort -n | \
298 perl -ne 'BEGIN { $cur=1 }
310 END { while ($cur < '"$maxslot"') { print "S:$cur:E\n"; $cur++; } } '
319 if [ -f $dir/slot{$slotdest} ]; then
320 echo "destination Element Address $slot is Full"
323 if [ ! -f $dir/slot${slot} ] ; then
324 echo "source Element Address $slot is Empty"
328 echo "Transfering $slot to $slotdest"
329 mv $dir/slot${slot} $dir/slot{$slotdest}
331 if [ -f $dir/barcodes ]; then
332 sed "s/^$slot:/$slotdest:/" > $TMPFILE
333 sort -n $TMPFILE > $dir/barcodes
338 debug "Doing disk -f $ctl $drive -- to find what is loaded"
340 if [ -f $dir/loaded${drive} ]; then
341 cat $dir/loaded${drive}
349 debug "Doing disk -f $ctl -- to get count of slots"