1#!/bin/sh 2# 3# Bareos interface to mtx autoloader 4# 5# If you set in your Device resource 6# 7# Changer Command = "path-to-this-script/mtx-changer %c %o %S %a %d" 8# you will have the following input to this script: 9# 10# So Bareos will always call with all the following arguments, even though 11# in come cases, not all are used. 12# 13# mtx-changer "changer-device" "command" "slot" "archive-device" "drive-index" 14# $1 $2 $3 $4 $5 15# 16# for example: 17# 18# mtx-changer /dev/sg0 load 1 /dev/nst0 0 (on a Linux system) 19# 20# will request to load the first cartidge into drive 0, where 21# the SCSI control channel is /dev/sg0, and the read/write device 22# is /dev/nst0. 23# 24# The commands are: 25# Command Function 26# unload unload a given slot 27# load load a given slot 28# loaded which slot is loaded? 29# list list Volume names (requires barcode reader) 30# slots how many slots total? 31# listall list all info 32# transfer 33# 34# Slots are numbered from 1 ... 35# Drives are numbered from 0 ... 36# 37# 38# If you need to an offline, refer to the drive as $4 39# e.g. mt -f $4 offline 40# 41# Many changers need an offline after the unload. Also many 42# changers need a sleep 60 after the mtx load. 43# 44# N.B. If you change the script, take care to return either 45# the mtx exit code or a 0. If the script exits with a non-zero 46# exit code, Bareos will assume the request failed. 47# 48 49# source our conf file 50if test ! -r @confdir@/mtx-changer.conf ; then 51 echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 52 echo "ERROR: @confdir@/mtx-changer.conf file not found!!!!" 53 echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 54 exit 1 55fi 56. @confdir@/mtx-changer.conf 57 58MTX=@MTX@ 59if test ! -x "$MTX" ; then 60 echo "ERROR: mtx program not found ($MTX)" 61 exit 1 62fi 63 64dbgfile="@logdir@/mtx.log" 65if test ${debug_log} -ne 0 ; then 66 touch $dbgfile 67fi 68debug() { 69 if test -f $dbgfile; then 70 echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile 71 fi 72} 73 74 75# 76# Create a temporary file 77# 78make_temp_file() { 79 TMPFILE=`mktemp @working_dir@/mtx.XXXXXXXXXX` 80 if test x${TMPFILE} = x; then 81 TMPFILE="@working_dir@/mtx.$$" 82 if test -f ${TMPFILE}; then 83 echo "ERROR: Temp file security problem on: ${TMPFILE}" 84 exit 1 85 fi 86 fi 87} 88 89# 90# Create a temporary file for stderr 91# 92# Note, this file is used because sometime mtx emits 93# unexpected error messages followed by the output 94# expected during success. 95# So we separate STDOUT and STDERR in 96# certain of the mtx commands. The contents of STDERR 97# is then printed after the STDOUT produced by mtx 98# thus we sometimes get better changer results. 99# 100make_err_file() { 101 ERRFILE=`mktemp @working_dir@/mtx.err.XXXXXXXXXX` 102 if test x${ERRFILE} = x; then 103 ERRFILE="@working_dir@/mtx.err.$$" 104 if test -f ${ERRFILE}; then 105 echo "ERROR: Temp file security problem on: ${ERRFILE}" 106 exit 1 107 fi 108 fi 109} 110 111 112# 113# The purpose of this function to wait a maximum 114# time for the drive. It will 115# return as soon as the drive is ready, or after 116# waiting a maximum of 300 seconds. 117# Note, this is very system dependent, so if you are 118# not running on Linux, you will probably need to 119# re-write it, or at least change the grep target. 120# We've attempted to get the appropriate OS grep targets 121# in the code at the top of this script. 122# 123wait_for_drive() { 124 i=0 125 while [ $i -le 300 ]; do # Wait max 300 seconds 126 if mt -f $1 status 2>&1 | grep "${ready}" >/dev/null 2>&1; then 127 break 128 fi 129 debug "Device $1 - not ready, retrying..." 130 sleep 1 131 i=`expr $i + 1` 132 done 133} 134 135# check parameter count on commandline 136# 137check_parm_count() { 138 pCount=$1 139 pCountNeed=$2 140 if test $pCount -lt $pCountNeed; then 141 echo "ERROR: usage: mtx-changer ctl-device command [slot archive-device drive-index]" 142 echo " Insufficient number of arguments given." 143 if test $pCount -lt 2; then 144 echo " Mimimum usage is first two arguments ..." 145 else 146 echo " Command expected $pCountNeed arguments" 147 fi 148 exit 1 149 fi 150} 151 152# Check for special cases where only 2 arguments are needed, 153# all others are a minimum of 5 154# 155case $2 in 156 list|listall) 157 check_parm_count $# 2 158 ;; 159 slots) 160 check_parm_count $# 2 161 ;; 162 transfer) 163 check_parm_count $# 4 164 ;; 165 *) 166 check_parm_count $# 5 167 ;; 168esac 169 170 171# Setup arguments 172ctl=$1 173cmd="$2" 174slot=$3 175device=$4 176drive=$5 177 178debug "Parms: $ctl $cmd $slot $device $drive" 179 180case $cmd in 181 unload) 182 debug "Doing mtx -f $ctl unload $slot $drive" 183 184 if test ${offline} -eq 1 ; then 185 mt -f $device offline 186 fi 187 if test ${offline_sleep} -ne 0 ; then 188 sleep ${offline_sleep} 189 fi 190 make_err_file 191 ${MTX} -f $ctl unload $slot $drive 2>${ERRFILE} 192 rtn=$? 193 cat ${ERRFILE} 194 rm -f ${ERRFILE} >/dev/null 2>&1 195 exit $rtn 196 ;; 197 198 load) 199 debug "Doing mtx -f $ctl load $slot $drive" 200 make_err_file 201 ${MTX} -f $ctl load $slot $drive 2>${ERRFILE} 202 rtn=$? 203 if test ${load_sleep} -ne 0 ; then 204 sleep ${load_sleep} 205 fi 206 wait_for_drive $device 207 cat ${ERRFILE} 208 rm -f ${ERRFILE} >/dev/null 2>&1 209 exit $rtn 210 ;; 211 212 list) 213 debug "Doing mtx -f $ctl -- to list volumes" 214 make_temp_file 215 if test ${inventory} -ne 0 ; then 216 ${MTX} -f $ctl inventory 217 fi 218 ${MTX} -f $ctl status >${TMPFILE} 219 rtn=$? 220 if test ${vxa_packetloader} -ne 0 ; then 221 cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | sed "s/ Storage Element //" | sed "s/Full :VolumeTag=//" 222 else 223 cat ${TMPFILE} | grep " Storage Element [0-9]*:.*Full" | awk "{print \$3 \$4}" | sed "s/Full *\(:VolumeTag=\)*//" 224 fi 225 cat ${TMPFILE} | grep "^Data Transfer Element [0-9]*:Full (Storage Element [0-9]" | awk '{printf "%s:%s\n",$7,$10}' 226 rm -f ${TMPFILE} >/dev/null 2>&1 227 exit $rtn 228 ;; 229 230 listall) 231# Drive content: D:Drive num:F:Slot loaded:Volume Name 232# D:0:F:2:vol2 or D:Drive num:E 233# D:1:F:42:vol42 234# D:3:E 235# 236# Slot content: 237# S:1:F:vol1 S:Slot num:F:Volume Name 238# S:2:E or S:Slot num:E 239# S:3:F:vol4 240# 241# Import/Export tray slots: 242# I:10:F:vol10 I:Slot num:F:Volume Name 243# I:11:E or I:Slot num:E 244# I:12:F:vol40 245 246 debug "Doing mtx -f $ctl -- to list all" 247 make_temp_file 248 if test ${inventory} -ne 0 ; then 249 ${MTX} -f $ctl inventory 250 fi 251 ${MTX} -f $ctl status >${TMPFILE} 252 rtn=$? 253 # can be converted to awk+sed+cut, see below 254 perl -ne ' 255/Data Transfer Element (\d+):Empty/ && print "D:$1:E\n"; 256/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "D:$1:F:$2:$4\n"; 257/Storage Element (\d+):Empty/ && print "S:$1:E\n"; 258/Storage Element (\d+):Full( :VolumeTag=(.+))?/ && print "S:$1:F:$3\n"; 259/Storage Element (\d+) IMPORT.EXPORT:Empty/ && print "I:$1:E\n"; 260/Storage Element (\d+) IMPORT.EXPORT:Full( :VolumeTag=(.+))?/ && print "I:$1:F:$3\n";' ${TMPFILE} 261 # If perl isn't installed, you can use by those commands 262#cat ${TMPFILE} | grep "Data Transfer Element" | awk "{print \"D:\"\$4 \$7 \$9 \$10}" | sed "s/=/:/" | sed "s/Full/F:/" | sed "s/Empty/E/" 263#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/" 264#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/" 265 266 rm -f ${TMPFILE} >/dev/null 2>&1 267 exit $rtn 268 ;; 269 270 transfer) 271 slotdest=$device 272 debug "Doing transfer from $slot to $slotdest" 273 ${MTX} -f $ctl transfer $slot $slotdest 274 rtn=$? 275 exit $rtn 276 ;; 277 278 loaded) 279 debug "Doing mtx -f $ctl $drive -- to find what is loaded" 280 make_temp_file 281 ${MTX} -f $ctl status >${TMPFILE} 282 rtn=$? 283 cat ${TMPFILE} | grep "^Data Transfer Element $drive:Full" | awk "{print \$7}" 284 cat ${TMPFILE} | grep "^Data Transfer Element $drive:Empty" | awk "{print 0}" 285 rm -f ${TMPFILE} >/dev/null 2>&1 286 exit $rtn 287 ;; 288 289 slots) 290 debug "Doing mtx -f $ctl -- to get count of slots" 291 ${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}" 292 ;; 293esac 294