3 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
6 # lustre_createcsv - generate a csv file from a running lustre cluster
8 # This script is used to collect lustre target informations, linux MD/LVM device
9 # informations and HA software configurations in a lustre cluster to generate a
10 # csv file. In reverse, the csv file could be parsed by lustre_config to
11 # configure multiple lustre servers in parallel.
13 # This script should be run on the MGS node.
15 ################################################################################
21 Usage: `basename $0` [-t HAtype] [-d] [-h] [-v] [-f csv_filename]
23 This script is used to collect lustre target informations, linux MD/LVM
24 device informations and HA software configurations from a running lustre
25 cluster to generate a csv file. It should be run on the MGS node.
27 -t HAtype collect High-Availability software configurations
28 The argument following -t is used to indicate the High-
29 Availability software type. The HA software types which
30 are currently supported are: hbv1 (Heartbeat version 1)
31 and hbv2 (Heartbeat version 2).
32 -d collect linux MD/LVM device informations
35 -f csv_filename designate a name for the csv file
36 Default is lustre_config.csv.
41 # Get the library of functions
42 . @scriptlibdir@/lc_common
44 #**************************** Global variables ****************************#
46 LUSTRE_CSV_FILE=${LUSTRE_CSV_FILE:-"lustre_config.csv"}
49 LUSTRE_PROC=${LUSTRE_PROC:-"/proc/fs/lustre"}
50 LUSTRE_PROC_DEVICES=${LUSTRE_PROC}/devices
52 LNET_PROC=${LNET_PROC:-"/proc/sys/lnet"}
53 LNET_PROC_PEERS=${LNET_PROC}/peers
55 # Default network module options
56 DEFAULT_MOD_OPTS=${DEFAULT_MOD_OPTS:-"options lnet networks=tcp"}
58 # Lustre target obd device types
59 MGS_TYPE=${MGS_TYPE:-"mgs"}
60 MDT_TYPE=${MDT_TYPE:-"mds"}
61 OST_TYPE=${OST_TYPE:-"obdfilter"}
63 # The obd name of MGS target server
64 MGS_SVNAME=${MGS_SVNAME:-"MGS"}
66 # Hostnames of the lustre cluster nodes
68 MGS_HOSTNAME=${MGS_HOSTNAME:-"`hostname`"} # Hostname of the MGS node
70 # Configs of lustre targets in one cluster node
71 declare -a TARGET_CONFIGS
72 declare -a TARGET_SVNAMES TARGET_DEVNAMES TARGET_DEVSIZES TARGET_MNTPNTS
73 declare -a TARGET_DEVTYPES TARGET_FSNAMES TARGET_MGSNIDS TARGET_INDEXES
74 declare -a TARGET_FMTOPTS TARGET_MKFSOPTS TARGET_MNTOPTS TARGET_FAILNIDS
76 declare -a ALL_TARGET_SVNAMES # All the target services in the cluster
77 declare -a FAILOVER_FMTOPTS # "--noformat"
79 # Informations of linux MD/LVM devices in one cluster node
80 declare -a MD_NAME MD_LEVEL MD_DEVS # MD
81 declare -a VG_NAME VG_PVNAMES # VG
82 declare -a LV_NAME LV_SIZE LV_VGNAME # LV
84 # Lustre target service types
85 let "LDD_F_SV_TYPE_MDT = 0x0001"
86 let "LDD_F_SV_TYPE_OST = 0x0002"
87 let "LDD_F_SV_TYPE_MGS = 0x0004"
89 # Permanent mount options for ext3 or ldiskfs
90 ALWAYS_MNTOPTS=${ALWAYS_MNTOPTS:-"errors=remount-ro"}
91 MDT_MGS_ALWAYS_MNTOPTS=${MDT_MGS_ALWAYS_MNTOPTS:-",iopen_nopriv,user_xattr"}
92 OST_ALWAYS_MNTOPTS=${OST_ALWAYS_MNTOPTS:-",asyncdel"}
93 OST_DEFAULT_MNTOPTS=${OST_DEFAULT_MNTOPTS:-",extents,mballoc"}
95 # User-settable parameter keys
96 PARAM_MGSNODE=${PARAM_MGSNODE:-"mgsnode="}
97 PARAM_FAILNODE=${PARAM_FAILNODE:-"failover.node="}
102 # Option string of mkfs.lustre
103 OPTSTR_STRIPE_COUNT=${OPTSTR_STRIPE_COUNT:-"--stripe-count-hint="}
106 # Get and check the positional parameters
109 while getopts "t:dhvf:" OPTION; do
113 if [ "${HATYPE_OPT}" != "${HBVER_HBV1}" ] \
114 && [ "${HATYPE_OPT}" != "${HBVER_HBV2}" ] \
115 && [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" ]; then
116 error_output "Invalid HA software type" \
122 d) GET_MDLVM_INFO=true;;
124 v) VERBOSE_OUTPUT=true;;
125 f) LUSTRE_CSV_FILE=$OPTARG;;
126 ?) usage 1>&2 && exit 1;;
130 # Verify the local host is the MGS node
132 if [ ! -e ${LUSTRE_PROC_DEVICES} ]; then
133 error_output "${LUSTRE_PROC_DEVICES} does" \
134 "not exist. Lustre kernel modules may not be loaded!"
138 if [ -z "`cat ${LUSTRE_PROC_DEVICES}`" ]; then
139 error_output "${LUSTRE_PROC_DEVICES} is" \
140 "empty. Lustre services may not be started!"
144 if [ -z "`grep ${MGS_TYPE} ${LUSTRE_PROC_DEVICES}`" ]; then
145 error_output "This node is not a MGS node." \
146 "The script should be run on the MGS node!"
154 # Get lustre cluster node names
157 declare -i idx # Index of HOST_NIDS array
158 declare -i i # Index of HOST_NAMES array
164 if [ ! -e ${LNET_PROC_PEERS} ]; then
165 error_output "${LNET_PROC_PEERS} does not" \
166 "exist. LNET kernel modules may not be loaded" \
167 "or LNET network may not be up!"
171 HOST_NAMES[0]=${MGS_HOSTNAME} # MGS node
172 HOST_NIDS[0]=${HOST_NAMES[0]}
174 # Get the nids of the nodes which have contacted MGS
176 for nid in `cat ${LNET_PROC_PEERS} | awk '{print $1}'`; do
177 if [ "${nid}" = "nid" ]; then
181 HOST_NIDS[idx]=${nid}
185 if [ ${idx} -eq 1 ]; then
186 verbose_output "Only one node running in the lustre cluster." \
187 "It's ${HOST_NAMES[0]}."
191 # Get the hostnames of the nodes
192 for ((idx = 1, i = 1; idx < ${#HOST_NIDS[@]}; idx++, i++)); do
193 if [ -z "${HOST_NIDS[idx]}" ]; then
194 error_output "get_hostnames():" \
195 "Invalid nid - \"${HOST_NIDS[idx]}\"!"
199 HOST_NAMES[i]=$(nid2hostname ${HOST_NIDS[idx]})
200 if [ $? -ne 0 ]; then
201 error_output "${HOST_NAMES[i]}"
205 if [ "${HOST_NAMES[i]}" = "${HOST_NAMES[0]}" ]; then
214 #********************** Linux MD/LVM device informations **********************#
215 # get_md_configs hostname
216 # Get all the active MD device informations from the node @hostname
221 local ret_line line first_item
223 # Initialize the arrays
228 # Execute remote command to the node ${host_name} and get all the
229 # active MD device informations.
230 while read -r ret_line; do
239 first_item=`echo "${line}" | awk '{print $1}'`
241 # Get the MD device name and raid level
242 if [ "${first_item}" = "ARRAY" ]; then
243 MD_NAME[i]=`echo "${line}" | awk '{print $2}'`
244 MD_LEVEL[i]=`echo "${line}" | awk '{print $3}' | sed -e 's/level=//'`
249 # Get the MD component devices
250 if [ "${first_item}" != "${first_item#devices=}" ]; then
251 MD_DEVS[j]=`echo "${line}" | sed -e 's/devices=//' -e 's/,/ /g'`
253 done < <(${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin
254 ${MDADM} --detail --scan --verbose")
256 if [ $i -eq 0 ]; then
257 verbose_output "There are no active MD devices" \
258 "in the host ${host_name}!"
264 # get_pv_configs hostname
265 # Get all the LVM PV informations from the node @hostname
271 # Execute remote command to get all the PV informations.
272 cmd="PATH=\$PATH:/sbin:/usr/sbin \
273 pvdisplay -c | awk -F: '{print \$1}' | xargs"
274 ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
275 if [ $? -ne 0 ]; then
276 if [ -n "${ret_str}" ]; then
277 error_output "get_pv_configs():" \
278 "remote command to ${host_name} error: ${ret_str}"
280 remote_error "get_pv_configs" ${host_name}
285 PV_NAMES=`echo "${ret_str}" | sed -e 's/^'${host_name}':[[:space:]]//'`
286 if [ -z "${PV_NAMES}" ]; then
287 verbose_output "There are no PVs in the host ${host_name}!"
294 # get_vg_pvnames hostname vgname
295 # Get the PVs contained in @vgname from the node @hostname
302 # Execute remote command to get the PV names.
303 cmd="PATH=\$PATH:/sbin:/usr/sbin vgdisplay -v ${vg_name} 2>/dev/null\
304 | grep \"PV Name\" | awk '{print \$3}' | xargs"
305 ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
306 if [ $? -ne 0 ]; then
307 if [ -n "${ret_str}" ]; then
308 echo "`basename $0`: get_vg_pvnames() error:" \
309 "remote command to ${host_name} error: ${ret_str}"
311 remote_error "get_vg_pvnames" ${host_name}
316 pv_names=`echo "${ret_str}" | sed -e 's/^'${host_name}':[[:space:]]//'`
317 if [ -z "${pv_names}" ]; then
318 echo "`basename $0`: get_vg_pvnames() error:" \
319 "There are no PVs in VG ${vg_name} in the host ${host_name}!"\
320 "Or VG ${vg_name} does not exist."
328 # get_vg_configs hostname
329 # Get all the LVM VG informations from the node @hostname
336 # Initialize the arrays
340 # Execute remote command to get all the VG names.
341 cmd="PATH=\$PATH:/sbin:/usr/sbin vgdisplay \
342 | grep \"VG Name\" | awk '{print \$3}' | xargs"
343 ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`
344 if [ $? -ne 0 ]; then
345 if [ -n "${ret_str}" ]; then
346 error_output "get_vg_configs():" \
347 "remote command to ${host_name} error: ${ret_str}"
349 remote_error "get_vg_configs" ${host_name}
354 if [ -z "${ret_str}" ] \
355 || [ "${ret_str}" != "${ret_str#*No volume groups found*}" ]; then
356 verbose_output "There are no VGs in the host ${host_name}!"
360 # Get all the VG informations
361 for vg_name in `echo "${ret_str}" | sed -e 's/^'${host_name}'://'`; do
362 VG_NAME[i]=${vg_name}
363 VG_PVNAMES[i]=$(get_vg_pvnames ${host_name} ${VG_NAME[i]})
364 if [ $? -ne 0 ]; then
365 error_output "${VG_PVNAMES[i]}"
374 # get_lv_configs hostname
375 # Get all the LVM LV informations from the node @hostname
381 # Initialize the arrays
386 # Execute remote command to get all the LV informations.
387 while read -r ret_line; do
396 [ "${line}" != "${line#*volume group*}" ] && break
398 LV_NAME[i]=`echo "${line}" | awk -F: '{print $1}' | sed -e 's/.*\///g'`
399 LV_VGNAME[i]=`echo "${line}" | awk -F: '{print $2}'`
400 LV_SIZE[i]=`echo "${line}" | awk -F: '{print $7}' | sed -e 's/.*/&K/'`
403 done < <(${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin lvdisplay -c")
405 if [ $i -eq 0 ]; then
406 verbose_output "There are no LVs in the host ${host_name}"
412 #*************************** Network module options ***************************#
413 # last_is_backslash line
414 # Check whether the last effective letter of @line is a backslash
415 last_is_backslash() {
419 local letter last_letter
422 for ((i = ${length}-1; i >= 0; i--)); do
423 letter=${line:${i}:1}
424 [ "x${letter}" != "x " -a "x${letter}" != "x " -a -n "${letter}" ]\
425 && last_letter=${letter} && break
428 [ "x${last_letter}" = "x\\" ] && return 0
433 # get_module_opts hostname
434 # Get the network module options from the node @hostname
438 local MODULE_CONF KERNEL_VER
439 local ret_line line find_options
442 MODULE_OPTS=${DEFAULT_MOD_OPTS}
444 # Execute remote command to get the kernel version
445 ret_str=`${REMOTE} ${host_name} "uname -r" 2>&1`
446 if [ $? -ne 0 -a -n "${ret_str}" ]; then
447 error_output "get_module_opts():" \
448 "remote command error: ${ret_str}"
451 remote_error "get_module_opts" ${host_name} "${ret_str}" && return 1
454 KERNEL_VER=`echo ${ret_str} | awk '{print $2}'`
456 KERNEL_VER=`echo ${ret_str} | awk '{print $1}'`
459 # Get the module configuration file name
460 if [ "${KERNEL_VER:0:3}" = "2.4" ]; then
461 MODULE_CONF=/etc/modules.conf
463 MODULE_CONF=/etc/modprobe.conf
466 # Execute remote command to get the lustre network module options
469 while read -r ret_line; do
478 # Get rid of the comment line
479 [ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue
481 if [ "${line}" != "${line#*options lnet*}" ]; then
482 if ! ${find_options}; then
486 MODULE_OPTS=${MODULE_OPTS}$" \n "${line}
489 last_is_backslash "${line}" && continue_flag=true \
490 || continue_flag=false
494 if ${continue_flag}; then
495 MODULE_OPTS=${MODULE_OPTS}$" \n "${line}
496 ! last_is_backslash "${line}" && continue_flag=false
499 done < <(${REMOTE} ${host_name} "cat ${MODULE_CONF}")
501 if [ -z "${MODULE_OPTS}" ]; then
502 MODULE_OPTS=${DEFAULT_MOD_OPTS}
508 #************************ HA software configurations ************************#
509 # is_ha_target hostname target_devname
510 # Check whether the target @target_devname was made to be high-available
513 local target_svname=$2
517 case "${HATYPE_OPT}" in
518 "${HBVER_HBV1}") res_file=${HA_RES};;
519 "${HBVER_HBV2}") res_file=${HA_CIB};;
520 "${HATYPE_CLUMGR}") res_file=${CLUMAN_CONFIG};;
523 # Execute remote command to check the resource file
524 ret_str=`${REMOTE} ${host_name} \
525 "grep ${target_svname} ${res_file}" 2>&1`
526 if [ $? -ne 0 -a -n "${ret_str}" ]; then
527 error_output "is_ha_target():" \
528 "remote command error: ${ret_str}"
532 [ "${ret_str}" = "${ret_str#*${target_svname}*}" ] && return 1
537 # get_hb_configs hostname
538 # Get the Heartbeat configurations from the node @hostname
549 # Execute remote command to get the configs of Heartbeat channels, etc
550 while read -r ret_line; do
559 # Get rid of the comment line
560 [ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue
562 if [ "${line}" != "${line#*serial*}" ] \
563 || [ "${line}" != "${line#*cast*}" ]; then
564 if [ -z "${HB_CHANNELS}" ]; then
567 HB_CHANNELS=${HB_CHANNELS}:${line}
571 if [ "${line}" != "${line#*stonith*}" ] \
572 || [ "${line}" != "${line#*ping*}" ] \
573 || [ "${line}" != "${line#*respawn*}" ] \
574 || [ "${line}" != "${line#*apiauth*}" ] \
575 || [ "${line}" != "${line#*compression*}" ]; then
576 if [ -z "${HB_OPTIONS}" ]; then
579 HB_OPTIONS=${HB_OPTIONS}:${line}
582 done < <(${REMOTE} ${host_name} "cat ${HA_CF}")
584 if [ -z "${HB_CHANNELS}" ]; then
585 error_output "get_hb_configs():" \
586 "There are no heartbeat channel configs in ${HA_CF}" \
587 "of host ${host_name} or ${HA_CF} does not exist!"
591 # Execute remote command to get Heartbeat service address
592 if [ "${HATYPE_OPT}" = "${HBVER_HBV1}" ]; then
593 while read -r ret_line; do
602 # Get rid of the empty line
603 [ -z "`echo ${line}|awk '/[[:alnum:]]/ {print $0}'`" ]\
606 # Get rid of the comment line
607 [ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue
609 SRV_IPADDRS=`echo ${line} | awk '{print $2}'`
610 [ -n "${SRV_IPADDRS}" ] \
611 && [ "`echo ${line} | awk '{print $1}'`" = "${host_name}" ] && break
612 done < <(${REMOTE} ${host_name} "cat ${HA_RES}")
614 if [ -z "${SRV_IPADDRS}" ]; then
615 error_output "get_hb_configs(): There"\
616 "are no service address in ${HA_RES} of host"\
617 "${host_name} or ${HA_RES} does not exist!"
622 # Construct HA configuration items
623 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
624 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
626 # Execute remote command to check whether this target service
627 # was made to be high-available
628 if is_ha_target ${host_name} ${TARGET_DEVNAMES[i]}; then
629 HA_CONFIGS[i]=${HB_CHANNELS},${SRV_IPADDRS},${HB_OPTIONS}
636 # get_cluman_channel hostname
637 # Get the Heartbeat channel of CluManager from the node @hostname
638 get_cluman_channel() {
641 local cluman_channel=
644 while read -r ret_line; do
653 if [ "${line}" != "${line#*broadcast*}" ] \
654 && [ "`echo ${line}|awk '{print $3}'`" = "yes" ]; then
655 cluman_channel="broadcast"
659 if [ "${line}" != "${line#*multicast_ipaddress*}" ]; then
660 mcast_ipaddr=`echo ${line}|awk '{print $3}'`
661 if [ "${mcast_ipaddr}" != "225.0.0.11" ]; then
662 cluman_channel="multicast ${mcast_ipaddr}"
666 done < <(${REMOTE} ${host_name} "${CONFIG_CMD} --clumembd")
668 echo ${cluman_channel}
672 # get_cluman_srvaddr hostname target_svname
673 # Get the service IP addresses of @target_svname from the node @hostname
674 get_cluman_srvaddr() {
676 local target_svname=$2
678 local srvaddr cluman_srvaddr=
680 while read -r ret_line; do
689 if [ "${line}" != "${line#*ipaddress = *}" ]; then
690 srvaddr=`echo ${line}|awk '{print $3}'`
691 if [ -z "${cluman_srvaddr}" ]; then
692 cluman_srvaddr=${srvaddr}
694 cluman_srvaddr=${cluman_srvaddr}:${srvaddr}
697 done < <(${REMOTE} ${host_name} "${CONFIG_CMD} \
698 --service=${target_svname} --service_ipaddresses")
700 if [ -z "${cluman_srvaddr}" ]; then
701 echo "`basename $0`: get_cluman_srvaddr() error: Cannot" \
702 "get the service IP addresses of ${target_svname} in" \
703 "${host_name}! Check ${CONFIG_CMD} command!"
707 echo ${cluman_srvaddr}
711 # get_cluman_configs hostname
712 # Get the CluManager configurations from the node @hostname
713 get_cluman_configs() {
720 # Execute remote command to get the configs of CluManager
721 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
725 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
727 # Execute remote command to check whether this target service
728 # was made to be high-available
729 ! is_ha_target ${host_name} ${TARGET_DEVNAMES[i]} && continue
731 # Execute remote command to get Heartbeat channel
732 HB_CHANNELS=$(get_cluman_channel ${host_name})
733 if [ $? -ne 0 ]; then
734 error_output "${HB_CHANNELS}"
737 # Execute remote command to get service IP address
738 SRV_IPADDRS=$(get_cluman_srvaddr ${host_name} \
739 ${TARGET_SVNAMES[i]})
740 if [ $? -ne 0 ]; then
741 error_output "${SRV_IPADDRS}"
745 HA_CONFIGS[i]=${HB_CHANNELS},${SRV_IPADDRS},${HB_OPTIONS}
751 # get_ha_configs hostname
752 # Get the HA software configurations from the node @hostname
758 if [ -z "${HATYPE_OPT}" ]; then
762 verbose_output "Collecting HA software configurations from host $1..."
764 case "${HATYPE_OPT}" in
765 "${HBVER_HBV1}" | "${HBVER_HBV2}") # Heartbeat
766 if ! get_hb_configs ${host_name}; then
770 "${HATYPE_CLUMGR}") # CluManager
771 if ! get_cluman_configs ${host_name}; then
780 #*********************** Lustre targets configurations ***********************#
782 # is_failover_service target_svname
783 # Check whether a target service @target_svname is a failover service.
784 is_failover_service() {
785 local target_svname=$1
788 for ((i = 0; i < ${#ALL_TARGET_SVNAMES[@]}; i++)); do
789 [ "${target_svname}" = "${ALL_TARGET_SVNAMES[i]}" ] && return 0
795 # get_svnames hostname
796 # Get the lustre target server obd names from the node @hostname
803 # Initialize the TARGET_SVNAMES array
805 unset FAILOVER_FMTOPTS
807 # Execute remote command to the node @hostname and figure out what
808 # lustre services are running.
810 j=${#ALL_TARGET_SVNAMES[@]}
811 while read -r ret_line; do
820 if [ -z "`echo ${line} | grep ${MGS_TYPE}`" ] \
821 && [ -z "`echo ${line} | grep ${MDT_TYPE}`" ] \
822 && [ -z "`echo ${line} | grep ${OST_TYPE}`" ]; then
826 # Get target server name
827 TARGET_SVNAMES[i]=`echo ${line} | awk '{print $4}'`
828 if [ -n "${TARGET_SVNAMES[i]}" ]; then
829 if is_failover_service ${TARGET_SVNAMES[i]}; then
830 FAILOVER_FMTOPTS[i]="--noformat"
832 ALL_TARGET_SVNAMES[j]=${TARGET_SVNAMES[i]}
836 error_output "get_svnames(): Invalid"\
837 "line in ${host_name}'s ${LUSTRE_PROC_DEVICES}"\
841 done < <(${REMOTE} ${host_name} "cat ${LUSTRE_PROC_DEVICES}")
843 if [ $i -eq 0 ]; then
844 verbose_output "There are no lustre services running" \
845 "on the node ${host_name}!"
852 # Check whether a device @devname is a loop device or not
856 if [ -z "${devname}" ] || \
857 [ -z "`echo ${devname}|awk '/\/dev\/loop[[:digit:]]/ {print $0}'`" ]
865 # get_devname hostname svname
866 # Get the device name of lustre target @svname from node @hostname
869 local target_svname=$2
870 local target_devname=
872 local target_type target_obdtype mntdev_file
874 if [ "${target_svname}" = "${MGS_SVNAME}" ]; then
875 # Execute remote command to get the device name of mgs target
876 ret_str=`${REMOTE} ${host_name} \
877 "PATH=\$PATH:/sbin:/usr/sbin findfs LABEL=${target_svname}" 2>&1`
878 if [ $? -ne 0 -a -n "${ret_str}" ]; then
879 if [ "${ret_str}" = "${ret_str#*Unable to resolve*}" ]
881 echo "`basename $0`: get_devname() error:" \
882 "remote command error: ${ret_str}"
887 if [ "${ret_str}" = "${ret_str#*Unable to resolve*}" ]; then
889 target_devname=`echo ${ret_str} | awk '{print $2}'`
891 target_devname=`echo ${ret_str} | awk '{print $1}'`
894 else # Execute remote command to get the device name of mdt/ost target
895 target_type=`echo ${target_svname} | cut -d - -f 2`
896 target_obdtype=${target_type:0:3}_TYPE
898 mntdev_file=${LUSTRE_PROC}/${!target_obdtype}/${target_svname}/mntdev
900 ret_str=`${REMOTE} ${host_name} "cat ${mntdev_file}" 2>&1`
901 if [ $? -ne 0 -a -n "${ret_str}" ]; then
902 echo "`basename $0`: get_devname() error:" \
903 "remote command error: ${ret_str}"
907 if [ "${ret_str}" != "${ret_str#*No such file*}" ]; then
908 echo "`basename $0`: get_devname() error:"\
909 "${mntdev_file} does not exist in ${host_name}!"
913 target_devname=`echo ${ret_str} | awk '{print $2}'`
915 target_devname=`echo ${ret_str} | awk '{print $1}'`
920 echo ${target_devname}
924 # get_devsize hostname target_devname
925 # Get the device size (KB) of @target_devname from node @hostname
928 local target_devname=$2
929 local target_devsize=
932 # Execute remote command to get the device size
933 ret_str=`${REMOTE} ${host_name} \
934 "PATH=\$PATH:/sbin:/usr/sbin blockdev --getsize ${target_devname}" 2>&1`
935 if [ $? -ne 0 -a -n "${ret_str}" ]; then
936 echo "`basename $0`: get_devsize() error:" \
937 "remote command error: ${ret_str}"
942 target_devsize=`echo ${ret_str} | awk '{print $2}'`
944 target_devsize=`echo ${ret_str} | awk '{print $1}'`
947 if [ -z "`echo ${target_devsize}|awk '/^[[:digit:]]/ {print $0}'`" ]
949 echo "`basename $0`: get_devsize() error: can't" \
950 "get device size of ${target_devname} in ${host_name}!"
954 let " target_devsize /= 2"
956 echo ${target_devsize}
960 # get_realdevname hostname loop_dev
961 # Get the real device name of loop device @loop_dev from node @hostname
965 local target_devname=
968 # Execute remote command to get the real device name
969 ret_str=`${REMOTE} ${host_name} \
970 "PATH=\$PATH:/sbin:/usr/sbin losetup ${loop_dev}" 2>&1`
971 if [ $? -ne 0 -a -n "${ret_str}" ]; then
972 echo "`basename $0`: get_realdevname() error:" \
973 "remote command error: ${ret_str}"
978 target_devname=`echo ${ret_str} | awk '{print $4}' \
979 | sed 's/^(//' | sed 's/)$//'`
981 target_devname=`echo ${ret_str} | awk '{print $3}' \
982 | sed 's/^(//' | sed 's/)$//'`
985 if [ "${ret_str}" != "${ret_str#*No such*}" ] \
986 || [ -z "${target_devname}" ]; then
987 echo "`basename $0`: get_realdevname() error: can't" \
988 "get info on device ${loop_dev} in ${host_name}!"
992 echo ${target_devname}
996 # get_mntpnt hostname target_devname
997 # Get the lustre target mount point from the node @hostname
1000 local target_devname=$2
1004 # Execute remote command to get the mount point
1005 ret_str=`${REMOTE} ${host_name} \
1006 "cat /etc/mtab | grep ${target_devname}" 2>&1`
1007 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1008 echo "`basename $0`: get_mntpnt() error:" \
1009 "remote command error: ${ret_str}"
1014 mnt_point=`echo ${ret_str} | awk '{print $3}'`
1016 mnt_point=`echo ${ret_str} | awk '{print $2}'`
1019 if [ -z "${mnt_point}" ]; then
1020 echo "`basename $0`: get_mntpnt() error: can't" \
1021 "get the mount point of ${target_devname} in ${host_name}!"
1029 # get_devnames hostname
1030 # Get the lustre target device names, mount points
1031 # and loop device sizes from the node @hostname
1037 # Initialize the arrays
1038 unset TARGET_DEVNAMES
1039 unset TARGET_DEVSIZES
1040 unset TARGET_MNTPNTS
1042 for ((i = 0; i < ${#TARGET_SVNAMES[@]}; i++)); do
1043 TARGET_DEVNAMES[i]=$(get_devname ${host_name} \
1044 ${TARGET_SVNAMES[i]})
1045 if [ $? -ne 0 ]; then
1046 error_output "${TARGET_DEVNAMES[i]}"
1050 if [ -z "${TARGET_DEVNAMES[i]}" ]; then
1051 if [ "${TARGET_SVNAMES[i]}" = "${MGS_SVNAME}" ]; then
1052 verbose_output "There exists combo mgs/mdt"\
1053 "target in ${host_name}."
1056 error_output "get_devname():"\
1057 "No device corresponding to target" \
1058 "${TARGET_SVNAMES[i]} in ${host_name}!"
1063 # Get the mount point of the target
1064 TARGET_MNTPNTS[i]=$(get_mntpnt ${host_name} \
1065 ${TARGET_DEVNAMES[i]})
1066 if [ $? -ne 0 ]; then
1067 error_output "${TARGET_MNTPNTS[i]}"
1071 # The target device is a loop device?
1072 if [ -n "${TARGET_DEVNAMES[i]}" ] \
1073 && is_loopdev ${TARGET_DEVNAMES[i]}; then
1074 # Get the device size
1075 TARGET_DEVSIZES[i]=$(get_devsize ${host_name} \
1076 ${TARGET_DEVNAMES[i]})
1077 if [ $? -ne 0 ]; then
1078 error_output "${TARGET_DEVSIZES[i]}"
1082 # Get the real device name
1083 TARGET_DEVNAMES[i]=$(get_realdevname ${host_name} \
1084 ${TARGET_DEVNAMES[i]})
1085 if [ $? -ne 0 ]; then
1086 error_output "${TARGET_DEVNAMES[i]}"
1095 # is_target target_svtype ldd_flags
1096 # Check the service type of a lustre target
1099 "mdt") let "ret = $2 & LDD_F_SV_TYPE_MDT";;
1100 "ost") let "ret = $2 & LDD_F_SV_TYPE_OST";;
1101 "mgs") let "ret = $2 & LDD_F_SV_TYPE_MGS";;
1103 error_output "is_target(): Invalid" \
1104 "target service type - \"$1\"!"
1109 if [ ${ret} -eq 0 ]; then
1116 # get_devtype ldd_flags
1117 # Get the service type of a lustre target from @ldd_flags
1119 local target_devtype=
1121 if [ -z "${flags}" ]; then
1122 echo "`basename $0`: get_devtype() error: Invalid" \
1123 "ldd_flags - it's value is null!"
1127 if is_target "mgs" $1; then
1128 if is_target "mdt" $1; then
1129 target_devtype="mgs|mdt"
1131 target_devtype="mgs"
1133 elif is_target "mdt" $1; then
1134 target_devtype="mdt"
1135 elif is_target "ost" $1; then
1136 target_devtype="ost"
1138 echo "`basename $0`: get_devtype() error: Invalid" \
1139 "ldd_flags - \"$1\"!"
1143 echo ${target_devtype}
1147 # get_mntopts ldd_mount_opts
1148 # Get the user-specified lustre target mount options from @ldd_mount_opts
1151 local ldd_mount_opts=$1
1153 mount_opts="${ldd_mount_opts#${ALWAYS_MNTOPTS}}"
1154 mount_opts="${mount_opts#${MDT_MGS_ALWAYS_MNTOPTS}}"
1155 mount_opts="${mount_opts#${OST_ALWAYS_MNTOPTS}}"
1156 mount_opts="${mount_opts#${OST_DEFAULT_MNTOPTS}}"
1157 mount_opts="`echo \"${mount_opts}\" | sed 's/^,//'`"
1159 [ "${mount_opts}" != "${mount_opts#*,*}" ] && echo "\""${mount_opts}"\"" \
1160 || echo ${mount_opts}
1165 # get_mgsnids ldd_params
1166 # Get the mgs nids of lustre target from @ldd_params
1168 local mgs_nids= # mgs nids in one mgs node
1169 local all_mgs_nids= # mgs nids in all mgs failover nodes
1171 local ldd_params="$*"
1173 for param in ${ldd_params}; do
1174 if [ -n "`echo ${param}|awk '/mgsnode=/ {print $0}'`" ]; then
1175 mgs_nids=`echo ${param#${PARAM_MGSNODE}}`
1177 if [ -n "${all_mgs_nids}" ]; then
1178 all_mgs_nids=${all_mgs_nids}:${mgs_nids}
1180 all_mgs_nids=${mgs_nids}
1185 [ "${all_mgs_nids}" != "${all_mgs_nids#*,*}" ] \
1186 && echo "\""${all_mgs_nids}"\"" || echo ${all_mgs_nids}
1191 # get_failnids ldd_params
1192 # Get the failover nids of lustre target from @ldd_params
1194 local fail_nids= # failover nids in one failover node
1195 local all_fail_nids= # failover nids in all failover nodes
1198 local ldd_params="$*"
1200 for param in ${ldd_params}; do
1201 if [ -n "`echo ${param}|awk '/failover.node=/ {print $0}'`" ]; then
1202 fail_nids=`echo ${param#${PARAM_FAILNODE}}`
1204 if [ -n "${all_fail_nids}" ]; then
1205 all_fail_nids=${all_fail_nids}:${fail_nids}
1207 all_fail_nids=${fail_nids}
1212 [ "${all_fail_nids}" != "${all_fail_nids#*,*}" ] \
1213 && echo "\""${all_fail_nids}"\"" || echo ${all_fail_nids}
1218 # get_fmtopts target_devname hostname ldd_params
1219 # Get other format options of the lustre target @target_devname from @ldd_params
1221 local target_devname=$1
1225 local ldd_params="$*"
1229 for param in ${ldd_params}; do
1230 [ -n "`echo ${param}|awk '/mgsnode=/ {print $0}'`" ] && continue
1231 [ -n "`echo ${param}|awk '/failover.node=/ {print $0}'`" ] && continue
1233 if [ -n "${param}" ]; then
1234 if [ -n "${fmt_opts}" ]; then
1235 fmt_opts=${fmt_opts}" --param=\""${param}"\""
1237 fmt_opts="--param=\""${param}"\""
1246 # get_stripecount host_name target_fsname
1247 # Get the stripe count for @target_fsname
1250 local target_fsname=$2
1252 local stripecount_file
1255 # Get the stripe count
1256 stripecount_file=${LUSTRE_PROC}/lov/${target_fsname}-mdtlov/stripecount
1257 ret_str=`${REMOTE} ${host_name} "cat ${stripecount_file}" 2>&1`
1258 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1259 echo "`basename $0`: get_stripecount() error:" \
1260 "remote command to ${host_name} error: ${ret_str}"
1265 stripe_count=`echo ${ret_str} | awk '{print $2}'`
1267 stripe_count=`echo ${ret_str} | awk '{print $1}'`
1270 if [ "$stripe_count" != "-1" ] && \
1271 [ -z "`echo ${stripe_count}|awk '/^[[:digit:]]/ {print $0}'`" ]; then
1272 echo "`basename $0`: get_stripecount() error: can't" \
1273 "get stripe count of ${target_fsname} in ${host_name}!"
1277 echo ${stripe_count}
1281 # get_stripecount_opt host_name target_fsname
1282 # Get the stripe count option for lustre mdt target
1283 get_stripecount_opt() {
1285 local target_fsname=$2
1287 local stripecount_opt=
1289 # Get the stripe count
1290 [ -z "${target_fsname}" ] && target_fsname="lustre"
1291 stripe_count=$(get_stripecount ${host_name} ${target_fsname})
1292 if [ $? -ne 0 ]; then
1293 echo "${stripe_count}"
1297 if [ "${stripe_count}" != "1" ]; then
1298 stripecount_opt=${OPTSTR_STRIPE_COUNT}${stripe_count}
1301 echo ${stripecount_opt}
1306 # Get the lustre target disk data from the node @hostname
1311 local flags mnt_opts params
1312 local stripecount_opt
1314 # Initialize the arrays
1315 unset TARGET_DEVTYPES TARGET_FSNAMES TARGET_MGSNIDS TARGET_INDEXES
1316 unset TARGET_FMTOPTS TARGET_MNTOPTS TARGET_FAILNIDS
1318 # Get lustre target device type, fsname, index, etc.
1319 # from MOUNT_DATA_FILE. Using tunefs.lustre to read it.
1320 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
1325 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
1327 # Execute remote command to read MOUNT_DATA_FILE
1328 while read -r ret_line; do
1337 if [ -n "`echo ${line}|awk '/Index:/ {print $0}'`" ]; then
1338 TARGET_INDEXES[i]=`echo ${line}|awk '{print $2}'`
1342 if [ -n "`echo ${line}|awk '/Lustre FS:/ {print $0}'`" ]; then
1343 TARGET_FSNAMES[i]=`echo ${line}|awk '{print $3}'`
1347 if [ -n "`echo ${line}|awk '/Flags:/ {print $0}'`" ]; then
1348 flags=`echo ${line}|awk '{print $2}'`
1352 if [ -n "`echo ${line}|awk '/Persistent mount opts:/ {print $0}'`" ]; then
1353 mnt_opts=`echo ${line}|awk '{print $0}'`
1354 mnt_opts=`echo ${mnt_opts#Persistent mount opts: }`
1358 if [ -n "`echo ${line}|awk '/Parameters:/ {print $0}'`" ]; then
1359 params=`echo ${line}|awk '{print $0}'`
1360 params=`echo ${params#Parameters:}`
1363 done < <(${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin
1364 ${TUNEFS} --print --verbose ${TARGET_DEVNAMES[i]} 2>/dev/null")
1366 if [ -z "${flags}" ]; then
1367 error_output "get_ldds(): Invalid" \
1368 "ldd_flags of target ${TARGET_DEVNAMES[i]}" \
1369 "in host ${host_name} - it's value is null!"\
1370 "Check ${TUNEFS} command!"
1374 if [ "${TARGET_INDEXES[i]}" = "unassigned" ] \
1375 || is_target "mgs" ${flags}; then
1379 [ "${TARGET_FSNAMES[i]}" = "lustre" ] && TARGET_FSNAMES[i]=
1381 # Get the lustre target service type
1382 TARGET_DEVTYPES[i]=$(get_devtype ${flags})
1383 if [ $? -ne 0 ]; then
1384 error_output "${TARGET_DEVTYPES[i]} From device" \
1385 "${TARGET_DEVNAMES[i]} in host ${host_name}!"
1389 # Get the lustre target mount options
1390 TARGET_MNTOPTS[i]=$(get_mntopts "${mnt_opts}")
1392 # Get mgs nids of the lustre target
1393 TARGET_MGSNIDS[i]=$(get_mgsnids "${params}")
1395 # Get failover nids of the lustre target
1396 TARGET_FAILNIDS[i]=$(get_failnids "${params}")
1397 if [ $? -ne 0 ]; then
1398 error_output "${TARGET_FAILNIDS[i]} From device" \
1399 "${TARGET_DEVNAMES[i]} in host ${host_name}!"
1403 # Get other format options of the lustre target
1404 TARGET_FMTOPTS[i]=$(get_fmtopts ${TARGET_DEVNAMES[i]} ${host_name} "${params}")
1405 if [ $? -ne 0 ]; then
1406 error_output "${TARGET_FMTOPTS[i]}"
1410 if [ -n "${TARGET_DEVSIZES[i]}" ]; then
1411 if [ -n "${TARGET_FMTOPTS[i]}" ]; then
1412 TARGET_FMTOPTS[i]="--device-size=${TARGET_DEVSIZES[i]} ""${TARGET_FMTOPTS[i]}"
1414 TARGET_FMTOPTS[i]="--device-size=${TARGET_DEVSIZES[i]}"
1418 if [ -n "${FAILOVER_FMTOPTS[i]}" ]; then
1419 if [ -n "${TARGET_FMTOPTS[i]}" ]; then
1420 TARGET_FMTOPTS[i]=${TARGET_FMTOPTS[i]}" "${FAILOVER_FMTOPTS[i]}
1422 TARGET_FMTOPTS[i]=${FAILOVER_FMTOPTS[i]}
1426 if is_target "mdt" ${flags}; then
1427 # Get the stripe count option
1428 stripecount_opt=$(get_stripecount_opt ${host_name} ${TARGET_FSNAMES[i]})
1429 if [ $? -ne 0 ]; then
1430 error_output "${stripecount_opt}"
1434 if [ -n "${stripecount_opt}" ]; then
1435 if [ -n "${TARGET_FMTOPTS[i]}" ]; then
1436 TARGET_FMTOPTS[i]=${TARGET_FMTOPTS[i]}" "${stripecount_opt}
1438 TARGET_FMTOPTS[i]=${stripecount_opt}
1443 if [ "${TARGET_FMTOPTS[i]}" != "${TARGET_FMTOPTS[i]#*,*}" ]; then
1444 TARGET_FMTOPTS[i]="\""${TARGET_FMTOPTS[i]}"\""
1451 # get_journalsize target_devname hostname
1452 # Get the journal size of lustre target @target_devname from @hostname
1454 local target_devname=$1
1456 local journal_inode=
1460 # Execute remote command to get the journal inode number
1461 ret_str=`${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin \
1462 debugfs -R 'stats -h' ${target_devname} | grep 'Journal inode:'" 2>&1`
1463 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1464 echo "`basename $0`: get_journalsize() error:" \
1465 "remote command error: ${ret_str}"
1469 ret_str=${ret_str#${ret_str%Journal inode:*}}
1470 journal_inode=`echo ${ret_str} | awk '{print $3}'`
1471 if [ -z "`echo ${journal_inode}|awk '/^[[:digit:]]/ {print $0}'`" ]
1473 echo "`basename $0`: get_journalsize() error: can't" \
1474 "get journal inode of ${target_devname} in ${host_name}!"
1478 # Execute remote command to get the journal size
1479 ret_str=`${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin \
1480 debugfs -R 'stat <${journal_inode}>' ${target_devname}|grep '^User:'" 2>&1`
1481 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1482 echo "`basename $0`: get_journalsize() error:" \
1483 "remote command error: ${ret_str}"
1487 ret_str=${ret_str#${ret_str%User:*}}
1488 journal_size=`echo ${ret_str} | awk '{print $6}'`
1489 if [ -z "`echo ${journal_size}|awk '/^[[:digit:]]/ {print $0}'`" ]
1491 echo "`basename $0`: get_journalsize() error: can't" \
1492 "get journal size of ${target_devname} in ${host_name}!"
1496 let "journal_size /= 1024*1024" # MB
1498 echo ${journal_size}
1502 # get_defaultjournalsize target_devsize
1503 # Calculate the default journal size from target device size @target_devsize
1504 get_defaultjournalsize() {
1505 declare -i target_devsize=$1
1506 declare -i journal_size=0
1507 declare -i max_size base_size
1509 let "base_size = 1024*1024"
1510 if [ ${target_devsize} -gt ${base_size} ]; then # 1GB
1511 let "journal_size = target_devsize / 102400"
1512 let "journal_size *= 4"
1515 let "max_size = 102400 * L_BLOCK_SIZE"
1516 let "max_size >>= 20" # 400MB
1518 if [ ${journal_size} -gt ${max_size} ]; then
1519 let "journal_size = max_size"
1522 echo ${journal_size}
1526 # figure_journal_size target_devname hostname
1527 # Find a reasonable journal file size given the number of blocks
1528 # in the filesystem. This algorithm is derived from figure_journal_size()
1529 # function in util.c of e2fsprogs-1.38.cfs2-1.src.rpm.
1530 figure_journal_size() {
1531 local target_devname=$1
1534 declare -i block_count
1535 declare -i journal_blocks
1536 declare -i journal_size
1538 # Execute remote command to get the block count
1539 ret_str=`${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin \
1540 debugfs -R 'stats -h' ${target_devname} | grep 'Block count:'" 2>&1`
1541 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1542 echo "`basename $0`: figure_journal_size() error:" \
1543 "remote command error: ${ret_str}"
1547 ret_str=${ret_str#${ret_str%Block count:*}}
1548 block_count=`echo ${ret_str} | awk '{print $3}'`
1549 if [ -z "`echo ${block_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1551 echo "`basename $0`: figure_journal_size() error: can't" \
1552 "get block count of ${target_devname} in ${host_name}!"
1556 if ((block_count < 32768)); then
1557 let "journal_blocks = 1024"
1558 elif ((block_count < 256*1024)); then
1559 let "journal_blocks = 4096"
1560 elif ((block_count < 512*1024)); then
1561 let "journal_blocks = 8192"
1562 elif ((block_count < 1024*1024)); then
1563 let "journal_blocks = 16384"
1565 let "journal_blocks = 32768"
1568 let "journal_size = journal_blocks * L_BLOCK_SIZE / 1048576"
1570 echo ${journal_size}
1574 # get_J_opt hostname target_devname target_devsize
1575 # Get the mkfs -J option of lustre target @target_devname
1576 # from the node @hostname
1579 local target_devname=$2
1580 local target_devsize=$3
1582 local default_journal_size=
1585 # Get the real journal size of lustre target
1586 journal_size=$(get_journalsize ${target_devname} ${host_name})
1587 if [ $? -ne 0 ]; then
1588 echo "${journal_size}"
1592 # Get the default journal size of lustre target
1593 default_journal_size=$(get_defaultjournalsize ${target_devsize})
1594 if [ "${default_journal_size}" = "0" ]; then
1595 default_journal_size=$(figure_journal_size ${target_devname} \
1597 if [ $? -ne 0 ]; then
1598 echo "${default_journal_size}"
1603 if [ "${journal_size}" != "${default_journal_size}" ]; then
1604 journal_opt="-J size=${journal_size}"
1611 # get_ratio target_devname hostname
1612 # Get the bytes/inode ratio of lustre target @target_devname from @hostname
1614 local target_devname=$1
1621 # Execute remote command to get the inode count
1622 ret_str=`${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin \
1623 debugfs -R 'stats -h' ${target_devname} | grep 'Inode count:'" 2>&1`
1624 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1625 echo "`basename $0`: get_ratio() error:" \
1626 "remote command error: ${ret_str}"
1630 ret_str=${ret_str#${ret_str%Inode count:*}}
1631 inode_count=`echo ${ret_str} | awk '{print $3}'`
1632 if [ -z "`echo ${inode_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1634 echo "`basename $0`: get_ratio() error: can't" \
1635 "get inode count of ${target_devname} in ${host_name}!"
1639 # Execute remote command to get the block count
1640 ret_str=`${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin \
1641 debugfs -R 'stats -h' ${target_devname} | grep 'Block count:'" 2>&1`
1642 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1643 echo "`basename $0`: get_ratio() error:" \
1644 "remote command error: ${ret_str}"
1648 ret_str=${ret_str#${ret_str%Block count:*}}
1649 block_count=`echo ${ret_str} | awk '{print $3}'`
1650 if [ -z "`echo ${block_count}|awk '/^[[:digit:]]/ {print $0}'`" ]
1652 echo "`basename $0`: get_ratio() error: can't" \
1653 "get block count of ${target_devname} in ${host_name}!"
1657 let "ratio = block_count*L_BLOCK_SIZE/inode_count"
1663 # get_default_ratio target_devtype target_devsize
1664 # Calculate the default bytes/inode ratio from target type @target_devtype
1665 get_default_ratio() {
1666 local target_devtype=$1
1667 declare -i target_devsize=$2
1670 case "${target_devtype}" in
1671 "mdt" | "mgs|mdt" | "mdt|mgs")
1674 [ ${target_devsize} -gt 1000000 ] && ratio=16384;;
1677 [ -z "${ratio}" ] && ratio=${L_BLOCK_SIZE}
1683 # get_i_opt hostname target_devname target_devtype target_devsize
1684 # Get the mkfs -i option of lustre target @target_devname
1685 # from the node @hostname
1688 local target_devname=$2
1689 local target_devtype=$3
1690 local target_devsize=$4
1692 local default_ratio=
1695 # Get the real bytes/inode ratio of lustre target
1696 ratio=$(get_ratio ${target_devname} ${host_name})
1697 if [ $? -ne 0 ]; then
1702 # Get the default bytes/inode ratio of lustre target
1703 default_ratio=$(get_default_ratio ${target_devtype} ${target_devsize})
1705 if [ "${ratio}" != "${default_ratio}" ]; then
1706 ratio_opt="-i ${ratio}"
1713 # get_isize target_devname hostname
1714 # Get the inode size of lustre target @target_devname from @hostname
1716 local target_devname=$1
1721 # Execute remote command to get the inode size
1722 ret_str=`${REMOTE} ${host_name} "PATH=\$PATH:/sbin:/usr/sbin \
1723 debugfs -R 'stats -h' ${target_devname} | grep 'Inode size:'" 2>&1`
1724 if [ $? -ne 0 -a -n "${ret_str}" ]; then
1725 echo "`basename $0`: get_isize() error:" \
1726 "remote command error: ${ret_str}"
1730 ret_str=${ret_str#${ret_str%Inode size:*}}
1731 inode_size=`echo ${ret_str} | awk '{print $3}'`
1732 if [ -z "`echo ${inode_size}|awk '/^[[:digit:]]/ {print $0}'`" ]
1734 echo "`basename $0`: get_isize() error: can't" \
1735 "get inode size of ${target_devname} in ${host_name}!"
1743 # get_mdt_default_isize host_name target_fsname
1744 # Calculate the default inode size of lustre mdt target
1745 get_mdt_default_isize() {
1747 local target_fsname=$2
1748 declare -i stripe_count
1751 # Get the stripe count
1752 stripe_count=$(get_stripecount ${host_name} ${target_fsname})
1753 if [ $? -ne 0 ]; then
1754 echo "${stripe_count}"
1758 if ((stripe_count > 77)); then
1760 elif ((stripe_count > 34)); then
1762 elif ((stripe_count > 13)); then
1772 # get_default_isize host_name target_devtype target_fsname
1773 # Calculate the default inode size of lustre target type @target_devtype
1774 get_default_isize() {
1776 local target_devtype=$2
1777 local target_fsname=$3
1780 case "${target_devtype}" in
1781 "mdt" | "mgs|mdt" | "mdt|mgs")
1782 inode_size=$(get_mdt_default_isize ${host_name} ${target_fsname})
1783 if [ $? -ne 0 ]; then
1784 echo "${inode_size}"
1792 [ -z "${inode_size}" ] && inode_size=128
1798 # get_I_opt hostname target_devname target_devtype target_fsname
1799 # Get the mkfs -I option of lustre target @target_devname
1800 # from the node @hostname
1803 local target_devname=$2
1804 local target_devtype=$3
1805 local target_fsname=$4
1807 local default_isize=
1810 # Get the real inode size of lustre target
1811 isize=$(get_isize ${target_devname} ${host_name})
1812 if [ $? -ne 0 ]; then
1817 # Get the default inode size of lustre target
1818 [ -z "${target_fsname}" ] && target_fsname="lustre"
1819 default_isize=$(get_default_isize ${host_name} ${target_devtype} \
1821 if [ $? -ne 0 ]; then
1822 echo "${default_isize}"
1826 if [ "${isize}" != "${default_isize}" ]; then
1827 isize_opt="-I ${isize}"
1834 # get_mkfsopts hostname
1835 # Get the mkfs options of lustre targets from the node @hostname
1841 local inode_size_opt
1843 # Initialize the arrays
1844 unset TARGET_MKFSOPTS
1846 # FIXME: Get other mkfs options of ext3/ldiskfs besides -J, -i and -I
1847 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
1852 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
1854 if [ -z "${TARGET_DEVSIZES[i]}" ]; then
1855 # Get the device size
1856 TARGET_DEVSIZES[i]=$(get_devsize ${host_name} \
1857 ${TARGET_DEVNAMES[i]})
1858 if [ $? -ne 0 ]; then
1859 error_output "${TARGET_DEVSIZES[i]}"
1864 # Get the journal option
1865 journal_opt=$(get_J_opt ${host_name} ${TARGET_DEVNAMES[i]} \
1866 ${TARGET_DEVSIZES[i]})
1867 if [ $? -ne 0 ]; then
1868 error_output "${journal_opt}"
1872 if [ -n "${journal_opt}" ]; then
1873 if [ -z "${TARGET_MKFSOPTS[i]}" ]; then
1874 TARGET_MKFSOPTS[i]="${journal_opt}"
1876 TARGET_MKFSOPTS[i]=${TARGET_MKFSOPTS[i]}" ${journal_opt}"
1880 # Get the bytes-per-inode ratio option
1881 ratio_opt=$(get_i_opt ${host_name} ${TARGET_DEVNAMES[i]} \
1882 ${TARGET_DEVTYPES[i]} ${TARGET_DEVSIZES[i]})
1883 if [ $? -ne 0 ]; then
1884 error_output "${ratio_opt}"
1888 if [ -n "${ratio_opt}" ]; then
1889 if [ -z "${TARGET_MKFSOPTS[i]}" ]; then
1890 TARGET_MKFSOPTS[i]="${ratio_opt}"
1892 TARGET_MKFSOPTS[i]=${TARGET_MKFSOPTS[i]}" ${ratio_opt}"
1896 # Get the inode size option
1897 inode_size_opt=$(get_I_opt ${host_name} ${TARGET_DEVNAMES[i]} \
1898 ${TARGET_DEVTYPES[i]} ${TARGET_FSNAMES[i]})
1899 if [ $? -ne 0 ]; then
1900 error_output "${inode_size_opt}"
1904 if [ -n "${inode_size_opt}" ]; then
1905 if [ -z "${TARGET_MKFSOPTS[i]}" ]; then
1906 TARGET_MKFSOPTS[i]="${inode_size_opt}"
1908 TARGET_MKFSOPTS[i]=${TARGET_MKFSOPTS[i]}" ${inode_size_opt}"
1912 if [ "${TARGET_MKFSOPTS[i]}" != "${TARGET_MKFSOPTS[i]#*,*}" ]; then
1913 TARGET_MKFSOPTS[i]="\""${TARGET_MKFSOPTS[i]}"\""
1919 # get_target_configs hostname
1920 # Get the lustre target informations from the node @hostname
1921 get_target_configs() {
1926 # Initialize the arrays
1927 unset TARGET_CONFIGS
1929 # Get lustre target server names
1930 if ! get_svnames ${host_name}; then
1934 # Get lustre target device names, mount points and loop device sizes
1935 if ! get_devnames ${host_name}; then
1939 # Get lustre target device type, fsname, index, etc.
1940 if ! get_ldds ${host_name}; then
1944 # Get mkfs options of lustre targets
1945 if ! get_mkfsopts ${host_name}; then
1949 # Construct lustre target configs
1950 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
1951 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
1952 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]}
1958 # get_configs hostname
1959 # Get all the informations needed to generate a csv file from
1960 # the node @hostname
1962 # Check the hostname
1963 if [ -z "$1" ]; then
1964 error_output "get_configs():" \
1969 # Get network module options
1971 verbose_output "Collecting network module options from host $1..."
1972 if ! get_module_opts $1; then
1977 # Get lustre target informations
1978 verbose_output "Collecting Lustre targets informations from host $1..."
1979 if ! get_target_configs $1; then
1984 # Get HA software configurations
1985 if ! get_ha_configs $1; then
1992 # Collect linux MD/LVM device informations from the lustre cluster and
1993 # append them to the csv file
1999 # Collect and append linux MD/LVM informations to the csv file
2000 for ((idx = 0; idx < ${#HOST_NAMES[@]}; idx++)); do
2001 [ -z "${HOST_NAMES[idx]}" ] && continue
2003 # Collect MD device informations
2004 ! get_md_configs ${HOST_NAMES[idx]} && return 1
2006 # Append MD device informations to the csv file
2007 for ((i = 0; i < ${#MD_NAME[@]}; i++)); do
2008 line=${HOST_NAMES[idx]},${MD_MARKER},${MD_NAME[i]},,,${MD_LEVEL[i]},${MD_DEVS[i]}
2009 verbose_output "Informations of MD device ${MD_NAME[i]}" \
2010 "in host ${HOST_NAMES[idx]} are as follows:"
2011 verbose_output "${line}"
2012 echo "${line}" >> ${LUSTRE_CSV_FILE}
2015 # Collect PV informations
2016 ! get_pv_configs ${HOST_NAMES[idx]} && return 1
2018 # Append PV informations to the csv file
2019 if [ -n "${PV_NAMES}" ]; then
2020 line=${HOST_NAMES[idx]},${PV_MARKER},${PV_NAMES}
2021 verbose_output "Informations of PVs" \
2022 "in host ${HOST_NAMES[idx]} are as follows:"
2023 verbose_output "${line}"
2024 echo "${line}" >> ${LUSTRE_CSV_FILE}
2027 # Collect VG informations
2028 ! get_vg_configs ${HOST_NAMES[idx]} && return 1
2030 # Append VG informations to the csv file
2031 for ((i = 0; i < ${#VG_NAME[@]}; i++)); do
2032 line=${HOST_NAMES[idx]},${VG_MARKER},${VG_NAME[i]},,,${VG_PVNAMES[i]}
2033 verbose_output "Informations of VG ${VG_NAME[i]}" \
2034 "in host ${HOST_NAMES[idx]} are as follows:"
2035 verbose_output "${line}"
2036 echo "${line}" >> ${LUSTRE_CSV_FILE}
2039 # Collect LV informations
2040 ! get_lv_configs ${HOST_NAMES[idx]} && return 1
2042 # Append LV informations to the csv file
2043 for ((i = 0; i < ${#LV_NAME[@]}; i++)); do
2044 line=${HOST_NAMES[idx]},${LV_MARKER},${LV_NAME[i]},,,${LV_SIZE[i]},${LV_VGNAME[i]}
2045 verbose_output "Informations of LV /dev/${LV_VGNAME[i]}/${LV_NAME[i]}"\
2046 "in host ${HOST_NAMES[idx]} are as follows:"
2047 verbose_output "${line}"
2048 echo "${line}" >> ${LUSTRE_CSV_FILE}
2054 # Generate the csv file from the lustre cluster
2060 # Get lustre cluster node names
2061 verbose_output "Collecting Lustre cluster node names..."
2062 if ! get_hostnames; then
2067 : > ${LUSTRE_CSV_FILE}
2069 ${GET_MDLVM_INFO} && get_mdlvm_info
2071 # Collect and append lustre target informations to the csv file
2072 for ((idx = 0; idx < ${#HOST_NAMES[@]}; idx++)); do
2073 # Collect informations
2074 if ! get_configs ${HOST_NAMES[idx]}; then
2075 rm -f ${LUSTRE_CSV_FILE}
2079 # Append informations to the csv file
2080 for ((i = 0; i < ${#TARGET_DEVNAMES[@]}; i++)); do
2081 [ -z "${TARGET_DEVNAMES[i]}" ] && continue
2083 if [ -z "${HA_CONFIGS[i]}" ]; then
2084 line=${HOST_NAMES[idx]},${MODULE_OPTS},${TARGET_CONFIGS[i]}
2086 line=${HOST_NAMES[idx]},${MODULE_OPTS},${TARGET_CONFIGS[i]},${HA_CONFIGS[i]}
2088 verbose_output "Informations of target ${TARGET_DEVNAMES[i]}" \
2089 "in host ${HOST_NAMES[idx]} are as follows:"
2090 verbose_output "${line}"
2091 echo "" >> ${LUSTRE_CSV_FILE}
2092 echo "${line}" >> ${LUSTRE_CSV_FILE}
2100 echo "`basename $0`: ******** Generate csv file -- ${LUSTRE_CSV_FILE} START ********"
2101 if ! gen_csvfile; then
2104 echo "`basename $0`: ******** Generate csv file -- ${LUSTRE_CSV_FILE} OK **********"