diff --git a/configure.ac b/configure.ac index b54e71cf..ba00e151 100644 --- a/configure.ac +++ b/configure.ac @@ -1,321 +1,323 @@ # 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]), [linux-cluster@redhat.com]) AM_INIT_AUTOMAKE([-Wno-portability dist-bzip2 dist-xz]) LT_PREREQ([2.2.6]) LT_INIT AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([fence/agents/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 if test "x$AGENTS_LIST" != xall; then for j in $AGENTS_LIST; do if ! test -d fence/agents/$j; then AC_ERROR([Agent $j does not exists]) fi done fi if test "x$AGENTS_LIST" = xall; then AGENTS_LIST=`find $srcdir/fence/agents -mindepth 2 -maxdepth 2 -name Makefile.am -printf '%h ' | sed -e 's#'$srcdir'/fence/agents/##g' -e 's#lib ##g' -e 's#nss_wrapper ##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_PYTHON_MODULE(suds, 1) AC_PYTHON_MODULE(pexpect, 1) AC_PYTHON_MODULE(pycurl, 1) AC_PYTHON_MODULE(requests, 1) ## path to 3rd-party binaries AC_PATH_PROG([IPMITOOL_PATH], [ipmitool], [/usr/bin/ipmitool]) 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]) ## 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_XENAPILIB, test $XENAPILIB -eq 1) AC_SUBST([IPMITOOL_PATH]) AC_SUBST([AMTTOOL_PATH]) AC_SUBST([COROSYNC_CMAPCTL_PATH]) AC_SUBST([SG_PERSIST_PATH]) AC_SUBST([SG_TURS_PATH]) AC_SUBST([VGS_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" AC_CONFIG_FILES([Makefile fence/Makefile fence/agents/Makefile fence/agents/alom/Makefile fence/agents/apc/Makefile fence/agents/apc_snmp/Makefile fence/agents/amt/Makefile fence/agents/bladecenter/Makefile fence/agents/brocade/Makefile fence/agents/cisco_mds/Makefile fence/agents/cisco_ucs/Makefile fence/agents/compute/Makefile fence/agents/docker/Makefile fence/agents/drac/Makefile fence/agents/drac5/Makefile fence/agents/dummy/Makefile fence/agents/eaton_snmp/Makefile fence/agents/emerson/Makefile fence/agents/eps/Makefile fence/agents/hpblade/Makefile fence/agents/ibmblade/Makefile fence/agents/ipdu/Makefile fence/agents/ifmib/Makefile fence/agents/ilo/Makefile fence/agents/ilo_moonshot/Makefile fence/agents/ilo_mp/Makefile fence/agents/ilo_ssh/Makefile fence/agents/intelmodular/Makefile fence/agents/ipmilan/Makefile fence/agents/kdump/Makefile fence/agents/ldom/Makefile fence/agents/lib/Makefile fence/agents/lpar/Makefile fence/agents/manual/Makefile fence/agents/mpath/Makefile fence/agents/netio/Makefile fence/agents/ovh/Makefile fence/agents/pve/Makefile fence/agents/raritan/Makefile fence/agents/rcd_serial/Makefile fence/agents/rhevm/Makefile fence/agents/rsa/Makefile fence/agents/rsb/Makefile + fence/agents/sbd/Makefile fence/agents/sanbox2/Makefile fence/agents/scsi/Makefile fence/agents/virsh/Makefile fence/agents/vmware/Makefile fence/agents/vmware_soap/Makefile fence/agents/wti/Makefile fence/agents/xenapi/Makefile fence/agents/hds_cb/Makefile fence/agents/zvm/Makefile doc/Makefile]) AC_OUTPUT diff --git a/fence/agents/sbd/Makefile.am b/fence/agents/sbd/Makefile.am new file mode 100644 index 00000000..36a89253 --- /dev/null +++ b/fence/agents/sbd/Makefile.am @@ -0,0 +1,17 @@ +MAINTAINERCLEANFILES = Makefile.in + +TARGET = fence_sbd + +SRC = $(TARGET).py + +EXTRA_DIST = $(SRC) + +sbin_SCRIPTS = $(TARGET) + +man_MANS = $(TARGET).8 + +FENCE_TEST_ARGS = -n test --devices test + +include $(top_srcdir)/make/fencebuild.mk +include $(top_srcdir)/make/fenceman.mk +include $(top_srcdir)/make/agentpycheck.mk diff --git a/fence/agents/sbd/fence_sbd.py b/fence/agents/sbd/fence_sbd.py new file mode 100644 index 00000000..7120c4db --- /dev/null +++ b/fence/agents/sbd/fence_sbd.py @@ -0,0 +1,421 @@ +#!/usr/bin/python -tt + +import sys, stat +import logging +import os +import atexit +sys.path.append("@FENCEAGENTSLIBDIR@") +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 + +#BEGIN_VERSION_GENERATION +RELEASE_VERSION="" +REDHAT_COPYRIGHT="" +BUILD_DATE="" +#END_VERSION_GENERATION + +DEVICE_INIT = 1 +DEVICE_NOT_INIT = -3 +PATH_NOT_EXISTS = -1 +PATH_NOT_BLOCK = -2 + +def is_block_device(filename): + """Checks if a given path is a valid block device + + Key arguments: + filename -- the file to check + + Return codes: + True if it's a valid block device + False, otherwise + """ + + try: + mode = os.lstat(filename).st_mode + except OSError: + return False + else: + return stat.S_ISBLK(mode) + +def is_link(filename): + """Checks if a given path is a link. + + Key arguments: + filename -- the file to check + + Return codes: + True if it's a link + False, otherwise + """ + + try: + mode = os.lstat(filename).st_mode + except OSError: + return False + else: + return stat.S_ISLNK(mode) + +def check_sbd_device(options, device_path): + """checks that a given sbd device exists and is initialized + + Key arguments: + options -- options dictionary + device_path -- device path to check + + Return Codes: + 1 / DEVICE_INIT if the device exists and is initialized + -1 / PATH_NOT_EXISTS if the path does not exists + -2 / PATH_NOT_BLOCK if the path exists but is not a valid block device + -3 / DEVICE_NOT_INIT if the sbd device is not initialized + """ + + # First of all we need to check if the device is valid + if not os.path.exists(device_path): + return PATH_NOT_EXISTS + + # We need to check if device path is a symbolic link. If so we resolve that + # link. + if is_link(device_path): + link_target = os.readlink(device_path) + device_path = os.path.join(os.path.dirname(device_path), link_target) + + # As second step we make sure it's a valid block device + if not is_block_device(device_path): + return PATH_NOT_BLOCK + + cmd = "%s -d %s dump" % (options["--sbd-path"], device_path) + + (return_code, out, err) = run_command(options, cmd) + + for line in out.split("\n"): + if len(line) == 0: + continue + + # If we read "NOT dumped" something went wrong, e.g. the device is not + # initialized. + if "NOT dumped" in line: + return DEVICE_NOT_INIT + + return DEVICE_INIT + +def generate_sbd_command(options, command, arguments=None): + """Generates a sbd command based on given arguments. + + Return Value: + generated sbd command (string) + """ + cmd = options["--sbd-path"] + + # add "-d" for each sbd device + for device in parse_sbd_devices(options): + cmd += " -d %s" % device + + cmd += " %s %s" % (command, arguments) + + return cmd + +def send_sbd_message(conn, options, plug, message): + """Sends a message to all sbd devices. + + Key arguments: + conn -- connection structure + options -- options dictionary + plug -- plug to sent the message to + message -- message to send + + Return Value: + (return_code, out, err) Tuple containing the error code, + """ + + del conn + + arguments = "%s %s" % (plug, message) + cmd = generate_sbd_command(options, "message", arguments) + + (return_code, out, err) = run_command(options, cmd) + + return (return_code, out, err) + +def get_msg_timeout(options): + """Reads the configured sbd message timeout from each device. + + Key arguments: + options -- options dictionary + + Return Value: + msg_timeout (integer, seconds) + """ + + # get the defined msg_timeout + msg_timeout = -1 # default sbd msg timeout + + cmd = generate_sbd_command(options, "dump") + + (return_code, out, err) = run_command(options, cmd) + + for line in out.split("\n"): + if len(line) == 0: + continue + + if "msgwait" in line: + tmp_msg_timeout = int(line.split(':')[1]) + if -1 != msg_timeout and tmp_msg_timeout != msg_timeout: + logging.warn(\ + "sbd message timeouts differ in different devices") + # we only save the highest timeout + if tmp_msg_timeout > msg_timeout: + msg_timeout = tmp_msg_timeout + + return msg_timeout + +def set_power_status(conn, options): + """send status to sbd device (poison pill) + + Key arguments: + conn -- connection structure + options -- options dictionary + + Return Value: + return_code -- return code (integer) + """ + + target_status = options["--action"] + plug = options["--plug"] + return_code = 99 + out = "" + err = "" + + # Map fencing actions to sbd messages + if "on" == target_status: + (return_code, out, err) = send_sbd_message(conn, options, plug, "clear") + elif "off" == target_status: + (return_code, out, err) = send_sbd_message(conn, options, plug, "off") + elif "reboot" == target_status: + (return_code, out, err) = send_sbd_message(conn, options, plug, "reset") + + if 0 != return_code: + logging.error("sending message to sbd device(s) \ + failed with return code %d", return_code) + logging.error("DETAIL: output on stdout was \"%s\"", out) + logging.error("DETAIL: output on stderr was \"%s\"", err) + + return return_code + +def reboot_cycle(conn, options): + """" trigger reboot by sbd messages + + Key arguments: + conn -- connection structure + options -- options dictionary + + Return Value: + return_code -- return code (integer) + """ + + plug = options["--plug"] + return_code = 99 + out = "" + err = "" + + (return_code, out, err) = send_sbd_message(conn, options, plug, "reset") + return return_code + +def get_power_status(conn, options): + """Returns the status of a specific node. + + Key arguments: + conn -- connection structure + options -- option dictionary + + Return Value: + status -- status code (string) + """ + + status = "UNKWNOWN" + plug = options["--plug"] + + nodelist = get_node_list(conn, options) + + # We need to check if the specified plug / node a already a allocated slot + # on the device. + if not nodelist.has_key(plug): + logging.error("node \"%s\" not found in node list", plug) + else: + status = nodelist[plug][1] + + + return status + +def translate_status(sbd_status): + """Translates the sbd status to fencing status. + + Key arguments: + sbd_status -- status to translate (string) + + Return Value: + status -- fencing status (string) + """ + + status = "UNKNOWN" + + + # Currently we only accept "clear" to be marked as online. Eventually we + # should also check against "test" + online_status = ["clear"] + + offline_status = ["reset", "off"] + + if any(online_status_element in sbd_status \ + for online_status_element in online_status): + status = "on" + + if any(offline_status_element in sbd_status \ + for offline_status_element in offline_status): + status = "off" + + return status + +def get_node_list(conn, options): + """Returns a list of hostnames, registerd on the sbd device. + + Key arguments: + conn -- connection options + options -- options + + Return Value: + nodelist -- dictionary wich contains all node names and there status + """ + + del conn + + nodelist = {} + + cmd = generate_sbd_command(options, "list") + + (return_code, out, err) = run_command(options, cmd) + + for line in out.split("\n"): + if len(line) == 0: + continue + + # if we read "unreadable" something went wrong + if "NOT dumped" in line: + return nodelist + + words = line.split() + port = words[1] + sbd_status = words[2] + nodelist[port] = (port, translate_status(sbd_status)) + + return nodelist + +def parse_sbd_devices(options): + """Returns an array of all sbd devices. + + Key arguments: + options -- options dictionary + + Return Value: + devices -- array of device paths + """ + + devices = [str.strip(dev) \ + for dev in str.split(options["--devices"], ",")] + + return devices + +def define_new_opts(): + """Defines the all opt list + """ + all_opt["devices"] = { + "getopt" : ":", + "longopt" : "devices", + "help":"--devices=[device_a,device_b] \ +Comma separated list of sbd devices", + "required" : "1", + "shortdesc" : "SBD Device", + "order": 1 + } + + all_opt["sbd_path"] = { + "getopt" : ":", + "longopt" : "sbd-path", + "help" : "--sbd-path=[path] Path to SBD binary", + "required" : "0", + "default" : "@SBD_PATH@", + "order": 200 + } + +def main(): + """Main function + """ + # We need to define "no_password" otherwise we will be ask about it if + # we don't provide any password. + device_opt = ["no_password", "devices", "port", "method", "sbd_path"] + + # close stdout if we get interrupted + atexit.register(atexit_handler) + + define_new_opts() + + all_opt["method"]["default"] = "cycle" + all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)" + + options = check_input(device_opt, process_input(device_opt)) + + # fill the needed variables to generate metadata and help text output + docs = {} + docs["shortdesc"] = "Fence agent for sbd" + docs["longdesc"] = "fence_sbd is I/O Fencing agent \ +which can be used in environments where sbd can be used (shared storage)." + docs["vendorurl"] = "" + show_docs(options, docs) + + # We need to check if --devices is given and not empty. + if not options.has_key("--devices"): + fail_usage("No SBD devices specified. \ + At least one SBD device is required.") + + run_delay(options) + + # We need to check if the provided sbd_devices exists. We need to do + # that for every given device. + for device_path in parse_sbd_devices(options): + logging.debug("check device \"%s\"", device_path) + + return_code = check_sbd_device(options, device_path) + if PATH_NOT_EXISTS == return_code: + logging.error("\"%s\" does not exist", device_path) + elif PATH_NOT_BLOCK == return_code: + logging.error("\"%s\" is not a valid block device", device_path) + elif DEVICE_NOT_INIT == return_code: + logging.error("\"%s\" is not initialized", device_path) + elif DEVICE_INIT != return_code: + logging.error("UNKNOWN error while checking \"%s\"", device_path) + + # If we get any error while checking the device we need to exit at this + # point. + if DEVICE_INIT != return_code: + exit(return_code) + + # we check against the defined timeouts. If the pacemaker timeout is smaller + # then that defined within sbd we should report this. + power_timeout = int(options["--power-timeout"]) + sbd_msg_timeout = get_msg_timeout(options) + if power_timeout <= sbd_msg_timeout: + logging.warn("power timeout needs to be \ + greater then sbd message timeout") + + result = fence_action(\ + None, \ + options, \ + set_power_status, \ + get_power_status, \ + get_node_list, \ + reboot_cycle) + + sys.exit(result) + +if __name__ == "__main__": + main() diff --git a/make/fencebuild.mk b/make/fencebuild.mk index 9b394844..2e9330cb 100644 --- a/make/fencebuild.mk +++ b/make/fencebuild.mk @@ -1,37 +1,38 @@ $(TARGET): $(SRC) bash $(top_srcdir)/scripts/fenceparse \ $(top_srcdir)/make/copyright.cf REDHAT_COPYRIGHT \ $(VERSION) \ $(abs_srcdir) $@ | \ sed \ -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#@''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' \ > $@ if [ 0 -eq `echo "$(SRC)" | grep fence_ &> /dev/null; echo $$?` ]; then \ PYTHONPATH=$(abs_srcdir)/../lib:$(abs_builddir)/../lib $(top_srcdir)/fence/agents/lib/check_used_options.py $@; \ else true ; fi clean: clean-man rm -f $(TARGET) $(SYMTARGET) *.pyc *.wiki clean-local: clean \ No newline at end of file diff --git a/tests/data/metadata/fence_sbd.xml b/tests/data/metadata/fence_sbd.xml new file mode 100644 index 00000000..1909507c --- /dev/null +++ b/tests/data/metadata/fence_sbd.xml @@ -0,0 +1,101 @@ + + +fence_sbd is I/O Fencing agent which can be used in environments where sbd can be used (shared storage). + + + + + + Fencing action + + + + + SBD Device + + + + + + Method to fence + + + + + Physical plug number on device, UUID or identification of machine + + + + + Verbose mode + + + + + Write debug information to given file + + + + + Display version information and exit + + + + + Display help and exit + + + + + Separator for CSV created by 'list' operation + + + + + 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 + + + + + Path to SBD binary + + + + + Wait X seconds for cmd prompt after issuing command + + + + + Count of attempts to retry power on + + + + + + + + + + + + + +