diff --git a/agents/heuristics_resource/fence_heuristics_resource.py b/agents/heuristics_resource/fence_heuristics_resource.py index b1ceec7e..bcd7c89b 100755 --- a/agents/heuristics_resource/fence_heuristics_resource.py +++ b/agents/heuristics_resource/fence_heuristics_resource.py @@ -1,160 +1,193 @@ -#!/usr/libexec/platform-python -tt +#!@PYTHON@ -tt import io import re import subprocess import shlex import sys, stat import logging import atexit import time +import xml.etree.ElementTree as ET +import distutils.util as dist sys.path.append("/usr/share/fence") from fencing import fail_usage, run_command, fence_action, all_opt from fencing import atexit_handler, check_input, process_input, show_docs from fencing import run_delay def heuristics_resource(con, options): # Search the node where the resource is running and determine # the ACT node or not. For SBY node, a delay is generated. # Note that this method always returns FALSE. if not "--nodename" in options or options["--nodename"] == "": logging.error("nodename parameter required") return False if not "--resource" in options or options["--resource"] == "": logging.error("resource parameter required") return False target = options["--nodename"] - resource = options["--resource"] - promotable = options["--promotable"] in ["", "1"] - standby_wait = int(options["--standby-wait"]) - crm_resource_path = options["--crm-resource-path"] + resource_id = options["--resource"] + wait_time = int(options["--standby-wait"]) crm_node_path = options["--crm-node-path"] + crm_mon_path = options["--crm-mon-path"] (rc, out, err) = run_command(options, "%s --name" % crm_node_path) - if rc != 0 or out == None: + if not rc == 0 or out is None: logging.error("Can not get my nodename. rc=%s, stderr=%s" % (rc, err)) return False - mynodename = out.strip() + node = out.strip() - if mynodename == target: + if node == target: logging.info("Skip standby wait due to self-fencing.") return False - (rc, out, err) = run_command(options, "%s -r %s -W" % (crm_resource_path, resource)) - if rc != 0 or out == None: - logging.error("Command failed. rc=%s, stderr=%s" % (rc, err)) + (rc, out, err) = run_command(options, "%s --as-xml" % crm_mon_path) + if not rc == 0 or out is None: + logging.error("crm_mon command failed. rc=%s, stderr=%s" % (rc, err)) return False - search_str = re.compile(r"\s%s%s$" % (mynodename, '\sMaster' if promotable else '')) - for line in out.splitlines(): - searchres = search_str.search(line.strip()) - if searchres: - logging.info("This node is ACT! Skip standby wait.") - return False - - logging.info("Resource %s NOT found on this node" % resource) - - if standby_wait > 0: - # The SBY node waits for fencing from the ACT node, and tries to fence - # the ACT node on next fencing level waking up from sleep. - logging.info("Standby wait %s sec" % standby_wait) - time.sleep(standby_wait) - + tree = ET.fromstring(out) + resources = tree.findall('./resources//*[@id="%s"]' % resource_id) + if len(resources) == 0: + logging.error("Resource '%s' not found." % resource_id) + elif len(resources) == 1: + resource = resources[0] + type = resource.tag + if type == "resource": + # primitive resource + standby_node = check_standby_node(resource, node) + failed = check_failed_attrib(resource) + if standby_node and not failed: + return standby_wait(wait_time) + elif type == "group": + # resource group + standby_node = True + failed = False + for child in resource: + failed |= check_failed_attrib(child) + standby_node &= check_standby_node(child, node) + if standby_node and not failed: + return standby_wait(wait_time) + elif type == "clone" and dist.strtobool(resource.get("multi_state")): + # promotable resource + master_nodes = 0 + standby_node = True + failed = False + for native in resource: + failed |= check_failed_attrib(native) + if native.get("role") in ["Master"]: + master_nodes += 1 + standby_node &= check_standby_node(native, node) + if master_nodes == 1 and standby_node and not failed: + return standby_wait(wait_time) + else: + # clone or bundle resource + logging.error("Unsupported resource type: '%s'" % type) + else: + logging.error("Multiple active resources found.") + + logging.info("Skip standby wait.") return False +def standby_wait(wait_time): + logging.info("Standby wait %s sec" % wait_time) + time.sleep(wait_time) + return False + +def check_failed_attrib(resource): + failed = dist.strtobool(resource.get("failed")) + ignored = dist.strtobool(resource.get("failure_ignored")) + return failed and not ignored + +def check_standby_node(resource, nodename): + running_nodes = [] + for node in resource: + running_nodes.append(node.get("name")) + return len(set(running_nodes)) == 1 and not running_nodes[0] == nodename def define_new_opts(): all_opt["nodename"] = { "getopt" : "n:", "longopt" : "nodename", "required" : "1", "help" : "-n, --nodename=[nodename] Name of node to be fenced", "shortdesc" : "Name of node to be fenced", "default" : "", "order" : 1 } all_opt["resource"] = { "getopt" : "r:", "longopt" : "resource", "required" : "1", - "help" : "-r, --resource=[resource-id] ID of the resource that should be running in the ACT node", - "shortdesc" : "Resource ID", + "help" : "-r, --resource=[resource-id] ID of the resource that should be running on the ACT node. It does not make sense to specify a cloned or bundled resource unless it is promotable and has only a single master instance.", + "shortdesc" : "Resource ID. It does not make sense to specify a cloned or bundled resource unless it is promotable and has only a single master instance.", "default" : "", "order" : 1 } - all_opt["promotable"] = { - "getopt" : "p", - "longopt" : "promotable", - "required" : "0", - "help" : "-p, --promotable Specify if resource parameter is promotable (master/slave) resource", - "shortdesc" : "Handle the promotable resource. The node on which the master resource is running is considered as ACT.", - "default" : "False", - "order" : 1 - } all_opt["standby_wait"] = { "getopt" : "w:", "longopt" : "standby-wait", "required" : "0", - "help" : "-w, --standby-wait=[seconds] Wait X seconds on SBY node. If a positive number is specified, fencing action of this agent will always succeed after waits.", - "shortdesc" : "Wait X seconds on SBY node. If a positive number is specified, fencing action of this agent will always succeed after waits.", - "default" : "0", + "help" : "-w, --standby-wait=[seconds] Wait X seconds on SBY node. The agent will delay but not succeed.", + "shortdesc" : "Wait X seconds on SBY node. The agent will delay but not succeed.", + "default" : "5", "order" : 1 } - all_opt["crm_resource_path"] = { + all_opt["crm_mon_path"] = { "getopt" : ":", - "longopt" : "crm-resource-path", + "longopt" : "crm-mon-path", "required" : "0", - "help" : "--crm-resource-path=[path] Path to crm_resource", - "shortdesc" : "Path to crm_resource command", - "default" : "@CRM_RESOURCE_PATH@", + "help" : "--crm-mon-path=[path] Path to crm_mon", + "shortdesc" : "Path to crm_mon command", + "default" : "@CRM_MON_PATH@", "order" : 1 } all_opt["crm_node_path"] = { "getopt" : ":", "longopt" : "crm-node-path", "required" : "0", "help" : "--crm-node-path=[path] Path to crm_node", "shortdesc" : "Path to crm_node command", "default" : "@CRM_NODE_PATH@", "order" : 1 } def main(): - device_opt = ["no_status", "no_password", "nodename", "resource", "promotable", "standby_wait", "crm_resource_path", "crm_node_path", "method"] + device_opt = ["no_status", "no_password", "nodename", "resource", "standby_wait", "crm_mon_path", "crm_node_path", "method"] define_new_opts() atexit.register(atexit_handler) all_opt["method"]["default"] = "cycle" all_opt["method"]["help"] = "-m, --method=[method] Method to fence (cycle|onoff) (Default: cycle)" options = check_input(device_opt, process_input(device_opt)) docs = {} docs["shortdesc"] = "Fence agent for resource-heuristic based fencing delay" docs["longdesc"] = "fence_heuristics_resource uses resource-heuristics to delay execution of fence agent running on next level.\ \n.P\n\ This is not a fence agent by itself! \ Its only purpose is to delay execution of another fence agent that lives on next fencing level. \ Note that this agent always returns FALSE. Therefore, subsequent agents on the same fencing level will not run" docs["vendorurl"] = "" show_docs(options, docs) run_delay(options) result = fence_action(\ None, \ options, \ None, \ None, \ reboot_cycle_fn = heuristics_resource, sync_set_power_fn = heuristics_resource) sys.exit(result) if __name__ == "__main__": main() diff --git a/configure.ac b/configure.ac index d7d8ccfe..b40f9a93 100644 --- a/configure.ac +++ b/configure.ac @@ -1,408 +1,408 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) AC_INIT([fence-agents], m4_esyscmd([make/git-version-gen .tarball-version]), [developers@clusterlabs.org]) AC_CONFIG_AUX_DIR([.]) AM_INIT_AUTOMAKE([-Wno-portability dist-bzip2 dist-xz subdir-objects]) LT_PREREQ([2.2.6]) LT_INIT AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([lib/fencing.py.py]) AC_CONFIG_HEADERS([make/clusterautoconfig.h]) AC_CANONICAL_HOST AC_PROG_LIBTOOL AC_LANG([C]) # Sanitize path if test "$prefix" = "NONE"; then prefix="/usr" if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi if test "$libdir" = "\${exec_prefix}/lib"; then if test -e /usr/lib64; then libdir="/usr/lib64" else libdir="/usr/lib" fi fi fi case $exec_prefix in NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac # Checks for programs. # check stolen from gnulib/m4/gnu-make.m4 if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then AC_MSG_ERROR([you don't seem to have GNU make; it is required]) fi AC_PROG_CC AM_PROG_CC_C_O AC_PROG_LN_S AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_AWK AC_PROG_CXX AC_PROG_RANLIB ## local helper functions # this function checks if CC support options passed as # args. Global CFLAGS are ignored during this test. cc_supports_flag() { local CFLAGS="$@" AC_MSG_CHECKING([whether $CC supports "$@"]) AC_COMPILE_IFELSE([int main(){return 0;}] , [RC=0; AC_MSG_RESULT([yes])], [RC=1; AC_MSG_RESULT([no])]) return $RC } # this function tests if a library has a certain function # by using AC_CHECK_LIB but restores the original LIBS global # envvar. This is required to avoid libtool to link everything # with everything. check_lib_no_libs() { AC_CHECK_LIB([$1], [$2],, [AC_MSG_ERROR([Unable to find $1 library])]) LIBS=$ac_check_lib_save_LIBS } # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h netdb.h stddef.h sys/socket.h sys/time.h syslog.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT32_T # Checks for library functions. AC_FUNC_FORK AC_FUNC_MALLOC AC_CHECK_FUNCS([alarm atexit bzero dup2 memmove memset select socket strcasecmp strchr strdup strerror strtol]) # local options AC_ARG_ENABLE([debug], [ --enable-debug enable debug build. ], [ default="no" ]) AC_ARG_WITH([fenceagentslibdir], [ --with-fenceagentslibdir=PATH installation path for fence library. ], [ FENCEAGENTSLIBDIR="$withval" ], [ FENCEAGENTSLIBDIR="${datadir}/fence" ]) AC_ARG_WITH([default-config-dir], [ --with-default-config-dir=DIR cluster config directory. ], [ DEFAULT_CONFIG_DIR="$withval" ], [ DEFAULT_CONFIG_DIR="$sysconfdir/cluster" ]) AC_ARG_WITH([default-config-file], [ --with-default-config-file=FILE cluster config file. ], [ DEFAULT_CONFIG_FILE="$withval" ], [ DEFAULT_CONFIG_FILE="cluster.conf" ]) AC_ARG_WITH([agents], [ --with-agents=LIST list of agents to build/ship (default: all). ], [ AGENTS_LIST="$withval" ], [ AGENTS_LIST="all" ]) if test "x$AGENTS_LIST" = x; then AC_ERROR([No agents selected]) fi FENCE_KDUMP=0 if echo "$AGENTS_LIST" | grep -q -E "all|kdump"; then case "$host_os" in *bsd*) ;; *) FENCE_KDUMP=1 ;; esac AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/kdump( |$)//") fi FENCE_MANUAL=0 if echo "$AGENTS_LIST" | grep -q -E "all|manual"; then FENCE_MANUAL=1 AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/manual( |$)//") fi FENCE_MPATH=0 if echo "$AGENTS_LIST" | grep -q -E "all|mpath"; then FENCE_MPATH=1 fi FENCE_SCSI=0 if echo "$AGENTS_LIST" | grep -q -E "all|scsi"; then FENCE_SCSI=1 fi FENCE_ZVM=0 if echo "$AGENTS_LIST" | grep -q -E "all|zvm( |$)"; then FENCE_ZVM=1 fi if test "x$AGENTS_LIST" != xall; then for j in $AGENTS_LIST; do if ! test -f agents/$j/fence_$j*.py; then AC_ERROR([Agent $j does not exists]) fi AGENTS_LIST=`echo "$AGENTS_LIST" | sed -E -e "s#$j([^_/]|$)#$j/fence_$j\1#g" -e "s#zvm/fence_zvm( |$)#zvm/fence_zvmip\1#g"` done fi if test "x$AGENTS_LIST" = xall; then AGENTS_LIST=`find $srcdir/agents -mindepth 2 -maxdepth 2 -name 'fence_*.py' -print0 | xargs -0 | sed -e 's#[^ ]*/agents/##g' -e 's#lib/[A-Za-z_.]* ##g' -e 's#nss_wrapper/[A-Za-z_.]* ##g' -e 's#autodetect/[A-Za-z_.]* ##g'` fi XENAPILIB=0 if echo "$AGENTS_LIST" | grep -q xenapi; then XENAPILIB=1 fi ## random vars LOGDIR=${localstatedir}/log/cluster CLUSTERVARRUN=${localstatedir}/run/cluster CLUSTERDATA=${datadir}/cluster AC_PATH_PROGS(XMLLINT, xmllint) AM_CONDITIONAL(BUILD_DOC, test "x$XMLLINT" != "x" ) if test "x$XMLLINT" = "x"; then AC_MSG_WARN([xmllint not installed, unable to (re-)build manual pages]) exit 1 fi AC_SUBST(XMLLINT) AC_PATH_PROGS(XSLTPROC, xsltproc) AM_CONDITIONAL(BUILD_DOC, test "x$XSLTPROC" != "x" ) if test "x$XSLTPROC" = "x"; then AC_MSG_WARN([xsltproc not installed, unable to (re-)build manual pages]) exit 1 fi AC_SUBST(XSLTPROC) dnl Ensure PYTHON is an absolute path AC_PATH_PROG([PYTHON], [$PYTHON]) AM_PATH_PYTHON if test -z "$PYTHON"; then echo "*** Essential program python not found" 1>&2 exit 1 fi AC_PYTHON_MODULE(pexpect, 1) AC_PYTHON_MODULE(pycurl, 1) AC_PYTHON_MODULE(requests, 1) if echo "$AGENTS_LIST" | grep -q amt_ws; then AC_PYTHON_MODULE(pywsman) if test "x${HAVE_PYMOD_PYWSMAN}" != xyes; then AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#amt_ws/fence_amt_ws.py( |$)##") AC_MSG_WARN("Not building fence_amt_ws") fi fi if echo "$AGENTS_LIST" | grep -q aws; then AC_PYTHON_MODULE(boto3) if test "x${HAVE_PYMOD_BOTO3}" != xyes; then AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#aws/fence_aws.py( |$)##") AC_MSG_WARN("Not building fence_aws") fi fi if echo "$AGENTS_LIST" | grep -q -E "ovh|vmware_soap"; then AC_PYTHON_MODULE(suds) if test "x${HAVE_PYMOD_SUDS}" != xyes; then AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#(ovh/fence_ovh|vmware_soap/fence_vmware_soap).py( |$)##g") AC_MSG_WARN("Not building fence_ovh and fence_vmware_soap") fi fi if echo "$AGENTS_LIST" | grep -q gce; then AC_PYTHON_MODULE(googleapiclient) if test "x${HAVE_PYMOD_GOOGLEAPICLIENT}" != xyes; then AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#gce/fence_gce.py( |$)##") AC_MSG_WARN("Not building fence_ovh and fence_gce") fi fi if echo "$AGENTS_LIST" | grep -q openstack; then AC_PYTHON_MODULE(novaclient) AC_PYTHON_MODULE(keystoneauth1) AC_PYTHON_MODULE(keystoneclient) if test "x${HAVE_PYMOD_NOVACLIENT}" != xyes || \ (test "x${HAVE_PYMOD_KEYSTONEAUTH1}" != xyes || \ test "x${HAVE_PYMOD_KEYSTONECLIENT}" != xyes); then AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#openstack/fence_openstack.py( |$)##") AC_MSG_WARN("Not building fence_openstack") fi fi ## path to 3rd-party binaries AC_PATH_PROG([IPMITOOL_PATH], [ipmitool], [/usr/bin/ipmitool]) AC_PATH_PROG([OPENSTACK_PATH], [openstack], [/usr/bin/openstack]) AC_PATH_PROG([AMTTOOL_PATH], [amttool], [/usr/bin/amttool]) AC_PATH_PROG([GNUTLSCLI_PATH], [gnutlscli], [/usr/bin/gnutls-cli]) AC_PATH_PROG([COROSYNC_CMAPCTL_PATH], [corosync-cmapctl], [/usr/sbin/corosync-cmapctl]) AC_PATH_PROG([SG_PERSIST_PATH], [sg_persist], [/usr/bin/sg_persist]) AC_PATH_PROG([SG_TURS_PATH], [sg_turs], [/usr/bin/sg_turs]) AC_PATH_PROG([VGS_PATH], [vgs], [/usr/sbin/vgs]) AC_PATH_PROG([SUDO_PATH], [sudo], [/usr/bin/sudo]) AC_PATH_PROG([SSH_PATH], [ssh], [/usr/bin/ssh]) AC_PATH_PROG([TELNET_PATH], [telnet], [/usr/bin/telnet]) AC_PATH_PROG([MPATH_PATH], [mpathpersist], [/usr/sbin/mpathpersist]) AC_PATH_PROG([SBD_PATH], [sbd], [/sbin/sbd]) AC_PATH_PROG([SUDO_PATH], [sudo], [/usr/bin/sudo]) AC_PATH_PROG([SNMPWALK_PATH], [snmpwalk], [/usr/bin/snmpwalk]) AC_PATH_PROG([SNMPSET_PATH], [snmpset], [/usr/bin/snmpset]) AC_PATH_PROG([SNMPGET_PATH], [snmpget], [/usr/bin/snmpget]) AC_PATH_PROG([NOVA_PATH], [nova], [/usr/bin/nova]) AC_PATH_PROG([POWERMAN_PATH], [powerman], [/usr/bin/powerman]) -AC_PATH_PROG([CRM_RESOURCE_PATH], [crm_resource], [/usr/sbin/crm_resource]) +AC_PATH_PROG([CRM_MON_PATH], [crm_mon], [/usr/sbin/crm_mon]) AC_PATH_PROG([CRM_NODE_PATH], [crm_node], [/usr/sbin/crm_node]) AC_PATH_PROG([PING_CMD], [ping]) AC_PATH_PROG([PING6_CMD], [ping6]) AC_PATH_PROG([PING4_CMD], [ping4]) if test "x${ac_cv_path_PING_CMD}" = x; then # assume multicall-ping just not available in build-environment PING_CMD="/bin/ping" PING4_CMD="/bin/ping -4" PING6_CMD="/bin/ping -6" elif test "x${ac_cv_path_PING6_CMD}" = x; then # just IPv4 PING4_CMD="${ac_cv_path_PING_CMD}" elif test -L ${ac_cv_path_PING6_CMD}; then # assume multicall-ping PING4_CMD="${ac_cv_path_PING_CMD} -4" else # ping is just IPv4 PING4_CMD="${ac_cv_path_PING_CMD}" fi ## do subst AC_SUBST([DEFAULT_CONFIG_DIR]) AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_DIR], "$(eval echo ${DEFAULT_CONFIG_DIR})", [Default config directory]) AC_SUBST([DEFAULT_CONFIG_FILE]) AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_FILE], "$(eval echo ${DEFAULT_CONFIG_FILE})", [Default config file]) AC_SUBST([LOGDIR]) AC_DEFINE_UNQUOTED([LOGDIR], "$(eval echo ${LOGDIR})", [Default logging directory]) AC_SUBST([CLUSTERVARRUN]) AC_DEFINE_UNQUOTED([CLUSTERVARRUN], "$(eval echo ${CLUSTERVARRUN})", [Default cluster var/run directory]) AC_SUBST([CLUSTERDATA]) AC_SUBST([FENCEAGENTSLIBDIR]) AC_SUBST([SNMPBIN]) AC_SUBST([AGENTS_LIST]) AM_CONDITIONAL(BUILD_FENCE_KDUMP, test $FENCE_KDUMP -eq 1) AM_CONDITIONAL(BUILD_FENCE_MANUAL, test $FENCE_MANUAL -eq 1) AM_CONDITIONAL(BUILD_FENCE_MPATH, test $FENCE_MPATH -eq 1) AM_CONDITIONAL(BUILD_FENCE_SCSI, test $FENCE_SCSI -eq 1) AM_CONDITIONAL(BUILD_FENCE_ZVM, test $FENCE_ZVM -eq 1) AM_CONDITIONAL(BUILD_XENAPILIB, test $XENAPILIB -eq 1) AC_SUBST([IPMITOOL_PATH]) AC_SUBST([OPENSTACK_PATH]) AC_SUBST([AMTTOOL_PATH]) AC_SUBST([COROSYNC_CMAPCTL_PATH]) AC_SUBST([SG_PERSIST_PATH]) AC_SUBST([SG_TURS_PATH]) AC_SUBST([VGS_PATH]) AC_SUBST([POWERMAN_PATH]) ## *FLAGS handling ENV_CFLAGS="$CFLAGS" ENV_CPPFLAGS="$CPPFLAGS" ENV_LDFLAGS="$LDFLAGS" # debug build stuff if test "x${enable_debug}" = xyes; then AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code]) OPT_CFLAGS="-O0" else OPT_CFLAGS="-O2" fi # gdb flags if test "x${GCC}" = xyes; then GDB_FLAGS="-ggdb3" else GDB_FLAGS="-g" fi # extra warnings EXTRA_WARNINGS="" WARNLIST=" all shadow missing-prototypes missing-declarations strict-prototypes declaration-after-statement pointer-arith write-strings cast-align bad-function-cast missing-format-attribute format=2 format-security format-nonliteral no-long-long unsigned-char gnu89-inline no-strict-aliasing " for j in $WARNLIST; do if cc_supports_flag -W$j; then EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j"; fi done CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS \ $EXTRA_WARNINGS $WERROR_CFLAGS" CPPFLAGS="-I\$(top_builddir)/make -I\$(top_srcdir)/make -I. $ENV_CPPFLAGS" LDFLAGS="$ENV_LDFLAGS" AM_EXTRA_RECURSIVE_TARGETS([xml-check xml-upload]) AC_CONFIG_FILES([Makefile agents/Makefile lib/Makefile doc/Makefile]) AC_OUTPUT diff --git a/make/fencebuild.mk b/make/fencebuild.mk index 7f057ea6..a552d74f 100644 --- a/make/fencebuild.mk +++ b/make/fencebuild.mk @@ -1,87 +1,87 @@ define gen_agent_from_py mkdir -p `dirname $@` cat $(abs_srcdir)/$@.py | \ sed \ -e 's#@''PYTHON@#${PYTHON}#g' \ -e 's#@''RELEASE_VERSION@#${VERSION}#g' \ -e 's#@''FENCEAGENTSLIBDIR@#${FENCEAGENTSLIBDIR}#g' \ -e 's#@''LOGDIR@#${LOGDIR}#g' \ -e 's#@''SBINDIR@#${sbindir}#g' \ -e 's#@''LIBEXECDIR@#${libexecdir}#g' \ -e 's#@''IPMITOOL_PATH@#${IPMITOOL_PATH}#g' \ -e 's#@''OPENSTACK_PATH@#${OPENSTACK_PATH}#g' \ -e 's#@''AMTTOOL_PATH@#${AMTTOOL_PATH}#g' \ -e 's#@''GNUTLSCLI_PATH@#${GNUTLSCLI_PATH}#g' \ -e 's#@''COROSYNC_CMAPCTL_PATH@#${COROSYNC_CMAPCTL_PATH}#g' \ -e 's#@''SG_PERSIST_PATH@#${SG_PERSIST_PATH}#g' \ -e 's#@''SG_TURS_PATH@#${SG_TURS_PATH}#g' \ -e 's#@''VGS_PATH@#${VGS_PATH}#g' \ -e 's#@''SUDO_PATH@#${SUDO_PATH}#g' \ -e 's#@''SSH_PATH@#${SSH_PATH}#g' \ -e 's#@''TELNET_PATH@#${TELNET_PATH}#g' \ -e 's#@''MPATH_PATH@#${MPATH_PATH}#g' \ -e 's#@''SBD_PATH@#${SBD_PATH}#g' \ -e 's#@''STORE_PATH@#${CLUSTERVARRUN}#g' \ -e 's#@''SUDO_PATH@#${SUDO_PATH}#g' \ -e 's#@''SNMPWALK_PATH@#${SNMPWALK_PATH}#g' \ -e 's#@''SNMPSET_PATH@#${SNMPSET_PATH}#g' \ -e 's#@''SNMPGET_PATH@#${SNMPGET_PATH}#g' \ -e 's#@''NOVA_PATH@#${NOVA_PATH}#g' \ -e 's#@''POWERMAN_PATH@#${POWERMAN_PATH}#g' \ - -e 's#@''CRM_RESOURCE_PATH@#${CRM_RESOURCE_PATH}#g' \ + -e 's#@''CRM_MON_PATH@#${CRM_MON_PATH}#g' \ -e 's#@''CRM_NODE_PATH@#${CRM_NODE_PATH}#g' \ -e 's#@''PING_CMD@#${PING_CMD}#g' \ -e 's#@''PING6_CMD@#${PING6_CMD}#g' \ -e 's#@''PING4_CMD@#${PING4_CMD}#g' \ > $@ if [ 0 -eq `echo "$(@)" | grep fence_ > /dev/null 2>&1; echo $$?` ]; then \ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(top_srcdir)/lib/check_used_options.py $@; \ else true ; fi for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ cp -f $(@) $(@D)/$$x; \ $(MAKE) $(@D)/$$x.8; \ done endef # dependency, one on one $(foreach t,$(TARGET),$(eval $(t) : $(t:=.py))) # rule $(TARGET): $(call gen_agent_from_py) clean: clean-man rm -f $(CLEAN_TARGET:%.8=%) $(CLEAN_TARGET_ADDITIONAL) $(mpathdata_SCRIPTS) $(scsidata_SCRIPTS) */*.pyc *.pyc */*.wiki if [ "$(abs_builddir)" = "$(abs_top_builddir)/lib" ]; then \ rm -rf $(TARGET) __pycache__; \ fi clean-local: clean install-exec-hook: $(TARGET) if [ -n "$(man8dir)" ]; then \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ fi for p in $(TARGET); do \ dir=`dirname $$p`; \ for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ echo " $(INSTALL_SCRIPT) $$dir/$$x '$(DESTDIR)$(sbindir)'"; \ $(INSTALL_SCRIPT) $$dir/$$x "$(DESTDIR)$(sbindir)" || exit $$?; \ echo " $(INSTALL_DATA) '$$dir/$$x.8' '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) "$$dir/$$x.8" "$(DESTDIR)$(man8dir)" || exit $$?; \ done; \ done uninstall-hook: $(TARGET) files=`for p in $(TARGET); do \ for x in \`PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"\`; do \ echo " rm -f '$(DESTDIR)$(sbindir)/$$x'"; \ rm -f "$(DESTDIR)$(sbindir)/$$x"; \ echo " rm -f '$(DESTDIR)$(man8dir)/$$x.8'"; \ rm -f "$(DESTDIR)$(man8dir)/$$x.8"; \ done; \ done` diff --git a/tests/data/metadata/fence_heuristics_resource.xml b/tests/data/metadata/fence_heuristics_resource.xml index 157b98fc..4ac693cf 100644 --- a/tests/data/metadata/fence_heuristics_resource.xml +++ b/tests/data/metadata/fence_heuristics_resource.xml @@ -1,119 +1,114 @@ fence_heuristics_resource uses resource-heuristics to delay execution of fence agent running on next level. This is not a fence agent by itself! Its only purpose is to delay execution of another fence agent that lives on next fencing level. Note that this agent always returns FALSE. Therefore, subsequent agents on the same fencing level will not run Fencing action + + + Path to crm_mon command + Path to crm_node command - - - Path to crm_resource command - Method to fence Name of node to be fenced - - - - Handle the promotable resource. The node on which the master resource is running is considered as ACT. - - Resource ID + Resource ID. It does not make sense to specify a cloned or bundled resource unless it is promotable and has only a single master instance. - - Wait X seconds on SBY node. If a positive number is specified, fencing action of this agent will always succeed after waits. + + Wait X seconds on SBY node. The agent will delay but not succeed. Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. Verbose mode Write debug information to given file Write debug information to given file Display version information and exit Display help and exit Wait X seconds before fencing is started Wait X seconds for cmd prompt after login Test X seconds for status change after ON/OFF Wait X seconds after issuing ON/OFF Wait X seconds for cmd prompt after issuing command Count of attempts to retry power on