Update spec file for 0.06 release
[blkdevalias.git] / blkdevalias
1 #!/bin/bash
2 #
3 #  blkdevalias - manage aliases and permissions for block devices
4 #
5 #  Bryn M. Reeves <bmr@redhat.com>
6 #
7 #  Copyright (C) Red Hat, Inc. 2012
8 #
9 #  This program is free software; you can redistribute it and/or modify
10 #  it under the terms of the GNU General Public License as published by
11 #  the Free Software Foundation; either version 2 of the License, or
12 #  (at your option) any later version.
13 #
14 #  This program is distributed in the hope that it will be useful,
15 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 #  GNU General Public License for more details.
18 #
19 #  You should have received a copy of the GNU General Public License
20 #  along with this program; if not, write to the Free Software
21 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 #
23 declare -A WWIDMAP
24 declare -A NAMEMAP
25 declare -A TYPEMAP
26 declare -A PARTMAP
27
28 BA_DEBUG=yes
29 BA_DEFAULT_USER="oracle"
30 BA_DEFAULT_GROUP="oracle"
31 BA_CONF_PATH="/etc/blkdevalias"
32 BA_DEV_PATH="oracleasm/disks"
33 BA_MAP_PATH="${BA_CONF_PATH}/blkdevalias.map"
34 BA_CONF="${BA_CONF_PATH}/blkdevalias.conf"
35 BA_USER="$BA_DEFAULT_USER"
36 BA_GROUP="$BA_DEFAULT_GROUP"
37 BA_LOCK="/var/lock/blkdevalias"
38 BA_SCSI_ID="/sbin/scsi_id"
39 BA_SCSI_ID_FLAGS="-g -u"
40
41 # load config
42 . $BA_CONF
43
44 _error () {
45     echo "ERROR: $@" 1>&2
46 }
47
48 _warn () {
49     echo "WARNING: $@" 1>&2
50 }
51
52 _debug () {
53     [ "$BA_DEBUG" == "yes" ] && echo "$@" 1>&2
54 }
55
56 # store the WWID map to disk
57 ba_store_wwid_map() {
58     TMP_MAP=$(mktemp --tmpdir=$BA_CONF_DIR)
59     if [ ! -f "$TMP_MAP" ]; then
60         _error "could not write temporary file"
61         exit 1
62     fi
63     for WWID in ${!WWIDMAP[@]}; do
64         echo "$WWID ${WWIDMAP[$WWID]} ${TYPEMAP[$WWID]} ${PARTMAP[$WWID]}"
65     done  >> $TMP_MAP
66     mv $TMP_MAP $BA_MAP_PATH
67 }
68
69 # read the WWID map from disk
70 ba_load_wwid_map() {
71     if [ ! -f "$BA_MAP_PATH" ] || [ ! -r "$BA_MAP_PATH"  ]; then
72         _error "$BA_MAP_PATH does not exist or is not readable"
73         exit 1
74     fi
75     while read WWID ALIAS TYPE PART; do
76         if [[ $WWID == \#* ]] || [[ $WWID == "" ]]; then
77             continue
78         fi
79         WWIDMAP[$WWID]="$ALIAS"
80         NAMEMAP[$ALIAS]="$WWID"
81         TYPEMAP[$WWID]="$TYPE"
82         PARTMAP[$WWID]="$PART"
83     done < $BA_MAP_PATH
84 }
85
86 # ba_add_wwid_mapping <wwid> <alias> <sd|mpath> <part>
87 ba_add_wwid_mapping() {
88     local WWID
89     WWID="$1"
90     ALIAS="$2"
91     TYPE="$3"
92     PART="$4"
93     DEV="$5"
94     _debug "ba_add_wwid_mapping: WWID=\"$WWID\" ALIAS=\"$ALIAS\"" \
95         "TYPE=\"$TYPE\" PART=\"$PART\""
96     if [ "$WWID" == "" ]; then
97         _warn "no wwid given"
98         return
99     fi
100     if [ "$ALIAS" == "" ]; then
101         _warn "no alias given"
102         return
103     fi
104     if [ "$PART" == "" ]; then
105         _warn "no partition number given"
106     fi
107     if [ "${WWIDMAP[$WWID]}" != "" ]; then
108         _debug "ba_add_wwid_mapping: WWIDMAP[\$WWID]=${WWIDMAP[$WWID]}"
109         _warn "$DEV already mapped to alias ${WWIDMAP[$WWID]}; replacing it."
110         ba_del_wwid_mapping "$WWID"
111     fi
112     if [ "${NAMEMAP[$ALIAS]}" != "" ]; then
113         _debug "ba_add_wwid_mapping: NAMEMAP[\$ALIAS]=${NAMEMAP[$ALIAS]}"
114         _warn "$DEV already mapped to disk ${NAMEMAP[$ALIAS]}; replacing it."
115         ba_del_wwid_mapping ${NAMEMAP[$ALIAS]}
116     fi
117     WWIDMAP[$WWID]="$ALIAS"
118     NAMEMAP[$ALIAS]="$WWID"
119     TYPEMAP[$WWID]=${TYPE:-"sd"}
120     PARTMAP[$WWID]="$PART"
121 }
122
123 # ba_del_wwid_mapping <wwid>
124 ba_del_wwid_mapping() {
125     local WWID ALIAS
126     WWID="$1"
127     if [ "$WWID" == "" ]; then
128         return 1
129     fi
130     if [ "${WWIDMAP[$WWID]}" == "" ]; then
131         _warn "WARNING: $WWID does not exist; doing nothing."
132         return 1
133     fi
134     _debug "ba_del_wwid_mapping: unsetting WWIDMAP[$WWID]"
135     ALIAS=${WWIDMAP[$WWID]}
136     unset WWIDMAP[$WWID]
137     unset NAMEMAP[$ALIAS]
138     unset TYPEMAP[$WWID]
139     unset PARTMAP[$WWID]
140 }
141
142 ba_get_partnum () {
143     local DEV="$1"
144     if [[ $DEV == dm-* ]]; then
145         DEV=$DM_NAME
146     fi
147     _debug "ba_get_partnum: $DEV"
148     /sbin/dmsetup info $DEV > /dev/null 2>&1
149     if [ "$?" == "0" ]; then
150         NUM=$(echo $DEV | sed -e 's/\/dev.*\///' -e 's/.*p\([0-9]*\).*/\1/')
151     else
152         NUM=$(echo $DEV | sed 's/\(\/dev\/\)*sd[a-z]*//')
153     fi
154     if [ "$NUM" == "" ]; then
155         NUM="0"
156     fi
157     echo $NUM
158 }
159
160 ba_scsi_id () {
161     local DEV=$1
162     _debug "ba_scsi_id: getting ID for device $DEV"
163     dmsetup info $DEV > /dev/null  2>&1
164     if [ $? -eq 0 ]; then
165         DEV=$(echo $DEV | sed 's/p[0-9].*//')
166     else
167         DEV=$(echo $DEV | sed 's/[0-9].*//')
168     fi
169     _debug "ba_scsi_id: calling \"$BA_SCSI_ID $BA_SCSI_ID_FLAGS $DEV\""
170     $BA_SCSI_ID $BA_SCSI_ID_FLAGS $DEV
171 }
172
173 ba_configure () {
174     cat <<EOF
175 Configuring the blkdevalias map.
176
177 This will configure persistent aliases and permissions for storage
178 devices. The current values will be shown in brackets ('[]'). Hitting
179 <ENTER> without typing an answer will keep the current value.
180
181 Ctrl-C will abort.
182
183 EOF
184
185     echo -n "Default user to own device nodes [$BA_USER]: "
186     read _BA_USER
187     if [ "$_BA_USER" != "" ]; then
188         BA_USER=$_BA_USER;
189     fi
190     echo -n "Default group to own device nodes [$BA_GROUP]: "
191     read _BA_GROUP
192     if [ "$_BA_GROUP" != "" ]; then
193         BA_GROUP=$_BA_GROUP;
194     fi
195     echo -n "Default device directory [$BA_DEV_PATH]: "
196     read _BA_DEV_PATH
197     if [ "$_BA_DEV_PATH" != "" ]; then
198         BA_DEV_PATH=$_BA_DEV_PATH;
199     fi
200     _debug "BA_DEV_PATH=\"$BA_DEV_PATH\""
201     _debug "BA_USER=\"$BA_USER\""
202     _debug "BA_GROUP=\"$BA_GROUP\""
203     echo -n "Writing wwid map configuration: "
204     TMP_CONF=$(mktemp --tmpdir=$BA_CONF_PATH)
205     if [ ! -f "$TMP_CONF" ]; then
206         echo
207         _error "could not write temporary file"
208         exit 1
209     fi
210     echo "BA_DEV_PATH=\"$BA_DEV_PATH\"" >> $TMP_CONF
211     echo "BA_USER=\"$BA_USER\"" >> $TMP_CONF
212     echo "BA_GROUP=\"$BA_GROUP\"" >> $TMP_CONF
213     mv $TMP_CONF $BA_CONF
214     if [ "$?" != 0 ]; then
215         _error "could not create configuration file $BA_CONF"
216         exit
217     fi
218     echo -e "done\n"
219 }
220
221 # createdisk <alias> <device>
222 ba_createdisk () {
223     local WWID DEV ALIAS PART
224     ALIAS="$1"
225     DEV="$2"
226     if [ "$DEV" == "" ] || [ "$ALIAS" == "" ]; then
227         echo "Usage: $0 createdisk <alias> <device>"
228         exit 2
229     fi
230     _debug "ba_createdisk: WWID=\"$WWID\" DEV=\"$DEV\" ALIAS=\"$ALIAS\""
231
232     WWID=$(ba_scsi_id $DEV)
233     if [ "$WWID" == "" ]; then
234         _error "could not get SCSI ID for $DEV"
235         exit 1
236     fi
237
238     if dmsetup info $DEV > /dev/null  2>&1; then
239         TYPE="mpath"
240     else
241         TYPE="sd"
242     fi
243
244     PART=$(ba_get_partnum $DEV) 
245
246     ba_add_wwid_mapping $WWID $ALIAS $TYPE $PART $DEV
247     ba_store_wwid_map
248 }
249
250 ba_deletedisk () {
251     local WWID ALIAS
252     ALIAS=$1
253     if [ "$ALIAS" == "" ]; then
254         echo "Usage: $0 deletedisk <alias>"
255         exit 2
256     fi
257     WWID=${NAMEMAP[$ALIAS]}
258     if [ "$WWID" == "" ]; then
259         _error "\"$ALIAS\" does not exist"
260         echo "Usage: $0 deletedisk <alias>"
261         exit 2
262     fi
263     echo -n "Removing wwid map disk \"$ALIAS\":"
264     ba_del_wwid_mapping $WWID \
265     && echo "                                  [  OK  ]"
266     ba_store_wwid_map
267 }
268
269 ba_list_disks () {
270     for D in ${WWIDMAP[@]}; do
271         echo $D
272     done | sort -V
273 }
274
275 ba_querydisk () {
276     local LISTDEV ONDEV WWID ALIAS
277     if [ "$1" == "-d" ]; then
278         LISTDEV=1
279         shift
280     fi
281     ALIAS=$1
282     if [ "$ALIAS" == "" ]; then
283         echo "Usage: $0 querydisk <alias>"
284         exit 2
285     fi
286     WWID=${NAMEMAP[$ALIAS]}
287     _debug "ba_querydisk: ALIAS=\"$ALIAS\" WWID=\"$WWID\" LISTDEV=\"$LISTDEV\""
288     if [ "$LISTDEV" == "1" ]; then
289         DEV="/dev/$BA_DEV_PATH/$(readlink "/dev/$BA_DEV_PATH/$ALIAS")"
290         MAJ="$[0x$(stat --format "%t" $DEV)]"
291         MIN="$[0x$(stat --format "%T" $DEV)]"
292         ONDEV="on device [$MAJ,$MIN]"
293         _debug "ba_querydisk: DEV=\"$DEV\" MAJ=\"$MAJ\" MIN=\"$MIN\""
294     fi
295     if [ "$WWID" != "" ]; then
296         echo "$ALIAS is a valid blkdevalias disk $ONDEV"
297         return
298     fi
299     exit 1
300 }
301
302 ba_scandisks () {
303     _warn "(unimplemented)"
304 }
305
306 ba_map () {
307     local WWID TYPE PART
308     WWID="$1"
309     if [ "$WWID" == "" ] || [ "${WWIDMAP[$WWID]}" == "" ]; then
310         echo "Usage: $0 map <wwid>" 1>&2
311         exit 2
312     fi
313     PART=$(ba_get_partnum $DEVNAME)
314     if [ "$ID_BUS" == "scsi" ]; then
315         TYPE=sd
316     else
317         TYPE=mpath
318     fi
319     if [ "$PART" != ${PARTMAP[$WWID]} ] \
320         || [ "$TYPE" != ${TYPEMAP[$WWID]} ] ; then
321         exit 1
322     fi
323     echo "BA_WWID=$WWID"
324     echo "BA_NAME=$BA_DEV_PATH/${WWIDMAP[$WWID]}"
325     echo "BA_TYPE=${TYPEMAP[$WWID]}"
326     echo "BA_USER=$BA_USER"
327     echo "BA_GROUP=$BA_GROUP"
328 }
329
330 # no point optimizing this out for configure
331 ba_load_wwid_map
332 case "$1" in
333     configure)
334         ba_configure
335         ;;
336     create*)
337         ba_createdisk $2 $3
338         ;;
339     delete*)
340         ba_deletedisk $2
341         ;;
342     list*)
343         ba_list_disks
344         ;;
345     query*)
346         ba_querydisks $2 $3
347         ;;
348     scan*)
349         ba_scandisks
350         ;;
351     map)
352         ba_map $2
353         ;;
354     *)
355         echo -n "Usage: $0 "
356         echo "{configure|createdisk|deletedisk|listdisks|scandisks|querydisk|map}"
357         exit 2
358 esac
359