lustre_createcsv.in

来自「lustre 1.6.5 source code」· IN 代码 · 共 2,102 行 · 第 1/4 页

IN
2,102
字号
#!/bin/bash## lustre_createcsv - generate a csv file from a running lustre cluster## This script is used to collect lustre target informations, linux MD/LVM device# informations and HA software configurations in a lustre cluster to generate a# csv file. In reverse, the csv file could be parsed by lustre_config to # configure multiple lustre servers in parallel.## This script should be run on the MGS node.################################################################################## Usageusage() {	cat >&2 <<EOFUsage:	`basename $0` [-t HAtype] [-d] [-h] [-v] [-f csv_filename]	This script is used to collect lustre target informations, linux MD/LVM	device informations and HA software configurations from a running lustre	cluster to generate a csv file. It should be run on the MGS node.	-t HAtype	collect High-Availability software configurations			The argument following -t is used to indicate the High-			Availability software type. The HA software types which 			are currently supported are: hbv1 (Heartbeat version 1)			and hbv2 (Heartbeat version 2).	-d		collect linux MD/LVM device informations	-h		help	-v		verbose mode	-f csv_filename	designate a name for the csv file			Default is lustre_config.csv.EOF	exit 1}# Get the library of functions. @scriptlibdir@/lc_common#**************************** Global variables ****************************## csv fileLUSTRE_CSV_FILE=${LUSTRE_CSV_FILE:-"lustre_config.csv"}# Lustre proc filesLUSTRE_PROC=${LUSTRE_PROC:-"/proc/fs/lustre"}LUSTRE_PROC_DEVICES=${LUSTRE_PROC}/devicesLNET_PROC=${LNET_PROC:-"/proc/sys/lnet"}LNET_PROC_PEERS=${LNET_PROC}/peers# Default network module optionsDEFAULT_MOD_OPTS=${DEFAULT_MOD_OPTS:-"options lnet networks=tcp"}# Lustre target obd device typesMGS_TYPE=${MGS_TYPE:-"mgs"}MDT_TYPE=${MDT_TYPE:-"mds"}OST_TYPE=${OST_TYPE:-"obdfilter"}# The obd name of MGS target serverMGS_SVNAME=${MGS_SVNAME:-"MGS"}		# Hostnames of the lustre cluster nodesdeclare -a HOST_NAMES			MGS_HOSTNAME=${MGS_HOSTNAME:-"`hostname`"} # Hostname of the MGS node# Configs of lustre targets in one cluster nodedeclare -a TARGET_CONFIGS		declare -a TARGET_SVNAMES TARGET_DEVNAMES TARGET_DEVSIZES TARGET_MNTPNTSdeclare -a TARGET_DEVTYPES TARGET_FSNAMES TARGET_MGSNIDS TARGET_INDEXESdeclare -a TARGET_FMTOPTS TARGET_MKFSOPTS TARGET_MNTOPTS TARGET_FAILNIDSdeclare -a HA_CONFIGSdeclare -a ALL_TARGET_SVNAMES		# All the target services in the clusterdeclare -a FAILOVER_FMTOPTS		# "--noformat"	# Informations of linux MD/LVM devices in one cluster nodedeclare -a MD_NAME MD_LEVEL MD_DEVS	# MDdeclare -a VG_NAME VG_PVNAMES		# VGdeclare -a LV_NAME LV_SIZE LV_VGNAME	# LV# Lustre target service typeslet "LDD_F_SV_TYPE_MDT = 0x0001"let "LDD_F_SV_TYPE_OST = 0x0002"let "LDD_F_SV_TYPE_MGS = 0x0004"# Permanent mount options for ext3 or ldiskfsALWAYS_MNTOPTS=${ALWAYS_MNTOPTS:-"errors=remount-ro"}MDT_MGS_ALWAYS_MNTOPTS=${MDT_MGS_ALWAYS_MNTOPTS:-",iopen_nopriv,user_xattr"}OST_ALWAYS_MNTOPTS=${OST_ALWAYS_MNTOPTS:-",asyncdel"}OST_DEFAULT_MNTOPTS=${OST_DEFAULT_MNTOPTS:-",extents,mballoc"}# User-settable parameter keysPARAM_MGSNODE=${PARAM_MGSNODE:-"mgsnode="}PARAM_FAILNODE=${PARAM_FAILNODE:-"failover.node="}# Block sizeL_BLOCK_SIZE=4096# Option string of mkfs.lustreOPTSTR_STRIPE_COUNT=${OPTSTR_STRIPE_COUNT:-"--stripe-count-hint="}# Get and check the positional parametersVERBOSE_OUTPUT=falseGET_MDLVM_INFO=falsewhile getopts "t:dhvf:" OPTION; do	case $OPTION in	t) 		HATYPE_OPT=$OPTARG		if [ "${HATYPE_OPT}" != "${HBVER_HBV1}" ] \		&& [ "${HATYPE_OPT}" != "${HBVER_HBV2}" ] \		&& [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" ]; then			echo >&2 "`basename $0`: Invalid HA software type" \				 "- ${HATYPE_OPT}!"			usage		fi		;;	d)	GET_MDLVM_INFO=true;;	h)	usage;;	v) 	VERBOSE_OUTPUT=true;;	f)	LUSTRE_CSV_FILE=$OPTARG;;        ?) 	usage 	esacdone# Verify the local host is the MGS nodemgs_node() {	if [ ! -e ${LUSTRE_PROC_DEVICES} ]; then		echo >&2 "`basename $0`: error: ${LUSTRE_PROC_DEVICES} does" \			 "not exist. Lustre kernel modules may not be loaded!"		return 1	fi	if [ -z "`cat ${LUSTRE_PROC_DEVICES}`" ]; then		echo >&2 "`basename $0`: error: ${LUSTRE_PROC_DEVICES} is" \			 "empty. Lustre services may not be started!"		return 1	fi	if [ -z "`grep ${MGS_TYPE} ${LUSTRE_PROC_DEVICES}`" ]; then		echo >&2 "`basename $0`: error: This node is not a MGS node." \                         "The script should be run on the MGS node!"		return 1	fi	return 0}# get_hostnames# Get lustre cluster node namesget_hostnames() {	declare -a HOST_NIDS	declare -i idx		# Index of HOST_NIDS array	declare -i i		# Index of HOST_NAMES array	if ! mgs_node; then		return 1	fi	if [ ! -e ${LNET_PROC_PEERS} ]; then		echo >&2 "`basename $0`: error: ${LNET_PROC_PEERS} does not" \                         "exist. LNET kernel modules may not be loaded" \			 "or LNET network may not be up!"		return 1	fi	HOST_NAMES[0]=${MGS_HOSTNAME} # MGS node	HOST_NIDS[0]=${HOST_NAMES[0]}	# Get the nids of the nodes which have contacted MGS	idx=1	for nid in `cat ${LNET_PROC_PEERS} | awk '{print $1}'`; do		if [ "${nid}" = "nid" ]; then			continue		fi		HOST_NIDS[idx]=${nid}		let "idx += 1"	done	if [ ${idx} -eq 1 ]; then		verbose_output "Only one node running in the lustre cluster." \			       "It's ${HOST_NAMES[0]}."		return 0			fi	# Get the hostnames of the nodes	for ((idx = 1, i = 1; idx < ${#HOST_NIDS[@]}; idx++, i++)); do		if [ -z "${HOST_NIDS[idx]}" ]; then			echo >&2 "`basename $0`: get_hostnames() error:" \				 "Invalid nid - \"${HOST_NIDS[idx]}\"!"			return 1		fi		HOST_NAMES[i]=$(nid2hostname ${HOST_NIDS[idx]})		if [ $? -ne 0 ]; then			echo >&2 "${HOST_NAMES[i]}"			return 1		fi		if [ "${HOST_NAMES[i]}" = "${HOST_NAMES[0]}" ]; then			unset HOST_NAMES[i]			let "i -= 1"		fi	done	return 0}#********************** Linux MD/LVM device informations **********************## get_md_configs hostname# Get all the active MD device informations from the node @hostnameget_md_configs() {	declare -i i=0	declare -i j=0	local host_name=$1	local ret_line line first_item	# Initialize the arrays	unset MD_NAME	unset MD_LEVEL	unset MD_DEVS		# Execute remote command to the node ${host_name} and get all the	# active MD device informations.	while read -r ret_line; do		if is_pdsh; then                	set -- ${ret_line}			shift			line="$*"		else			line="${ret_line}"		fi		first_item=`echo "${line}" | awk '{print $1}'`		# Get the MD device name and raid level		if [ "${first_item}" = "ARRAY" ]; then			MD_NAME[i]=`echo "${line}" | awk '{print $2}'`			MD_LEVEL[i]=`echo "${line}" | awk '{print $3}' | sed -e 's/level=//'`			let "j = i"			let "i += 1"		fi		# Get the MD component devices		if [ "${first_item}" != "${first_item#devices=}" ]; then			MD_DEVS[j]=`echo "${line}" | sed -e 's/devices=//' -e 's/,/ /g'`		fi        done < <(${REMOTE} ${host_name} "${MDADM} --detail --scan --verbose")	if [ $i -eq 0 ]; then		verbose_output "There are no active MD devices" \			       "in the host ${host_name}!"	fi	return 0}# get_pv_configs hostname# Get all the LVM PV informations from the node @hostnameget_pv_configs() {	PV_NAMES=	local host_name=$1	local cmd ret_str	# Execute remote command to get all the PV informations.	cmd="${EXPORT_PATH} pvdisplay -c | awk -F: '{print \$1}' | xargs"	ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`	if [ $? -ne 0 ]; then		if [ -n "${ret_str}" ]; then			echo >&2 "`basename $0`: get_pv_configs() error:" \			"remote command to ${host_name} error: ${ret_str}"		else			remote_error "get_pv_configs" ${host_name}		fi		return 1	fi	PV_NAMES=`echo "${ret_str}" | sed -e 's/^'${host_name}':[[:space:]]//'`	if [ -z "${PV_NAMES}" ]; then		verbose_output "There are no PVs in the host ${host_name}!"		return 0	fi	return 0}# get_vg_pvnames hostname vgname# Get the PVs contained in @vgname from the node @hostnameget_vg_pvnames() {	local host_name=$1	local vg_name=$2	local pv_names=	local cmd ret_str	# Execute remote command to get the PV names.	cmd="${EXPORT_PATH} vgdisplay -v ${vg_name} 2>/dev/null\	     | grep \"PV Name\" | awk '{print \$3}' | xargs"	ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`	if [ $? -ne 0 ]; then		if [ -n "${ret_str}" ]; then			echo "`basename $0`: get_vg_pvnames() error:" \			"remote command to ${host_name} error: ${ret_str}"		else			remote_error "get_vg_pvnames" ${host_name}		fi		return 1	fi	pv_names=`echo "${ret_str}" | sed -e 's/^'${host_name}':[[:space:]]//'`	if [ -z "${pv_names}" ]; then		echo "`basename $0`: get_vg_pvnames() error:" \		"There are no PVs in VG ${vg_name} in the host ${host_name}!"\		"Or VG ${vg_name} does not exist."		return 1	fi	echo "${pv_names}"	return 0}# get_vg_configs hostname# Get all the LVM VG informations from the node @hostnameget_vg_configs() {	declare -i i=0	local host_name=$1	local cmd ret_str	local vg_name	# Initialize the arrays	unset VG_NAME	unset VG_PVNAMES	# Execute remote command to get all the VG names.	cmd="${EXPORT_PATH} vgdisplay \	     | grep \"VG Name\" | awk '{print \$3}' | xargs"	ret_str=`${REMOTE} ${host_name} "${cmd}" 2>&1`	if [ $? -ne 0 ]; then		if [ -n "${ret_str}" ]; then			echo >&2 "`basename $0`: get_vg_configs() error:" \			"remote command to ${host_name} error: ${ret_str}"		else			remote_error "get_vg_configs" ${host_name}		fi		return 1	fi	if [ -z "${ret_str}" ] \	|| [ "${ret_str}" != "${ret_str#*No volume groups found*}" ]; then		verbose_output "There are no VGs in the host ${host_name}!"		return 0	fi	# Get all the VG informations	for vg_name in `echo "${ret_str}" | sed -e 's/^'${host_name}'://'`; do		VG_NAME[i]=${vg_name}		VG_PVNAMES[i]=$(get_vg_pvnames ${host_name} ${VG_NAME[i]})		if [ $? -ne 0 ]; then			echo >&2 "${VG_PVNAMES[i]}"			return 1		fi		let "i += 1"	done	return 0}# get_lv_configs hostname# Get all the LVM LV informations from the node @hostnameget_lv_configs() {	declare -i i=0	local host_name=$1	local ret_line line	# Initialize the arrays	unset LV_NAME	unset LV_SIZE	unset LV_VGNAME	# Execute remote command to get all the LV informations.	while read -r ret_line; do		if is_pdsh; then                	set -- ${ret_line}			shift			line="$*"		else			line="${ret_line}"		fi		[ "${line}" != "${line#*volume group*}" ] && break		LV_NAME[i]=`echo "${line}" | awk -F: '{print $1}' | sed -e 's/.*\///g'`		LV_VGNAME[i]=`echo "${line}" | awk -F: '{print $2}'`		LV_SIZE[i]=`echo "${line}" | awk -F: '{print $7}' | sed -e 's/.*/&K/'`		let "i += 1"        done < <(${REMOTE} ${host_name} "${EXPORT_PATH} lvdisplay -c")	if [ $i -eq 0 ]; then		verbose_output "There are no LVs in the host ${host_name}"	fi	return 0}#*************************** Network module options ***************************## last_is_backslash line# Check whether the last effective letter of @line is a backslashlast_is_backslash() {	local line="$*"	declare -i i	declare -i length	local letter last_letter	length=${#line}	for ((i = ${length}-1; i >= 0; i--)); do		letter=${line:${i}:1}        	[ "x${letter}" != "x " -a "x${letter}" != "x	" -a -n "${letter}" ]\		&& last_letter=${letter} && break	done	[ "x${last_letter}" = "x\\" ] && return 0	return 1}# get_module_opts hostname# Get the network module options from the node @hostname get_module_opts() {	local host_name=$1	local ret_str	local MODULE_CONF KERNEL_VER	local ret_line line find_options	local continue_flag	MODULE_OPTS=${DEFAULT_MOD_OPTS}	# Execute remote command to get the kernel version	ret_str=`${REMOTE} ${host_name} "uname -r" 2>&1`	if [ $? -ne 0 -a -n "${ret_str}" ]; then		echo >&2 "`basename $0`: get_module_opts() error:" \			 "remote command error: ${ret_str}"		return 1	fi	remote_error "get_module_opts" ${host_name} "${ret_str}" && return 1	if is_pdsh; then		KERNEL_VER=`echo ${ret_str} | awk '{print $2}'`	else		KERNEL_VER=`echo ${ret_str} | awk '{print $1}'`	fi	# Get the module configuration file name	if [ "${KERNEL_VER:0:3}" = "2.4" ]; then        	MODULE_CONF=/etc/modules.conf	else        	MODULE_CONF=/etc/modprobe.conf	fi	# Execute remote command to get the lustre network module options	continue_flag=false	find_options=false	while read -r ret_line; do		if is_pdsh; then                	set -- ${ret_line}			shift			line="$*"		else			line="${ret_line}"		fi		# Get rid of the comment line		[ -z "`echo \"${line}\"|egrep -v \"^#\"`" ] && continue		if [ "${line}" != "${line#*options lnet*}" ]; then			if ! ${find_options}; then				find_options=true				MODULE_OPTS=${line}			else				MODULE_OPTS=${MODULE_OPTS}$" \n "${line}			fi			last_is_backslash "${line}" && continue_flag=true \			|| continue_flag=false			continue		fi			if ${continue_flag}; then			MODULE_OPTS=${MODULE_OPTS}$" \n "${line}			! last_is_backslash "${line}" && continue_flag=false		fi        done < <(${REMOTE} ${host_name} "cat ${MODULE_CONF}")	if [ -z "${MODULE_OPTS}" ]; then		MODULE_OPTS=${DEFAULT_MOD_OPTS}	fi	return 0}#************************ HA software configurations ************************## is_ha_target hostname target_devname# Check whether the target @target_devname was made to be high-availableis_ha_target() {	local host_name=$1	local target_svname=$2	local res_file	local ret_str	case "${HATYPE_OPT}" in	"${HBVER_HBV1}")	res_file=${HA_RES};;	"${HBVER_HBV2}")	res_file=${HA_CIB};;	"${HATYPE_CLUMGR}")	res_file=${CLUMAN_CONFIG};;	esac	# Execute remote command to check the resource file	ret_str=`${REMOTE} ${host_name} \		"grep ${target_svname} ${res_file}" 2>&1`	if [ $? -ne 0 -a -n "${ret_str}" ]; then		echo >&2 "`basename $0`: is_ha_target() error:" \			 "remote command error: ${ret_str}"		return 1	fi

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?