Whamcloud - gitweb
b=22679 quota fixes for mds_orphan_add_link
[fs/lustre-release.git] / lustre / scripts / lustre_config.in
1 #!/bin/bash
2
3 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 #
6 # lustre_config - format and set up multiple lustre servers from a csv file
7 #
8 # This script is used to parse each line of a spreadsheet (csv file) and 
9 # execute remote commands to format (mkfs.lustre) every Lustre target 
10 # that will be part of the Lustre cluster.
11
12 # In addition, it can also verify the network connectivity and hostnames in 
13 # the cluster, configure Linux MD/LVM devices and produce High-Availability
14 # software configurations for Heartbeat or CluManager.
15 #
16 ################################################################################
17
18 # Usage
19 usage() {
20     cat <<EOF
21
22 Usage: $(basename $0) [options] <-a|-w|-x> <csv file>
23
24     This script is used to format and set up multiple lustre servers from a
25     csv file.
26
27     Options:
28     -h          help and examples
29     -a          select all the nodes from the csv file to operate on
30     -w hostname,hostname,...
31                 select the specified list of nodes (separated by commas) to
32                 operate on rather than all the nodes in the csv file
33     -x hostname,hostname,...
34                 exclude the specified list of nodes (separated by commas)
35     -t HAtype   produce High-Availability software configurations
36                 The argument following -t is used to indicate the High-
37                 Availability software type. The HA software types which 
38                 are currently supported are: hbv1 (Heartbeat version 1)
39                 and hbv2 (Heartbeat version 2).
40     -n          no net - don't verify network connectivity and hostnames
41                 in the cluster
42     -d          configure Linux MD/LVM devices before formatting the
43                 Lustre targets
44     -f          force-format the Lustre targets using --reformat option
45     -m          no fstab change - don't modify /etc/fstab to add the new
46                 Lustre targets
47                 If using this option, then the value of "mount options"
48                 item in the csv file will be passed to mkfs.lustre, else
49                 the value will be added into the /etc/fstab.
50     -u          upgrade Lustre targets from 1.4 to 1.6
51     -v          verbose mode
52     csv file    a spreadsheet that contains configuration parameters
53                 (separated by commas) for each target in a Lustre cluster
54
55 EOF
56 }
57
58 # Samples 
59 sample() {
60     cat <<EOF
61
62 This script is used to parse each line of a spreadsheet (csv file) and 
63 execute remote commands to format (mkfs.lustre) every Lustre target 
64 that will be part of the Lustre cluster.
65
66 It can also optionally: 
67  * upgrade Lustre targets from 1.4 to 1.6
68    It does not support "rolling upgrade". Before upgrading, the entire Lustre
69    filesystem (all servers and clients) need be shut down. After upgrading, old
70    configuration logs for the filesystem would be erased and new configuration
71    logs would be regenerated as Lustre servers restart.
72  * verify the network connectivity and hostnames in the cluster
73  * configure Linux MD/LVM devices
74  * modify /etc/modprobe.conf to add Lustre networking info
75  * add the Lustre server info to /etc/fstab
76  * produce configurations for Heartbeat or CluManager.
77
78 There are 5 kinds of line formats in the csv file. They represent the following 
79 targets:
80 1) Linux MD device
81 The format is:
82 hostname,MD,md name,operation mode,options,raid level,component devices
83
84 hostname            hostname of the node in the cluster
85 MD                  marker of MD device line
86 md name             MD device name, e.g. /dev/md0
87 operation mode      create or remove, default is create
88 options             a "catchall" for other mdadm options, e.g. "-c 128"
89 raid level          raid level: 0,1,4,5,6,10,linear and multipath
90 component devices   block devices to be combined into the MD device
91                     Multiple devices are separated by space or by using
92                     shell expansions, e.g. "/dev/sd{a,b,c}"
93
94 2) Linux LVM PV (Physical Volume)
95 The format is:
96 hostname,PV,pv names,operation mode,options
97
98 hostname            hostname of the node in the cluster
99 PV                  marker of PV line
100 pv names            devices or loopback files to be initialized for later
101                     use by LVM or to be wiped the label, e.g. /dev/sda
102                     Multiple devices or files are separated by space or by
103                     using shell expansions, e.g. "/dev/sd{a,b,c}"
104 operation mode      create or remove, default is create
105 options             a "catchall" for other pvcreate/pvremove options
106                     e.g. "-vv"
107
108 3) Linux LVM VG (Volume Group)
109 The format is:
110 hostname,VG,vg name,operation mode,options,pv paths
111
112 hostname            hostname of the node in the cluster
113 VG                  marker of VG line
114 vg name             name of the volume group, e.g. ost_vg
115 operation mode      create or remove, default is create
116 options             a "catchall" for other vgcreate/vgremove options
117                     e.g. "-s 32M"
118 pv paths            physical volumes to construct this VG, required by
119                     create mode
120                     Multiple PVs are separated by space or by using
121                     shell expansions, e.g. "/dev/sd[k-m]1"
122
123 4) Linux LVM LV (Logical Volume)
124 The format is:
125 hostname,LV,lv name,operation mode,options,lv size,vg name
126
127 hostname            hostname of the node in the cluster
128 LV                  marker of LV line
129 lv name             name of the logical volume to be created (optional)
130                     or path of the logical volume to be removed (required
131                     by remove mode)
132 operation mode      create or remove, default is create
133 options             a "catchall" for other lvcreate/lvremove options
134                     e.g. "-i 2 -I 128"
135 lv size             size [kKmMgGtT] to be allocated for the new LV
136                     Default unit is megabytes.
137 vg name             name of the VG in which the new LV will be created
138
139 5) Lustre target
140 The format is:
141 hostname,module_opts,device name,mount point,device type,fsname,mgs nids,index,
142 format options,mkfs options,mount options,failover nids
143
144 hostname            hostname of the node in the cluster, must match "uname -n"
145 module_opts         Lustre networking module options
146 device name         Lustre target (block device or loopback file)
147 mount point         Lustre target mount point
148 device type         Lustre target type (mgs, mdt, ost, mgs|mdt, mdt|mgs)
149 fsname              Lustre filesystem name, should be limited to 8 characters 
150                     Default is "lustre".
151 mgs nids            NID(s) of remote mgs node, required for mdt and ost targets
152                     If this item is not given for an mdt, it is assumed that
153                     the mdt will also be an mgs, according to mkfs.lustre.
154 index               Lustre target index
155 format options      a "catchall" contains options to be passed to mkfs.lustre
156                     "--device-size", "--param", etc. all goes into this item.
157 mkfs options        format options to be wrapped with --mkfsoptions="" and
158                     passed to mkfs.lustre
159 mount options       If this script is invoked with "-m" option, then the value of
160                     this item will be wrapped with --mountfsoptions="" and passed
161                     to mkfs.lustre, else the value will be added into /etc/fstab.
162 failover nids       NID(s) of failover partner node
163
164 All the NIDs in one node are delimited by commas (','). When multiple nodes are
165 specified, they are delimited by a colon (':').
166
167 Items left blank will be set to defaults.
168
169 Example 1 - Simple, with combo MGS/MDT:
170 -------------------------------------------------------------------------------
171 # combo mdt/mgs
172 lustre-mgs,options lnet networks=tcp,/tmp/mgs,/mnt/mgs,mgs|mdt,,,,--device-size=10240
173
174 # ost0
175 lustre-ost,options lnet networks=tcp,/tmp/ost0,/mnt/ost0,ost,,lustre-mgs@tcp0,,--device-size=10240
176
177 # ost1
178 lustre-ost,options lnet networks=tcp,/tmp/ost1,/mnt/ost1,ost,,lustre-mgs@tcp0,,--device-size=10240
179 -------------------------------------------------------------------------------
180
181 Example 2 - Separate MGS/MDT, two networks interfaces:
182 -------------------------------------------------------------------------------
183 # mgs
184 lustre-mgs1,options lnet 'networks="tcp,elan"',/dev/sda,/mnt/mgs,mgs,,,,--quiet --param="sys.timeout=50",,"defaults,noauto","lustre-mgs2,2@elan"
185
186 # mdt
187 lustre-mdt1,options lnet 'networks="tcp,elan"',/dev/sdb,/mnt/mdt,mdt,lustre2,"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--quiet --param="lov.stripesize=4194304",-J size=16,"defaults,noauto",lustre-mdt2
188
189 # ost
190 lustre-ost1,options lnet 'networks="tcp,elan"',/dev/sdc,/mnt/ost,ost,lustre2,"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--quiet,-I 512,"defaults,noauto",lustre-ost2
191 -------------------------------------------------------------------------------
192
193 Example 3 - with combo MGS/MDT failover pair and OST failover pair:
194 -------------------------------------------------------------------------------
195 # combo mgs/mdt
196 lustre-mgs1,options lnet networks=tcp,/tmp/mgs,/mnt/mgs,mgs|mdt,,,,--quiet --device-size=10240,,,lustre-mgs2@tcp0
197
198 # combo mgs/mdt backup (--noformat)
199 lustre-mgs2,options lnet networks=tcp,/tmp/mgs,/mnt/mgs,mgs|mdt,,,,--quiet --device-size=10240 --noformat,,,lustre-mgs1@tcp0
200
201 # ost
202 lustre-ost1,options lnet networks=tcp,/tmp/ost1,/mnt/ost1,ost,,"lustre-mgs1@tcp0:lustre-mgs2@tcp0",,--quiet --device-size=10240,,,lustre-ost2@tcp0
203
204 # ost backup (--noformat) (note different device name)
205 lustre-ost2,options lnet networks=tcp,/tmp/ost2,/mnt/ost2,ost,,"lustre-mgs1@tcp0:lustre-mgs2@tcp0",,--quiet --device-size=10240 --noformat,,,lustre-ost1@tcp0
206 -------------------------------------------------------------------------------
207
208 Example 4 - Configure Linux MD/LVM devices before formatting Lustre targets:
209 -------------------------------------------------------------------------------
210 # MD device on mgsnode
211 mgsnode,MD,/dev/md0,,-q,1,/dev/sda1 /dev/sdb1
212
213 # MD/LVM devices on ostnode
214 ostnode,MD,/dev/md0,,-q -c 128,5,"/dev/sd{a,b,c}"
215 ostnode,MD,/dev/md1,,-q -c 128,5,"/dev/sd{d,e,f}"
216 ostnode,PV,/dev/md0 /dev/md1
217 ostnode,VG,ost_vg,,-s 32M,/dev/md0 /dev/md1
218 ostnode,LV,ost0,,-i 2 -I 128,300G,ost_vg
219 ostnode,LV,ost1,,-i 2 -I 128,300G,ost_vg
220
221 # combo mgs/mdt
222 mgsnode,options lnet networks=tcp,/dev/md0,/mnt/mgs,mgs|mdt,,,,--quiet
223
224 # ost0
225 ostnode,options lnet networks=tcp,/dev/ost_vg/ost0,/mnt/ost0,ost,,mgsnode,,--quiet
226
227 # ost1
228 ostnode,options lnet networks=tcp,/dev/ost_vg/ost1,/mnt/ost1,ost,,mgsnode,,--quiet
229 -------------------------------------------------------------------------------
230
231 EOF
232     exit 0
233 }
234
235 # Get the library of functions
236 . @scriptlibdir@/lc_common
237
238 #***************************** Global variables *****************************#
239 declare -a NODE_NAMES               # node names in the failover group
240 declare -a TARGET_OPTS              # target services in one failover group
241
242 CONFIG_MD_LVM=false
243 MODIFY_FSTAB=true
244 UPGRADE_TARGET=false
245 # Get and check the positional parameters
246 while getopts "aw:x:t:ndfmuhv" OPTION; do
247     case $OPTION in
248     a)
249         [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ] \
250         && USE_ALLNODES=true
251         NODELIST_OPT="${NODELIST_OPT} -a"
252         ;;
253     w)
254         USE_ALLNODES=false
255         SPECIFIED_NODELIST=$OPTARG
256         NODELIST_OPT="${NODELIST_OPT} -w ${SPECIFIED_NODELIST}"
257         ;;
258     x)
259         USE_ALLNODES=false
260         EXCLUDED_NODELIST=$OPTARG
261         NODELIST_OPT="${NODELIST_OPT} -x ${EXCLUDED_NODELIST}"
262         ;;
263     t)
264         HATYPE_OPT=$OPTARG
265         if [ "${HATYPE_OPT}" != "${HBVER_HBV1}" ] \
266         && [ "${HATYPE_OPT}" != "${HBVER_HBV2}" ] \
267         && [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" ]; then
268             error_output "Invalid HA software type" \
269                       "- ${HATYPE_OPT}!"
270             usage 1>&2
271             exit 1
272         fi
273         ;;
274     n)
275         VERIFY_CONNECT=false
276         ;;
277     d)
278         CONFIG_MD_LVM=true
279         ;;
280     f)
281         REFORMAT_OPTION=$"--reformat "
282         ;;
283     m)
284         MODIFY_FSTAB=false
285         ;;
286     u)
287         UPGRADE_TARGET=true 
288         ;;
289     h)
290         usage
291         sample
292         ;;
293     v)
294         VERBOSE_OPT=$" -v"
295         VERBOSE_OUTPUT=true
296         ;;
297     ?)
298         usage 1>&2
299         exit 1
300         ;;
301     esac
302 done
303
304 # Toss out the parameters we've already processed
305 shift  `expr $OPTIND - 1`
306
307 # Here we expect the csv file
308 if [ $# -eq 0 ]; then
309     error_output "Missing csv file!"
310     usage 1>&2
311     exit 1
312 fi
313
314 CSV_FILE=$1
315
316 # Construct the command line of mkfs.lustre
317 construct_mkfs_cmdline() {
318     # Check argument
319     if [ $# -eq 0 ]; then
320         error_output "construct_mkfs_cmdline():"\
321                   "Missing argument for function construct_mkfs_cmdline()!"
322         return 1
323     fi
324
325     declare -i i=$1
326     local mgsnids mgsnids_str
327     local failnids failnids_str
328
329     if $UPGRADE_TARGET; then
330         MKFS_CMD="$TUNEFS --writeconf"
331     else
332         MKFS_CMD="$MKFS $REFORMAT_OPTION"
333     fi
334
335     case "${DEVICE_TYPE[i]}" in
336     "ost")
337         MKFS_CMD="$MKFS_CMD --ost"
338         ;;
339     "mdt")
340         MKFS_CMD="$MKFS_CMD --mdt"
341         $UPGRADE_TARGET && [ -n "${MGS_NIDS[i]}" ] && \
342         MKFS_CMD="$MKFS_CMD --nomgs"
343         ;;
344     "mgs")
345         MKFS_CMD="$MKFS_CMD --mgs"
346         ;;
347     "mdt|mgs" | "mgs|mdt")
348         MKFS_CMD="$MKFS_CMD --mgs --mdt"
349         ;;
350     *)
351         error_output "construct_mkfs_cmdline():"\
352                   "Invalid device type - \"${DEVICE_TYPE[i]}\"!"
353         return 1
354         ;;
355     esac
356
357     if [ -n "${FS_NAME[i]}" ]; then
358         MKFS_CMD="$MKFS_CMD --fsname=${FS_NAME[i]}"
359     fi
360
361     if [ -n "${MGS_NIDS[i]}" ]; then
362         mgsnids_str=${MGS_NIDS[i]}
363         for mgsnids in ${mgsnids_str//:/ }; do
364             MKFS_CMD="$MKFS_CMD --mgsnode=$mgsnids"
365         done
366     fi
367
368     if [ -n "${INDEX[i]}" ]; then
369         MKFS_CMD="$MKFS_CMD --index=${INDEX[i]}"
370     fi
371
372     if [ -n "${FORMAT_OPTIONS[i]}" ]; then
373         MKFS_CMD="$MKFS_CMD ${FORMAT_OPTIONS[i]}"
374     fi
375
376     if ! $UPGRADE_TARGET && [ -n "${MKFS_OPTIONS[i]}" ]; then
377         MKFS_CMD="$MKFS_CMD --mkfsoptions=\"${MKFS_OPTIONS[i]}\""
378     fi
379
380     if [ -n "${MOUNT_OPTIONS[i]}" ] && ! $MODIFY_FSTAB; then
381         MKFS_CMD="$MKFS_CMD --mountfsoptions=\"${MOUNT_OPTIONS[i]}\""
382     fi
383
384     if [ -n "${FAILOVERS[i]}" ]; then
385         failnids_str=${FAILOVERS[i]}
386         for failnids in ${failnids_str//:/ }; do
387             MKFS_CMD="$MKFS_CMD --failnode=$failnids"
388         done
389     fi
390
391     MKFS_CMD="$MKFS_CMD ${DEVICE_NAME[i]}"
392     return 0
393
394
395 # Get all the node names in this failover group
396 get_nodenames() {
397     # Check argument
398     if [ $# -eq 0 ]; then
399         error_output "get_nodenames(): Missing"\
400                   "argument for function get_nodenames()!"
401         return 1
402     fi
403
404     declare -i i=$1
405     declare -i idx
406     local nids
407
408     # Initialize the NODE_NAMES array
409     unset NODE_NAMES
410
411     NODE_NAMES[0]=${HOST_NAME[i]}
412
413     idx=1
414     for nids in ${FAILOVERS_NAMES[i]//:/ }
415     do
416         NODE_NAMES[idx]=$(nids2hostname ${nids})
417         if [ ${PIPESTATUS[0]} -ne 0 ]; then
418             error_output "${NODE_NAMES[idx]}"
419             return 1
420         fi
421     
422         idx=$idx+1
423     done
424
425     return 0
426 }
427
428 # Verify whether the format line has HA items
429 is_ha_line() {
430     declare -i i=$1
431
432     [ -n "${FAILOVERS[i]}" ] && return 0
433
434     return 1
435 }
436
437 # Produce HA software's configuration files
438 gen_ha_config() {
439     declare -i i=$1
440     declare -i idx
441     local  cmd_line
442
443     # Prepare parameters
444     # Hostnames option
445     HOSTNAME_OPT=${HOST_NAME[i]}
446
447     if ! get_nodenames $i; then
448         error_output "gen_ha_config(): Can not get the"\
449         "failover nodenames from failover nids - \"${FAILOVERS[i]}\" in"\
450         "the \"${HOST_NAME[i]}\" failover group!"
451         return 1
452     fi
453
454     for ((idx = 1; idx < ${#NODE_NAMES[@]}; idx++)); do
455         HOSTNAME_OPT=${HOSTNAME_OPT}$":"${NODE_NAMES[idx]}
456     done
457
458     # Target devices option
459     DEVICE_OPT=" -d "${TARGET_OPTS[0]}
460     for ((idx = 1; idx < ${#TARGET_OPTS[@]}; idx++)); do
461         DEVICE_OPT=${DEVICE_OPT}" -d "${TARGET_OPTS[idx]}
462     done
463
464     # Construct the generation script command line
465     case "${HATYPE_OPT}" in
466     "${HBVER_HBV1}"|"${HBVER_HBV2}")    # Heartbeat 
467         cmd_line=${GEN_HB_CONFIG}$" -r ${HATYPE_OPT} -n ${HOSTNAME_OPT}"
468         cmd_line=${cmd_line}${DEVICE_OPT}${VERBOSE_OPT}
469         ;;
470     "${HATYPE_CLUMGR}")                 # CluManager
471         cmd_line=${GEN_CLUMGR_CONFIG}$" -n ${HOSTNAME_OPT}"
472         cmd_line=${cmd_line}${DEVICE_OPT}${VERBOSE_OPT}
473         ;;
474     esac
475     
476     # Execute script to generate HA software's configuration files
477     verbose_output "Generating HA software's configurations in"\
478                "${HOST_NAME[i]} failover group..."
479     verbose_output "${cmd_line}"
480     eval $(echo "${cmd_line}")
481     if [ ${PIPESTATUS[0]} -ne 0 ]; then
482         return 1
483     fi
484     verbose_output "Generate HA software's configurations in"\
485                "${HOST_NAME[i]} failover group OK"
486     
487     return 0
488 }
489
490 # Configure HA software
491 config_ha() {
492     if $UPGRADE_TARGET || [ -z "${HATYPE_OPT}" ]; then
493         return 0
494     fi
495
496     declare -i i j k
497     declare -i prim_idx         # Index for PRIM_HOSTNAMES array
498     declare -i target_idx       # Index for TARGET_OPTS and HOST_INDEX arrays
499
500     declare -a PRIM_HOSTNAMES   # Primary hostnames in all the failover
501                                 # groups in the lustre cluster
502     declare -a HOST_INDEX       # Indices for the same node in all the 
503                                 # format lines in the csv file
504     local prim_host
505
506     # Initialize the PRIM_HOSTNAMES array
507     prim_idx=0
508     unset PRIM_HOSTNAMES
509
510     # Get failover groups and generate HA configuration files
511     for ((i = 0; i < ${#HOST_NAME[@]}; i++)); do
512         prim_host=${HOST_NAME[i]}
513
514         for ((j = 0; j < ${#PRIM_HOSTNAMES[@]}; j++)); do
515             [ "${prim_host}" = "${PRIM_HOSTNAMES[j]}" ] && continue 2
516         done
517
518         target_idx=0
519         unset HOST_INDEX
520         unset TARGET_OPTS
521         for ((k = 0; k < ${#HOST_NAME[@]}; k++)); do
522             if [ "${prim_host}" = "${HOST_NAME[k]}" ] && is_ha_line "${k}"
523             then
524                 HOST_INDEX[target_idx]=$k
525                 TARGET_OPTS[target_idx]=${DEVICE_NAME[k]}:${MOUNT_POINT[k]}
526                 target_idx=$(( target_idx + 1 ))
527             fi
528         done
529
530         if [ ${#TARGET_OPTS[@]} -ne 0 ]; then
531             PRIM_HOSTNAMES[prim_idx]=${prim_host}
532             prim_idx=$(( prim_idx + 1 ))
533
534             if ! gen_ha_config ${HOST_INDEX[0]}; then
535                 return 1
536             fi
537         fi
538     done
539
540     if [ ${#PRIM_HOSTNAMES[@]} -eq 0 ]; then
541         verbose_output "There are no \"failover nids\" items in the"\
542         "csv file. No HA configuration files are generated!"
543     fi
544
545     rm -rf ${TMP_DIRS}
546     return 0
547 }
548
549 # Execute remote command to add lnet options lines to remote nodes'
550 # modprobe.conf/modules.conf and format(mkfs.lustre) Lustre targets
551 mass_config() {
552     local COMMAND
553     declare -a REMOTE_PID 
554     declare -a REMOTE_CMD 
555     declare -i pid_num=0
556     declare -i i=0
557     local checked_hosts=""
558
559     if [ ${#HOST_NAME[@]} -eq 0 ]; then
560         verbose_output "There are no Lustre targets specified."
561         return 0
562     fi
563
564     if ! $UPGRADE_TARGET; then
565         # Start lnet network in the MGS node
566         start_mgs_lnet || return 1    
567     fi
568
569     for ((i = 0; i < ${#HOST_NAME[@]}; i++)); do
570         # Construct the command line of mkfs.lustre
571         if ! construct_mkfs_cmdline $i; then
572             return 1    
573         fi
574
575         # create the mount point on the node
576         COMMAND="mkdir -p ${MOUNT_POINT[i]}"
577         verbose_output "Creating the mount point ${MOUNT_POINT[i]} on" \
578                        "${HOST_NAME[i]}"
579         ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2 
580         if [ ${PIPESTATUS[0]} -ne 0 ]; then
581             error_output "mass_config():"\
582                  "Failed to execute remote command to"\
583                  "create the mountpoint on ${HOST_NAME[i]}!"
584             return 1
585         fi
586
587         if ! $UPGRADE_TARGET && ! is_mgs_node ${HOST_NAME[i]} && \
588         ! host_in_hostlist ${HOST_NAME[i]} $checked_hosts; then
589             # Execute remote command to add lnet options lines to 
590             # modprobe.conf/modules.conf
591             add_module_options $i ${HOST_NAME[i]} || return ${PIPESTATUS[0]}
592
593             # Check lnet networks
594             check_lnet $i || return ${PIPESTATUS[0]}
595
596             checked_hosts="$checked_hosts,${HOST_NAME[i]}"
597         fi
598
599         # Execute remote command to format or upgrade Lustre target
600         local OP
601         $UPGRADE_TARGET && OP="Upgrading" || OP="Formatting"
602         verbose_output "$OP Lustre target ${DEVICE_NAME[i]} on ${HOST_NAME[i]}..."
603
604         COMMAND="export PATH=\$PATH:/sbin:/usr/sbin; $MKFS_CMD"
605         REMOTE_CMD[$pid_num]="$REMOTE ${HOST_NAME[i]} \"$COMMAND\""
606         verbose_output "$OP command line is: ${REMOTE_CMD[$pid_num]}"
607
608         $REMOTE ${HOST_NAME[i]} "$COMMAND" &
609         REMOTE_PID[$pid_num]=$!
610         let pid_num=$pid_num+1
611         sleep 1
612     done
613
614     # Wait for the exit status of the background remote command
615     verbose_output "Waiting for the return of the remote command..."
616     fail_exit_status=false
617     for ((pid_num = 0; pid_num < ${#REMOTE_PID[@]}; pid_num++)); do
618         wait ${REMOTE_PID[${pid_num}]}
619         if [ ${PIPESTATUS[0]} -ne 0 ]; then
620             error_output "mass_config(): Failed"\
621             "to execute \"${REMOTE_CMD[${pid_num}]}\"!"
622             fail_exit_status=true
623         fi
624     done
625
626     if ${fail_exit_status}; then
627         return 1
628     fi    
629
630     verbose_output "Success on all Lustre targets!"
631     return 0
632 }
633
634 # get_mntopts hostname device_name failovers
635 # Construct the mount options of Lustre target @device_name in host @hostname
636 get_mntopts() {
637     local host_name=$1
638     local device_name=$2
639     local failovers=$3
640     local mnt_opts=
641     local ret_str
642
643     [ -n "${failovers}" ] && mnt_opts=defaults,noauto || mnt_opts=defaults
644
645     # Execute remote command to check whether the device
646     # is a block device or not
647     ret_str=$(${REMOTE} ${host_name} \
648             "[ -b ${device_name} ] && echo block || echo loop" 2>&1)
649     if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then
650         echo "`basename $0`: get_mntopts() error:" \
651         "remote command to ${host_name} error: ${ret_str}"
652         return 1
653     fi
654
655     if [ -z "${ret_str}" ]; then
656         echo "`basename $0`: get_mntopts() error: remote error:" \
657         "No results from remote!" \
658         "Check network connectivity between the local host and ${host_name}!"
659         return 1
660     fi
661
662     [ "${ret_str}" != "${ret_str#*loop}" ] && mnt_opts=${mnt_opts},loop
663
664     echo ${mnt_opts}
665     return 0
666 }
667
668 # Execute remote command to modify /etc/fstab to add the new Lustre targets
669 modify_fstab() {
670     declare -i i
671     local mntent mntopts device_name
672     local COMMAND
673
674     if ! ${MODIFY_FSTAB}; then
675         return 0    
676     fi
677
678     for ((i = 0; i < ${#HOST_NAME[@]}; i++)); do
679         verbose_output "Modify /etc/fstab of host ${HOST_NAME[i]}"\
680                    "to add Lustre target ${DEVICE_NAME[i]}"
681         mntent=${DEVICE_NAME[i]}"\t\t"${MOUNT_POINT[i]}"\t\t"${FS_TYPE}
682
683         # Get mount options
684         if [ -n "${MOUNT_OPTIONS[i]}" ]; then
685             # The mount options already specified in the csv file.
686             mntopts="${MOUNT_OPTIONS[i]}"
687         else
688             mntopts=$(get_mntopts ${HOST_NAME[i]} ${DEVICE_NAME[i]}\
689                     ${FAILOVERS[i]})
690             if [ ${PIPESTATUS[0]} -ne 0 ]; then
691                 error_output "${mntopts}"
692                 return 1
693             fi
694         fi
695
696         mntent=${mntent}"\t"${mntopts}"\t"0" "0
697         verbose_output "`echo -e ${mntent}`"
698
699         # Execute remote command to modify /etc/fstab
700         device_name=${DEVICE_NAME[i]//\//\\/}
701         COMMAND=". @scriptlibdir@/lc_common; \
702                 sed -i \"/^${device_name}\t/d\" \$(fcanon /etc/fstab); \
703                 echo -e \"${mntent}\" >> \$(fcanon /etc/fstab)"
704         ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2
705         if [ ${PIPESTATUS[0]} -ne 0 ]; then
706             error_output "modify_fstab():"\
707             "Failed to modify /etc/fstab of host ${HOST_NAME[i]}"\
708             "to add Lustre target ${DEVICE_NAME[i]}!"
709             return 1
710         fi
711     done
712
713     return 0
714 }
715
716 #********************************* Main Flow **********************************#
717
718 # Check the csv file
719 check_file $CSV_FILE || exit ${PIPESTATUS[0]}
720
721 # Get the list of nodes to be operated on
722 NODES_TO_USE=$(get_nodelist) || error_exit ${PIPESTATUS[0]} "$NODES_TO_USE"
723
724 # Check the node list
725 check_nodelist $NODES_TO_USE || exit ${PIPESTATUS[0]}
726
727 if ${VERIFY_CONNECT}; then
728 # Check the network connectivity and hostnames
729     echo "`basename $0`: Checking the cluster network connectivity"\
730          "and hostnames..."
731     if ! ${VERIFY_CLUSTER_NET} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then
732         exit 1
733     fi
734     echo "`basename $0`: Check the cluster network connectivity"\
735          "and hostnames OK!"
736     echo
737 fi
738
739 if $CONFIG_MD_LVM && ! $UPGRADE_TARGET; then
740 # Configure Linux MD/LVM devices
741     echo "`basename $0`: Configuring Linux MD/LVM devices..."
742     if ! ${SCRIPT_CONFIG_MD} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then
743         exit 1
744     fi
745
746     if ! ${SCRIPT_CONFIG_LVM} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then
747         exit 1
748     fi
749     echo "`basename $0`: Configure Linux MD/LVM devices OK!"
750     echo
751 fi
752
753 # Configure the Lustre cluster
754 echo "`basename $0`: ******** Lustre cluster configuration BEGIN ********"
755
756 get_lustre_items $CSV_FILE || exit ${PIPESTATUS[0]}
757
758 check_mgs || exit ${PIPESTATUS[0]}
759
760 # Format or upgrade Lustre server targets
761 mass_config || exit ${PIPESTATUS[0]}
762
763 # Modify /etc/fstab to add the new Lustre server targets
764 modify_fstab || exit ${PIPESTATUS[0]}
765
766 # Produce HA software's configuration files
767 if ! config_ha; then
768     rm -rf ${TMP_DIRS}
769     exit 1
770 fi
771
772 echo "`basename $0`: ******** Lustre cluster configuration END **********"
773
774 exit 0