3 # lustre_createcsv - generate a csv file from a running lustre cluster
5 # This script is used to collect lustre target informations, linux MD/LVM device
6 # informations and HA software configurations in a lustre cluster to generate a
7 # csv file. In reverse, the csv file could be parsed by lustre_config to
8 # configure multiple lustre servers in parallel.
10 # This script should be run on the MGS node.
12 ################################################################################
18 Usage: `basename $0` [-t HAtype] [-d] [-h] [-v] [-f csv_filename]
20 This script is used to collect lustre target informations, linux MD/LVM
21 device informations and HA software configurations from a running lustre
22 cluster to generate a csv file. It should be run on the MGS node.
24 -t HAtype collect High-Availability software configurations
25 The argument following -t is used to indicate the High-
26 Availability software type. The HA software types which
27 are currently supported are: hbv1 (Heartbeat version 1)
28 and hbv2 (Heartbeat version 2).
29 -d collect linux MD/LVM device informations
32 -f csv_filename designate a name for the csv file
33 Default is lustre_config.csv.
39 # Get the library of functions
40 . @scriptlibdir@/lc_common
42 #**************************** Global variables ****************************#
44 LUSTRE_CSV_FILE=${LUSTRE_CSV_FILE:-"lustre_config.csv"}
47 LUSTRE_PROC=${LUSTRE_PROC:-"/proc/fs/lustre"}
48 LUSTRE_PROC_DEVICES=${LUSTRE_PROC}/devices
50 LNET_PROC=${LNET_PROC:-"/proc/sys/lnet"}
51 LNET_PROC_PEERS=${LNET_PROC}/peers
53 # Default network module options
54 DEFAULT_MOD_OPTS=${DEFAULT_MOD_OPTS:-"options lnet networks=tcp"}
56 # Lustre target obd device types
57 MGS_TYPE=${MGS_TYPE:-"mgs"}
58 MDT_TYPE=${MDT_TYPE:-"mds"}
59 OST_TYPE=${OST_TYPE:-"obdfilter"}
61 # The obd name of MGS target server
62 MGS_SVNAME=${MGS_SVNAME:-"MGS"}
64 # Hostnames of the lustre cluster nodes
66 MGS_HOSTNAME=${MGS_HOSTNAME:-"`hostname`"} # Hostname of the MGS node
68 # Configs of lustre targets in one cluster node
69 declare -a TARGET_CONFIGS
70 declare -a TARGET_SVNAMES TARGET_DEVNAMES TARGET_DEVSIZES TARGET_MNTPNTS
71 declare -a TARGET_DEVTYPES TARGET_FSNAMES TARGET_MGSNIDS TARGET_INDEXES
72 declare -a TARGET_FMTOPTS TARGET_MKFSOPTS TARGET_MNTOPTS TARGET_FAILNIDS
74 declare -a ALL_TARGET_SVNAMES # All the target services in the cluster
75 declare -a FAILOVER_FMTOPTS # "--noformat"
77 # Informations of linux MD/LVM devices in one cluster node
78 declare -a MD_NAME MD_LEVEL MD_DEVS # MD
79 declare -a VG_NAME VG_PVNAMES # VG
80 declare -a LV_NAME LV_SIZE LV_VGNAME # LV
82 # Lustre target service types
83 let "LDD_F_SV_TYPE_MDT = 0x0001"
84 let "LDD_F_SV_TYPE_OST = 0x0002"
85 let "LDD_F_SV_TYPE_MGS = 0x0004"
87 # Permanent mount options for ext3 or ldiskfs
88 ALWAYS_MNTOPTS=${ALWAYS_MNTOPTS:-"errors=remount-ro"}
89 MDT_MGS_ALWAYS_MNTOPTS=${MDT_MGS_ALWAYS_MNTOPTS:-",iopen_nopriv,user_xattr"}
90 OST_ALWAYS_MNTOPTS=${OST_ALWAYS_MNTOPTS:-",asyncdel"}
91 OST_DEFAULT_MNTOPTS=${OST_DEFAULT_MNTOPTS:-",extents,mballoc"}
93 # User-settable parameter keys
94 PARAM_MGSNODE=${PARAM_MGSNODE:-"mgsnode="}
95 PARAM_FAILNODE=${PARAM_FAILNODE:-"failover.node="}
100 # Option string of mkfs.lustre
101 OPTSTR_STRIPE_COUNT=${OPTSTR_STRIPE_COUNT:-"--stripe-count-hint="}
104 # Get and check the positional parameters
107 while getopts "t:dhvf:" OPTION; do
111 if [ "${HATYPE_OPT}" != "${HBVER_HBV1}" ] \
112 && [ "${HATYPE_OPT}" != "${HBVER_HBV2}" ] \
113 && [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" ]; then
114 echo >&2 "`basename $0`: Invalid HA software type" \
119 d) GET_MDLVM_INFO=true;;
121 v) VERBOSE_OUTPUT=true;;
122 f) LUSTRE_CSV_FILE=$OPTARG;;
127 # Verify the local host is the MGS node
129 if [ ! -e ${LUSTRE_PROC_DEVICES} ]; then
130 echo >&2 "`basename $0`: error: ${LUSTRE_PROC_DEVICES} does" \
131 "not exist. Lustre kernel modules may not be loaded!"
135 if [ -z "`cat ${LUSTRE_PROC_DEVICES}`" ]; then
136 echo >&2 "`basename $0`: error: ${LUSTRE_PROC_DEVICES} is" \
137 "empty. Lustre services may not be started!"
141 if [ -z "`grep ${MGS_TYPE} ${LUSTRE_PROC_DEVICES}`" ]; then
142 echo >&2 "`basename $0`: error: This node is not a MGS node." \
143 "The script should be run on the MGS node!"
151 # Get lustre cluster node names
154 declare -i idx # Index of HOST_NIDS array
155 declare -i i # Index of HOST_NAMES array
161 if [ ! -e ${LNET_PROC_PEERS} ]; then
162 echo >&2 "`basename $0`: error: ${LNET_PROC_PEERS} does not" \
163 "exist. LNET kernel modules may not be loaded" \
164 "or LNET network may not be up!"
168 HOST_NAMES[0]=${MGS_HOSTNAME} # MGS node
169 HOST_NIDS[0]=${HOST_NAMES[0]}
171 # Get the nids of the nodes which have contacted MGS
173 for nid in `cat ${LNET_PROC_PEERS} | awk '{print $1}'`; do
174 if [ "${nid}" = "nid" ]; then
178 HOST_NIDS[idx]=${nid}
182 if [ ${idx} -eq 1 ]; then
183 verbose_output "Only one node running in the lustre cluster." \
184 "It's ${HOST_NAMES[0]}."
188 # Get the hostnames of the nodes
189 for ((idx = 1, i = 1; idx < ${#HOST_NIDS[@]}; idx++, i++)); do
190 if [ -z "${HOST_NIDS[idx]}" ]; then
191 echo >&2 "`basename $0`: get_hostnames() error:" \
192 "Invalid nid - \"${HOST_NIDS[idx]}\"!"
196 HOST_NAMES[i]=$(nid2hostname ${HOST_NIDS[idx]})
197 if [ $? -ne 0 ]; then
198 echo >&2 "${HOST_NAMES[i]}"
202 if [ "${HOST_NAMES[i]}" = "${HOST_NAMES[0]}" ]; then
211 #********************** Linux MD/LVM device informations **********************#
212 # get_md_configs hostname
213 # Get all the active MD device informations from the node @hostname
218 local ret_line line first_item
220 # Initialize the arrays
225 # Execute remote command to the node ${host_name} and get all the
226 # active MD device informations.
227 while read -r ret_line; do
236 first_item=`echo "${line}" | awk '{print $1}'`
238 # Get the MD device name and raid level
239 if [ "${first_item}" = "ARRAY" ]; then
240 MD_NAME[i]=`echo "${line}" | awk '{print $2}'`
241 MD_LEVEL[i]=`echo "${line}" | awk '{print $3}' | sed -e 's/level=//'`
246 # Get the MD component devices
247 if [ "${first_item}" != "${first_item#devices=}" ]; then
248 MD_DEVS[j]=`echo "${line}" | sed -e 's/devices=//' -e 's/,/ /g'`
250 done < <(${REMOTE} ${host_name} "${MDADM} --detail --scan --verbose")
252 if [ $i -eq 0 ]; then
253 verbose_output "There are no active MD devices" \
254 "in the host ${host_name}!"
260 # get_pv_configs hostname
261 # Get all the LVM PV informations from the node @hostname
267 # Execute remote command to get all the PV informations.
268 cmd="${EXPORT_PATH} pvdisplay -c | awk -F: '{print \$1}' | xargs"
269 ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
270 if [ $? -ne 0 ]; then
271 if [ -n "${ret_str}" ]; then
272 echo >&2 "`basename $0`: get_pv_configs() error:" \
273 "remote command to ${host_name} error: ${ret_str}"
275 remote_error "get_pv_configs" ${host_name}
280 PV_NAMES=`echo "${ret_str}" | sed -e 's/^'${host_name}':[[:space:]]//'`
281 if [ -z "${PV_NAMES}" ]; then
282 verbose_output "There are no PVs in the host ${host_name}!"
289 # get_vg_pvnames hostname vgname
290 # Get the PVs contained in @vgname from the node @hostname
297 # Execute remote command to get the PV names.
298 cmd="${EXPORT_PATH} vgdisplay -v ${vg_name} 2>/dev/null\
299 | grep \"PV Name\" | awk '{print \$3}' | xargs"
300 ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
301 if [ $? -ne 0 ]; then
302 if [ -n "${ret_str}" ]; then
303 echo "`basename $0`: get_vg_pvnames() error:" \
304 "remote command to ${host_name} error: ${ret_str}"
306 remote_error "get_vg_pvnames" ${host_name}
311 pv_names=`echo "${ret_str}" | sed -e 's/^'${host_name}':[[:space:]]//'`
312 if [ -z "${pv_names}" ]; then
313 echo "`basename $0`: get_vg_pvnames() error:" \
314 "There are no PVs in VG ${vg_name} in the host ${host_name}!"\
315 "Or VG ${vg_name} does not exist."
323 # get_vg_configs hostname
324 # Get all the LVM VG informations from the node @hostname
331 # Initialize the arrays
335 # Execute remote command to get all the VG names.
336 cmd="${EXPORT_PATH} vgdisplay \
337 | grep \"VG Name\" | awk '{print \$3}' | xargs"
338 ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
339 if [ $? -ne 0 ]; then
340 if [ -n "${ret_str}" ]; then
341 echo >&2 "`basename $0`: get_vg_configs() error:" \
342 "remote command to ${host_name} error: ${ret_str}"
344 remote_error "get_vg_configs" ${host_name}
349 if [ -z "${ret_str}" ] \
350 || [ "${ret_str}" != "${ret_str#*No volume groups found*}" ]; then
351 verbose_output "There are no VGs in the host ${host_name}!"
355 # Get all the VG informations
356 for vg_name in `echo "${ret_str}" | sed -e 's/^'${host_name}'://'`; do
357 VG_NAME[i]=${vg_name}
358 VG_PVNAMES[i]=$(get_vg_pvnames ${host_name} ${VG_NAME[i]})
359 if [ $? -ne 0 ]; then
360 echo >&2 "${VG_PVNAMES[i]}"
369 # get_lv_configs hostname
370 # Get all the LVM LV informations from the node @hostname
376 # Initialize the arrays
381 # Execute remote command to get all the LV informations.
382 while read -r ret_line; do
391 [ "${line}" != "${line#*volume group*}" ] && break
393 LV_NAME[i]=`echo "${line}" | awk -F: '{print $1}' | sed -e 's/.*\///g'`
394 LV_VGNAME[i]=`echo "${line}" | awk -F: '{print $2}'`
395 LV_SIZE[i]=`echo "${line}" | awk -F: '{print $7}' | sed -e 's/.*/&K/'`
398 done < <(${REMOTE} ${host_name} "${EXPORT_PATH} lvdisplay -c")
400 if [ $i -eq 0 ]; then
401 verbose_output "There are no LVs in the host ${host_name}"
407 #*************************** Network module options ***************************#
408 # last_is_backslash line
409 # Check whether the last effective letter of @line is a backslash
410 last_is_backslash() {
414 local letter last_letter
417 for ((i = ${length}-1; i >= 0; i--)); do
418 letter=${line:${i}:1}
419 [ "x${letter}" != "x " -a "x${letter}" != "x " -a -n "${letter}" ]\
420 && last_letter=${letter} && break
423 [ "x${last_letter}" = "x\\" ] && return 0
428 # get_module_opts hostname
429 # Get the network module options from the node @hostname
433 local MODULE_CONF KERNEL_VER
434 local ret_line line find_options
437 MODULE_OPTS=${DEFAULT_MOD_OPTS}
439 # Execute remote command to get the kernel version
440 ret_str=`${REMOTE} ${host_name} "uname -r" 2>&1`
441 if [ $? -ne 0 -a -n "${ret_str}" ]; then
442 echo >&2 "`basename $0`: get_module_opts() error:" \
443 "remote command error: ${ret_str}"
446 remote_error "get_module_opts" ${host_name} "${ret_str}" && return 1
449 KERNEL_VER=`echo ${ret_str} | awk '{print $2}'`
451 KERNEL_VER=`echo ${ret_str} | awk '{print $1}'`
454 # Get the module configuration file name
455 if [ "${KERNEL_VER:0:3}" = "2.4" ]; then
456 MODULE_CONF=/etc/modules.conf
458 MODULE_CONF=/etc/modprobe.conf
461 # Execute remote command to get the lustre network module options
464 while read -r ret_line; do
473 # Get rid of the comment line
474 [ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue
476 if [ "${line}" != "${line#*options lnet*}" ]; then
477 if ! ${find_options}; then
481 MODULE_OPTS=${MODULE_OPTS}$" \n "${line}
484 last_is_backslash "${line}" && continue_flag=true \
485 || continue_flag=false
489 if ${continue_flag}; then
490 MODULE_OPTS=${MODULE_OPTS}$" \n "${line}
491 ! last_is_backslash "${line}" && continue_flag=false
494 done < <(${REMOTE} ${host_name} "cat ${MODULE_CONF}")
496 if [ -z "${MODULE_OPTS}" ]; then
497 MODULE_OPTS=${DEFAULT_MOD_OPTS}
503 #************************ HA software configurations ************************#
504 # is_ha_target hostname target_devname
505 # Check whether the target @target_devname was made to be high-available
508 local target_svname=$2
512 case "${HATYPE_OPT}" in
513 "${HBVER_HBV1}") res_file=${HA_RES};;
514 "${HBVER_HBV2}") res_file=${HA_CIB};;
515 "${HATYPE_CLUMGR}") res_file=${CLUMAN_CONFIG};;
518 # Execute remote command to check the resource file
519 ret_str=`${REMOTE} ${host_name} \
520 "grep ${target_svname} ${res_file}" 2>&1`
521 if [ $? -ne 0 -a -n "${ret_str}" ]; then
522 echo >&2 "`basename $0`: is_ha_target() error:" \
523 "remote command error: ${ret_str}"
527 [ "${ret_str}" = "${ret_str#*${target_svname}*}" ] && return 1
532 # get_hb_configs hostname
533 # Get the Heartbeat configurations from the node @hostname
544 # Execute remote command to get the configs of Heartbeat channels, etc
545 while read -r ret_line; do
554 # Get rid of the comment line
555 [ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue
557 if [ "${line}" != "${line#*serial*}" ] \
558 || [ "${line}" != "${line#*cast*}" ]; then
559 if [ -z "${HB_CHANNELS}" ]; then
562 HB_CHANNELS=${HB_CHANNELS}:${line}
566 if [ "${line}" != "${line#*stonith*}" ] \
567 || [ "${line}" != "${line#*ping*}" ] \
568 || [ "${line}" != "${line#*respawn*}" ] \
569 || [ "${line}" != "${line#*apiauth*}" ] \
570 || [ "${line}" != "${line#*compression*}" ]; then
571 if [ -z "${HB_OPTIONS}" ]; then
574 HB_OPTIONS=${HB_OPTIONS}:${line}
577 done < <(${REMOTE} ${host_name} "cat ${HA_CF}")
579 if [ -z "${HB_CHANNELS}" ]; then
580 echo >&2 "`basename $0`: get_hb_configs() error:" \
581 "There are no heartbeat channel configs in ${HA_CF}" \
582 "of host ${host_name} or ${HA_CF} does not exist!"
586 # Execute remote command to get Heartbeat service address
587 if [ "${HATYPE_OPT}" = "${HBVER_HBV1}" ]; then
588 while read -r ret_line; do
597 # Get rid of the empty line
598 [ -z "`echo ${line}|awk '/[[:alnum:]]/ {print $0}'`" ]\
601 # Get rid of the comment line
602 [ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue
604 SRV_IPADDRS=`echo ${line} | awk '{print $2}'`
605 [ -n "${SRV_IPADDRS}" ] \
606 && [ "`echo ${line} | awk '{print $1}'`" = "${host_name}" ] && break
607 done < <(${REMOTE} ${host_name} "cat ${HA_RES}")
609 if [ -z "${SRV_IPADDRS}" ]; then
610 echo >&2 "`basename $0`: get_hb_configs() error: There"\
611 "are no service address in ${HA_RES} of host"\
612 "${host_name} or ${HA_RES} does not exist!"
617 # Construct HA configuration items
618 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
619 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
621 # Execute remote command to check whether this target service
622 # was made to be high-available
623 if is_ha_target ${host_name} ${TARGET_DEVNAMES[i]}; then
624 HA_CONFIGS[i]=${HB_CHANNELS},${SRV_IPADDRS},${HB_OPTIONS}
631 # get_cluman_channel hostname
632 # Get the Heartbeat channel of CluManager from the node @hostname
633 get_cluman_channel() {
636 local cluman_channel=
639 while read -r ret_line; do
648 if [ "${line}" != "${line#*broadcast*}" ] \
649 && [ "`echo ${line}|awk '{print $3}'`" = "yes" ]; then
650 cluman_channel="broadcast"
654 if [ "${line}" != "${line#*multicast_ipaddress*}" ]; then
655 mcast_ipaddr=`echo ${line}|awk '{print $3}'`
656 if [ "${mcast_ipaddr}" != "225.0.0.11" ]; then
657 cluman_channel="multicast ${mcast_ipaddr}"
661 done < <(${REMOTE} ${host_name} "${CONFIG_CMD} --clumembd")
663 echo ${cluman_channel}
667 # get_cluman_srvaddr hostname target_svname
668 # Get the service IP addresses of @target_svname from the node @hostname
669 get_cluman_srvaddr() {
671 local target_svname=$2
673 local srvaddr cluman_srvaddr=
675 while read -r ret_line; do
684 if [ "${line}" != "${line#*ipaddress = *}" ]; then
685 srvaddr=`echo ${line}|awk '{print $3}'`
686 if [ -z "${cluman_srvaddr}" ]; then
687 cluman_srvaddr=${srvaddr}
689 cluman_srvaddr=${cluman_srvaddr}:${srvaddr}
692 done < <(${REMOTE} ${host_name} "${CONFIG_CMD} \
693 --service=${target_svname} --service_ipaddresses")
695 if [ -z "${cluman_srvaddr}" ]; then
696 echo "`basename $0`: get_cluman_srvaddr() error: Cannot" \
697 "get the service IP addresses of ${target_svname} in" \
698 "${host_name}! Check ${CONFIG_CMD} command!"
702 echo ${cluman_srvaddr}
706 # get_cluman_configs hostname
707 # Get the CluManager configurations from the node @hostname
708 get_cluman_configs() {
715 # Execute remote command to get the configs of CluManager
716 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
720 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
722 # Execute remote command to check whether this target service
723 # was made to be high-available
724 ! is_ha_target ${host_name} ${TARGET_DEVNAMES[i]} && continue
726 # Execute remote command to get Heartbeat channel
727 HB_CHANNELS=$(get_cluman_channel ${host_name})
728 if [ $? -ne 0 ]; then
729 echo >&2 "${HB_CHANNELS}"
732 # Execute remote command to get service IP address
733 SRV_IPADDRS=$(get_cluman_srvaddr ${host_name} \
734 ${TARGET_SVNAMES[i]})
735 if [ $? -ne 0 ]; then
736 echo >&2 "${SRV_IPADDRS}"
740 HA_CONFIGS[i]=${HB_CHANNELS},${SRV_IPADDRS},${HB_OPTIONS}
746 # get_ha_configs hostname
747 # Get the HA software configurations from the node @hostname
753 if [ -z "${HATYPE_OPT}" ]; then
757 verbose_output "Collecting HA software configurations from host $1..."
759 case "${HATYPE_OPT}" in
760 "${HBVER_HBV1}" | "${HBVER_HBV2}") # Heartbeat
761 if ! get_hb_configs ${host_name}; then
765 "${HATYPE_CLUMGR}") # CluManager
766 if ! get_cluman_configs ${host_name}; then
775 #*********************** Lustre targets configurations ***********************#
777 # is_failover_service target_svname
778 # Check whether a target service @target_svname is a failover service.
779 is_failover_service() {
780 local target_svname=$1
783 for ((i = 0; i < ${#ALL_TARGET_SVNAMES[@]}; i++)); do
784 [ "${target_svname}" = "${ALL_TARGET_SVNAMES[i]}" ] && return 0
790 # get_svnames hostname
791 # Get the lustre target server obd names from the node @hostname
798 # Initialize the TARGET_SVNAMES array
800 unset FAILOVER_FMTOPTS
802 # Execute remote command to the node @hostname and figure out what
803 # lustre services are running.
805 j=${#ALL_TARGET_SVNAMES[@]}
806 while read -r ret_line; do
815 if [ -z "`echo ${line} | grep ${MGS_TYPE}`" ] \
816 && [ -z "`echo ${line} | grep ${MDT_TYPE}`" ] \
817 && [ -z "`echo ${line} | grep ${OST_TYPE}`" ]; then
821 # Get target server name
822 TARGET_SVNAMES[i]=`echo ${line} | awk '{print $4}'`
823 if [ -n "${TARGET_SVNAMES[i]}" ]; then
824 if is_failover_service ${TARGET_SVNAMES[i]}; then
825 FAILOVER_FMTOPTS[i]="--noformat"
827 ALL_TARGET_SVNAMES[j]=${TARGET_SVNAMES[i]}
831 echo >&2 "`basename $0`: get_svnames() error: Invalid"\
832 "line in ${host_name}'s ${LUSTRE_PROC_DEVICES}"\
836 done < <(${REMOTE} ${host_name} "cat ${LUSTRE_PROC_DEVICES}")
838 if [ $i -eq 0 ]; then
839 verbose_output "There are no lustre services running" \
840 "on the node ${host_name}!"
847 # Check whether a device @devname is a loop device or not
851 if [ -z "${devname}" ] || \
852 [ -z "`echo ${devname}|awk '/\/dev\/loop[[:digit:]]/ {print $0}'`" ]
860 # get_devname hostname svname
861 # Get the device name of lustre target @svname from node @hostname
864 local target_svname=$2
865 local target_devname=
867 local target_type target_obdtype mntdev_file
869 if [ "${target_svname}" = "${MGS_SVNAME}" ]; then
870 # Execute remote command to get the device name of mgs target
871 ret_str=`${REMOTE} ${host_name} \
872 "/sbin/findfs LABEL=${target_svname}" 2>&1`
873 if [ $? -ne 0 -a -n "${ret_str}" ]; then
874 if [ "${ret_str}" = "${ret_str#*Unable to resolve*}" ]
876 echo "`basename $0`: get_devname() error:" \
877 "remote command error: ${ret_str}"
882 if [ "${ret_str}" = "${ret_str#*Unable to resolve*}" ]; then
884 target_devname=`echo ${ret_str} | awk '{print $2}'`
886 target_devname=`echo ${ret_str} | awk '{print $1}'`
889 else # Execute remote command to get the device name of mdt/ost target
890 target_type=`echo ${target_svname} | cut -d - -f 2`
891 target_obdtype=${target_type:0:3}_TYPE
893 mntdev_file=${LUSTRE_PROC}/${!target_obdtype}/${target_svname}/mntdev
895 ret_str=`${REMOTE} ${host_name} "cat ${mntdev_file}" 2>&1`
896 if [ $? -ne 0 -a -n "${ret_str}" ]; then
897 echo "`basename $0`: get_devname() error:" \
898 "remote command error: ${ret_str}"
902 if [ "${ret_str}" != "${ret_str#*No such file*}" ]; then
903 echo "`basename $0`: get_devname() error:"\
904 "${mntdev_file} does not exist in ${host_name}!"
908 target_devname=`echo ${ret_str} | awk '{print $2}'`
910 target_devname=`echo ${ret_str} | awk '{print $1}'`
915 echo ${target_devname}
919 # get_devsize hostname target_devname
920 # Get the device size (KB) of @target_devname from node @hostname
923 local target_devname=$2
924 local target_devsize=
927 # Execute remote command to get the device size
928 ret_str=`${REMOTE} ${host_name} \
929 "/sbin/blockdev --getsize ${target_devname}" 2>&1`
930 if [ $? -ne 0 -a -n "${ret_str}" ]; then
931 echo "`basename $0`: get_devsize() error:" \
932 "remote command error: ${ret_str}"
937 target_devsize=`echo ${ret_str} | awk '{print $2}'`
939 target_devsize=`echo ${ret_str} | awk '{print $1}'`
942 if [ -z "`echo ${target_devsize}|awk '/^[[:digit:]]/ {print $0}'`" ]
944 echo "`basename $0`: get_devsize() error: can't" \
945 "get device size of ${target_devname} in ${host_name}!"
949 let " target_devsize /= 2"
951 echo ${target_devsize}
955 # get_realdevname hostname loop_dev
956 # Get the real device name of loop device @loop_dev from node @hostname
960 local target_devname=
963 # Execute remote command to get the real device name
964 ret_str=`${REMOTE} ${host_name} \
965 "/sbin/losetup ${loop_dev}" 2>&1`
966 if [ $? -ne 0 -a -n "${ret_str}" ]; then
967 echo "`basename $0`: get_realdevname() error:" \
968 "remote command error: ${ret_str}"
973 target_devname=`echo ${ret_str} | awk '{print $4}' \
974 | sed 's/^(//' | sed 's/)$//'`
976 target_devname=`echo ${ret_str} | awk '{print $3}' \
977 | sed 's/^(//' | sed 's/)$//'`
980 if [ "${ret_str}" != "${ret_str#*No such*}" ] \
981 || [ -z "${target_devname}" ]; then
982 echo "`basename $0`: get_realdevname() error: can't" \
983 "get info on device ${loop_dev} in ${host_name}!"
987 echo ${target_devname}
991 # get_mntpnt hostname target_devname
992 # Get the lustre target mount point from the node @hostname
995 local target_devname=$2
999 # Execute remote command to get the mount point
1000 ret_str=`${REMOTE} ${host_name} \
1001 "cat /etc/mtab | grep ${target_devname}" 2>&1`
1002 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1003 echo "`basename $0`: get_mntpnt() error:" \
1004 "remote command error: ${ret_str}"
1009 mnt_point=`echo ${ret_str} | awk '{print $3}'`
1011 mnt_point=`echo ${ret_str} | awk '{print $2}'`
1014 if [ -z "${mnt_point}" ]; then
1015 echo "`basename $0`: get_mntpnt() error: can't" \
1016 "get the mount point of ${target_devname} in ${host_name}!"
1024 # get_devnames hostname
1025 # Get the lustre target device names, mount points
1026 # and loop device sizes from the node @hostname
1032 # Initialize the arrays
1033 unset TARGET_DEVNAMES
1034 unset TARGET_DEVSIZES
1035 unset TARGET_MNTPNTS
1037 for ((i = 0; i < ${#TARGET_SVNAMES[@]}; i++)); do
1038 TARGET_DEVNAMES[i]=$(get_devname ${host_name} \
1039 ${TARGET_SVNAMES[i]})
1040 if [ $? -ne 0 ]; then
1041 echo >&2 "${TARGET_DEVNAMES[i]}"
1045 if [ -z "${TARGET_DEVNAMES[i]}" ]; then
1046 if [ "${TARGET_SVNAMES[i]}" = "${MGS_SVNAME}" ]; then
1047 verbose_output "There exists combo mgs/mdt"\
1048 "target in ${host_name}."
1051 echo >&2 "`basename $0`: get_devname() error:"\
1052 "No device corresponding to target" \
1053 "${TARGET_SVNAMES[i]} in ${host_name}!"
1058 # Get the mount point of the target
1059 TARGET_MNTPNTS[i]=$(get_mntpnt ${host_name} \
1060 ${TARGET_DEVNAMES[i]})
1061 if [ $? -ne 0 ]; then
1062 echo >&2 "${TARGET_MNTPNTS[i]}"
1066 # The target device is a loop device?
1067 if [ -n "${TARGET_DEVNAMES[i]}" ] \
1068 && is_loopdev ${TARGET_DEVNAMES[i]}; then
1069 # Get the device size
1070 TARGET_DEVSIZES[i]=$(get_devsize ${host_name} \
1071 ${TARGET_DEVNAMES[i]})
1072 if [ $? -ne 0 ]; then
1073 echo >&2 "${TARGET_DEVSIZES[i]}"
1077 # Get the real device name
1078 TARGET_DEVNAMES[i]=$(get_realdevname ${host_name} \
1079 ${TARGET_DEVNAMES[i]})
1080 if [ $? -ne 0 ]; then
1081 echo >&2 "${TARGET_DEVNAMES[i]}"
1090 # is_target target_svtype ldd_flags
1091 # Check the service type of a lustre target
1094 "mdt") let "ret = $2 & LDD_F_SV_TYPE_MDT";;
1095 "ost") let "ret = $2 & LDD_F_SV_TYPE_OST";;
1096 "mgs") let "ret = $2 & LDD_F_SV_TYPE_MGS";;
1098 echo >&2 "`basename $0`: is_target() error: Invalid" \
1099 "target service type - \"$1\"!"
1104 if [ ${ret} -eq 0 ]; then
1111 # get_devtype ldd_flags
1112 # Get the service type of a lustre target from @ldd_flags
1114 local target_devtype=
1116 if [ -z "${flags}" ]; then
1117 echo "`basename $0`: get_devtype() error: Invalid" \
1118 "ldd_flags - it's value is null!"
1122 if is_target "mgs" $1; then
1123 if is_target "mdt" $1; then
1124 target_devtype="mgs|mdt"
1126 target_devtype="mgs"
1128 elif is_target "mdt" $1; then
1129 target_devtype="mdt"
1130 elif is_target "ost" $1; then
1131 target_devtype="ost"
1133 echo "`basename $0`: get_devtype() error: Invalid" \
1134 "ldd_flags - \"$1\"!"
1138 echo ${target_devtype}
1142 # get_mntopts ldd_mount_opts
1143 # Get the user-specified lustre target mount options from @ldd_mount_opts
1146 local ldd_mount_opts=$1
1148 mount_opts="${ldd_mount_opts#${ALWAYS_MNTOPTS}}"
1149 mount_opts="${mount_opts#${MDT_MGS_ALWAYS_MNTOPTS}}"
1150 mount_opts="${mount_opts#${OST_ALWAYS_MNTOPTS}}"
1151 mount_opts="${mount_opts#${OST_DEFAULT_MNTOPTS}}"
1152 mount_opts="`echo \"${mount_opts}\" | sed 's/^,//'`"
1154 [ "${mount_opts}" != "${mount_opts#*,*}" ] && echo "\""${mount_opts}"\"" \
1155 || echo ${mount_opts}
1160 # get_mgsnids ldd_params
1161 # Get the mgs nids of lustre target from @ldd_params
1163 local mgs_nids= # mgs nids in one mgs node
1164 local all_mgs_nids= # mgs nids in all mgs failover nodes
1166 local ldd_params="$*"
1168 for param in ${ldd_params}; do
1169 if [ -n "`echo ${param}|awk '/mgsnode=/ {print $0}'`" ]; then
1170 mgs_nids=`echo ${param#${PARAM_MGSNODE}}`
1172 if [ -n "${all_mgs_nids}" ]; then
1173 all_mgs_nids=${all_mgs_nids}:${mgs_nids}
1175 all_mgs_nids=${mgs_nids}
1180 [ "${all_mgs_nids}" != "${all_mgs_nids#*,*}" ] \
1181 && echo "\""${all_mgs_nids}"\"" || echo ${all_mgs_nids}
1186 # get_failnids ldd_params
1187 # Get the failover nids of lustre target from @ldd_params
1189 local fail_nids= # failover nids in one failover node
1190 local all_fail_nids= # failover nids in all failover nodes
1193 local ldd_params="$*"
1195 for param in ${ldd_params}; do
1196 if [ -n "`echo ${param}|awk '/failover.node=/ {print $0}'`" ]; then
1197 fail_nids=`echo ${param#${PARAM_FAILNODE}}`
1199 if [ -n "${all_fail_nids}" ]; then
1200 all_fail_nids=${all_fail_nids}:${fail_nids}
1202 all_fail_nids=${fail_nids}
1207 [ "${all_fail_nids}" != "${all_fail_nids#*,*}" ] \
1208 && echo "\""${all_fail_nids}"\"" || echo ${all_fail_nids}
1213 # get_fmtopts target_devname hostname ldd_params
1214 # Get other format options of the lustre target @target_devname from @ldd_params
1216 local target_devname=$1
1220 local ldd_params="$*"
1224 for param in ${ldd_params}; do
1225 [ -n "`echo ${param}|awk '/mgsnode=/ {print $0}'`" ] && continue
1226 [ -n "`echo ${param}|awk '/failover.node=/ {print $0}'`" ] && continue
1228 if [ -n "${param}" ]; then
1229 if [ -n "${fmt_opts}" ]; then
1230 fmt_opts=${fmt_opts}" --param=\""${param}"\""
1232 fmt_opts="--param=\""${param}"\""
1241 # get_stripecount host_name target_fsname
1242 # Get the stripe count for @target_fsname
1245 local target_fsname=$2
1247 local stripecount_file
1250 # Get the stripe count
1251 stripecount_file=${LUSTRE_PROC}/lov/${target_fsname}-mdtlov/stripecount
1252 ret_str=`${REMOTE} ${host_name} "cat ${stripecount_file}" 2>&1`
1253 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1254 echo "`basename $0`: get_stripecount() error:" \
1255 "remote command to ${host_name} error: ${ret_str}"
1260 stripe_count=`echo ${ret_str} | awk '{print $2}'`
1262 stripe_count=`echo ${ret_str} | awk '{print $1}'`
1265 if [ -z "`echo ${stripe_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1267 echo "`basename $0`: get_stripecount() error: can't" \
1268 "get stripe count of ${target_fsname} in ${host_name}!"
1272 echo ${stripe_count}
1276 # get_stripecount_opt host_name target_fsname
1277 # Get the stripe count option for lustre mdt target
1278 get_stripecount_opt() {
1280 local target_fsname=$2
1282 local stripecount_opt=
1284 # Get the stripe count
1285 [ -z "${target_fsname}" ] && target_fsname="lustre"
1286 stripe_count=$(get_stripecount ${host_name} ${target_fsname})
1287 if [ $? -ne 0 ]; then
1288 echo "${stripe_count}"
1292 if [ "${stripe_count}" != "1" ]; then
1293 stripecount_opt=${OPTSTR_STRIPE_COUNT}${stripe_count}
1296 echo ${stripecount_opt}
1301 # Get the lustre target disk data from the node @hostname
1306 local flags mnt_opts params
1307 local stripecount_opt
1309 # Initialize the arrays
1310 unset TARGET_DEVTYPES TARGET_FSNAMES TARGET_MGSNIDS TARGET_INDEXES
1311 unset TARGET_FMTOPTS TARGET_MNTOPTS TARGET_FAILNIDS
1313 # Get lustre target device type, fsname, index, etc.
1314 # from MOUNT_DATA_FILE. Using tunefs.lustre to read it.
1315 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
1320 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
1322 # Execute remote command to read MOUNT_DATA_FILE
1323 while read -r ret_line; do
1332 if [ -n "`echo ${line}|awk '/Index:/ {print $0}'`" ]; then
1333 TARGET_INDEXES[i]=`echo ${line}|awk '{print $2}'`
1337 if [ -n "`echo ${line}|awk '/Lustre FS:/ {print $0}'`" ]; then
1338 TARGET_FSNAMES[i]=`echo ${line}|awk '{print $3}'`
1342 if [ -n "`echo ${line}|awk '/Flags:/ {print $0}'`" ]; then
1343 flags=`echo ${line}|awk '{print $2}'`
1347 if [ -n "`echo ${line}|awk '/Persistent mount opts:/ {print $0}'`" ]; then
1348 mnt_opts=`echo ${line}|awk '{print $0}'`
1349 mnt_opts=`echo ${mnt_opts#Persistent mount opts: }`
1353 if [ -n "`echo ${line}|awk '/Parameters:/ {print $0}'`" ]; then
1354 params=`echo ${line}|awk '{print $0}'`
1355 params=`echo ${params#Parameters:}`
1358 done < <(${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin
1359 ${TUNEFS} --print --verbose ${TARGET_DEVNAMES[i]} 2>/dev/null")
1361 if [ -z "${flags}" ]; then
1362 echo >&2 "`basename $0`: get_ldds() error: Invalid" \
1363 "ldd_flags of target ${TARGET_DEVNAMES[i]}" \
1364 "in host ${host_name} - it's value is null!"\
1365 "Check ${TUNEFS} command!"
1369 if [ "${TARGET_INDEXES[i]}" = "unassigned" ] \
1370 || is_target "mgs" ${flags}; then
1374 [ "${TARGET_FSNAMES[i]}" = "lustre" ] && TARGET_FSNAMES[i]=
1376 # Get the lustre target service type
1377 TARGET_DEVTYPES[i]=$(get_devtype ${flags})
1378 if [ $? -ne 0 ]; then
1379 echo >&2 "${TARGET_DEVTYPES[i]} From device" \
1380 "${TARGET_DEVNAMES[i]} in host ${host_name}!"
1384 # Get the lustre target mount options
1385 TARGET_MNTOPTS[i]=$(get_mntopts "${mnt_opts}")
1387 # Get mgs nids of the lustre target
1388 TARGET_MGSNIDS[i]=$(get_mgsnids "${params}")
1390 # Get failover nids of the lustre target
1391 TARGET_FAILNIDS[i]=$(get_failnids "${params}")
1392 if [ $? -ne 0 ]; then
1393 echo >&2 "${TARGET_FAILNIDS[i]} From device" \
1394 "${TARGET_DEVNAMES[i]} in host ${host_name}!"
1398 # Get other format options of the lustre target
1399 TARGET_FMTOPTS[i]=$(get_fmtopts ${TARGET_DEVNAMES[i]} ${host_name} "${params}")
1400 if [ $? -ne 0 ]; then
1401 echo >&2 "${TARGET_FMTOPTS[i]}"
1405 if [ -n "${TARGET_DEVSIZES[i]}" ]; then
1406 if [ -n "${TARGET_FMTOPTS[i]}" ]; then
1407 TARGET_FMTOPTS[i]="--device-size=${TARGET_DEVSIZES[i]} ""${TARGET_FMTOPTS[i]}"
1409 TARGET_FMTOPTS[i]="--device-size=${TARGET_DEVSIZES[i]}"
1413 if [ -n "${FAILOVER_FMTOPTS[i]}" ]; then
1414 if [ -n "${TARGET_FMTOPTS[i]}" ]; then
1415 TARGET_FMTOPTS[i]=${TARGET_FMTOPTS[i]}" "${FAILOVER_FMTOPTS[i]}
1417 TARGET_FMTOPTS[i]=${FAILOVER_FMTOPTS[i]}
1421 if is_target "mdt" ${flags}; then
1422 # Get the stripe count option
1423 stripecount_opt=$(get_stripecount_opt ${host_name} ${TARGET_FSNAMES[i]})
1424 if [ $? -ne 0 ]; then
1425 echo >&2 "${stripecount_opt}"
1429 if [ -n "${stripecount_opt}" ]; then
1430 if [ -n "${TARGET_FMTOPTS[i]}" ]; then
1431 TARGET_FMTOPTS[i]=${TARGET_FMTOPTS[i]}" "${stripecount_opt}
1433 TARGET_FMTOPTS[i]=${stripecount_opt}
1438 if [ "${TARGET_FMTOPTS[i]}" != "${TARGET_FMTOPTS[i]#*,*}" ]; then
1439 TARGET_FMTOPTS[i]="\""${TARGET_FMTOPTS[i]}"\""
1446 # get_journalsize target_devname hostname
1447 # Get the journal size of lustre target @target_devname from @hostname
1449 local target_devname=$1
1451 local journal_inode=
1455 # Execute remote command to get the journal inode number
1456 ret_str=`${REMOTE} ${host_name} "/sbin/debugfs -R 'stats -h' \
1457 ${target_devname} | grep 'Journal inode:'" 2>&1`
1458 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1459 echo "`basename $0`: get_journalsize() error:" \
1460 "remote command error: ${ret_str}"
1464 ret_str=${ret_str#${ret_str%Journal inode:*}}
1465 journal_inode=`echo ${ret_str} | awk '{print $3}'`
1466 if [ -z "`echo ${journal_inode}|awk '/^[[:digit:]]/ {print $0}'`" ]
1468 echo "`basename $0`: get_journalsize() error: can't" \
1469 "get journal inode of ${target_devname} in ${host_name}!"
1473 # Execute remote command to get the journal size
1474 ret_str=`${REMOTE} ${host_name} "/sbin/debugfs -R \
1475 'stat <${journal_inode}>' ${target_devname}|grep '^User:'" 2>&1`
1476 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1477 echo "`basename $0`: get_journalsize() error:" \
1478 "remote command error: ${ret_str}"
1482 ret_str=${ret_str#${ret_str%User:*}}
1483 journal_size=`echo ${ret_str} | awk '{print $6}'`
1484 if [ -z "`echo ${journal_size}|awk '/^[[:digit:]]/ {print $0}'`" ]
1486 echo "`basename $0`: get_journalsize() error: can't" \
1487 "get journal size of ${target_devname} in ${host_name}!"
1491 let "journal_size /= 1024*1024" # MB
1493 echo ${journal_size}
1497 # get_defaultjournalsize target_devsize
1498 # Calculate the default journal size from target device size @target_devsize
1499 get_defaultjournalsize() {
1500 declare -i target_devsize=$1
1501 declare -i journal_size=0
1502 declare -i max_size base_size
1504 let "base_size = 1024*1024"
1505 if [ ${target_devsize} -gt ${base_size} ]; then # 1GB
1506 let "journal_size = target_devsize / 102400"
1507 let "journal_size *= 4"
1510 let "max_size = 102400 * L_BLOCK_SIZE"
1511 let "max_size >>= 20" # 400MB
1513 if [ ${journal_size} -gt ${max_size} ]; then
1514 let "journal_size = max_size"
1517 echo ${journal_size}
1521 # figure_journal_size target_devname hostname
1522 # Find a reasonable journal file size given the number of blocks
1523 # in the filesystem. This algorithm is derived from figure_journal_size()
1524 # function in util.c of e2fsprogs-1.38.cfs2-1.src.rpm.
1525 figure_journal_size() {
1526 local target_devname=$1
1529 declare -i block_count
1530 declare -i journal_blocks
1531 declare -i journal_size
1533 # Execute remote command to get the block count
1534 ret_str=`${REMOTE} ${host_name} "/sbin/debugfs -R 'stats -h' \
1535 ${target_devname} | grep 'Block count:'" 2>&1`
1536 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1537 echo "`basename $0`: figure_journal_size() error:" \
1538 "remote command error: ${ret_str}"
1542 ret_str=${ret_str#${ret_str%Block count:*}}
1543 block_count=`echo ${ret_str} | awk '{print $3}'`
1544 if [ -z "`echo ${block_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1546 echo "`basename $0`: figure_journal_size() error: can't" \
1547 "get block count of ${target_devname} in ${host_name}!"
1551 if ((block_count < 32768)); then
1552 let "journal_blocks = 1024"
1553 elif ((block_count < 256*1024)); then
1554 let "journal_blocks = 4096"
1555 elif ((block_count < 512*1024)); then
1556 let "journal_blocks = 8192"
1557 elif ((block_count < 1024*1024)); then
1558 let "journal_blocks = 16384"
1560 let "journal_blocks = 32768"
1563 let "journal_size = journal_blocks * L_BLOCK_SIZE / 1048576"
1565 echo ${journal_size}
1569 # get_J_opt hostname target_devname target_devsize
1570 # Get the mkfs -J option of lustre target @target_devname
1571 # from the node @hostname
1574 local target_devname=$2
1575 local target_devsize=$3
1577 local default_journal_size=
1580 # Get the real journal size of lustre target
1581 journal_size=$(get_journalsize ${target_devname} ${host_name})
1582 if [ $? -ne 0 ]; then
1583 echo "${journal_size}"
1587 # Get the default journal size of lustre target
1588 default_journal_size=$(get_defaultjournalsize ${target_devsize})
1589 if [ "${default_journal_size}" = "0" ]; then
1590 default_journal_size=$(figure_journal_size ${target_devname} \
1592 if [ $? -ne 0 ]; then
1593 echo "${default_journal_size}"
1598 if [ "${journal_size}" != "${default_journal_size}" ]; then
1599 journal_opt="-J size=${journal_size}"
1606 # get_ratio target_devname hostname
1607 # Get the bytes/inode ratio of lustre target @target_devname from @hostname
1609 local target_devname=$1
1616 # Execute remote command to get the inode count
1617 ret_str=`${REMOTE} ${host_name} "/sbin/debugfs -R 'stats -h' \
1618 ${target_devname} | grep 'Inode count:'" 2>&1`
1619 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1620 echo "`basename $0`: get_ratio() error:" \
1621 "remote command error: ${ret_str}"
1625 ret_str=${ret_str#${ret_str%Inode count:*}}
1626 inode_count=`echo ${ret_str} | awk '{print $3}'`
1627 if [ -z "`echo ${inode_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1629 echo "`basename $0`: get_ratio() error: can't" \
1630 "get inode count of ${target_devname} in ${host_name}!"
1634 # Execute remote command to get the block count
1635 ret_str=`${REMOTE} ${host_name} "/sbin/debugfs -R 'stats -h' \
1636 ${target_devname} | grep 'Block count:'" 2>&1`
1637 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1638 echo "`basename $0`: get_ratio() error:" \
1639 "remote command error: ${ret_str}"
1643 ret_str=${ret_str#${ret_str%Block count:*}}
1644 block_count=`echo ${ret_str} | awk '{print $3}'`
1645 if [ -z "`echo ${block_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1647 echo "`basename $0`: get_ratio() error: can't" \
1648 "get block count of ${target_devname} in ${host_name}!"
1652 let "ratio = block_count*L_BLOCK_SIZE/inode_count"
1658 # get_default_ratio target_devtype target_devsize
1659 # Calculate the default bytes/inode ratio from target type @target_devtype
1660 get_default_ratio() {
1661 local target_devtype=$1
1662 declare -i target_devsize=$2
1665 case "${target_devtype}" in
1666 "mdt" | "mgs|mdt" | "mdt|mgs")
1669 [ ${target_devsize} -gt 1000000 ] && ratio=16384;;
1672 [ -z "${ratio}" ] && ratio=${L_BLOCK_SIZE}
1678 # get_i_opt hostname target_devname target_devtype target_devsize
1679 # Get the mkfs -i option of lustre target @target_devname
1680 # from the node @hostname
1683 local target_devname=$2
1684 local target_devtype=$3
1685 local target_devsize=$4
1687 local default_ratio=
1690 # Get the real bytes/inode ratio of lustre target
1691 ratio=$(get_ratio ${target_devname} ${host_name})
1692 if [ $? -ne 0 ]; then
1697 # Get the default bytes/inode ratio of lustre target
1698 default_ratio=$(get_default_ratio ${target_devtype} ${target_devsize})
1700 if [ "${ratio}" != "${default_ratio}" ]; then
1701 ratio_opt="-i ${ratio}"
1708 # get_isize target_devname hostname
1709 # Get the inode size of lustre target @target_devname from @hostname
1711 local target_devname=$1
1716 # Execute remote command to get the inode size
1717 ret_str=`${REMOTE} ${host_name} "/sbin/debugfs -R 'stats -h' \
1718 ${target_devname} | grep 'Inode size:'" 2>&1`
1719 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1720 echo "`basename $0`: get_isize() error:" \
1721 "remote command error: ${ret_str}"
1725 ret_str=${ret_str#${ret_str%Inode size:*}}
1726 inode_size=`echo ${ret_str} | awk '{print $3}'`
1727 if [ -z "`echo ${inode_size}|awk '/^[[:digit:]]/ {print $0}'`" ]
1729 echo "`basename $0`: get_isize() error: can't" \
1730 "get inode size of ${target_devname} in ${host_name}!"
1738 # get_mdt_default_isize host_name target_fsname
1739 # Calculate the default inode size of lustre mdt target
1740 get_mdt_default_isize() {
1742 local target_fsname=$2
1743 declare -i stripe_count
1746 # Get the stripe count
1747 stripe_count=$(get_stripecount ${host_name} ${target_fsname})
1748 if [ $? -ne 0 ]; then
1749 echo "${stripe_count}"
1753 if ((stripe_count > 77)); then
1755 elif ((stripe_count > 34)); then
1757 elif ((stripe_count > 13)); then
1767 # get_default_isize host_name target_devtype target_fsname
1768 # Calculate the default inode size of lustre target type @target_devtype
1769 get_default_isize() {
1771 local target_devtype=$2
1772 local target_fsname=$3
1775 case "${target_devtype}" in
1776 "mdt" | "mgs|mdt" | "mdt|mgs")
1777 inode_size=$(get_mdt_default_isize ${host_name} ${target_fsname})
1778 if [ $? -ne 0 ]; then
1779 echo "${inode_size}"
1787 [ -z "${inode_size}" ] && inode_size=128
1793 # get_I_opt hostname target_devname target_devtype target_fsname
1794 # Get the mkfs -I option of lustre target @target_devname
1795 # from the node @hostname
1798 local target_devname=$2
1799 local target_devtype=$3
1800 local target_fsname=$4
1802 local default_isize=
1805 # Get the real inode size of lustre target
1806 isize=$(get_isize ${target_devname} ${host_name})
1807 if [ $? -ne 0 ]; then
1812 # Get the default inode size of lustre target
1813 [ -z "${target_fsname}" ] && target_fsname="lustre"
1814 default_isize=$(get_default_isize ${host_name} ${target_devtype} \
1816 if [ $? -ne 0 ]; then
1817 echo "${default_isize}"
1821 if [ "${isize}" != "${default_isize}" ]; then
1822 isize_opt="-I ${isize}"
1829 # get_mkfsopts hostname
1830 # Get the mkfs options of lustre targets from the node @hostname
1836 local inode_size_opt
1838 # Initialize the arrays
1839 unset TARGET_MKFSOPTS
1841 # FIXME: Get other mkfs options of ext3/ldiskfs besides -J, -i and -I
1842 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
1847 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
1849 if [ -z "${TARGET_DEVSIZES[i]}" ]; then
1850 # Get the device size
1851 TARGET_DEVSIZES[i]=$(get_devsize ${host_name} \
1852 ${TARGET_DEVNAMES[i]})
1853 if [ $? -ne 0 ]; then
1854 echo >&2 "${TARGET_DEVSIZES[i]}"
1859 # Get the journal option
1860 journal_opt=$(get_J_opt ${host_name} ${TARGET_DEVNAMES[i]} \
1861 ${TARGET_DEVSIZES[i]})
1862 if [ $? -ne 0 ]; then
1863 echo >&2 "${journal_opt}"
1867 if [ -n "${journal_opt}" ]; then
1868 if [ -z "${TARGET_MKFSOPTS[i]}" ]; then
1869 TARGET_MKFSOPTS[i]="${journal_opt}"
1871 TARGET_MKFSOPTS[i]=${TARGET_MKFSOPTS[i]}" ${journal_opt}"
1875 # Get the bytes-per-inode ratio option
1876 ratio_opt=$(get_i_opt ${host_name} ${TARGET_DEVNAMES[i]} \
1877 ${TARGET_DEVTYPES[i]} ${TARGET_DEVSIZES[i]})
1878 if [ $? -ne 0 ]; then
1879 echo >&2 "${ratio_opt}"
1883 if [ -n "${ratio_opt}" ]; then
1884 if [ -z "${TARGET_MKFSOPTS[i]}" ]; then
1885 TARGET_MKFSOPTS[i]="${ratio_opt}"
1887 TARGET_MKFSOPTS[i]=${TARGET_MKFSOPTS[i]}" ${ratio_opt}"
1891 # Get the inode size option
1892 inode_size_opt=$(get_I_opt ${host_name} ${TARGET_DEVNAMES[i]} \
1893 ${TARGET_DEVTYPES[i]} ${TARGET_FSNAMES[i]})
1894 if [ $? -ne 0 ]; then
1895 echo >&2 "${inode_size_opt}"
1899 if [ -n "${inode_size_opt}" ]; then
1900 if [ -z "${TARGET_MKFSOPTS[i]}" ]; then
1901 TARGET_MKFSOPTS[i]="${inode_size_opt}"
1903 TARGET_MKFSOPTS[i]=${TARGET_MKFSOPTS[i]}" ${inode_size_opt}"
1907 if [ "${TARGET_MKFSOPTS[i]}" != "${TARGET_MKFSOPTS[i]#*,*}" ]; then
1908 TARGET_MKFSOPTS[i]="\""${TARGET_MKFSOPTS[i]}"\""
1914 # get_target_configs hostname
1915 # Get the lustre target informations from the node @hostname
1916 get_target_configs() {
1921 # Initialize the arrays
1922 unset TARGET_CONFIGS
1924 # Get lustre target server names
1925 if ! get_svnames ${host_name}; then
1929 # Get lustre target device names, mount points and loop device sizes
1930 if ! get_devnames ${host_name}; then
1934 # Get lustre target device type, fsname, index, etc.
1935 if ! get_ldds ${host_name}; then
1939 # Get mkfs options of lustre targets
1940 if ! get_mkfsopts ${host_name}; then
1944 # Construct lustre target configs
1945 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
1946 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
1947 TARGET_CONFIGS[i]=${TARGET_DEVNAMES[i]},${TARGET_MNTPNTS[i]},${TARGET_DEVTYPES[i]},${TARGET_FSNAMES[i]},${TARGET_MGSNIDS[i]},${TARGET_INDEXES[i]},${TARGET_FMTOPTS[i]},${TARGET_MKFSOPTS[i]},${TARGET_MNTOPTS[i]},${TARGET_FAILNIDS[i]}
1953 # get_configs hostname
1954 # Get all the informations needed to generate a csv file from
1955 # the node @hostname
1957 # Check the hostname
1958 if [ -z "$1" ]; then
1959 echo >&2 "`basename $0`: get_configs() error:" \
1964 # Get network module options
1966 verbose_output "Collecting network module options from host $1..."
1967 if ! get_module_opts $1; then
1972 # Get lustre target informations
1973 verbose_output "Collecting Lustre targets informations from host $1..."
1974 if ! get_target_configs $1; then
1979 # Get HA software configurations
1980 if ! get_ha_configs $1; then
1987 # Collect linux MD/LVM device informations from the lustre cluster and
1988 # append them to the csv file
1994 # Collect and append linux MD/LVM informations to the csv file
1995 for ((idx = 0; idx < ${#HOST_NAMES[@]}; idx++)); do
1996 [ -z "${HOST_NAMES[idx]}" ] && continue
1998 # Collect MD device informations
1999 ! get_md_configs ${HOST_NAMES[idx]} && return 1
2001 # Append MD device informations to the csv file
2002 for ((i = 0; i < ${#MD_NAME[@]}; i++)); do
2003 line=${HOST_NAMES[idx]},${MD_MARKER},${MD_NAME[i]},,,${MD_LEVEL[i]},${MD_DEVS[i]}
2004 verbose_output "Informations of MD device ${MD_NAME[i]}" \
2005 "in host ${HOST_NAMES[idx]} are as follows:"
2006 verbose_output "${line}"
2007 echo "${line}" >> ${LUSTRE_CSV_FILE}
2010 # Collect PV informations
2011 ! get_pv_configs ${HOST_NAMES[idx]} && return 1
2013 # Append PV informations to the csv file
2014 if [ -n "${PV_NAMES}" ]; then
2015 line=${HOST_NAMES[idx]},${PV_MARKER},${PV_NAMES}
2016 verbose_output "Informations of PVs" \
2017 "in host ${HOST_NAMES[idx]} are as follows:"
2018 verbose_output "${line}"
2019 echo "${line}" >> ${LUSTRE_CSV_FILE}
2022 # Collect VG informations
2023 ! get_vg_configs ${HOST_NAMES[idx]} && return 1
2025 # Append VG informations to the csv file
2026 for ((i = 0; i < ${#VG_NAME[@]}; i++)); do
2027 line=${HOST_NAMES[idx]},${VG_MARKER},${VG_NAME[i]},,,${VG_PVNAMES[i]}
2028 verbose_output "Informations of VG ${VG_NAME[i]}" \
2029 "in host ${HOST_NAMES[idx]} are as follows:"
2030 verbose_output "${line}"
2031 echo "${line}" >> ${LUSTRE_CSV_FILE}
2034 # Collect LV informations
2035 ! get_lv_configs ${HOST_NAMES[idx]} && return 1
2037 # Append LV informations to the csv file
2038 for ((i = 0; i < ${#LV_NAME[@]}; i++)); do
2039 line=${HOST_NAMES[idx]},${LV_MARKER},${LV_NAME[i]},,,${LV_SIZE[i]},${LV_VGNAME[i]}
2040 verbose_output "Informations of LV /dev/${LV_VGNAME[i]}/${LV_NAME[i]}"\
2041 "in host ${HOST_NAMES[idx]} are as follows:"
2042 verbose_output "${line}"
2043 echo "${line}" >> ${LUSTRE_CSV_FILE}
2049 # Generate the csv file from the lustre cluster
2055 # Get lustre cluster node names
2056 verbose_output "Collecting Lustre cluster node names..."
2057 if ! get_hostnames; then
2062 : > ${LUSTRE_CSV_FILE}
2064 ${GET_MDLVM_INFO} && get_mdlvm_info
2066 # Collect and append lustre target informations to the csv file
2067 for ((idx = 0; idx < ${#HOST_NAMES[@]}; idx++)); do
2068 # Collect informations
2069 if ! get_configs ${HOST_NAMES[idx]}; then
2070 rm -f ${LUSTRE_CSV_FILE}
2074 # Append informations to the csv file
2075 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
2076 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
2078 if [ -z "${HA_CONFIGS[i]}" ]; then
2079 line=${HOST_NAMES[idx]},${MODULE_OPTS},${TARGET_CONFIGS[i]}
2081 line=${HOST_NAMES[idx]},${MODULE_OPTS},${TARGET_CONFIGS[i]},${HA_CONFIGS[i]}
2083 verbose_output "Informations of target ${TARGET_DEVNAMES[i]}" \
2084 "in host ${HOST_NAMES[idx]} are as follows:"
2085 verbose_output "${line}"
2086 echo "" >> ${LUSTRE_CSV_FILE}
2087 echo "${line}" >> ${LUSTRE_CSV_FILE}
2095 echo "`basename $0`: ******** Generate csv file -- ${LUSTRE_CSV_FILE} START ********"
2096 if ! gen_csvfile; then
2099 echo "`basename $0`: ******** Generate csv file -- ${LUSTRE_CSV_FILE} OK **********"