Whamcloud - gitweb
- add mballoc to ldiskfs series
[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 # save client node config into config file
261 add_client_node()
262 {
263     local node=$1
264     local nettype=$DEFAULT_NETTYPE
265
266     in_list "$node" "$NODE_LIST" && return 0
267     NODE_LIST="$NODE_LIST $node"
268
269     run_lmc --add node --node "$node"
270     run_lmc --add net --node "$node" --nid "*"  \
271         --nettype "$nettype"
272
273     return 0
274 }
275
276 # get hostname, device , device_id and device name 
277 # from mds node 
278 get_name_in_list()
279 {
280     HOST_NAME=$(echo $1 | awk -F: '{ print $1 }')
281     DEVICE=$(echo $1 | awk -F: '{ print $2 }')
282     DEVICE_ID=$(echo $1 | awk -F: '{ print $3 }')
283     DEVICE_NAME=$(echo $1 | awk -F: '{ print $4 }')
284     DEVICE_MDS=$(echo $1 | awk -F: '{ print $5 }')
285     DEVICE_LOV=$(echo $1 | awk -F: '{ print $6 }')
286     DEVICE_SIZE=$(echo $1 | awk -F: '{ print $7 }')
287 }
288
289 # save command to file and do the command 
290 run_lmc()
291 {
292     echo "$@" >> "$LMC_BATCH_FILE"
293 }
294
295 # following user input to create xml config file 
296 create_config()
297 {
298     for device in $DEVICE_LIST ; do
299         get_name_in_list $device
300         echo -n " $DEVICE_NAME"
301         case $DEVICE_NAME in
302             mds*)
303                 add_client_node "$DEVICE_NAME"
304                 run_lmc --add mds \
305                     --node "$HOST_NAME" \
306                     --mds "$DEVICE_NAME" \
307                     --fstype "$DEFAULT_FSTYPE" \
308                     --dev "$DEVICE" \
309                     --size "$DEVICE_SIZE"
310                 ;;
311             lov*)
312                 run_lmc --add lov \
313                     --lov "$DEVICE_NAME" \
314                     --mds "$DEVICE_MDS" \
315                     --stripe_sz "$STRIPE_SIZE" \
316                     --stripe_cnt "$STRIPE_CNT" \
317                     --stripe_pattern "$STRIPE_PATTERN"
318                 ;;
319             ost*)
320                 add_node "$HOST_NAME"
321                 run_lmc --add ost \
322                     --node "$HOST_NAME" \
323                     --lov "$DEVICE_LOV" \
324                     --fstype "$DEFAULT_FSTYPE" \
325                     --dev "$DEVICE" \
326                     --size "$DEVICE_SIZE"
327                 ;;
328             client*)
329                 add_node "$DEVICE_NAME"
330                 run_lmc --add mtpt \
331                     --node "$DEVICE_NAME" \
332                     --mds "$DEVICE_MDS" \
333                     --lov "$DEVICE_LOV" \
334                     --path "$DEVICE" \
335                     --clientoptions "async"
336                 ;;
337         esac
338     done
339     echo
340     return 0
341 }
342
343 maybe_clean()
344 {
345     [ -f "$1" ] || return 0
346     if ! (( $FORCE )) ; then
347         echo -n "${0##*/}: overwrite existing $2 \"$1\"? "
348         read answer
349         if ! [ "${answer:0:1}" = "y" -o "${answer:0:1}" = "Y" ] ; then
350             echo "(${0##*/}: (Exiting.)"
351             exit 0
352         fi
353     fi
354     rm -f "$1"
355 }
356
357 # parse options 
358 get_option "$@"
359
360 # some default definitions
361 LMC=${LMC:-"/usr/sbin/lmc"}
362
363 CONFIG_FILE=${CONFIG_FILE:-"lwizard.xml"}
364
365 # Remove exiting files.
366
367 maybe_clean "$CONFIG_FILE" "Lustre configuration file"
368 if [ "$LMC_BATCH_FILE" ] ; then
369     maybe_clean "$LMC_BATCH_FILE" "lmc batch file"
370 else
371     LMC_BATCH_FILE=$(mktemp -q "/tmp/${CONFIG_FILE##*/}.XXXXXX")
372     [ $? -eq 0 ] || fatal 1 "Couldn't create temporary batch file."
373 fi
374
375 DEFAULT_FSTYPE=${DEFAULT_FSTYPE:-"ext3"}
376 DEFAULT_NETTYPE=${DEFAULT_NETTYPE:-"tcp"}
377 DEFAULT_MNTPT=${DEFAULT_MNTPT:-"/mnt/lustre"}
378
379 STRIPE_SIZE=${STRIPE_SIZE:-$((1 * 1024 * 1024))}
380 STRIPE_CNT=${STRIPE_CNT:-1}
381 STRIPE_PATTERN=${STRIPE_PATTERN:-0}
382
383 ANSWER="yes no"
384
385 CURRENT_LOV=
386 MDS_LIST=
387 OST_LIST=
388 CLIENT_LIST=
389
390 # print program information
391 cat <<EOF
392 ${0##*/} will help you create a Lustre configuration file.
393
394 EOF
395 while add_mds ; do
396     add_ost
397     add_client
398 done
399
400 create_config
401 $LMC --batch "$LMC_BATCH_FILE" -o "$CONFIG_FILE"
402 if [ $? -ne 0 ] ; then
403     fatal 1 "lmc returned an error; Please check above for more details."
404 fi
405
406 echo "The Lustre configuration has been written to $CONFIG_FILE."
407
408 if (( $RM_BATCH_FILE )) ; then
409     rm -f "$LMC_BATCH_FILE"
410 else
411     echo "The lmc batch file has been written to $LMC_BATCH_FILE."
412 fi
413
414 exit 0