Add COPYING and README
[blkdevalias.git] / wwidmap
1 #!/bin/bash
2 declare -A WWIDMAP
3 declare -A NAMEMAP
4 declare -A TYPEMAP
5
6 WM_DEBUG=yes
7 WM_DEFAULT_USER="oracle"
8 WM_DEFAULT_GROUP="oracle"
9 WM_CONF_PATH="/etc/wwidmap"
10 WM_DEV_PATH="oracleasm/disks"
11 WM_MAP_PATH="${WM_CONF_PATH}/map"
12 WM_CONF="${WM_CONF_PATH}/conf"
13 WM_USER="$WM_DEFAULT_USER"
14 WM_GROUP="$WM_DEFAULT_GROUP"
15 WM_LOCK="/var/lock/wm.lock"
16 WM_SCSI_ID="/sbin/scsi_id"
17 WM_SCSI_ID_FLAGS="-g -u"
18
19 # load config
20 . $WM_CONF
21
22 error () {
23     echo "ERROR: $@" 1>&2
24 }
25
26 warn () {
27     echo "WARNING: $@" 1>&2
28 }
29
30 debug () {
31     [ "$WM_DEBUG" == "yes" ] && echo "$@" 1>&2
32 }
33
34 # debug print
35 print_wwid_mapping() {
36     local WWID=$1
37     if [ "$WWID" == "" ]; then
38         return
39     fi
40     debug "NNAME for WWID '$WWID' is: '${WWIDMAP[$WWID]}' (${TYPEMAP[$WWID]})"
41 }
42
43 # store the WWID map to disk
44 wm_store_wwid_map() {
45     TMP_MAP=$(mktemp --tmpdir=$WM_CONF_DIR)
46     if [ ! -f $TMP_MAP ]; then
47         error "could not write temporary file"
48         exit 1
49     fi
50     for WWID in ${!WWIDMAP[@]}; do
51         echo "$WWID ${WWIDMAP[$WWID]} ${TYPEMAP[$WWID]}"
52     done  >> $TMP_MAP
53     mv $TMP_MAP $WM_MAP_PATH
54 }
55
56 # read the WWID map from disk
57 wm_load_wwid_map() {
58     if [ ! -f $WM_MAP_PATH ] || [ ! -r $WM_MAP_PATH  ]; then
59         error "$WM_MAP_PATH does not exist or is not readable"
60         exit 1
61     fi
62     while read WWID NNAME TYPE; do
63         if [[ $WWID == \#* ]]; then
64             continue
65         fi
66         WWIDMAP[$WWID]="$NNAME"
67         NAMEMAP[$NNAME]="$WWID"
68         TYPEMAP[$WWID]="$TYPE"
69     done < $WM_MAP_PATH
70 }
71
72 # add_wwid_mapping <wwid> <nickname> <sd|mpath>
73 add_wwid_mapping() {
74     local WWID
75     WWID="$1"
76     NNAME="$2"
77     TYPE="$3"
78     debug "add_wwid_mapping WWID=\"$WWID\" NNAME=\"$NNAME\""
79     if [ "$WWID" == "" ]; then
80         warn "no wwid given"
81         return
82     fi
83     if [ "$NNAME" == "" ]; then
84         warn "no nickname given"
85         return
86     fi
87     if [ "${NAMEMAP[$WWID]}" != "" ]; then
88         warn "$WWID already mapped to name ${NAMEMAP[$WWID]}; replacing it."
89     fi
90     WWIDMAP[$WWID]="$NNAME"
91     NAMEMAP[$NNAME]="$WWID"
92     TYPEMAP[$WWID]=${TYPE:-"sd"}
93 }
94
95 # del_wwid_mapping <wwid>
96 del_wwid_mapping() {
97     local WWID NNAME
98     WWID="$1"
99     if [ "$WWID" == "" ]; then
100         return 1
101     fi
102     if [ "${WWIDMAP[$WWID]}" == "" ]; then
103         warn "WARNING: $WWID does not exist; doing nothing."
104         return 1
105     fi
106     NNAME=${WWIDMAP[$WWID]}
107     unset WWIDMAP[$WWID]
108     unset NAMEMAP[$NNAME]
109     unset TYPEMAP[$WWID]
110 }
111
112 wm_scsi_id () {
113     $WM_SCSI_ID $WM_SCSI_ID_FLAGS $1
114 }
115
116 wm_configure () {
117     cat <<EOF
118 Configuring the udev wwid map.
119
120 This will configure persistent mappings and permissions for storage
121 devices. The current values will be shown in brackets ('[]'). Hitting
122 <ENTER> without typing an answer will keep the current value. Ctrl-C
123 will abort.
124
125 EOF
126
127     echo -n "Default user to own device nodes [$WM_USER]: "
128     read _WM_USER
129     if [ "$_WM_USER" != "" ]; then
130         WM_USER=$_WM_USER;
131     fi
132     echo -n "Default group to own device nodes [$WM_GROUP]: "
133     read _WM_GROUP
134     if [ "$_WM_GROUP" != "" ]; then
135         WM_GROUP=$_WM_GROUP;
136     fi
137     echo -n "Default device directory [$WM_DEV_PATH]: "
138     read _WM_DEV_PATH
139     if [ "$_WM_DEV_PATH" != "" ]; then
140         WM_DEV_PATH=$_WM_DEV_PATH;
141     fi
142     debug "WM_DEV_PATH=\"$WM_DEV_PATH\""
143     debug "WM_USER=\"$WM_USER\""
144     debug "WM_GROUP=\"$WM_GROUP\""
145     echo -n "Writing wwid map configuration: "
146     TMP_CONF=$(mktemp --tmpdir=$WM_CONF_PATH)
147     if [ ! -f $TMP_CONF ]; then
148         echo
149         error "could not write temporary file"
150         exit 1
151     fi
152     echo "WM_DEV_PATH=\"$WM_DEV_PATH\"" >> $TMP_CONF
153     echo "WM_USER=\"$WM_USER\"" >> $TMP_CONF
154     echo "WM_GROUP=\"$WM_GROUP\"" >> $TMP_CONF
155     mv $TMP_CONF $WM_CONF
156     if [ "$?" != 0 ]; then
157         error "could not create configuration file $WM_CONF"
158         exit
159     fi
160     echo -e "done\n"
161 }
162
163 # createdisk <nickname> <device>
164 wm_createdisk () {
165     local WWID DEV NNAME
166     NNAME="$1"
167     DEV="$2"
168     if [ "$DEV" == "" ] || [ "$NNAME" == "" ]; then
169         echo "Usage: $0 createdisk <nickname> <device>"
170         exit 2
171     fi
172     debug "wm_createdisk: WWID=\"$WWID\" DEV=\"$DEV\" NNAME=\"$NNAME\""
173     WWID=$(wm_scsi_id $DEV)
174     add_wwid_mapping $WWID $NNAME "sd"
175     wm_store_wwid_map
176 }
177
178 wm_deletedisk () {
179     local WWID NNAME
180     NNAME=$1
181     if [ "$NNAME" == "" ]; then
182         echo "Usage: $0 deletedisk <nickname>"
183         exit 2
184     fi
185     WWID=${NAMEMAP[$NNAME]}
186     if [ "$WWID" == "" ]; then
187         error "\"$NNAME\" does not exist"
188         echo "Usage: $0 deletedisk <nickname>"
189         exit 2
190     fi
191     echo -n "Removing wwid map disk \"$NNAME\":"
192     del_wwid_mapping $WWID \
193     && echo "                                  [  OK  ]"
194     wm_store_wwid_map
195 }
196
197 wm_list_disks () {
198     for D in ${WWIDMAP[@]}; do
199         echo $D
200     done | sort -V
201 }
202
203 wm_querydisk () {
204     local LISTDEV ONDEV WWID NNAME
205     if [ $1 == "-d" ]; then
206         LISTDEV=1
207         shift
208     fi
209     NNAME=$1
210     if [ "$NNAME" == "" ]; then
211         echo "Usage: $0 querydisk <nickname>"
212         exit 2
213     fi
214     WWID=${NAMEMAP[$NNAME]}
215     debug "wm_querydisk: NNAME=\"$NNAME\" WWID=\"$WWID\" LISTDEV=\"$LISTDEV\""
216     if [ "$LISTDEV" == "1" ]; then
217         DEV="/dev/$WM_DEV_PATH/$(readlink "/dev/$WM_DEV_PATH/$NNAME")"
218         MAJ="$[0x$(stat --format "%t" $DEV)]"
219         MIN="$[0x$(stat --format "%T" $DEV)]"
220         ONDEV="on device [$MAJ,$MIN]"
221         debug "wm_querydisk: DEV=\"$DEV\" MAJ=\"$MAJ\" MIN=\"$MIN\""
222     fi
223     if [ "$WWID" != "" ]; then
224         echo "$NNAME is a valid wwidmap disk$ONDEV"
225         return
226     fi
227     exit 1
228 }
229
230 wm_scandisks () {
231     warn "(unimplemented)"
232 }
233
234 wm_map () {
235     local WWID
236     WWID="$1"
237     if [ "$WWID" == "" ] || [ "${WWIDMAP[$WWID]}" == "" ]; then
238         echo "Usage: $0 map <wwid>" 1>&2
239         exit 2
240     fi
241     echo "WM_WWID=$WWID"
242     echo "WM_NAME=$WM_DEV_PATH/${WWIDMAP[$WWID]}"
243     echo "WM_TYPE=${TYPEMAP[$WWID]}"
244     echo "WM_USER=$WM_USER"
245     echo "WM_GROUP=$WM_GROUP"
246 }
247
248 # no point optimizing this out for configure
249 wm_load_wwid_map
250 case "$1" in
251     configure)
252         wm_configure
253         ;;
254     createdisk)
255         wm_createdisk $2 $3
256         ;;
257     deletedisk)
258         wm_deletedisk $2
259         ;;
260     listdisks)
261         wm_list_disks
262         ;;
263     querydisk)
264         wm_querydisk $2 $3
265         ;;
266     scandisks)
267         wm_scandisks
268         ;;
269     map)
270         wm_map $2
271         ;;
272     *)
273         echo -n "Usage: $0 "
274         echo "{configure|createdisk|deletedisk|scandisks|querydisk|map}"
275         exit 2
276 esac
277