Whamcloud - gitweb
1) add nodelist options "-a", "-w" and "-x" to lustre config scripts
authoryujian <yujian>
Thu, 28 Sep 2006 03:43:30 +0000 (03:43 +0000)
committeryujian <yujian>
Thu, 28 Sep 2006 03:43:30 +0000 (03:43 +0000)
2) replace $? with ${PIPESTATUS[0]} and `` with $()

lustre/scripts/lc_common.sh
lustre/scripts/lc_lvm.sh.in
lustre/scripts/lc_md.sh.in
lustre/scripts/lc_net.sh.in
lustre/scripts/lustre_config.sh.in

index ef62b9a..8fb00d6 100644 (file)
@@ -72,6 +72,13 @@ LV_MARKER=${LV_MARKER:-"LV"}
 declare -a CONFIG_ITEM              # Items in each line of the csv file
 declare -a NODE_NAME                # Hostnames of nodes have been configured
 
+# Nodelist variables
+USE_ALLNODES=false                  # default is not to operate on all the nodes
+SPECIFIED_NODELIST=""               # specified list of nodes to be operated on
+EXCLUDED_NODELIST=""                # list of nodes to be excluded
+
+export PATH=$PATH:$CMD_PATH:$SCRIPTS_PATH:$CLUMAN_TOOLS_PATH:$RAID_CMD_PATH:/sbin:/usr/sbin
+
 
 # verbose_output string
 # Output verbose information $string
@@ -285,8 +292,8 @@ nid2hostname() {
         fi
 
         # Execute remote command to get the host name
-        ret_str=`${REMOTE} ${ip_addr} "hostname" 2>&1`
-        if [ $? -ne 0 -a -n "${ret_str}" ]; then
+        ret_str=$(${REMOTE} ${ip_addr} "hostname" 2>&1)
+        if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then
             echo "`basename $0`: nid2hostname() error:" \
             "remote command to ${ip_addr} error: ${ret_str}"
             return 1
@@ -320,7 +327,7 @@ nids2hostname() {
         lo* | elan* | gm* | ptl*) ;;
         *)  # tcp, o2ib, cib, openib, iib, vib, ra
             host_name=$(nid2hostname ${nid})
-            if [ $? -ne 0 ]; then
+            if [ ${PIPESTATUS[0]} -ne 0 ]; then
                 echo "${host_name}"
                 return 1
             fi
@@ -354,7 +361,7 @@ ip2hostname_single_node() {
         lo* | elan* | gm* | ptl*) ;;
         *)  # tcp, o2ib, cib, openib, iib, vib, ra
             host_name=$(nid2hostname ${nid})
-            if [ $? -ne 0 ]; then
+            if [ ${PIPESTATUS[0]} -ne 0 ]; then
                 echo "${host_name}"
                 return 1
             fi
@@ -380,7 +387,7 @@ ip2hostname_multi_node() {
 
     for nid in ${orig_nids//:/ }; do
         nid=$(ip2hostname_single_node ${nid})
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo "${nid}"
             return 1
         fi
@@ -391,3 +398,127 @@ ip2hostname_multi_node() {
     echo ${nids}
     return 0
 }
+
+# comma_list space-delimited-list
+# Convert a space-delimited list to a sorted list of unique values
+# separated by commas.
+comma_list() {
+    # the sed converts spaces to commas, but leaves the last space
+    # alone, so the line doesn't end with a comma.
+    echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
+}
+
+# host_in_hostlist hostname hostlist
+# Given a hostname, and a list of hostnames, return true if the hostname
+# appears in the list of hostnames, or false otherwise.
+host_in_hostlist() {
+    local HOST=$1
+    local HOSTLIST=$2
+
+    [ -z "$HOST" -o -z "$HOSTLIST" ] && false && return
+
+    # Hostnames in the list are separated by commas.
+    [[ ,$HOSTLIST, == *,$HOST,* ]] && true && return
+
+    false && return
+}
+
+# exclude_items_from_list list_of_items list_of_items_to_exclude
+# Given a list of items, and a second list of items to exclude from
+# the first list, return the contents of the first list minus the contents
+# of the second.
+exclude_items_from_list() {
+    local INLIST=$1
+    local EXCLUDELIST=$2
+    local ITEM OUTLIST
+
+    # Handle an empty inlist by throwing back an empty string.
+    if [ -z "$INLIST" ]; then
+        echo ""
+        return 0
+    fi
+
+    # Handle an empty excludelist by throwing back the inlist unmodified.
+    if [ -z "$EXCLUDELIST" ]; then
+        echo $INLIST
+        return 0
+    fi
+
+    for ITEM in ${INLIST//,/ }; do
+        if ! host_in_hostlist $ITEM $EXCLUDELIST; then
+           OUTLIST="$OUTLIST,$ITEM"
+        fi
+    done
+                                
+    # strip leading comma
+    echo ${OUTLIST#,}
+}
+
+# get_csv_nodelist csv_file
+# Get the comma-separated list of all the nodes from the csv file
+get_csv_nodelist() {
+    local csv_file=$1
+    local all_nodelist
+
+    # Check the csv file
+    ! check_file ${csv_file} 2>&1 && return 1
+
+    all_nodelist=$(egrep -v "([[:space:]]|^)#" ${csv_file} | cut -d, -f 1)
+    all_nodelist=$(comma_list ${all_nodelist})
+
+    echo ${all_nodelist}
+    return 0
+}
+
+# get_nodelist
+# Get the comma-separated list of nodes to be operated on
+# Note: CSV_FILE, USE_ALLNODES, SPECIFIED_NODELIST and EXCLUDED_NODELIST
+# are global variables
+get_nodelist() {
+    local ALL_NODELIST
+
+    # Get the list of all the nodes in the csv file
+    ALL_NODELIST=$(get_csv_nodelist ${CSV_FILE})
+    [ ${PIPESTATUS[0]} -ne 0 ] && echo "${ALL_NODELIST}" && return 1
+
+    if [ -z "${ALL_NODELIST}" ]; then
+        echo "`basename $0`: get_nodelist() error:"\
+             "There are no hosts in the ${CSV_FILE} file!"
+        return 1
+    fi
+
+    if ${USE_ALLNODES}; then
+        echo ${ALL_NODELIST} && return 0
+    fi
+
+    if [ -n "${SPECIFIED_NODELIST}" ]; then
+        echo $(exclude_items_from_list ${SPECIFIED_NODELIST} ${EXCLUDED_NODELIST})
+        return 0
+    fi
+
+    if [ -n "${EXCLUDED_NODELIST}" ]; then
+        echo $(exclude_items_from_list ${ALL_NODELIST} ${EXCLUDED_NODELIST})
+        return 0
+    fi
+
+    # No hosts to be operated on
+    echo ""
+    return 0
+}
+
+# check_nodelist nodelist
+# Given a list of nodes to be operated on, check whether the nodelist is 
+# empty or not and output prompt message.
+check_nodelist() {
+    local nodes_to_use=$1
+
+    if [ -z "${nodes_to_use}" ]; then
+        echo "`basename $0`: There are no hosts to be operated on."\
+             "Check the node selection options (-a, -w or -x)."
+        usage
+    else
+        verbose_output "Operating on the following nodes: ${nodes_to_use}"
+    fi
+
+    return 0
+}
index 64018d2..6d9f7e5 100644 (file)
 usage() {
     cat >&2 <<EOF
 
-Usage:  `basename $0` [-h] [-v] <csv file>
+Usage:  `basename $0` [options] <csv file>
 
     This script is used to configure Linux LVM devices in a Lustre cluster
     from a csv file.
 
+    Options:
+    -a          select all the nodes from the csv file to operate on
+    -w hostname,hostname,...
+                select the specified list of nodes (separated by commas)
+    -x hostname,hostname,...
+                exclude the specified list of nodes (separated by commas)
     -h          help and examples
     -v          verbose mode
     csv file    a spreadsheet that contains configuration parameters
@@ -126,8 +132,20 @@ declare -i pid_num=0
 
 VERBOSE_OUTPUT=false
 # Get and check the positional parameters
-while getopts "hv" OPTION; do
+while getopts "aw:x:hv" OPTION; do
     case $OPTION in
+    a)
+        [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ] \
+        && USE_ALLNODES=true
+        ;;
+    w)
+        USE_ALLNODES=false
+        SPECIFIED_NODELIST=$OPTARG
+        ;;
+    x)
+        USE_ALLNODES=false
+        EXCLUDED_NODELIST=$OPTARG
+        ;;
     h)
         sample
         ;;
@@ -225,6 +243,7 @@ get_lvm_items() {
 
     CSV_FILE=$1
     local LINE line_marker
+    local hostname
     declare -i line_num=0
     declare -i idx=0
 
@@ -235,11 +254,17 @@ get_lvm_items() {
         [ -z "`echo \"${LINE}\" | egrep -v \"([[:space:]]|^)#\"`" ] && continue
 
         # Skip the non-LVM line
-        line_marker=`echo ${LINE} | awk -F, '{print $2}'`
+        line_marker=$(echo ${LINE} | cut -d, -f 2)
         [ "${line_marker}" != "${PV_MARKER}" ] \
         && [ "${line_marker}" != "${VG_MARKER}" ] \
         && [ "${line_marker}" != "${LV_MARKER}" ] && continue
 
+        # Skip the host which is not specified in the host list
+        if ! ${USE_ALLNODES}; then
+            hostname=$(echo ${LINE} | cut -d, -f 1)
+            ! host_in_hostlist ${hostname} ${NODES_TO_USE} && continue
+        fi
+
         # Parse the config line into CONFIG_ITEM
         if ! parse_line "$LINE"; then
             return 1    
@@ -527,7 +552,7 @@ config_lvm() {
     failed_status=false
     for ((pid_num = 0; pid_num < ${#REMOTE_PID[@]}; pid_num++)); do
         wait ${REMOTE_PID[${pid_num}]}
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "`basename $0`: config_lvm() error: Failed"\
                  "to execute \"${REMOTE_CMD[${pid_num}]}\"!"
             failed_status=true
@@ -548,6 +573,13 @@ if ! check_file $1; then
     exit 1    
 fi
 
+# Get the list of nodes to be operated on
+NODES_TO_USE=$(get_nodelist)
+[ ${PIPESTATUS[0]} -ne 0 ] && echo >&2 "${NODES_TO_USE}" && exit 1
+
+# Check the node list
+check_nodelist ${NODES_TO_USE} || exit 1
+
 # Get all the LVM device items from the csv file 
 if ! get_lvm_items ${CSV_FILE}; then
     exit 1
index 77a508f..48109d0 100644 (file)
 usage() {
     cat >&2 <<EOF
 
-Usage:  `basename $0` [-h] [-v] <csv file>
+Usage:  `basename $0` [options] <csv file>
 
     This script is used to configure Linux MD devices in a Lustre cluster
     from a csv file.
 
+    Options:
+    -a          select all the nodes from the csv file to operate on
+    -w hostname,hostname,...
+                select the specified list of nodes (separated by commas)
+    -x hostname,hostname,...
+                exclude the specified list of nodes (separated by commas)
     -h          help and examples
     -v          verbose mode
     csv file    a spreadsheet that contains configuration parameters
@@ -78,8 +84,20 @@ declare -i pid_num=0
 
 VERBOSE_OUTPUT=false
 # Get and check the positional parameters
-while getopts "hv" OPTION; do
+while getopts "aw:x:hv" OPTION; do
     case $OPTION in
+    a)
+        [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ] \
+        && USE_ALLNODES=true
+        ;;
+    w)
+        USE_ALLNODES=false
+        SPECIFIED_NODELIST=$OPTARG
+        ;;
+    x)
+        USE_ALLNODES=false
+        EXCLUDED_NODELIST=$OPTARG
+        ;;
     h)
         sample
         ;;
@@ -157,6 +175,7 @@ get_md_items() {
 
     CSV_FILE=$1
     local LINE
+    local hostname
     declare -i line_num=0
     declare -i idx=0
 
@@ -167,7 +186,13 @@ get_md_items() {
         [ -z "`echo \"${LINE}\" | egrep -v \"([[:space:]]|^)#\"`" ] && continue
 
         # Skip the non-MD line
-        [ "`echo ${LINE}|awk -F, '{print $2}'`" != "${MD_MARKER}" ] && continue
+        [ "$(echo ${LINE} | cut -d, -f 2)" != "${MD_MARKER}" ] && continue
+
+        # Skip the host which is not specified in the host list
+        if ! ${USE_ALLNODES}; then
+            hostname=$(echo ${LINE} | cut -d, -f 1)
+            ! host_in_hostlist ${hostname} ${NODES_TO_USE} && continue
+        fi
 
         # Parse the config line into CONFIG_ITEM
         if ! parse_line "$LINE"; then
@@ -203,8 +228,8 @@ md_is_active() {
     local cmd ret_str
 
     cmd="grep -q ${md_name##*/} /proc/mdstat 2>&1"
-    ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
-    if [ $? -ne 0 ]; then
+    ret_str=$(${REMOTE} ${host_name} "${cmd}" 2>&1)
+    if [ ${PIPESTATUS[0]} -ne 0 ]; then
         if [ -n "${ret_str}" ]; then
             echo >&2 "`basename $0`: md_is_active() error:"\
             "remote command to ${host_name} error: ${ret_str}!"
@@ -318,7 +343,7 @@ construct_mdadm_cmdline() {
             "" | create)
                     # Check the status of the MD array
                     md_is_active ${host_name} ${MD_NAME[i]}
-                    rc=$?
+                    rc=${PIPESTATUS[0]}
                     if [ "$rc" -eq "2" ]; then
                         return 1
                     elif [ "$rc" -eq "0" ]; then
@@ -339,7 +364,7 @@ construct_mdadm_cmdline() {
 
                     # Construct the create command line
                     mdadm_cmd=$(construct_mdadm_create_cmdline ${i})
-                    if [ $? -ne 0 ]; then
+                    if [ ${PIPESTATUS[0]} -ne 0 ]; then
                         echo >&2 "${mdadm_cmd}"
                         return 1
                     fi
@@ -445,7 +470,7 @@ config_md() {
     failed_status=false
     for ((pid_num = 0; pid_num < ${#REMOTE_PID[@]}; pid_num++)); do
         wait ${REMOTE_PID[${pid_num}]}
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "`basename $0`: config_md() error: Failed"\
                  "to execute \"${REMOTE_CMD[${pid_num}]}\"!"
             failed_status=true
@@ -466,6 +491,13 @@ if ! check_file $1; then
     exit 1    
 fi
 
+# Get the list of nodes to be operated on
+NODES_TO_USE=$(get_nodelist)
+[ ${PIPESTATUS[0]} -ne 0 ] && echo >&2 "${NODES_TO_USE}" && exit 1
+
+# Check the node list
+check_nodelist ${NODES_TO_USE} || exit 1
+
 # Get all the MD device items from the csv file 
 if ! get_md_items ${CSV_FILE}; then
     exit 1
index 26fe899..4bc889f 100644 (file)
@@ -8,8 +8,14 @@
 usage() {
        cat >&2 <<EOF
 
-Usage: `basename $0` [-v] <csv file>
-
+Usage: `basename $0` [options] <csv file>
+
+       Options:
+       -a              select all the nodes from the csv file to operate on
+       -w hostname,hostname,...
+                       select the specified list of nodes (separated by commas)
+       -x hostname,hostname,...
+                       exclude the specified list of nodes (separated by commas)
        -v              verbose mode
        csv file        a spreadsheet that contains configuration parameters 
                        (separated by commas) for each target in a Lustre cl-
@@ -25,8 +31,20 @@ EOF
 
 VERBOSE_OUTPUT=false
 # Get and check the positional parameters
-while getopts "v" OPTION; do
+while getopts "aw:x:v" OPTION; do
        case $OPTION in
+       a)
+               [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ]\
+               && USE_ALLNODES=true
+               ;;
+       w)
+               USE_ALLNODES=false
+               SPECIFIED_NODELIST=$OPTARG
+               ;;
+       x)
+               USE_ALLNODES=false
+               EXCLUDED_NODELIST=$OPTARG
+               ;;
        v) 
                VERBOSE_OUTPUT=true
                ;;
@@ -49,34 +67,26 @@ CSV_FILE=$1
 declare -a HOST_NAMES
 declare -a HOST_IPADDRS
 
-# Get the host names from the csv file
+# Get the hosts to be operated on
 get_hostnames() {
-       local NAME CHECK_STR
-       declare -i i
-       declare -i j
+       local NODES_TO_USE
 
        # Initialize the HOST_NAMES array
        unset HOST_NAMES
 
-       CHECK_STR=`egrep -v "([[:space:]]|^)#" ${CSV_FILE} | awk -F, \
-                 '/[[:alnum:]]/{if ($1 !~/[[:alnum:]]/) print $0}'`
-       if [ -n "${CHECK_STR}" ]; then
-                echo >&2 $"`basename $0`: get_hostnames() error: Missing"\
-                         "hostname field in the line - ${CHECK_STR}"
+       # Get the list of nodes to be operated on
+       NODES_TO_USE=$(get_nodelist)
+       [ ${PIPESTATUS[0]} -ne 0 ] && echo >&2 "${NODES_TO_USE}" && return 1
+
+       # Check the node list
+       if [ -z "${NODES_TO_USE}" ]; then
+               echo "`basename $0`: There are no hosts to be operated on."\
+               "Check the node selection options (-a, -w or -x)."
                return 1
        fi
 
-       i=0
-       for NAME in `egrep -v "([[:space:]]|^)#" ${CSV_FILE}\
-                   | awk -F, '/[[:alnum:]]/{print $1}'`
-       do
-               for ((j = 0; j < ${#HOST_NAMES[@]}; j++)); do
-                       [ "${NAME}" = "${HOST_NAMES[j]}" ] && continue 2
-               done
-
-               HOST_NAMES[i]=${NAME}
-               i=$i+1
-       done
+       # Load the hostnames in the nodelist into the array
+       HOST_NAMES=( $(echo ${NODES_TO_USE//,/ }) )
 
        return 0
 }
@@ -95,8 +105,8 @@ ping_host() {
        fi
 
        # Run ping command
-       ret_str=`ping -c1 ${host_name} 2>&1`
-       if [ $? -ne 0 ]; then
+       ret_str=$(ping -c1 ${host_name} 2>&1)
+       if [ ${PIPESTATUS[0]} -ne 0 ]; then
                if [ -n "${ret_str}" ]; then
                        echo "`basename $0`: ping_host() error: ${ret_str}!"
                else
@@ -122,7 +132,7 @@ local_check() {
        # Check whether ${HOST_NAMES[i]} is reachable
        # and get the IP address of this host from ping
        HOST_IPADDRS[i]=$(ping_host ${HOST_NAMES[i]})
-       if [ $? -ne 0 ]; then
+       if [ ${PIPESTATUS[0]} -ne 0 ]; then
                echo >&2 "${HOST_IPADDRS[i]}"
                return 1
        fi
@@ -141,8 +151,8 @@ remote_check() {
        # Execute remote command to check whether ${HOST_NAMES[i]}
        # can resolve its own name
        cmd="ping -c1 ${HOST_NAMES[i]} 2>&1"
-       ret_str=`${REMOTE} ${HOST_NAMES[i]} "(${EXPORT_PATH} ${cmd})" 2>&1`
-       if [ $? -ne 0 -a -n "${ret_str}" ]; then
+       ret_str=$(${REMOTE} ${HOST_NAMES[i]} "${cmd}" 2>&1)
+       if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then
                echo >&2 "`basename $0`: remote_check() error:"\
                "remote to ${HOST_NAMES[i]} error: ${ret_str}!"
                return 1
@@ -185,7 +195,7 @@ network_verify() {
        # Initialize the HOST_IPADDRS array
        unset HOST_IPADDRS
 
-       # Get all the host names from the csv file
+       # Get all the host names to be operated on 
        ! get_hostnames && return 1
 
        # Check the network connectivity between local host 
index 5ee082f..cde6aee 100644 (file)
 usage() {
     cat >&2 <<EOF
 
-Usage:  `basename $0` [-t HAtype] [-n] [-d] [-f] [-m] [-h] [-v] <csv file>
+Usage:  `basename $0` [options] <csv file>
 
     This script is used to format and set up multiple lustre servers from a
     csv file.
 
+    Options:
     -h          help and examples
+    -a          select all the nodes from the csv file to operate on
+    -w hostname,hostname,...
+                select the specified list of nodes (separated by commas) to
+                operate on rather than all the nodes in the csv file
+    -x hostname,hostname,...
+                exclude the specified list of nodes (separated by commas)
     -t HAtype   produce High-Availability software configurations
                 The argument following -t is used to indicate the High-
                 Availability software type. The HA software types which 
@@ -172,7 +179,7 @@ Example 2 - Separate MGS/MDT, two networks interfaces:
 lustre-mgs1,options lnet 'networks="tcp,elan"',/dev/sda,/mnt/mgs,mgs,,,,--quiet --param="sys.timeout=50",,"defaults,noauto","lustre-mgs2,2@elan"
 
 # mdt
-lustre-mdt1,options lnet 'networks="tcp,elan"',/dev/sdb,/mnt/mdt,mdt,lustre2,"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--quiet --param="lov.stripe.size=4194304",-J size=16,"defaults,noauto",lustre-mdt2
+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
 
 # ost
 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
@@ -245,8 +252,23 @@ CONFIG_MD_LVM=false
 MODIFY_FSTAB=true
 VERBOSE_OUTPUT=false
 # Get and check the positional parameters
-while getopts "t:ndfmhv" OPTION; do
+while getopts "aw:x:t:ndfmhv" OPTION; do
     case $OPTION in
+    a)
+        [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ] \
+        && USE_ALLNODES=true
+        NODELIST_OPT="${NODELIST_OPT} -a"
+        ;;
+    w)
+        USE_ALLNODES=false
+        SPECIFIED_NODELIST=$OPTARG
+        NODELIST_OPT="${NODELIST_OPT} -w ${SPECIFIED_NODELIST}"
+        ;;
+    x)
+        USE_ALLNODES=false
+        EXCLUDED_NODELIST=$OPTARG
+        NODELIST_OPT="${NODELIST_OPT} -x ${EXCLUDED_NODELIST}"
+        ;;
     t)
         HATYPE_OPT=$OPTARG
         if [ "${HATYPE_OPT}" != "${HBVER_HBV1}" ] \
@@ -583,7 +605,7 @@ get_nodenames() {
     for nids in ${FAILOVERS_NAMES[i]//:/ }
     do
         NODE_NAMES[idx]=$(nids2hostname ${nids})
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "${NODE_NAMES[idx]}"
             return 1
         fi
@@ -647,7 +669,7 @@ gen_ha_config() {
                "${HOST_NAME[i]} failover group..."
     verbose_output "${cmd_line}"
     eval $(echo "${cmd_line}")
-    if [ $? -ne 0 ]; then
+    if [ ${PIPESTATUS[0]} -ne 0 ]; then
         return 1
     fi
     verbose_output "Generate HA software's configurations in"\
@@ -715,7 +737,6 @@ config_ha() {
     return 0
 }
 
-
 # Get all the items in the csv file and do some checks.
 get_items() {
     # Check argument
@@ -728,6 +749,7 @@ get_items() {
     CSV_FILE=$1
     local LINE
     local marker
+    local hostname
     declare -i line_num=0
     declare -i idx=0
 
@@ -747,12 +769,18 @@ get_items() {
         fi
 
         # Skip the Linux MD/LVM line
-        marker=`echo ${LINE} | awk -F, '{print $2}'`
+        marker=$(echo ${LINE} | cut -d, -f 2)
         if [ "${marker}" = "${MD_MARKER}" -o "${marker}" = "${PV_MARKER}" ] \
         || [ "${marker}" = "${VG_MARKER}" -o "${marker}" = "${LV_MARKER}" ]; then
             continue
         fi
 
+        # Skip the host which is not specified in the host list
+        if ! ${USE_ALLNODES}; then
+            hostname=$(echo ${LINE} | cut -d, -f 1)
+            ! host_in_hostlist ${hostname} ${NODES_TO_USE} && continue
+        fi
+
         # Parse the config line into CONFIG_ITEM
         if ! parse_line "$LINE"; then
             echo >&2 $"`basename $0`: parse_line() error: Occurred"\
@@ -777,13 +805,13 @@ get_items() {
 
         # Convert IP addresses in NIDs to hostnames
         MGS_NIDS_NAMES[idx]=$(ip2hostname_multi_node ${MGS_NIDS[idx]})
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "${MGS_NIDS_NAMES[idx]}"
             return 1
         fi
 
         FAILOVERS_NAMES[idx]=$(ip2hostname_multi_node ${FAILOVERS[idx]})
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "${FAILOVERS_NAMES[idx]}"
             return 1
         fi
@@ -832,7 +860,7 @@ check_lnet_connect() {
     else
         for nids in ${MGS_NIDS[i]//:/ }; do
             nids_names=$(ip2hostname_single_node ${nids})
-            if [ $? -ne 0 ]; then
+            if [ ${PIPESTATUS[0]} -ne 0 ]; then
                 echo >&2 "${nids_names}"
                 return 1
             fi
@@ -853,8 +881,8 @@ check_lnet_connect() {
     for mgs_nid in ${nids_str//,/ }
     do
         COMMAND=$"${LCTL} ping ${mgs_nid} 5 || echo failed 2>&1"
-        RET_STR=`${REMOTE} ${HOST_NAME[i]} "${COMMAND}" 2>&1`
-        if [ $? -eq 0 -a "${RET_STR}" = "${RET_STR#*failed*}" ]
+        RET_STR=$(${REMOTE} ${HOST_NAME[i]} "${COMMAND}" 2>&1)
+        if [ ${PIPESTATUS[0]} -eq 0 -a "${RET_STR}" = "${RET_STR#*failed*}" ]
         then
             # This node can contact the MGS node
             verbose_output "${HOST_NAME[i]} can contact the MGS" \
@@ -894,9 +922,9 @@ check_lnet() {
 
     # Execute remote command to start lnet network
     verbose_output "Starting lnet network in ${HOST_NAME[i]}"
-    COMMAND=$"modprobe lnet; ${LCTL} network up 2>&1"
-    RET_STR=`${REMOTE} ${HOST_NAME[i]} "(${EXPORT_PATH} ${COMMAND})" 2>&1`
-    if [ $? -ne 0 -o "${RET_STR}" = "${RET_STR#*LNET configured*}" ]
+    COMMAND="PATH=\$PATH:/sbin:/usr/sbin modprobe lnet; ${LCTL} network up 2>&1"
+    RET_STR=$(${REMOTE} ${HOST_NAME[i]} "${COMMAND}" 2>&1)
+    if [ ${PIPESTATUS[0]} -ne 0 -o "${RET_STR}" = "${RET_STR#*LNET configured*}" ]
     then
         echo >&2 "`basename $0`: check_lnet() error: remote" \
                  "${HOST_NAME[i]} error: ${RET_STR}"
@@ -925,7 +953,11 @@ start_mgs_lnet() {
     local COMMAND
 
     if [ -z "${MGS_NODENAME[0]}" -a  -z "${MGS_NODENAME[1]}" ]; then
-        verbose_output "There is no MGS target in the ${CSV_FILE} file."
+        if ${USE_ALLNODES}; then
+            verbose_output "There is no MGS target in the ${CSV_FILE} file."
+        else
+            verbose_output "There is no MGS target in the node list \"${NODES_TO_USE}\"."
+        fi
         return 0
     fi
 
@@ -936,7 +968,7 @@ start_mgs_lnet() {
         COMMAND=$"echo \"${MODULE_OPTS[${idx}]}\"|${MODULE_CONFIG}"
         verbose_output "Adding lnet module options to ${MGS_NODENAME[i]}"
         ${REMOTE} ${MGS_NODENAME[i]} "${COMMAND}" >&2 
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "`basename $0`: start_mgs_lnet() error:"\
                  "Failed to execute remote command to" \
                  "add module options to ${MGS_NODENAME[i]}!"\
@@ -982,8 +1014,8 @@ mass_config() {
         COMMAND="mkdir -p ${MOUNT_POINT[i]}"
         verbose_output "Creating the mount point ${MOUNT_POINT[i]} on" \
                        "${HOST_NAME[i]}"
-        ${REMOTE} ${HOST_NAME[i]} "(${EXPORT_PATH} ${COMMAND})" >&2 
-        if [ $? -ne 0 ]; then
+        ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2 
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "`basename $0`: mass_config() error:"\
                  "Failed to execute remote command to"\
                  "create the mountpoint on ${HOST_NAME[i]}!"
@@ -997,7 +1029,7 @@ mass_config() {
             verbose_output "Adding lnet module options to" \
                        "${HOST_NAME[i]}"
             ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2 
-            if [ $? -ne 0 ]; then
+            if [ ${PIPESTATUS[0]} -ne 0 ]; then
                 echo >&2 "`basename $0`: mass_config() error:"\
                      "Failed to execute remote command to"\
                      "add module options to ${HOST_NAME[i]}!"
@@ -1025,7 +1057,7 @@ mass_config() {
     fail_exit_status=false
     for ((pid_num = 0; pid_num < ${#REMOTE_PID[@]}; pid_num++)); do
         wait ${REMOTE_PID[${pid_num}]}
-        if [ $? -ne 0 ]; then
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "`basename $0`: mass_config() error: Failed"\
             "to execute \"${REMOTE_CMD[${pid_num}]}\"!"
             fail_exit_status=true
@@ -1053,9 +1085,9 @@ get_mntopts() {
 
     # Execute remote command to check whether the device
     # is a block device or not
-    ret_str=`${REMOTE} ${host_name} \
-            "[ -b ${device_name} ] && echo block || echo loop" 2>&1`
-    if [ $? -ne 0 -a -n "${ret_str}" ]; then
+    ret_str=$(${REMOTE} ${host_name} \
+            "[ -b ${device_name} ] && echo block || echo loop" 2>&1)
+    if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then
         echo "`basename $0`: get_mntopts() error:" \
         "remote command to ${host_name} error: ${ret_str}"
         return 1
@@ -1096,7 +1128,7 @@ modify_fstab() {
         else
             mntopts=$(get_mntopts ${HOST_NAME[i]} ${DEVICE_NAME[i]}\
                     ${FAILOVERS[i]})
-            if [ $? -ne 0 ]; then
+            if [ ${PIPESTATUS[0]} -ne 0 ]; then
                 echo >&2 "${mntopts}"
                 return 1
             fi
@@ -1110,8 +1142,8 @@ modify_fstab() {
         COMMAND=". @scriptlibdir@/lc_common.sh; \
                 sed -i \"/^${device_name}\t/d\" \$(fcanon /etc/fstab); \
                 echo -e \"${mntent}\" >> \$(fcanon /etc/fstab)"
-        ${REMOTE} ${HOST_NAME[i]} "(${EXPORT_PATH} ${COMMAND})" >&2
-        if [ $? -ne 0 ]; then
+        ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2
+        if [ ${PIPESTATUS[0]} -ne 0 ]; then
             echo >&2 "`basename $0`: modify_fstab() error:"\
             "Failed to modify /etc/fstab of host ${HOST_NAME[i]}"\
             "to add Lustre target ${DEVICE_NAME[i]}!"
@@ -1125,14 +1157,21 @@ modify_fstab() {
 # Main flow
 # Check the csv file
 if ! check_file $1; then
-    exit 1    
+    exit 1 
 fi
 
+# Get the list of nodes to be operated on
+NODES_TO_USE=$(get_nodelist)
+[ ${PIPESTATUS[0]} -ne 0 ] && echo >&2 "${NODES_TO_USE}" && exit 1
+
+# Check the node list
+check_nodelist ${NODES_TO_USE} || exit 1
+
 if ${VERIFY_CONNECT}; then
 # Check the network connectivity and hostnames
     echo "`basename $0`: Checking the cluster network connectivity"\
          "and hostnames..."
-    if ! ${VERIFY_CLUSTER_NET} ${VERBOSE_OPT} ${CSV_FILE}; then
+    if ! ${VERIFY_CLUSTER_NET} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then
         exit 1
     fi
     echo "`basename $0`: Check the cluster network connectivity"\
@@ -1143,11 +1182,11 @@ fi
 if ${CONFIG_MD_LVM}; then
 # Configure Linux MD/LVM devices
     echo "`basename $0`: Configuring Linux MD/LVM devices..."
-    if ! ${SCRIPT_CONFIG_MD} ${VERBOSE_OPT} ${CSV_FILE}; then
+    if ! ${SCRIPT_CONFIG_MD} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then
         exit 1
     fi
 
-    if ! ${SCRIPT_CONFIG_LVM} ${VERBOSE_OPT} ${CSV_FILE}; then
+    if ! ${SCRIPT_CONFIG_LVM} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then
         exit 1
     fi
     echo "`basename $0`: Configure Linux MD/LVM devices OK!"