#!/bin/bash # # Description: Stonith Plugin Wrapper # Version: 2.00 # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # # Copyright (c) 2009 NIPPON TELEGRAPH AND TELEPHONE CORPORATION # ####################################################################### #Grobal Variables command_name=${0##*/} command_args=("$@") admins_direction=/var/run/heartbeat/rsctmp/${command_args[1]}_stopped ha_log_file=/var/log/ha-log ha_debug_file=/var/log/ha-debug sfex_stat_path=/usr/lib64/heartbeat/sfex_stat pluginnum=0 #how many plugins are set in config file. declare -a seclist #list of section names (in config file). timer_popd=0 #action timeout ("kill_plugin_if_timed_out") popd(1) or not(0). #Define default values. conf_file=${conf_file=/etc/stonith_wrapper.conf} no_sfex=${no_sfex=FALSE} index=${index=1} default_real_plugin="ibmrsa-telnet" default_start_timeout=20 default_status_timeout=20 default_control_timeout=20 default_sby_wait=15 sby_wait=${sby_wait=${default_sby_wait}} # # Output a log message to Heartbeat's log file. # arg1 : log level # arg2 : log message # return: nothing # savelog() { typeset level=$1 shift msg=$(echo "$command_name[$$]:"; date '+%Y/%m/%d_%H:%M:%S'; echo "$level:" "$@") echo $msg >> ${ha_debug_file} if [[ "$level" != "debug" ]] && [[ "$level" != "DEBUG" ]]; then echo $msg >> ${ha_log_file} fi } # # Kill all processes which are to set timeout, # and exit with specified status number. # arg1 : exit status number # arg2- : message to output debug log. # return : nothing # kill_and_exit() { typeset status=$1 #unset all timeout for execute plugin(s). timerpids=`jobs -l | awk '{print $2}'` savelog debug "kill all timeout-processes. (pids=${timerpids})" kill ${timerpids} > /dev/null 2>&1 shift savelog debug "Leave: exitcd=$status : ${command_args[@]} : $@" exit $status } # # Check whether a file exists or not. # When the file exists, it means the administrator judged "STONITH is complete", # then exit normally. # If not, continue the following processes. # arg : nothing # return : nothing # ok_if_admin_judges_so() { if [[ -f $admins_direction ]]; then savelog info "admins decision is accepted." rm -f $admins_direction kill_and_exit 0 $FUNCNAME $LINENO fi } # # Set timeout for executing all plugins. # When the timeout occurs, kill itself and its children # by sending SIGKILL to my pgid. # arg1 : wait time (sec.) # arg2 : target pgid # return : nothing (error exit when failure occurs) # quit_if_timed_out() { typeset waitsec=$1 typeset pgid=$2 exec -a quit_if_timed_out perl -e "sleep $waitsec; kill -9, $pgid;" & if [[ $? != 0 ]]; then savelog ERROR "exec quit_if_timed_out failed." exit 1 fi savelog debug "set timeout for executing all plugins. "\ "(waittime=${waitsec}sec. pid=$!)" } # # Confirm the target node is dead or alive with ping command. # arg1 : section name (written on config file) for the plugin # which is now STONITHing. # return: 0 -> the node is dead # 1 -> the node is alive ok_if_target_died() { typeset ip_of_target typeset vname secname="$1" eval nodeip_list=\${!${secname}_wrapper_nodeip*} for vname in ${nodeip_list}; do eval ip_of_target=\$$vname if ping -w3 -c1 "$ip_of_target" >/dev/null 2>&1; then savelog info "$ip_of_target responded." return 1 else savelog info "$ip_of_target do not responded." fi done return 0 } # # Confirm the local node is ACT or SBY with check whether specified disk # device is mounted or not. # NOTE: This function is not used now. # Formerly, when the parameter "no_sfex" is true, call this function # in check_if_sby(). # but now, if "no_sfex" is true, it does not check the local node's # status, and does not wait before fence action. # arg : nothing # return: 0 -> the local node is SBY # 1 -> the local node is ACT # check_sby_using_mount() { if grep -q "$device" /proc/mounts; then savelog info "this node is active." return 1 else savelog info "this node is standby." return 0 fi } # # Confirm the local node is ACT or SBY with sfex_stat command. # sfex_stat returns... # 0 -> the local node is ACT # 1 -> the local node is SBY # This function should return... # return: 0 -> the local node is SBY # 1 -> the local node is ACT, or failure occurs. # check_sby_using_sfex() { typeset status if [[ ! -x "${sfex_stat_path}" ]]; then savelog ERROR "Unable to use sfex_stat." return 1 fi "${sfex_stat_path}" -i "${index}" "${device}" >/dev/null 2>&1 status=$? savelog info "sfex_stat: status=$status" if [[ "$status" = 0 ]]; then return 1 else return 0 fi } # # Check whether the local node is SBY or ACT only when the parameter "no_sfex" # is not true. # arg : nothing # return: 0 -> the local node is SBY # 1 -> the local node is ACT, or there is no need to check the local # node's status. # check_if_sby() { if (echo ${no_sfex} | grep -q -i "^true$"); then #When node_sfex is true, #don't wait even if the local node is SBY node. return 1 fi check_sby_using_sfex return $? } # # Execute itself as process group leader. # args : whole command-line strings # (command path and args when this script is executed) # return: nothing (error exit when failure occurs) # become_leader() { exec perl -e 'setpgrp; exec @ARGV' "$@" if [[ "$?" != 0 ]]; then savelog ERROR "Unable to become leader." exit 1 fi } # # Check the stonith-wrapper process itself is a process group leader or not. # return: 0 -> I am a process group leader. # 1 -> I am not a process group leader. # is_this_leader() { typeset mypgid mypgid=$(ps --no-headers -o '%r' $$) mypgid=${mypgid##* } if [[ "$mypgid" == $$ ]]; then return 0 fi return 1 } # # Check validation and check required parameters are specified or not. # arg : nothing # return: nothing (error exit when failure occurs) # check_parameters() { #Check validation. if [[ -n "${sby_wait}" ]]; then if (echo ${sby_wait} | grep -q '[^0-9]') ; then savelog WARN "parameter \"sby_wait\" is not digit "\ "(value=${sby_wait}). "\ "use default value. (value=${default_sby_wait})" sby_wait=${default_sby_wait} fi fi #Check required parameters. if (echo ${no_sfex} | grep -q -i "^true$"); then #When no_sfex is true, #There is no required parameter. return fi if [[ -z "${device}" ]]; then savelog ERROR "parameter \"device\" is required "\ "when \"no_sfex\" is not true." exit 1 fi } # # Check whether the same section name is already specified or not. # Section name has to be unique in config file. # Because each plugin's parameter (ex. "wrapper_real_plugin", # "wrapper_status_timeout", and so on... anyway, parameters which name is # "wrapper_xxx") is managed with variables which format is # "
_". # arg1 : new-commer sectionname # return: 0 -> the same section name already exists # 1 -> the same section name does not exist yet # does_same_secname_exist() { newcomer="$1" i=0 while [[ 1 ]] do if [[ ${i} -ge ${pluginnum} ]]; then break fi secname="${seclist[${i}]}" if [[ "${newcomer}" = "${secname}" ]]; then return 0 fi i=`expr ${i} + 1` done return 1 } # # Parse config file and get real plugins' settings. # This function's roles are: # 1) hold section names in section-name-list. # 2) set parameters for stonith-wrapper("wrapper_xxx") as variables which # format is "
_=" # 3) hold parameters and its value for real plugin in the list. # The format is "parameter=value". # The list name is "
_real_prmlist". # arg : nothing # return: nothing (error exit when failure occurs) # parse_config_file() { linenum=0 #line number in config file. pluginnum=0 #how many plugins are set in config file. if [[ ! -f ${conf_file} ]]; then savelog ERROR "${conf_file} does not exist." exit 1 fi while read line; do linenum=`expr ${linenum} + 1` #Trim. line=`echo "${line}" | sed 's/^\s*//' | sed 's/\s*$//'` #Ignore empty or comment line. if [[ -z "${line}" ]]; then continue fi if (echo "${line}" | grep -q -e '^#' -e '^;'); then continue fi #Get section name. if (echo "${line}" | grep -q '^\[.*\]$'); then secname=`echo "${line}" | sed 's/^\[//' | sed 's/\]$//'` secname=`echo "${secname}" | sed 's/^\s*//' | sed 's/\s*$//'` #Section name should not be empty. if [[ -z "${secname}" ]]; then savelog ERROR "section name is empty. (line:${linenum})" exit 1 fi #Only alphabet or numeric characters are allowed #to be section name. if (echo "${secname}" | grep -q '\W'); then savelog ERROR "section name has non-alphanumeric characters. "\ "(line:${linenum}, section:${secname})" exit 1 fi #Section name should be unique in config file. if (does_same_secname_exist "${secname}"); then savelog ERROR "section name should be unique in config file. "\ "(line:${linenum}, section:${secname})" exit 1 fi #Add the section name to section list. seclist[${pluginnum}]="${secname}" pluginnum=`expr ${pluginnum} + 1` set_default_prmvalue "${secname}" continue fi if [[ -z "${secname}" ]]; then savelog ERROR "the line for parameter setting appears "\ "before section. (line:${linenum})" exit 1 fi #Get parameter name and value without space and tab characters. key=`echo ${line} | awk -F '=' '{print $1}'` key=`echo "${key}" | sed 's/^\s*//' | sed 's/\s*$//'` value=`echo ${line} | awk -F '=' '{print $2}'` value=`echo "${value}" | sed 's/^\s*//' | sed 's/\s*$//'` #Check validation. #Empty parameter name and value are not allowed. if [[ -z "${key}" ]]; then savelog WARN "parameter name is empty. "\ "Ignore the setting. (line:${linenum})" continue fi if [[ -z "${value}" ]]; then savelog WARN "parameter value is empty. "\ "Ignore the setting. (line:${linenum})" continue fi #Get parameter settings. if (echo "${key}" | grep -q '^wrapper_'); then #parameters for stonith-wrapper. #Make format secname_paramname=value eval "${secname}_${key}"=\"${value}\" else #parameters for real plugin. #Make format parameter_name=value #to add it to parameter list. param="${key}=${value}" eval real_prm_index=\${#"${secname}"_real_prmlist[*]} eval ${secname}_real_prmlist[${real_prm_index}]=\"${param}\" fi done < ${conf_file} if [[ ${pluginnum} -le 0 ]]; then savelog ERROR "no section is specified." exit 1 fi check_prmvalue_validation } # # For each real plugin's settings, set default value. # This function is should be called in parse_config_file(). # arg : nothing # return: nothing # set_default_prmvalue() { secname="$1" eval "${secname}_wrapper_real_plugin"=${default_real_plugin} eval "${secname}_wrapper_start_timeout"=${default_start_timeout} eval "${secname}_wrapper_status_timeout"=${default_status_timeout} eval "${secname}_wrapper_control_timeout"=${default_control_timeout} } # # For each real plugin's settings, check parameter value's validation. # If it founds invalid parameter, set default value. # This function is should be called in or after parse_config_file(). # arg : nothing # return: nothing # check_prmvalue_validation() { i=0 while [[ 1 ]] do if [[ ${i} -ge ${pluginnum} ]]; then break fi secname=${seclist[${i}]} #Check wrapper_start_timeout. It should be digit. eval value=\${${secname}_wrapper_start_timeout} if (echo ${value} | grep -q '[^0-9]') ; then savelog WARN "parameter \"wrapper_start_timeout\" "\ "for [${secname}] is not digit (value=${value}). "\ "use default value. (value=${default_start_timeout})" eval "${secname}_wrapper_start_timeout"=${default_start_timeout} fi #Check wrapper_status_timeout. It should be digit. eval value=\${${secname}_wrapper_status_timeout} if (echo ${value} | grep -q '[^0-9]') ; then savelog WARN "parameter \"wrapper_status_timeout\" "\ "for [${secname}] is not digit (value=${value}). "\ "use default value. (value=${default_status_timeout})" eval "${secname}_wrapper_status_timeout"=${default_status_timeout} fi #Check wrapper_control_timeout. It should be digit. eval value=\${${secname}_wrapper_control_timeout} if (echo ${value} | grep -q '[^0-9]') ; then savelog WARN "parameter \"wrapper_control_timeout\" "\ "for [${secname}] is not digit (value=${value}). "\ "use default value. (value=${default_control_timeout})" eval "${secname}_wrapper_control_timeout"=${default_control_timeout} fi i=`expr ${i} + 1` done } # # Calculate the sum total of timeout value for specified action. # arg1 : action name [gethosts|status|on|off|reset] # return: nothing (output sum total of timeout value.) # get_action_timeout_value() { total=0 buffer=10 timeout_type="" action="$1" case "${action}" in gethosts) timeout_type="wrapper_start_timeout" default_value=${default_start_timeout} ;; status) timeout_type="wrapper_status_timeout" default_value=${default_status_timeout} ;; on|off|reset) timeout_type="wrapper_control_timeout" default_value=${default_control_timeout} total=`expr ${total} + ${sby_wait}` ;; *) #It does not execute real plugin in other actions, #so no need to set timeout in stonith-wrapper. echo "0" return ;; esac i=0 while [[ 1 ]] do if [[ ${i} -ge ${pluginnum} ]]; then break fi secname="${seclist[${i}]}" eval value=\${${secname}_${timeout_type}} total=`expr ${total} + ${value}` i=`expr ${i} + 1` done #Add buffer to avoid that timeout for executing a plugin and timeout for #executing all plugins occur at the same time. total=`expr ${total} + ${buffer}` savelog debug "timeout for ${action} action is ${total} sec." echo "${total}" return } # # Kill all children of stonith-wrapper. # The difference with quit_if_timed_out() is # this function kills child-processes only, does not kill stonith-wrapper # itself. # arg : nothing # return: nothing # kill_all_children() { timer_popd=1 action_timeout_pid=`jobs -l | awk '$0 ~ /quit_if_timed_out/ {print $2}'` childrenpids=`ps --no-headers -o pid,pgid | awk -v pgid=$$ -v except=${action_timeout_pid} 'BEGIN{childlist=""}{if ($2 == pgid && $1 != pgid && $1 != except) {childlist=childlist" "$1}}END{print childlist}'` savelog WARN "timeout for a plugin's action popd. "\ "kill all child proccesses. (pids =${childrenpids})" kill -9 ${childrenpids} > /dev/null 2>&1 wait ${childrenpids} > /dev/null 2>&1 } # # Send SIGUSR1 after sleep to kill all child-processes when the timeout of # a plugin's action occurs. # When it receives SIGUSR1, kill_all_children() will be called. # arg1 : wait time (sec.) # return : nothing (error exit when failure occurs) # kill_plugin_if_timed_out() { typeset waitsec=$1 #After sending SIGUSR1, sleep for a while to be killed and be waited #by main process (in kill_all_children()). exec -a kill_plugin_if_timed_out perl -e "sleep $waitsec; kill SIGUSR1, $$;sleep 10" & if [[ $? != 0 ]]; then savelog ERROR "exec $FUNCNAME failed." exit 1 fi savelog debug "set timeout for executing one plugin. "\ "(waittime=${waitsec}sec. pid=$!)" } # # Unset timeout for a plugin's action which set in kill_plugin_if_timed_out(). # arg1 : plugin name # return : nothing # unset_kill_plugin_timer() { plugin_name="$1" timerpid=`jobs -l | awk '$0 ~ /kill_plugin_if_timed_out/ {print $2}'` if [[ -n "${timerpid}" ]]; then savelog debug "unset timer for ${plugin_name}. (pid=${timerpid})" kill -9 ${timerpid} > /dev/null 2>&1 wait ${timerpid} > /dev/null 2>&1 fi } # # Execute one real plugin. # This function's roles are: # 1) set timeout for the plugin's action. # 2) execute a real plugin with parameters which are specified in config file. # 3) wait until the real plugin returns. # 4) return the real plugin's return code. # arg1 : section name (written on config file) for the plugin to execute # arg2- : all arguments which is specified when stonith-wrapper is executed # return: real plugin's return code # exec_one_real_plugin() { secname="$1" shift action="$1" timeout_value=0 eval plugin_name=\${${secname}_wrapper_real_plugin} #Get timeout value and set timer. case "${action}" in gethosts) eval timeout_value=\${${secname}_wrapper_start_timeout} ;; status) eval timeout_value=\${${secname}_wrapper_status_timeout} ;; on|off|reset) eval timeout_value=\${${secname}_wrapper_control_timeout} ;; *) #It does not execute real plugin in other actions. return 0 ;; esac kill_plugin_if_timed_out ${timeout_value} #Get the real plugin's parameters. #To realize this, change IFS to '\n' temporarily. #Otherwise, when a parameter's value has space, #env command misunderstands "oh, there are two or more strings." eval real_prmnum=\${#"${secname}"_real_prmlist[*]} parameters="" cIFS=$IFS IFS=' ' j=0 while [[ 1 ]] do if [[ ${j} -ge ${real_prmnum} ]]; then break fi eval tmp=\${${secname}_real_prmlist[${j}]} parameters="${parameters} ${tmp}" j=`expr ${j} + 1` done #Now, execute the real plugin! #Execute as background to allow main process receive SIGNAL. savelog debug "execute [env ${parameters} ${0%/*}/${plugin_name} $@]." (env ${parameters} ${0%/*}/${plugin_name} "$@")& IFS=${cIFS} wait $! > /dev/null 2>&1 rc=$? savelog debug "${action} action with ${plugin_name} is complete. (rc=${rc})" return ${rc} } # # Execute all real plugins in the list even if some of them is failed. # arg1 : all arguments which is specified when stonith-wrapper is executed # return: 0 -> all real plugins succeeded # 1 -> one or more real plugins failed # exec_real_plugins_all() { action="$1" errcnt=0 i=0 while [[ 1 ]] do timer_popd=0 if [[ ${i} -ge ${pluginnum} ]]; then break fi secname=${seclist[${i}]} eval plugin_name=\${${secname}_wrapper_real_plugin} exec_one_real_plugin "${secname}" "$@" rc=$? unset_kill_plugin_timer "${plugin_name}" if [[ ${timer_popd} != 0 ]]; then savelog ERROR "${plugin_name} failed to do ${action} action. "\ "(Timed Out)" errcnt=`expr ${errcnt} + 1` elif [[ ${rc} != 0 ]]; then savelog ERROR "${plugin_name} failed to do ${action} action. "\ "(rc=${rc})" errcnt=`expr ${errcnt} + 1` fi i=`expr ${i} + 1` done if [[ ${errcnt} -gt 0 ]]; then return 1 fi return 0 } # # Execute real plugins in the list until it succeeds to do the action. # arg1 : all arguments which is specified when stonith-wrapper is executed # return: 0 -> a real plugin succeeded # 1 -> all real plugins failed # exec_real_plugins_till_it_succeed() { action="$1" errcnt=0 i=0 while [[ 1 ]] do timer_popd=0 if [[ ${i} -ge ${pluginnum} ]]; then break fi secname=${seclist[${i}]} eval plugin_name=\${${secname}_wrapper_real_plugin} exec_one_real_plugin "${secname}" "$@" rc=$? #Check whether the real plugin succeeds in fencing or not. #There are 2 criteria for judging. #1)In the case which real plugin's return code is 0, # it means "fencing is complete successfully". #2)In the case which real plugin's return code is _not_ 0, then # - If the parameter named "wrapper_nodeip*" are specified for the # plugin, it judges whether fencing is complete or not based on # "nodeips are dead or alive". # When all IP address are dead, it means "fencing succeeded." # When even if one IP address is alive, it means "fencing is failed." # - If the plugin doesn't have any "wrapper_nodeip*", then # it just judges "fencing is failed" from return code. if [[ ${rc} = 0 ]]; then #action succeeded. unset_kill_plugin_timer "${plugin_name}" return 0 fi if [[ ${timer_popd} != 0 ]]; then savelog ERROR "${plugin_name} failed to do ${action} action. "\ "(Timed Out)" else eval nodeip_list=\${!${secname}_wrapper_nodeip*} if [[ -n "${nodeip_list}" ]]; then savelog info "waiting for the target to be dead." while [[ 1 ]]; do if [[ ${timer_popd} != 0 ]]; then #Wait until timeout occurs, but nodeip* is alive. #It means "fencing is failed!" savelog ERROR "${plugin_name} failed to do "\ "${action} action. (nodeip is alive)" break fi ok_if_target_died "${secname}" died=$? if [[ ${died} = 0 ]]; then #All nodeip* are dead. #It means "fencing succeeded!" savelog info "all nodeips are dead." unset_kill_plugin_timer "${plugin_name}" return 0 fi sleep 1 done else savelog ERROR "${plugin_name} failed to do ${action} action. "\ "(rc=${rc})" fi fi unset_kill_plugin_timer "${plugin_name}" i=`expr ${i} + 1` done return 1 } # # Output all configurations. # arg : nothing # return: nothing # output_all_config() { i=0 while [[ 1 ]] do if [[ ${i} -ge ${pluginnum} ]]; then break fi secname=${seclist[${i}]} eval plugin_name=\${${secname}_wrapper_real_plugin} eval start_timeout=\${${secname}_wrapper_start_timeout} eval status_timeout=\${${secname}_wrapper_status_timeout} eval control_timeout=\${${secname}_wrapper_control_timeout} eval real_prmnum=\${#"${secname}"_real_prmlist[*]} real_params="" if [[ ${real_prmnum} -gt 0 ]]; then #Output all parameters for real plugin. eval real_params=\${"${secname}"_real_prmlist[@]} fi nodeips="" eval nodeip_list=\${!${secname}_wrapper_nodeip*} if [[ -n "$nodeip_list" ]]; then for vname in ${nodeip_list}; do eval ip=\$$vname nodeips="${nodeips} ${ip}" done fi nodeips=`echo "${nodeips}" | sed 's/^\s*//' | sed 's/\s*$//'` savelog debug "plugin[${i}] -> type: ${plugin_name}, "\ "start_timeout(s): ${start_timeout}, "\ "status_timeout(s): ${status_timeout}, "\ "control_timeout(s): ${control_timeout}, "\ "nodeip: [${nodeips}], "\ "parameters: [${real_params}]" i=`expr ${i} + 1` done } #################### # Main function #################### trap 'kill_all_children' SIGUSR1 if ! is_this_leader; then become_leader $0 "$@" fi savelog debug "Enter: $@" case "$1" in gethosts) #Parse settings. check_parameters parse_config_file output_all_config #Set action timeout. action_timeout=`get_action_timeout_value "$1"` quit_if_timed_out ${action_timeout} $$ #Execute all real_plugins. exec_real_plugins_all "$@" kill_and_exit $? ;; on) #Parse settings. check_parameters parse_config_file output_all_config #Set action timeout. action_timeout=`get_action_timeout_value "$1"` quit_if_timed_out ${action_timeout} $$ #Execute real_plugins until STONITH succeeds. exec_real_plugins_till_it_succeed "$@" kill_and_exit $? ;; off|reset) #Parse settings. check_parameters parse_config_file output_all_config ok_if_admin_judges_so #Set action timeout. action_timeout=`get_action_timeout_value "$1"` quit_if_timed_out ${action_timeout} $$ #Wait for a while if the local node is SBY. if check_if_sby; then savelog info "sby_wait($sby_wait)" sleep $sby_wait fi #Execute real_plugins until STONITH succeeds. exec_real_plugins_till_it_succeed "$@" rc=$? if [[ ${rc} = 0 ]]; then kill_and_exit 0 fi #Wait admin's judgement until action timeout occurs. savelog info "waiting administrator's judgement. "\ "(targetfile=${admins_direction})" while true; do ok_if_admin_judges_so sleep 1 done ;; status) #Parse settings. check_parameters parse_config_file output_all_config #Set action timeout. action_timeout=`get_action_timeout_value "$1"` quit_if_timed_out ${action_timeout} $$ #Execute all real_plugins. exec_real_plugins_all "$@" kill_and_exit 0 ;; getconfignames) #No required paramter. exit 0 ;; getinfo-devid) echo "External STONITH plugin for wrapping plugins" exit 0 ;; getinfo-devname) echo "External STONITH plugin for wrapping one or more external STONITH plugins" exit 0 ;; getinfo-devdescr) echo "wrapper for external STONITH plugins." echo "To realize the following funcs." echo " - set fence timeout for each plugins." echo " - kill all child-processes when an operation timeout occurs." echo " - avoid fencing each other when Sprit-Brain occurs." echo " - realize escalation." echo " (if the plugin with higher priority is failed," echo " execute the lower one)" echo " - confirm that fencing is complete or not with ping command." echo " It's effective when STONITH device's power source is common" echo " with its host machine." echo " - allow administrator to break infinity loop which occurs" echo " because all STONITH plugins are failed." exit 0 ;; getinfo-devurl) echo "http://moin.linux-ha.org/lha/ja/StonithWrapper_ja" exit 0 ;; getinfo-xml) cat << XML Wait sec. for standby node time (sec.) to wait before fencing the target node when the local node is standby. To avoid fencing each other when Split-Brain occurs. Default is 15. Don't check the local is active/standby. If it is "true", stonith-wrapper does not check the local node's status ([active|standby]). If it is not "true" or not set, stonith-wrapper checks that with sfex_stat command before fencing, and wait for a while when it is standby. Default is "FALSE". device for sfex's control data Block device path that stores exclusive control data. When the parameter "no_sfex" is not true, this parameter is required. block device index for sfex Position in block device where exclusive control data for sfex is stored. 1 or more is specified. Default is 1. XML exit 0 ;; verify) #Check validation of config file. parse_config_file output_all_config exit 0 ;; *) exit 1 ;; esac # vim: set ai ts=8 sw=4: