Blame SOURCES/bz1504202-fence_mpath-watchdog-support.patch

6a3e49
From 199b1efee0ba1f01c27ca689a15465cf4a258ee6 Mon Sep 17 00:00:00 2001
6a3e49
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
6a3e49
Date: Mon, 22 Jan 2018 11:27:28 +0100
6a3e49
Subject: [PATCH] fence_mpath: add watchdog support
6a3e49
6a3e49
---
6a3e49
 agents/Makefile.am                  | 11 ++++++++
6a3e49
 agents/mpath/fence_mpath.py         | 50 ++++++++++++++++++++++++++++++++++---
6a3e49
 configure.ac                        |  6 +++++
6a3e49
 make/fencebuild.mk                  |  2 +-
6a3e49
 tests/data/metadata/fence_mpath.xml |  2 +-
6a3e49
 5 files changed, 66 insertions(+), 5 deletions(-)
6a3e49
6a3e49
diff --git a/agents/Makefile.am b/agents/Makefile.am
6a3e49
index 2524a3ab..833d2af5 100644
6a3e49
--- a/agents/Makefile.am
6a3e49
+++ b/agents/Makefile.am
6a3e49
@@ -50,6 +50,11 @@ zvm_fence_zvm_SOURCES		= zvm/fence_zvm.c
6a3e49
 zvm_fence_zvm_CFLAGS		= -D_GNU_SOURCE -Izvm
6a3e49
 endif
6a3e49
 
6a3e49
+if BUILD_FENCE_MPATH
6a3e49
+mpathdatadir			= $(CLUSTERDATA)
6a3e49
+mpathdata_SCRIPTS		= mpath/fence_mpath_check mpath/fence_mpath_check_hardreboot
6a3e49
+endif
6a3e49
+
6a3e49
 if BUILD_FENCE_SCSI
6a3e49
 scsidatadir			= $(CLUSTERDATA)
6a3e49
 scsidata_SCRIPTS		= scsi/fence_scsi_check scsi/fence_scsi_check_hardreboot
6a3e49
@@ -72,6 +77,12 @@ manual/fence_ack_manual: manual/fence_ack_manual.in
6a3e49
 		-e 's#@clustervarrun@#${CLUSTERVARRUN}#g' \
6a3e49
 	> $@
6a3e49
 
6a3e49
+mpath/fence_mpath_check: mpath/fence_mpath
6a3e49
+	cp $^ $@
6a3e49
+
6a3e49
+mpath/fence_mpath_check_hardreboot: mpath/fence_mpath
6a3e49
+	cp $^ $@
6a3e49
+
6a3e49
 scsi/fence_scsi_check: scsi/fence_scsi
6a3e49
 	cp $^ $@
6a3e49
 
6a3e49
diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py
6a3e49
index ac5bc794..d9ac2ef5 100644
6a3e49
--- a/agents/mpath/fence_mpath.py
6a3e49
+++ b/agents/mpath/fence_mpath.py
6a3e49
@@ -143,25 +143,63 @@ def dev_write(options, dev):
6a3e49
 		store_fh.write(dev + "\t" + options["--key"] + "\n")
6a3e49
 	store_fh.close()
6a3e49
 
6a3e49
-def dev_read(options):
6a3e49
+def dev_read(options, fail=True):
6a3e49
 	dev_key = {}
6a3e49
 	file_path = options["--store-path"] + "/mpath.devices"
6a3e49
 	try:
6a3e49
 		store_fh = open(file_path, "r")
6a3e49
 	except IOError:
6a3e49
-		fail_usage("Failed: Cannot open file \"" + file_path + "\"")
6a3e49
+		if fail:
6a3e49
+			fail_usage("Failed: Cannot open file \"" + file_path + "\"")
6a3e49
+		else:
6a3e49
+			return None
6a3e49
 	# get not empty lines from file
6a3e49
 	for (device, key) in [line.strip().split() for line in store_fh if line.strip()]:
6a3e49
 		dev_key[device] = key
6a3e49
 	store_fh.close()
6a3e49
 	return dev_key
6a3e49
 
6a3e49
+def mpath_check_get_verbose():
6a3e49
+	try:
6a3e49
+		f = open("/etc/sysconfig/watchdog", "r")
6a3e49
+	except IOError:
6a3e49
+		return False
6a3e49
+	match = re.search(r"^\s*verbose=yes", "".join(f.readlines()), re.MULTILINE)
6a3e49
+	f.close()
6a3e49
+	return bool(match)
6a3e49
+
6a3e49
+def mpath_check(hardreboot=False):
6a3e49
+	if len(sys.argv) >= 3 and sys.argv[1] == "repair":
6a3e49
+		return int(sys.argv[2])
6a3e49
+	options = {}
6a3e49
+	options["--mpathpersist-path"] = "/usr/sbin/mpathpersist"
6a3e49
+	options["--store-path"] = "/var/run/cluster"
6a3e49
+	options["--power-timeout"] = "5"
6a3e49
+	if mpath_check_get_verbose():
6a3e49
+		logging.getLogger().setLevel(logging.DEBUG)
6a3e49
+	devs = dev_read(options, fail=False)
6a3e49
+	if not devs:
6a3e49
+		logging.error("No devices found")
6a3e49
+		return 0
6a3e49
+	for dev, key in list(devs.items()):
6a3e49
+		if key in get_registration_keys(options, dev):
6a3e49
+			logging.debug("key " + key + " registered with device " + dev)
6a3e49
+			return 0
6a3e49
+		else:
6a3e49
+			logging.debug("key " + key + " not registered with device " + dev)
6a3e49
+	logging.debug("key " + key + " registered with any devices")
6a3e49
+
6a3e49
+	if hardreboot == True:
6a3e49
+		libc = ctypes.cdll['libc.so.6']
6a3e49
+		libc.reboot(0x1234567)
6a3e49
+	return 2
6a3e49
+
6a3e49
 def define_new_opts():
6a3e49
 	all_opt["devices"] = {
6a3e49
 		"getopt" : "d:",
6a3e49
 		"longopt" : "devices",
6a3e49
 		"help" : "-d, --devices=[devices]        List of devices to use for current operation",
6a3e49
-		"required" : "1",
6a3e49
+		"required" : "0",
6a3e49
 		"shortdesc" : "List of devices to use for current operation. Devices can \
6a3e49
 be comma-separated list of device-mapper multipath devices (eg. /dev/mapper/3600508b400105df70000e00000ac0000 or /dev/mapper/mpath1). \
6a3e49
 Each device must support SCSI-3 persistent reservations.",
6a3e49
@@ -205,6 +243,12 @@ def main():
6a3e49
 
6a3e49
 	define_new_opts()
6a3e49
 
6a3e49
+	# fence_mpath_check
6a3e49
+	if os.path.basename(sys.argv[0]) == "fence_mpath_check":
6a3e49
+		sys.exit(mpath_check())
6a3e49
+	elif os.path.basename(sys.argv[0]) == "fence_mpath_check_hardreboot":
6a3e49
+		sys.exit(mpath_check(hardreboot=True))
6a3e49
+
6a3e49
 	options = check_input(device_opt, process_input(device_opt), other_conditions=True)
6a3e49
 
6a3e49
 	docs = {}
6a3e49
diff --git a/configure.ac b/configure.ac
6a3e49
index e8b24211..24b857b3 100644
6a3e49
--- a/configure.ac
6a3e49
+++ b/configure.ac
6a3e49
@@ -148,6 +148,11 @@ if echo "$AGENTS_LIST" | grep -q -E "all|manual"; then
6a3e49
 	AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/manual( |$)//")
6a3e49
 fi
6a3e49
 
6a3e49
+FENCE_MPATH=0
6a3e49
+if echo "$AGENTS_LIST" | grep -q -E "all|mpath"; then
6a3e49
+	FENCE_MPATH=1
6a3e49
+fi
6a3e49
+
6a3e49
 FENCE_SCSI=0
6a3e49
 if echo "$AGENTS_LIST" | grep -q -E "all|scsi"; then
6a3e49
 	FENCE_SCSI=1
6a3e49
@@ -312,6 +317,7 @@ AC_SUBST([SNMPBIN])
6a3e49
 AC_SUBST([AGENTS_LIST])
6a3e49
 AM_CONDITIONAL(BUILD_FENCE_KDUMP, test $FENCE_KDUMP -eq 1)
6a3e49
 AM_CONDITIONAL(BUILD_FENCE_MANUAL, test $FENCE_MANUAL -eq 1)
6a3e49
+AM_CONDITIONAL(BUILD_FENCE_MPATH, test $FENCE_MPATH -eq 1)
6a3e49
 AM_CONDITIONAL(BUILD_FENCE_SCSI, test $FENCE_SCSI -eq 1)
6a3e49
 AM_CONDITIONAL(BUILD_FENCE_ZVM, test $FENCE_ZVM -eq 1)
6a3e49
 AM_CONDITIONAL(BUILD_XENAPILIB, test $XENAPILIB -eq 1)
6a3e49
diff --git a/make/fencebuild.mk b/make/fencebuild.mk
6a3e49
index e08d5200..6a7c6f63 100644
6a3e49
--- a/make/fencebuild.mk
6a3e49
+++ b/make/fencebuild.mk
6a3e49
@@ -51,7 +51,7 @@ $(TARGET):
6a3e49
 	$(call gen_agent_from_py)
6a3e49
 
6a3e49
 clean: clean-man
6a3e49
-	rm -f $(CLEAN_TARGET:%.8=%) $(CLEAN_TARGET_ADDITIONAL) $(scsidata_SCRIPTS) */*.pyc *.pyc */*.wiki
6a3e49
+	rm -f $(CLEAN_TARGET:%.8=%) $(CLEAN_TARGET_ADDITIONAL) $(mpathdata_SCRIPTS) $(scsidata_SCRIPTS) */*.pyc */*.wiki
6a3e49
 
6a3e49
 	if [ "$(abs_builddir)" = "$(abs_top_builddir)/lib" ]; then \
6a3e49
 		rm -f $(TARGET); \
6a3e49
diff --git a/tests/data/metadata/fence_mpath.xml b/tests/data/metadata/fence_mpath.xml
6a3e49
index f384e50b..bbe9ad2b 100644
6a3e49
--- a/tests/data/metadata/fence_mpath.xml
6a3e49
+++ b/tests/data/metadata/fence_mpath.xml
6a3e49
@@ -9,7 +9,7 @@ The fence_mpath agent works by having a unique key for each node that has to be
6a3e49
 		<content type="string" default="off"  />
6a3e49
 		<shortdesc lang="en">Fencing action</shortdesc>
6a3e49
 	</parameter>
6a3e49
-	<parameter name="devices" unique="0" required="1">
6a3e49
+	<parameter name="devices" unique="0" required="0">
6a3e49
 		<getopt mixed="-d, --devices=[devices]" />
6a3e49
 		<content type="string"  />
6a3e49
 		<shortdesc lang="en">List of devices to use for current operation. Devices can be comma-separated list of device-mapper multipath devices (eg. /dev/mapper/3600508b400105df70000e00000ac0000 or /dev/mapper/mpath1). Each device must support SCSI-3 persistent reservations.</shortdesc>