diff --git a/fence/agents/Makefile.am b/fence/agents/Makefile.am index 29136b3f..8feff038 100644 --- a/fence/agents/Makefile.am +++ b/fence/agents/Makefile.am @@ -1,116 +1,108 @@ MAINTAINERCLEANFILES = Makefile.in TARGET = $(AGENTS_LIST:%.py=%) SRC = $(TARGET:=.py) CLEAN_TARGET_ADDITIONAL = kdump/fence_kdump_send manual/fence_ack_manual */*.o EXTRA_DIST = $(SRC) sbin_PROGRAMS = sbin_SCRIPTS = $(TARGET) libexec_PROGRAMS = dist_man_MANS = noinst_HEADERS = kdump/list.h kdump/message.h kdump/options.h kdump/version.h zvm/fence_zvm.h EXTRA_SCRIPTS = man_MANS = $(sbin_SCRIPTS:=.8) if BUILD_FENCE_KDUMP sbin_PROGRAMS += kdump/fence_kdump libexec_PROGRAMS += kdump/fence_kdump_send dist_man_MANS += kdump/fence_kdump.8 kdump/fence_kdump_send.8 kdump_fence_kdump_SOURCES = kdump/fence_kdump.c kdump_fence_kdump_CFLAGS = -D_GNU_SOURCE -Ikdump kdump_fence_kdump_send_SOURCES = kdump/fence_kdump_send.c kdump_fence_kdump_send_CFLAGS = -D_GNU_SOURCE -Ikdump endif if BUILD_FENCE_MANUAL EXTRA_DIST += manual/fence_ack_manual.in manual/fence_ack_manual.8 sbin_SCRIPTS += manual/fence_ack_manual endif if BUILD_FENCE_ZVM EXTRA_DIST += zvm/fence_zvm_man_page sbin_PROGRAMS += zvm/fence_zvm dist_man_MANS += zvm/fence_zvm.8 zvm_fence_zvm_SOURCES = zvm/fence_zvm.c zvm_fence_zvm_CFLAGS = -D_GNU_SOURCE -Izvm endif if BUILD_FENCE_SCSI scsidatadir = $(CLUSTERDATA) scsidata_SCRIPTS = scsi/fence_scsi_check scsi/fence_scsi_check_hardreboot endif FENCE_TEST_ARGS = \ login=test\n\ passwd=test\n\ ipaddr=test\n\ port=1\n\ managed=1\n\ devices=test\n\ session_url=http://test\n\ email=test@test.te\n\ ping_targets=localhost manual/fence_ack_manual: manual/fence_ack_manual.in mkdir -p $(@D) cat $^ | sed \ -e 's#@clustervarrun@#${CLUSTERVARRUN}#g' \ > $@ scsi/fence_scsi_check: scsi/fence_scsi cp $^ $@ scsi/fence_scsi_check_hardreboot: scsi/fence_scsi cp $^ $@ kdump/fence_kdump.8: kdump/fence_kdump $(top_srcdir)/fence/agents/lib/fence2man.xsl set -e && \ ./$(@:%.8=%) -o metadata > $(@D)/.$(@F).tmp && \ xmllint --noout --relaxng $(top_srcdir)/fence/agents/lib/metadata.rng $(@D)/.$(@F).tmp && \ xsltproc $(top_srcdir)/fence/agents/lib/fence2man.xsl $(@D)/.$(@F).tmp > $@ xsltproc $(top_srcdir)/fence/agents/lib/fence2wiki.xsl $(@D)/.$(@F).tmp | grep -v ' $(@D)/$(@F:%.8=%.wiki) kdump/fence_kdump_send.8: true manual/fence_ack_manual.8: true zvm/fence_zvm.8: zvm/fence_zvm cp $(top_srcdir)/fence/agents/zvm/fence_zvm_man_page $(@D)/fence_zvm.8 cisco_mds/fence_cisco_mds.delay-check: cisco_mds/fence_cisco_mds $(eval INPUT=$(subst .delay-check,,$@)) FENCE_TEST_ARGS_CISCO_MDS=$$(printf '$(FENCE_TEST_ARGS)' | sed 's#port=1#port=fc1/1#'); \ test `PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/lib /usr/bin/time -p \ sh -c "printf 'delay=10\n $$FENCE_TEST_ARGS_CISCO_MDS' | $(PYTHON) ./$(INPUT)" 2>&1 |\ awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}'` -ge 1000 || ( \ PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/lib /usr/bin/time -p \ sh -c "printf "delay=0\n $$FENCE_TEST_ARGS_CISCO_MDS" | $(PYTHON) ./$(INPUT)"; false ) -heuristics_ping/fence_heuristics_ping.delay-check: heuristics_ping/fence_heuristics_ping - $(eval INPUT=$(subst .delay-check,,$@)) - test `PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/lib /usr/bin/time -p \ - sh -c "printf 'delay=11\n $(FENCE_TEST_ARGS)' | $(PYTHON) ./$(INPUT)" 2>&1 |\ - awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}'` -ge 1000 || ( \ - PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/lib /usr/bin/time -p \ - sh -c "printf "delay=0\n $(FENCE_TEST_ARGS)" | $(PYTHON) ./$(INPUT)"; false ) - include $(top_srcdir)/make/fencebuild.mk include $(top_srcdir)/make/fenceman.mk include $(top_srcdir)/make/agentpycheck.mk diff --git a/fence/agents/heuristics_ping/fence_heuristics_ping.py b/fence/agents/heuristics_ping/fence_heuristics_ping.py index 619d39bb..5b2c61d8 100644 --- a/fence/agents/heuristics_ping/fence_heuristics_ping.py +++ b/fence/agents/heuristics_ping/fence_heuristics_ping.py @@ -1,198 +1,198 @@ #!@PYTHON@ -tt # The Following Agent Has Been Tested On: # # RHEL 7.4 # import io import re import subprocess import shlex 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 def ping_test(con, options): # Send pings to the targets if options["--action"] == "on": # we want unfencing to always succeed return True if not "--ping-targets" in options or options["--ping-targets"] == "": # "off" was requested so fake "on" to provoke failure logging.error("ping target required") return False timeout = int(options["--ping-timeout"]) count = int(options["--ping-count"]) interval = int(options["--ping-interval"]) good_required = int(options["--ping-good-count"]) maxfail = int(options["--ping-maxfail"]) targets = options["--ping-targets"].split(",") exitcode = True p = {} failcount = 0 # search string for parsing the results of the ping-executable - packet_count = re.compile(r".*transmitted, ([0-9]*) received.*") + packet_count = re.compile(r".*transmitted, ([0-9]*)( packets)? received.*") # start a ping-process per target for target in targets: ping_path = '@PING_CMD@' target_mangled = target if target.startswith('inet6:'): if '@PING6_CMD@' == '': p[target] = None continue ping_path = '@PING6_CMD@' target_mangled = target.split(':',2)[1] elif target.startswith('inet:'): ping_path = '@PING4_CMD@' target_mangled = target.split(':',2)[1] ping_cmd = "%s -n -q -W %d -c %d -i %d %s" % ( ping_path, timeout, count, interval, target_mangled) logging.info("Running command: %s", ping_cmd) try: p[target] = subprocess.Popen(shlex.split(ping_cmd), stdout=subprocess.PIPE); except OSError: p[target] = None # collect the results of the ping-processes for target in targets: good = 0 if p[target] != None: p[target].wait() if p[target].returncode == 0: for line in p[target].stdout: searchres = packet_count.search(line.decode()) if searchres: good = int(searchres.group(1)) break if good >= good_required: logging.info("ping target %s received %d of %d" \ % (target, good, count)) continue failcount += 1 logging.info("ping target %s received %d of %d and thus failed" % (target, good, count)) else: failcount += 1 logging.error("ping target %s failed on OS level" % target) if failcount > maxfail: exitcode = False return exitcode def define_new_opts(): all_opt["ping_count"] = { "getopt" : ":", "longopt" : "ping-count", "required" : "0", "help" : "--ping-count=[number] Number of ping-probes to send", "shortdesc" : "The number of ping-probes that is being sent per target", "default" : "10", "order" : 1 } all_opt["ping_good_count"] = { "getopt" : ":", "longopt" : "ping-good-count", "required" : "0", "help" : "--ping-good-count=[number] Number of positive ping-probes required", "shortdesc" : "The number of positive ping-probes required to account a target as available", "default" : "8", "order" : 1 } all_opt["ping_interval"] = { "getopt" : ":", "longopt" : "ping-interval", "required" : "0", "help" : "--ping-interval=[seconds] Seconds between ping-probes", "shortdesc" : "The interval in seconds between ping-probes", "default" : "1", "order" : 1 } all_opt["ping_timeout"] = { "getopt" : ":", "longopt" : "ping-timeout", "required" : "0", "help" : "--ping-timeout=[seconds] Timeout for individual ping-probes", "shortdesc" : "The timeout in seconds till an individual ping-probe is accounted as lost", "default" : "2", "order" : 1 } all_opt["ping_maxfail"] = { "getopt" : ":", "longopt" : "ping-maxfail", "required" : "0", "help" : "--ping-maxfail=[number] Number of failed ping-targets allowed", "shortdesc" : "The number of failed ping-targets to still account as overall success", "default" : "0", "order" : 1 } all_opt["ping_targets"] = { "getopt" : ":", "longopt" : "ping-targets", "required" : "1", "help" : "--ping-targets=tgt1,[inet6:]tgt2 Comma separated list of ping-targets", "shortdesc" : "A comma separated list of ping-targets (optionally prepended by 'inet:' or 'inet6:') to be probed", "default" : "", "order" : 1 } def main(): device_opt = ["no_status", "no_password", "ping_count", "ping_good_count", "ping_interval", "ping_timeout", "ping_maxfail", "ping_targets", "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 ping-heuristic based fencing" docs["longdesc"] = "fence_heuristics_ping uses ping-heuristics to control execution of another fence agent on the same fencing level.\ \n.P\n\ This is not a fence agent by itself! \ Its only purpose is to enable/disable another fence agent that lives on the same fencing level but after fence_heuristics_ping." docs["vendorurl"] = "" show_docs(options, docs) # move ping-test to the end of the time-window set via --delay # as to give the network time to settle after the incident that has # caused fencing and have the results as current as possible max_pingcheck = (int(options["--ping-count"]) - 1) * \ int(options["--ping-interval"]) + int(options["--ping-timeout"]) run_delay(options, reserve=max_pingcheck) result = fence_action(\ None, \ options, \ None, \ None, \ reboot_cycle_fn = ping_test, sync_set_power_fn = ping_test) # execute the remaining delay run_delay(options, result=result) sys.exit(result) if __name__ == "__main__": main()