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
|
#!/bin/sh
#
# BAREOS interface to tape libraries and autoloaders for FreeBSD
# (by Rudolf Cejka <cej...@fit.vutbr.cz>, v1.2, 2012/11/14)
#
# If you set in your Device resource
# Changer Command = "path-to-this-script/chio-changer %c %o %S %a %d"
# you will have the following input to this script:
# chio-changer "changer-device" "command" "slot" "tape-device" "drive-index"
# $1 $2 $3 $4 $5
# for example (on a FreeBSD system):
# chio-changer /dev/ch0 load 1 /dev/nsa0 0
#
# If you change the script, take care to return either the chio exit
# code or a 0. If the script exits with a non-zero exit code, BAREOS
# will assume the request failed.
#
PROGNAME=`basename $0`
# Uncomment the following line, if you want to log debug output.
#DEBUG=/var/run/bareos/${PROGNAME}.log
# Uncomment the following line, if you need to eject a tape before moving
# it from the drive.
#OFFLINE=yes
# Uncomment one or more of the following lines, if you need to wait for
# some time (in seconds) after unloading, loading or transferring a tape.
#OFFLINE_SLEEP=10
#LOAD_SLEEP=10
#MOVE_SLEEP=10
# Uncomment the following line, if you do not have a changer with volume
# reader.
#FAKE_BARCODES=/usr/local/etc/bareos-barcodes
usage()
{
cat <<EOF
Usage: ${PROGNAME} <changer-device> <cmd> [slot] [tape-device] [drive-index]
Commands (<cmd>):
unload Unload a tape into the slot from where it was loaded
load <slot> Load a tape from the slot <slot> (1-based)
transfer <slot> <slotdst> Transfer a tape from the slot <slot> to
the slot <slotdst> (1-based)
list List full storage slots
listall List all storage slots and drives with source information
loaded Give slot from where the tape was loaded (0 = empty drive)
slots Give number of available slots
Example:
${PROGNAME} /dev/ch0 load 1 Load a tape from the slot 1
EOF
exit 1
}
# Default settings
CHANGER=/dev/ch0
TAPE=/dev/nsa0
DRIVE=0
CHIO=/bin/chio
MT=/usr/bin/mt
if [ -n "${DEBUG}" ]; then
MSG=$0
for PAR; do MSG="${MSG} \"${PAR}\""; done
echo `date +"%Y/%m/%d %H:%M:%S"` ${MSG} >> ${DEBUG}
fi
if [ -n "$1" ]; then
CHANGER=$1;
fi
COMMAND=$2
SLOT=$3
SLOTDST=$4
if [ -n "$4" ]; then
TAPE=$4
fi
if [ -n "$5" ]; then
DRIVE=$5
fi
case ${COMMAND} in
unload)
if [ "${OFFLINE}" = yes ]; then
${MT} -f ${TAPE} offline
if [ $? = 0 -a -n "${OFFLINE_SLEEP}" ]; then
sleep ${OFFLINE_SLEEP}
fi
fi
if [ -z "${SLOT}" ]; then
${CHIO} -f ${CHANGER} return drive ${DRIVE}
else
${CHIO} -f ${CHANGER} move drive ${DRIVE} slot $((${SLOT} - 1))
fi
if [ $? -ne 0 ]; then
# In case of an error, try to unload the cartridge to the first free slot
FREE=`${CHIO} -f ${CHANGER} status slot | \
sed -ne '/FULL/d;s/^slot *\([0-9]*\):.*/\1/p' | \
awk 'BEGIN { n = 0 } { n = $1 + 1; exit } END { print n }'`
if [ ${FREE} -gt 0 ]; then
${CHIO} -f ${CHANGER} move drive ${DRIVE} slot $((${FREE} - 1))
else
exit 1
fi
fi
;;
load)
if [ -z "${SLOT}" ]; then
usage
fi
${CHIO} -f ${CHANGER} move slot $((${SLOT} - 1)) drive ${DRIVE}
if [ $? -ne 0 ]; then
exit 1
fi
if [ -n "${LOAD_SLEEP}" ]; then
sleep ${LOAD_SLEEP}
fi
;;
transfer)
if [ -z "${SLOT}" -o -z "${SLOTDST}" ]; then
usage
fi
${CHIO} -f ${CHANGER} move slot $((${SLOT} - 1)) slot $((${SLOTDST} - 1))
if [ $? -ne 0 ]; then
exit 1
fi
if [ -n "${MOVE_SLEEP}" ]; then
sleep ${MOVE_SLEEP}
fi
;;
list)
if [ -z "${FAKE_BARCODES}" ]; then
${CHIO} -f ${CHANGER} status -v slot | \
sed -ne 's/^slot *\([0-9]*\):.*FULL.*voltag.*<\([^:]*\):.*/\1:\2/p' | \
awk -F: '{ print $1 + 1 ":" $2 }'
else
if [ -f "${FAKE_BARCODES}" ]; then
grep -v -e "^#" -e "^$" < ${FAKE_BARCODES}
else
echo "${PROGNAME}: Barcode file ${FAKE_BARCODES} is missing"
exit 1
fi
fi
;;
listall)
if [ -z "${FAKE_BARCODES}" ]; then
${CHIO} -f ${CHANGER} status -vS | \
sed -ne '
s/^slot *\([0-9]*\):.*ENAB.*FULL.*voltag.*<\([^:]*\):.*/I:\1:F:\2/p;t
s/^slot *\([0-9]*\):.*FULL.*voltag.*<\([^:]*\):.*/S:\1:F:\2/p;t
s/^drive *\([0-9]*\):.*FULL.*voltag.*<\([^:]*\):.*source.*<[^0-9]*\([0-9]*\)>.*/D:\1:F:\3:\2/p;t
s/^slot *\([0-9]*\):.*ENAB.*voltag.*<\([^:]*\):.*/I:\1:E/p;t
s/^slot *\([0-9]*\):.*voltag.*<\([^:]*\):.*/S:\1:E/p;t
s/^drive *\([0-9]*\):.*voltag.*<\([^:]*\):.*/D:\1:E/p' | \
awk -F: '{ for (n = 1; n <= NF; n++) printf "%s%s",
(n == ($1 == "D" ? 4 : 2)) ? ($n == "" ? 0 : $n + 1) : $n,
(n == NF) ? "\n" : ":" }'
else
if [ -f "${FAKE_BARCODES}" ]; then
grep -v -e "^#" -e "^$" < ${FAKE_BARCODES} | \
awk -F: '{ print "S:" $1 (match($2, "^ *$") ? ":E" : ":F:" $2) }'
else
echo "${PROGNAME}: Barcode file ${FAKE_BARCODES} is missing"
exit 1
fi
fi
;;
loaded)
# If a tape is loaded, but the source slot is unknown (for example,
# after library reboot), try to report the first free slot
FREE=`${CHIO} -f ${CHANGER} status slot | \
sed -ne '/FULL/d;s/^slot *\([0-9]*\):.*/\1/p' | \
awk 'BEGIN { n = 0 } { n = $1 + 1; exit } END { print n }'`
${CHIO} -f ${CHANGER} status -S drive | \
sed -ne 's/^drive *'${DRIVE}':.*FULL.*source.*<[^0-9]*\([0-9]*\)>.*/\1/p' \
| awk 'BEGIN { n = 0 } { n = ($1 == "") ? '${FREE}' : $1 + 1 } \
END { print n }'
;;
slots)
${CHIO} -f ${CHANGER} status | grep -c "^slot "
;;
*)
usage
;;
esac
|