]> git.sur5r.net Git - bacula/bacula/blob - bacula/scripts/disk-changer.in
Add make_catalog_backup.pl script that uses env variables and
[bacula/bacula] / bacula / scripts / disk-changer.in
1 #!/bin/sh
2 #
3 # Bacula interface to virtual autoloader using disk storage
4 #
5 #  Written by Kern Sibbald
6 #
7 #  Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
8 #
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.
15 #
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.
20 #
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
24 #  02110-1301, USA.
25 #
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.
30 #
31 #
32 #  $Id$
33 #
34 #  If you set in your Device resource
35 #
36 #  Changer Command = "path-to-this-script/disk-changer %c %o %S %a %d"
37 #    you will have the following input to this script:
38 #
39 #  So Bacula will always call with all the following arguments, even though
40 #    in come cases, not all are used.
41 #
42 #  disk-changer "changer-device" "command" "slot" "archive-device" "drive-index"
43 #                   $1              $2       $3        $4               $5
44 #
45 # By default the autochanger has 10 Volumes and 1 Drive.
46 #
47 # Note: For this script to work, you *must" specify
48 #    Device Type = File 
49 # in each of the Devices associated with your AutoChanger resource.
50 #
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)
55 #  
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 
59 #   barcodes file:
60 #      /var/bacula/barcodes
61 #      1:Vol001
62 #      2:Vol002
63 #      ...
64
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.
72 #
73 #  Full example: disk-changer /var/bacula/conf load 1 /var/bacula/drive0 0
74 #
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.
81 #
82 #
83
84 wd=@working_dir@
85
86 #
87 # log whats done
88 #
89 # to turn on logging, uncomment the following line
90 #touch $wd/disk-changer.log
91 #
92 dbgfile="$wd/disk-changer.log"
93 debug() {
94     if test -f $dbgfile; then
95         echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
96     fi
97 }
98
99
100 #
101 # Create a temporary file
102 #
103 make_temp_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}"
109         exit 1
110      fi
111   fi
112 }
113
114 # check parameter count on commandline
115 #
116 check_parm_count() {
117     pCount=$1
118     pCountNeed=$2
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 ..."
124         else
125             echo "  Command expected $pCountNeed arguments"
126         fi
127         exit 1
128     fi
129 }
130
131 #
132 # Strip off the final name in order to get the Directory ($dir)
133 #  that we are dealing with.
134 #
135 get_dir() {
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.\n"
140       echo "       You must create it.\n"
141       exit 1
142    fi
143 }
144
145
146 # Setup arguments
147 ctl=$1
148 cmd="$2"
149 slot=$3
150 device=$4
151 drive=$5
152
153 # set defaults
154 maxdrive=1
155 maxslot=10
156
157 # Pull in conf file
158 if [ -f $ctl ]; then 
159    . $ctl
160 fi
161
162
163 # Check for special cases where only 2 arguments are needed, 
164 #  all others are a minimum of 5
165 #
166 case $2 in
167     list|listall)
168         check_parm_count $# 2
169         ;;
170     slots)
171         check_parm_count $# 2
172         ;;
173     transfer)
174         check_parm_count $# 4
175         if [ $slot -gt $maxslot ]; then
176            echo "Slot ($slot) out of range (1-$maxslot)"
177            exit 1
178         fi
179         ;;
180     *)
181         check_parm_count $# 5
182         if [ $drive -gt $maxdrive ]; then
183            echo "Drive ($drive) out of range (0-$maxdrive)"
184            exit 1
185         fi
186         if [ $slot -gt $maxslot ]; then
187            echo "Slot ($slot) out of range (1-$maxslot)"
188            exit 1
189         fi
190         ;;
191 esac
192
193
194
195 debug "Parms: $ctl $cmd $slot $device $drive"
196
197 case $cmd in 
198    unload)
199       debug "Doing disk -f $ctl unload $slot $device $drive"
200       get_dir
201       if [ -f $dir/loaded${drive} ]; then
202          ld=`cat $dir/loaded${drive}`
203       else 
204          echo "Storage Element $slot is Already Full"
205          exit 1
206       fi
207       if [ $slot -eq $ld ]; then
208          echo "0" >$dir/loaded${drive}
209          unlink $device 2>/dev/null >/dev/null
210          rm -f $device
211       else
212          echo "Storage Element $slot is Already Full"
213          exit 1
214       fi
215       ;;
216
217    load)
218       debug "Doing disk $ctl load $slot $device $drive"
219       get_dir
220       i=0
221       while [ $i -le $maxdrive ]; do
222          if [ -f $dir/loaded${i} ]; then
223             ld=`cat $dir/loaded${i}`
224          else    
225             ld=0
226          fi
227          if [ $ld -eq $slot ]; then
228             echo "Drive ${i} Full (Storage element ${ld} loaded)"
229             exit 1
230          fi
231          i=`expr $i + 1`
232       done
233       # check if slot exists
234       if [ ! -f $dir/slot${slot} ] ; then
235          echo "source Element Address $slot is Empty"
236          exit 1
237       fi
238       if [ -f $dir/loaded${drive} ]; then
239          ld=`cat $dir/loaded${drive}`
240       else
241          ld=0
242       fi
243       if [ $ld -ne 0 ]; then
244          echo "Drive ${drive} Full (Storage element ${ld} loaded)"
245          exit 1
246       fi
247       echo "0" >$dir/loaded${drive}
248       unlink $device 2>/dev/null >/dev/null
249       rm -f $device
250       ln -s $dir/slot${slot} $device
251       rtn=$?
252       if [ $rtn -eq 0 ]; then
253          echo $slot >$dir/loaded${drive}
254       fi
255       exit $rtn
256       ;;
257
258    list) 
259       debug "Doing disk -f $ctl -- to list volumes"
260       get_dir 
261       if [ -f $dir/barcodes ]; then
262          cat $dir/barcodes
263       else
264          i=1
265          while [ $i -le $maxslot ]; do
266             echo "$i:"
267             i=`expr $i + 1`
268          done
269       fi
270       exit 0
271       ;;
272
273    listall) 
274       make_temp_file
275       debug "Doing disk -f $ctl -- to list volumes"
276       get_dir 
277       if [ ! -f $dir/barcodes ]; then
278           exit 0
279       fi
280
281       # we print drive content seen by autochanger
282       # and we also remove loaded media from the barcode list
283       i=0
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`
288              echo "D:$i:F:$ld:$v"
289              echo "^$ld:" >> $TMPFILE
290          fi
291          i=`expr $i + 1`
292       done
293
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 } 
299        if (/(\d+):(.+)?/) {
300          if ($cur == $1) { 
301            print "S:$1:F:$2\n" 
302          } else { 
303            while ($cur < $1) {
304               print "S:$cur:E\n";
305               $cur++;
306            }
307          }
308          $cur++;
309        } 
310        END { while ($cur < '"$maxslot"') { print "S:$cur:E\n"; $cur++; } } '
311
312       rm -f $TMPFILE
313       exit 0
314       ;;
315    transfer)
316       get_dir
317       make_temp_file
318       slotdest=$device
319       if [ -f $dir/slot{$slotdest} ]; then
320          echo "destination Element Address $slot is Full"
321          exit 1
322       fi
323       if [ ! -f $dir/slot${slot} ] ; then
324          echo "source Element Address $slot is Empty"
325          exit 1
326       fi
327
328       echo "Transfering $slot to $slotdest"
329       mv $dir/slot${slot} $dir/slot{$slotdest}
330
331       if [ -f $dir/barcodes ]; then
332          sed "s/^$slot:/$slotdest:/" >  $TMPFILE
333          sort -n $TMPFILE > $dir/barcodes
334       fi
335       exit 0
336       ;;
337    loaded)
338       debug "Doing disk -f $ctl $drive -- to find what is loaded"
339       get_dir
340       if [ -f $dir/loaded${drive} ]; then
341          cat $dir/loaded${drive}
342       else
343          echo "0"
344       fi
345       exit
346       ;;
347
348    slots)
349       debug "Doing disk -f $ctl -- to get count of slots"
350       echo $maxslot
351       ;;
352 esac