3 # mass_config.sh - spreadsheet parsing for massive parallel config
5 ########################################################################
9 echo -e >&2 $"\nUsage: `basename $0` <csv file>"
12 Each line in the csv file represents one Lustre target.
14 hostname,networks,device name,device type,fsname/poolname,mgmtnid,index,format options,mkfs options,mount options,failovers
16 Sample 1 for csv file:
17 lustre-mgs,options lnet networks=tcp,/r/tmp/mgmt,mgs,,,,--device_size 10240,-J size=4,,lustre-mgs@tcp0
18 lustre-ost,options lnet networks=tcp,/r/tmp/ost1,ost,lustre1,lustre-mgs@tcp0,0001,--device_size 10240,-J size=4,"extents,mballoc",lustre-mgs@tcp0
19 lustre-mdt,options lnet networks=tcp,/r/tmp/mdt1,mdt,lustre1,lustre-mgs@tcp0,0001,--device_size 10240,-J size=4,,lustre-mgs@tcp0
21 Sample 2 for csv file:
22 lustre-mgs,options lnet 'networks="tcp,elan"' \n options ost 'numthreads=23',/dev/sda,mgs,,,,,,,
23 lustre-ost,options lnet networks=tcp,/dev/sda,ost,,lustre-mgs@tcp0,,,,,
24 lustre-mdt,options lnet networks=tcp,/dev/sda,mdt,,lustre-mgs@tcp0,,,,,
39 echo >&2 $"check_file() error: Lack argument for function check_file()!"
44 if [ ! -s ${CSV_FILE} ]; then
45 echo >&2 $"check_file() error: ${CSV_FILE} does not exist or is empty!"
52 # Parse a line in the csv file
56 echo >&2 $"parse_line() error: Lack argument for function parse_line()!"
63 declare -i s_quote_flag=0
64 declare -i d_quote_flag=0
69 # Initialize the CONFIG_ITEM array
70 for ((i = 0; i < ${#CONFIG_ITEM[@]}; i++)); do
74 # Get the length of the line
78 while [ ${idx} -lt ${length} ]; do
79 # Get a letter from the line
80 TMP_LETTER=${LINE:${idx}:1}
82 case "${TMP_LETTER}" in
84 if [ ${s_quote_flag} -eq 1 ] || [ ${d_quote_flag} -eq 1 ]; then
85 CONFIG_ITEM[i]=${CONFIG_ITEM[i]}${TMP_LETTER}
93 if [ ${s_quote_flag} -eq 0 ]; then
100 if [ ${d_quote_flag} -eq 0 ]; then
106 if [ ${i} -eq 1 ]; then
107 CONFIG_ITEM[i]=${CONFIG_ITEM[i]}$"\\"${TMP_LETTER}
119 CONFIG_ITEM[i]=${CONFIG_ITEM[i]}${TMP_LETTER}
125 # Check the elements required for OSTs, MDTs and MGS
127 # When formatting an OST, the following elements: hostname, networks,
128 # device name, device type and mgmtnid, cannot have null value.
130 # When formatting an MDT or MGS, the following elements: hostname,
131 # networks, device name and device type, cannot have null value.
133 # Check hostname, networks, device name and device type
134 if [ -z "${HOST_NAME}" ]||[ -z "${NETWORKS}" ]||[ -z "${DEVICE_NAME}" ]\
135 ||[ -z "${DEVICE_TYPE}" ]; then
136 echo >&2 $"check_element() error: Some required element has null value!"
137 echo >&2 $"check_element() info: Check hostname, networks, device name and device type!"
142 if [ "${DEVICE_TYPE}" == "ost" ]&&[ -z "${MGMT_NID}" ]; then
143 echo >&2 $"check_element() error: OST's mgmtnid element has null value!"
150 # Check the number of MGS.
151 # There should be no more than one MGS specified in the entire csv file.
153 # Check the number of explicit MGS
154 if [ "${DEVICE_TYPE#*mgs*}" != "${DEVICE_TYPE}" ]; then
155 ex_mgs_count=${ex_mgs_count}+1
158 if [ ${ex_mgs_count} -gt 1 ]; then
159 echo >&2 $"check_mgs() error: More than one explicit MGS in the csv file!"
163 # Check the number of implicit MGS
164 if [ "${DEVICE_TYPE}" == "mdt" ]&&[ -z "${MGMT_NID}" ]; then
165 im_mgs_count=${im_mgs_count}+1
168 if [ `expr ${im_mgs_count} + ${ex_mgs_count}` -gt 1 ]; then
169 echo >&2 $"check_mgs() error: More than one MGS in the csv file!"
176 # Construct the command line of mkfs.lustre
177 construct_mkfs_cmdline() {
178 MKFS_CMD=$"mkfs.lustre "
180 case "${DEVICE_TYPE}" in
182 MKFS_CMD=${MKFS_CMD}$"--ost "
185 MKFS_CMD=${MKFS_CMD}$"--mdt "
188 MKFS_CMD=${MKFS_CMD}$"--mgmt "
191 MKFS_CMD=${MKFS_CMD}$"--mdt --mgmt "
194 MKFS_CMD=${MKFS_CMD}$"--mdt --mgmt "
197 echo >&2 $"construct_mkfs_cmdline() error: Invalid device type - \"${DEVICE_TYPE}\""
202 if [ -n "${FS_NAME}" ]; then
203 MKFS_CMD=${MKFS_CMD}$"--fsname="${FS_NAME}$" "
206 if [ -n "${MGMT_NID}" ]; then
207 MKFS_CMD=${MKFS_CMD}$"--mgmtnid="${MGMT_NID}$" "
210 if [ -n "${INDEX}" ]; then
211 MKFS_CMD=${MKFS_CMD}$"--index="${INDEX}$" "
214 if [ -n "${FORMAT_OPTIONS}" ]; then
215 MKFS_CMD=${MKFS_CMD}${FORMAT_OPTIONS}$" "
218 if [ -n "${MKFS_OPTIONS}" ]; then
219 MKFS_OPTIONS=`echo "${MKFS_OPTIONS}" | sed 's/^"//' | sed 's/"$//'`
220 MKFS_CMD=${MKFS_CMD}$"--mkfsoptions="$"\""${MKFS_OPTIONS}$"\""$" "
223 if [ -n "${MOUNT_OPTIONS}" ]; then
224 MOUNT_OPTIONS=`echo "${MOUNT_OPTIONS}" | sed 's/^"//' | sed 's/"$//'`
225 MKFS_CMD=${MKFS_CMD}$"--mountfsoptions="$"\""${MOUNT_OPTIONS}$"\""$" "
228 if [ -n "${FAILOVERS}" ]; then
229 MKFS_CMD=${MKFS_CMD}$"--failover="${FAILOVERS}$" "
232 MKFS_CMD=${MKFS_CMD}${DEVICE_NAME}
236 # Execute pdsh commands to add lnet options lines to remote nodes'
237 # modprobe.conf/modules.conf and format(mkfs.lustre) Lustre targets
240 if [ $# -eq 0 ]; then
241 echo >&2 $"mass_config() error: Lack argument for function mass_config()!"
247 declare -a CONFIG_ITEM
250 declare -i ex_mgs_count=0
251 declare -i im_mgs_count=0
252 declare -i line_num=1
255 ADD_LNET_OPTIONS=$"/usr/bin/add_lnet_options.sh"
257 while read -r LINE; do
258 # Get rid of the empty line
259 if [ -z "`echo ${LINE} | awk '/[[:alnum:]]/{print $0}'`" ]; then
260 line_num=${line_num}+1
264 # Parse the config line into CONFIG_ITEM
265 if ! parse_line $LINE; then
269 HOST_NAME=${CONFIG_ITEM[0]}
270 NETWORKS=${CONFIG_ITEM[1]}
271 DEVICE_NAME=${CONFIG_ITEM[2]}
272 DEVICE_TYPE=${CONFIG_ITEM[3]}
273 FS_NAME=${CONFIG_ITEM[4]}
274 MGMT_NID=${CONFIG_ITEM[5]}
275 INDEX=${CONFIG_ITEM[6]}
276 FORMAT_OPTIONS=${CONFIG_ITEM[7]}
277 MKFS_OPTIONS=${CONFIG_ITEM[8]}
278 MOUNT_OPTIONS=${CONFIG_ITEM[9]}
279 FAILOVERS=${CONFIG_ITEM[10]}
281 # Check some required elements
282 if ! check_element; then
283 echo >&2 $"check_element() error: Occurred on line ${line_num}."
287 # Check the number of MGS
289 echo >&2 $"check_mgs() error: Occurred on line ${line_num}."
293 # Execute pdsh command to add lnet options lines to modprobe.conf/modules.conf
294 COMMAND=$"echo \"${NETWORKS}\"|${ADD_LNET_OPTIONS}"
295 pdsh -w ${HOST_NAME} ${COMMAND} >&2 &
296 PDSH_PID[${pid_num}]=$!
297 PDSH_CMD[${pid_num}]="pdsh -w ${HOST_NAME} ${COMMAND}"
300 # Construct the command line of mkfs.lustre
301 if ! construct_mkfs_cmdline; then
302 echo >&2 $"construct_mkfs_cmdline() error: Occurred on line ${line_num}."
306 # Execute pdsh command to format Lustre target
307 pdsh -w ${HOST_NAME} ${MKFS_CMD} >&2 &
308 PDSH_PID[${pid_num}]=$!
309 PDSH_CMD[${pid_num}]="pdsh -w ${HOST_NAME} ${MKFS_CMD}"
312 line_num=${line_num}+1
315 # Wait for the exit status of the background pdsh command
317 for ((pid_num = 0; pid_num < ${#PDSH_PID[@]}; pid_num++)); do
318 wait ${PDSH_PID[${pid_num}]}
319 if [ $? -ne 0 ]; then
320 echo >&2 "mass_config() error: Fail to execute \"${PDSH_CMD[${pid_num}]}\"!"
328 if ! check_file $1; then
332 if ! mass_config ${CSV_FILE}; then