Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[fs/lustre-release.git] / lustre / utils / lwizard
1 #!/bin/sh
2 # Copyright (C) 2003  Cluster File Systems, Inc.
3 # Create a Lustre configuration file
4 #
5 # Usage: lwizard
6 #
7 # Jerrifer <jerrifer@clusterfs.com>
8 # wangdi <wangdi@clusterfs.com>
9
10 # fatal error to exit
11 fatal()
12 {
13     if [ "$#" -gt "1" ]; then
14         echo
15         echo "$2"
16         exit 1
17     fi
18
19     exit 1
20 }
21
22 #print usage and exit 
23 usage()
24 {
25     cat <<EOF
26 Usage: ${0##*/} [OPTIONS]...
27
28 ${0##*/} asks the user questions about their cluster configuration,
29 and writes an appropriate configuration file to config.xml.
30
31 Options:
32     --batch=FILE
33         save lmc batch commands to FILE
34     -o, --file=FILE
35         write Lustre configuration to FILE (default: lwizard.xml)
36     -f, --force
37         force existing files to be overwritten
38     --help
39         to get this help
40     --stripe_size=SIZE
41         size (in KB) of each stripe on an OST (default: 64)
42     --stripe_count=COUNT
43         the number of OSTs files are striped to (default: 1)
44 EOF
45
46     exit 0     
47 }
48
49 # check if $1 is a number
50 check_number()
51 {
52     local num=$(expr "$1" : "[0-9]*$")
53     if [ $num -gt "0" ]; then 
54         return 0 
55     fi
56
57     return 1
58 }
59
60 # parse options of this shell
61 LMC_BATCH_FILE=
62 RM_BATCH_FILE=1
63 FORCE=0
64 get_option()
65 {
66     local long_options="batch:,file:,force:,help,stripe_size:,stripe_count:"
67     local options
68
69     options=$(getopt -o o:hf --long "$long_options" -- "$@")
70
71     if [ $? -ne 0 ] ; then
72         usage
73     fi
74     eval set -- "$options"
75
76     while true ; do
77         case "$1" in
78             --batch)
79                 LMC_BATCH_FILE=$2
80                 RM_BATCH_FILE=0
81                 shift 2
82                 ;;
83             -o | --file)
84                 CONFIG_FILE=$2
85                 shift 2
86                 ;;
87             -f | --force)
88                 FORCE=1
89                 shift
90                 ;;
91             --stripe_count)
92                 STRIPE_CNT=$2
93                 check_number $STRIPE_CNT || \
94                     fatal 1 "Stripe count should be a number."
95                 shift 2
96                 ;;
97             --stripe_size)
98                 STRIPE_SIZE=$(($2 * 1024))
99                 check_number $STRIPE_SIZE || \
100                     fatal 1 "Stripe size should be a number."
101                 shift 2
102                 ;;
103             -h | --help)
104                 usage
105                 ;;
106             --)
107                 shift 1
108                 break
109         esac
110     done 
111 }
112
113 # if $1 in $2
114 in_list()
115 {
116     local node
117
118     for node in $2 ; do
119         [ "$1" = "$node" ] && return 0
120         done
121         return 1
122     }
123
124 # read device size from user and check devive size and convert device
125 # size to *K
126
127 get_device_size()
128 {
129     local size 
130     local tail
131
132     read size 
133     if [ -z $size ]; then 
134         device_size="0"
135         return 0
136     fi 
137
138     device_size=$(echo $size | awk -F[a-z,A-Z] '{print $1; }')
139     [ -z $device_size ] && return 1
140     tail=$(echo $size | awk -F$device_size '{print $2; }')
141     [ -z $tail ] && return 0
142     case $tail in
143         k | K)
144             ;;
145         m | M)
146             (( device_size *= 1024 ))
147             ;;
148         t | T)
149             (( device_size *= (1024 * 1024) ))
150             ;;
151         *)
152             return 1
153             ;;
154         esac
155
156     return 0
157 }
158
159 # ask user some questions to add a device 
160 add_device()
161 {
162     local hostnames
163     local device
164     local device_size
165
166     echo "Creating $1 \"$1$2\"..."
167     if [ "$2" -gt "1" ]; then 
168         echo -n "Please enter the hostname(s) for $1$2, or just hit enter to finish: "
169     else
170         echo -n "Please enter the hostname(s) for $1$2: "
171     fi
172     read hostnames
173
174     if [ -z "$hostnames" ] ; then
175         return 1
176     fi
177
178     for hostname in $hostnames ; do
179         device=
180         while [ -z "$device" ] ; do
181             echo -n "Please enter the device or loop file name for $1$2 on ${hostname}: "
182             read device
183             echo -n "Please enter the device size or 0 to use entire device: "
184             while ! get_device_size ; do
185                echo -n "Please enter the device size or 0 to use entire device: "
186             done
187         done
188         newdev="$hostname:$device:$2:$1$2:$CURRENT_MDS:$CURRENT_LOV:$device_size"
189         DEVICE_LIST="$DEVICE_LIST $newdev"
190     done
191
192     return 0 
193 }
194
195 cur_mds_id=1
196
197 # get mds information
198 add_mds()
199 {
200     CURRENT_LOV=
201     CURRENT_MDS=
202     add_device "mds" "$cur_mds_id" || return 1 
203     CURRENT_LOV="lov$cur_mds_id"
204     CURRENT_MDS="mds$cur_mds_id"
205
206     DEVICE_LIST="$DEVICE_LIST *:*:lov:$CURRENT_LOV:$CURRENT_MDS:*:"
207
208     (( cur_mds_id++ ))
209     return 0
210 }
211
212 cur_ost_id=1
213
214 # ask user to add ost 
215 add_ost()
216 {
217     # We have to add one...
218     while ! add_device "ost" "$cur_ost_id" ; do
219         true
220     done
221
222     (( cur_ost_id++ ))
223
224     # ...and maybe more
225     while add_device "ost" "$cur_ost_id" ; do
226             (( cur_ost_id++ ))
227     done
228     return 0
229 }
230
231 cur_cli_id=1
232
233 # ask user to add client to lustre
234 add_client()
235 {
236     echo -n "Please enter the clients' mountpoint (/mnt/lustre): "
237     read mtpt
238     [ -z "$mtpt" ] && mtpt="/mnt/lustre"
239     newdev="*:$mtpt:client:client:$CURRENT_MDS:$CURRENT_LOV"
240     DEVICE_LIST="$DEVICE_LIST $newdev"
241     (( cur_cli_id++ ))
242     return 0
243 }
244
245 # save node config into config file 
246 add_node()
247 {
248     local node=$1
249     local nettype=$DEFAULT_NETTYPE
250
251     in_list "$node" "$NODE_LIST" && return 0 
252     NODE_LIST="$NODE_LIST $node" 
253
254     run_lmc --add node --node "$node"
255     run_lmc --add net --node "$node" --nid "$node"  \
256         --nettype "$nettype"
257
258     return 0 
259
260
261 # get hostname, device , device_id and device name 
262 # from mds node 
263 get_name_in_list()
264 {
265     HOST_NAME=$(echo $1 | awk -F: '{ print $1 }')
266     DEVICE=$(echo $1 | awk -F: '{ print $2 }')
267     DEVICE_ID=$(echo $1 | awk -F: '{ print $3 }')
268     DEVICE_NAME=$(echo $1 | awk -F: '{ print $4 }')
269     DEVICE_MDS=$(echo $1 | awk -F: '{ print $5 }')
270     DEVICE_LOV=$(echo $1 | awk -F: '{ print $6 }')
271     DEVICE_SIZE=$(echo $1 | awk -F: '{ print $7 }')
272 }
273
274 # save command to file and do the command 
275 run_lmc()
276 {
277     echo "$@" >> "$LMC_BATCH_FILE"
278 }
279
280 # following user input to create xml config file 
281 create_config()
282 {
283     for device in $DEVICE_LIST ; do
284         get_name_in_list $device
285         echo -n " $DEVICE_NAME"
286         case $DEVICE_NAME in
287             mds*)
288                 add_node "$HOST_NAME"
289                 run_lmc --add mds \
290                     --node "$HOST_NAME" \
291                     --mds "$DEVICE_NAME" \
292                     --fstype "$DEFAULT_FSTYPE" \
293                     --dev "$DEVICE" \
294                     --size "$DEVICE_SIZE"
295                 ;;
296             lov*)
297                 run_lmc --add lov \
298                     --lov "$DEVICE_NAME" \
299                     --mds "$DEVICE_MDS" \
300                     --stripe_sz "$STRIPE_SIZE" \
301                     --stripe_cnt "$STRIPE_CNT" \
302                     --stripe_pattern "$STRIPE_PATTERN"
303                 ;;
304             ost*)
305                 add_node "$HOST_NAME"
306                 run_lmc --add ost \
307                     --node "$HOST_NAME" \
308                     --lov "$DEVICE_LOV" \
309                     --fstype "$DEFAULT_FSTYPE" \
310                     --dev "$DEVICE" \
311                     --size "$DEVICE_SIZE"
312                 ;;
313             client*)
314                 add_node "$DEVICE_NAME"
315                 run_lmc --add mtpt \
316                     --node "$DEVICE_NAME" \
317                     --mds "$DEVICE_MDS" \
318                     --lov "$DEVICE_LOV" \
319                     --path "$DEVICE"
320                 ;;
321         esac
322     done
323     echo
324     return 0
325 }
326
327 maybe_clean()
328 {
329     [ -f "$1" ] || return 0
330     if ! (( $FORCE )) ; then
331         echo -n "${0##*/}: overwrite existing $2 \"$1\"? "
332         read answer
333         if ! [ "${answer:0:1}" = "y" -o "${answer:0:1}" = "Y" ] ; then
334             echo "(${0##*/}: (Exiting.)"
335             exit 0
336         fi
337     fi
338     rm -f "$1"
339 }
340
341 # parse options 
342 get_option "$@"
343
344 # some default definitions
345 LMC=${LMC:-"/usr/sbin/lmc"}
346
347 CONFIG_FILE=${CONFIG_FILE:-"lwizard.xml"}
348
349 # Remove exiting files.
350
351 maybe_clean "$CONFIG_FILE" "Lustre configuration file"
352 if [ "$LMC_BATCH_FILE" ] ; then
353     maybe_clean "$LMC_BATCH_FILE" "lmc batch file"
354 else
355     LMC_BATCH_FILE=$(mktemp -q "/tmp/${CONFIG_FILE##*/}.XXXXXX")
356     [ $? -eq 0 ] || fatal 1 "Couldn't create temporary batch file."
357 fi
358
359 DEFAULT_FSTYPE=${DEFAULT_FSTYPE:-"ext3"}
360 DEFAULT_NETTYPE=${DEFAULT_NETTYPE:-"tcp"}
361 DEFAULT_MNTPT=${DEFAULT_MNTPT:-"/mnt/lustre"}
362
363 STRIPE_SIZE=${STRIPE_SIZE:-$((1 * 1024 * 1024))}
364 STRIPE_CNT=${STRIPE_CNT:-1}
365 STRIPE_PATTERN=${STRIPE_PATTERN:-0}
366
367 ANSWER="yes no"
368
369 CURRENT_LOV=
370 MDS_LIST=
371 OST_LIST=
372 CLIENT_LIST=
373
374 # print program information
375 cat <<EOF
376 ${0##*/} will help you create a Lustre configuration file.
377
378 EOF
379 while add_mds ; do
380     add_ost
381     add_client
382 done
383
384 create_config
385 $LMC --batch "$LMC_BATCH_FILE" -o "$CONFIG_FILE"
386 if [ $? -ne 0 ] ; then
387     fatal 1 "lmc returned an error; Please check above for more details."
388 fi
389
390 echo "The Lustre configuration has been written to $CONFIG_FILE."
391
392 if (( $RM_BATCH_FILE )) ; then
393     rm -f "$LMC_BATCH_FILE"
394 else
395     echo "The lmc batch file has been written to $LMC_BATCH_FILE."
396 fi
397
398 exit 0