File: mtx-changer

package info (click to toggle)
mtx 1.3.11-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 964 kB
  • ctags: 967
  • sloc: ansic: 7,075; sh: 3,266; python: 203; makefile: 158; perl: 117
file content (431 lines) | stat: -rwxr-xr-x 11,004 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
#! /bin/sh
###############################################################################
# AMANDA Tape Changer script for use with the MTX tape changer program
# Version 1.0 - Tue Feb 20 13:59:39 CST 2001
# 
# Based on 'stc-changer' by Eric Berggren (eric@ee.pdx.edu)
# Updated by Tim Skirvin (tskirvin@ks.uiuc.edu)
# 
# Given that there's no license...let's make this the Perl Artistic License.
# Just make sure you give me and Eric credit if you modify this.  
###############################################################################

### USER CONFIGURATION
# Name of the tape drive (takes place of "tapedev" option in amanda.conf)
#  and default driver number in library (usu 0) that DRIVE_NAME points to
DRIVE_NAME="/dev/rmt/0n"
DRIVE_NUM=0

# Location of "STC" command and control device
MTX_CMD="/usr/local/sbin/mtx";
MTX_CONTROL="/dev/scsi/changer/c4t1d0";

# Whether tape drive must eject tape before changer retrieves
#  (ie, EXB-2x0). Usually okay if set while not necessary, bad if
#  required but not set.
DRIVE_MUST_EJECT=1

# How long to check drive readiness (in seconds) after mounting (or
#  ejecting) a volume (on some libraries, the motion or eject command may
#  complete before the drive has the volume fully mounted and online,
#  or ready for retrieval, resulting in "Drive not ready"/"Media not
#  ready" errors). Do an "mt status" command every 5 seconds upto this
#  time.
DRIVE_READY_TIME_MAX=120

#  tape "mt" command location...
MT_CMD="/usr/bin/mt"     # called via "MT_CMD -f DRIVE_NAME rewind" &
                         #   "MT_CMD -f DRIVE_NAME offline" to eject
                         # and "MT_CMD -f DRIVE_NAME status" to get ready info

##############################################################################
#
NumDrives=-1
NumSlots=-1
LastSlot=-1
LoadedTape=-1

#
# Usage information
#
usage()
{
    echo
    echo "Usage: $Progname <command> [arg...]"
    echo "  -info          reports capability and loaded tape"
    echo "  -slot <slot>   loads specified tape into drive"
    echo "        current  reports current mounted tape"
    echo "        next     loads logically next tape (loops to top)"
    echo "        prev     loads logically previous tape (loops to bot)"
    echo "        first    loads first tape"
    echo "        last     loads last tape"
    echo "        0..99    loads tape from specified slot#"
    echo "  -eject         uloads current mounted tape"
    echo "  -reset         resets changer (and drive); loads first tape"
    echo
    exit 5
}

#
# Perform "stc" changer command (& handle the "fatal" errors)
#  else, set 'CommandResStr' and 'CommandRawResStr' to the result string 
#  and 'CommandResCode' to the exit code
#
dotapecmd()
{
    cmd=$1
    arg=$2

    CommandResStr=`$MTX_CMD $MTX_CONTROL $cmd $arg 2>&1`
    CommandRawResStr=$CommandResStr
    CommandResCode=$?

    CommandResStr=`echo $CommandResStr | head -1 | sed 's/^[^:]*: //'`
    if [ $CommandResCode -gt 1 ]; then
        echo "0 $Progname: returned $CommandResStr"
        exit 2
    fi
}

#
# Unload tape from drive (a drive command; "ejecttape" is a changer command
#  to actually retrieve the tape). Needed by some changers (controlled by
#  setting "DRIVE_MUST_EJECT")
#
ejectdrive()
{
    # Tell drive to eject tape before changer retrieves; req'd by some
    #  drives (ie, EXB-2x0). Not needed by QDLT-4x00. Do a "rewind"
    #  command first, then "offline" to eject (instead of "rewoffl")
    #
    if [ "$DRIVE_MUST_EJECT" -ne 0 ]; then
        mtresstr=`$MT_CMD -f $DRIVE_NAME rewind 2>&1`
        mtrescode=$?

        if [ $mtrescode -ne 0 ]; then
            if echo "$mtresstr" | egrep -s 'no tape'; then
                :;   # no tape mounted; assume okay...
            else
                # can't eject tape, bad; output: <tape#> reason
                echo "0 $mtresstr"
                exit 1
            fi
        else
            mtresstr=`$MT_CMD -f $DRIVE_NAME offline 2>&1`
            mtrescode=$?

            checkdrive 1
        fi
    fi
}

#
# Check drive readiness after (un)mounting a volume (which may take a while
#  after the volume change command completes)
#
checkdrive()
{
    unmounting=$1

    if [ "$DRIVE_READY_TIME_MAX" -gt 0 ]; then

        # sleep time between checks
        pausetime=5

        # number of interations to check
        numchecks=`expr $DRIVE_READY_TIME_MAX / $pausetime`
        if [ "$numchecks" -eq 0 ]; then
            numchecks=1
        fi

        # check until success, or out of attempts...
        while [ "$numchecks" -gt 0 ]; do
            mtresstr=`$MT_CMD -f $DRIVE_NAME status 2>&1`
            mtrescode=$?

            if [ $mtrescode -eq 0 ]; then
                # Success ?
                return 0
            else
                # pause, before trying again....
                if [ "$numchecks" -gt 1 ]; then
                    sleep $pausetime

                    # if unmounting a volume, check for 'mt' command
                    #  failure; (sleep first for additional comfort)
                    if [ "$unmounting" -ne 0 ]; then
                        return 0
                    fi
                fi
            fi
            numchecks=`expr $numchecks - 1`
        done

        # failed; output: -1 reason
        echo "-1 drive won't report ready"
        exit 1
    fi
}

#
# Get changer parameters
#
getchangerparms()
{
    dotapecmd status
    if [ $CommandResCode -eq 0 ] && \
        echo "$CommandResStr" | egrep -s '^Storage Changer'; then

        NumDrives=`echo $dspec | wc -l`
	NumDrives=`echo "$CommandRawResStr" | \
			grep 'Data Transfer Element' | wc -l`
        if [ "$NumDrives" -le "$DRIVE_NUM" ]; then
            echo "$Program: Invalid drive # specified ($DRIVE_NUM > $NumDrives)"
            exit 3
        fi
			# grep 'Data Transfer Element $DRIVE_NUM' | \
	LoadedTape=`echo "$CommandRawResStr" | \
			grep 'Data Transfer Element' | \
			grep 'Storage Element [0-9]' | \
			awk '{ print $7 }'	`
        if [ -z "$LoadedTape" -o "$LoadedTape" = "e" ]; then
            LoadedTape=-1
        fi
        NumSlots=`echo "$CommandRawResStr" | \
		grep 'Storage Element [0-9]\{1,\}:' | \
		grep -v 'Data Element' | \
		wc -l | sed -e 's/ //g' `
        LastSlot=`expr $NumSlots - 1`
    else
        echo \
          "$Progname: Can't get changer parameters; Result was $CommandResStr"
        exit 3
    fi
}
    
#
# Display changer info
#
changerinfo()
{
    getchangerparms

    # output status string: currenttape numslots randomaccess?
    echo "$LoadedTape $NumSlots 1"
    exit 0
}

#
# Eject current mounted tape
#
ejecttape()
{
    getchangerparms
    ct=$LoadedTape

    # If no tape reported mounted, assume success (could be bad if changer
    #  lost track of tape)
    #
    if [ $ct -lt 0 ]; then
        CommandResCode=0
    else
        ejectdrive
        dotapecmd unload
    fi

    if [ $CommandResCode -ne 0 ]; then
        # failed; output: <tape#> reason
        echo "$ct $CommandResStr"
        exit 1
    else
        # success; output: <tape#> drive
        echo "$ct $DRIVE_NAME"
        exit 0
    fi
}

#
# Move specified tape into drive (operation level)
#
doloadtape()
{
    slot=$1
    if [ "$slot" -eq "$LoadedTape" ]; then
        return 0
    fi
    ejectdrive
    dotapecmd load $slot
    return $CommandResCode
}

#
# Load next available tape into drive
#
loadnexttape()
{
    curslot=$1
    direction=$2

    startslot=$curslot
    while true; do
        if doloadtape $curslot; then
            return 0
        else
            if echo $CommandResStr | egrep -s 'Slot.*reported empty'; then

                if [ "$direction" -lt 0 ]; then
                    curslot=`expr $curslot - 1`
                    if [ "$curslot" -lt 0 ]; then
                        curslot=$LastSlot
                    fi
                else
                    curslot=`expr $curslot + 1`
                    if [ "$curslot" -gt "$LastSlot" ]; then
                        curslot=0
                    fi
                fi

                # Check if we're back to where we started...
                if [ "$curslot" = "$startslot" ]; then
                    if [ "$direction" -lt 0 ]; then
                        CommandResStr="No previous volume available"
                    else
                        CommandResStr="No subsequent volume available"
                    fi
                    return 1
                fi
            else
                return 1
            fi
        fi
    done
}

#
# Report loadtape() status
#
reportstatus()
{
    if [ $CommandResCode -eq 0 ]; then
        # success; output currenttape drivename
        echo "$LoadedTape $DRIVE_NAME"
        exit 0
    else
        # failed (empty slot?); output currenttape reason
        echo "$LoadedTape $CommandResStr"
        exit 1
    fi
}


#
# Move specified tape into drive (command level)
#
loadtape()
{
    slot=$1

    getchangerparms

    case "$slot" in
        current)
            if [ $LoadedTape -lt 0 ]; then
                CommandResStr="Can't determine current tape; drive empty ?"
                CommandResCode=1
            fi
            ;;
        prev)
            if [ $LoadedTape -le 0 ]; then
                loadnexttape $LastSlot -1
            else
                loadnexttape `expr $LoadedTape - 1` -1
            fi
            ;;
        next)
            if [ $LoadedTape -ge $LastSlot -o $LoadedTape -lt 0 ]; then
                loadnexttape 0 1
            else
                loadnexttape `expr $LoadedTape + 1` 1
            fi
            ;;
        first)
            loadnexttape 0 1
            ;;
        last)
            loadnexttape $LastSlot -1
            ;;
        [0-9]*)
            doloadtape $slot
            ;;
        *)
            # error; no valid slot specified
            echo "$Progname: No valid slot specified"
            exit 1
            ;;
    esac

    if [ $CommandResCode -eq 0 ]; then
        getchangerparms
        checkdrive
    fi
    reportstatus
}

#
# Reset changer to known state
#
resetchanger()
{
    ejectdrive
    dotapecmd reset
    if [ $CommandResCode -ne 0 ]; then
        # failed; output: failed? reason
        echo "-1 $CommandResStr"
        exit 2;
    else
        loadtape first
    fi
}

#############################################################################
#
# MAIN
#
Progname=`basename $0`

if [ ! -x "$MTX_CMD" ]; then
    echo "-1 $Progname: cannot run STC command ($MTX_CMD)"
    exit 2
fi
if [ -n "$MTX_CONTROL" ]; then
    if echo "$MTX_CONTROL" | egrep -s '^-f'; then
        :;
    else
        MTX_CONTROL="-f $MTX_CONTROL"
    fi
fi
if [ -n "$DRIVE_NUM" ]; then
    DRIVE_NUM=0
fi

if [ $# -ge 1 ]; then command=$1; else command="-usage"; fi

case "$command" in
    -info)
        changerinfo
        ;;
    -slot)
        loadtape $2
        ;;
    -eject)
        ejecttape
        ;;
    -reset)
        resetchanger
        ;;
    *)
        usage
        ;;
esac

exit 0