|
|
21d5fd |
From 11a63822fbdc0a9ebe1b668b26a59f1cc9649f6c Mon Sep 17 00:00:00 2001
|
|
|
21d5fd |
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
|
|
21d5fd |
Date: Wed, 24 Oct 2018 14:51:27 +0200
|
|
|
21d5fd |
Subject: [PATCH] fence_scsi: watchdog retries support
|
|
|
21d5fd |
|
|
|
21d5fd |
---
|
|
|
21d5fd |
agents/scsi/fence_scsi.py | 60 ++++++++++++++++++++----------
|
|
|
21d5fd |
tests/data/metadata/fence_scsi.xml | 4 +-
|
|
|
21d5fd |
2 files changed, 43 insertions(+), 21 deletions(-)
|
|
|
21d5fd |
|
|
|
21d5fd |
diff --git a/agents/scsi/fence_scsi.py b/agents/scsi/fence_scsi.py
|
|
|
21d5fd |
index 79ada4fa..8a1e4c77 100644
|
|
|
21d5fd |
--- a/agents/scsi/fence_scsi.py
|
|
|
21d5fd |
+++ b/agents/scsi/fence_scsi.py
|
|
|
21d5fd |
@@ -158,13 +158,15 @@ def get_reservation_key(options, dev):
|
|
|
21d5fd |
return match.group(1) if match else None
|
|
|
21d5fd |
|
|
|
21d5fd |
|
|
|
21d5fd |
-def get_registration_keys(options, dev):
|
|
|
21d5fd |
+def get_registration_keys(options, dev, fail=True):
|
|
|
21d5fd |
reset_dev(options,dev)
|
|
|
21d5fd |
keys = []
|
|
|
21d5fd |
cmd = options["--sg_persist-path"] + " -n -i -k -d " + dev
|
|
|
21d5fd |
out = run_cmd(options, cmd)
|
|
|
21d5fd |
if out["err"]:
|
|
|
21d5fd |
- fail_usage("Cannot get registration keys")
|
|
|
21d5fd |
+ fail_usage("Cannot get registration keys", fail)
|
|
|
21d5fd |
+ if not fail:
|
|
|
21d5fd |
+ return []
|
|
|
21d5fd |
for line in out["out"].split("\n"):
|
|
|
21d5fd |
match = re.search(r"\s+0x(\S+)\s*", line)
|
|
|
21d5fd |
if match:
|
|
|
21d5fd |
@@ -218,9 +220,8 @@ def get_key(fail=True):
|
|
|
21d5fd |
try:
|
|
|
21d5fd |
f = open(file_path, "r")
|
|
|
21d5fd |
except IOError:
|
|
|
21d5fd |
- if fail:
|
|
|
21d5fd |
- fail_usage("Failed: Cannot open file \""+ file_path + "\"")
|
|
|
21d5fd |
- else:
|
|
|
21d5fd |
+ fail_usage("Failed: Cannot open file \""+ file_path + "\"", fail)
|
|
|
21d5fd |
+ if not fail:
|
|
|
21d5fd |
return None
|
|
|
21d5fd |
return f.readline().strip().lower()
|
|
|
21d5fd |
|
|
|
21d5fd |
@@ -244,9 +245,8 @@ def dev_read(fail=True):
|
|
|
21d5fd |
try:
|
|
|
21d5fd |
f = open(file_path, "r")
|
|
|
21d5fd |
except IOError:
|
|
|
21d5fd |
- if fail:
|
|
|
21d5fd |
- fail_usage("Failed: Cannot open file \"" + file_path + "\"")
|
|
|
21d5fd |
- else:
|
|
|
21d5fd |
+ fail_usage("Failed: Cannot open file \"" + file_path + "\"", fail)
|
|
|
21d5fd |
+ if not fail:
|
|
|
21d5fd |
return None
|
|
|
21d5fd |
# get not empty lines from file
|
|
|
21d5fd |
devs = [line.strip() for line in f if line.strip()]
|
|
|
21d5fd |
@@ -371,14 +371,20 @@ def define_new_opts():
|
|
|
21d5fd |
}
|
|
|
21d5fd |
|
|
|
21d5fd |
|
|
|
21d5fd |
-def scsi_check_get_verbose():
|
|
|
21d5fd |
+def scsi_check_get_options(options):
|
|
|
21d5fd |
try:
|
|
|
21d5fd |
- f = open("/etc/sysconfig/watchdog", "r")
|
|
|
21d5fd |
+ f = open("/etc/sysconfig/stonith", "r")
|
|
|
21d5fd |
except IOError:
|
|
|
21d5fd |
- return False
|
|
|
21d5fd |
- match = re.search(r"^\s*verbose=yes", "".join(f.readlines()), re.MULTILINE)
|
|
|
21d5fd |
+ return options
|
|
|
21d5fd |
+
|
|
|
21d5fd |
+ match = re.findall(r"^\s*(\S*)\s*=\s*(\S*)\s*", "".join(f.readlines()), re.MULTILINE)
|
|
|
21d5fd |
+
|
|
|
21d5fd |
+ for m in match:
|
|
|
21d5fd |
+ options[m[0].lower()] = m[1].lower()
|
|
|
21d5fd |
+
|
|
|
21d5fd |
f.close()
|
|
|
21d5fd |
- return bool(match)
|
|
|
21d5fd |
+
|
|
|
21d5fd |
+ return options
|
|
|
21d5fd |
|
|
|
21d5fd |
|
|
|
21d5fd |
def scsi_check(hardreboot=False):
|
|
|
21d5fd |
@@ -388,7 +394,10 @@ def scsi_check(hardreboot=False):
|
|
|
21d5fd |
options["--sg_turs-path"] = "@SG_TURS_PATH@"
|
|
|
21d5fd |
options["--sg_persist-path"] = "@SG_PERSIST_PATH@"
|
|
|
21d5fd |
options["--power-timeout"] = "5"
|
|
|
21d5fd |
- if scsi_check_get_verbose():
|
|
|
21d5fd |
+ options["retry"] = "0"
|
|
|
21d5fd |
+ options["retry-sleep"] = "1"
|
|
|
21d5fd |
+ options = scsi_check_get_options(options)
|
|
|
21d5fd |
+ if "verbose" in options and options["verbose"] == "yes":
|
|
|
21d5fd |
logging.getLogger().setLevel(logging.DEBUG)
|
|
|
21d5fd |
devs = dev_read(fail=False)
|
|
|
21d5fd |
if not devs:
|
|
|
21d5fd |
@@ -399,11 +408,18 @@ def scsi_check(hardreboot=False):
|
|
|
21d5fd |
logging.error("Key not found")
|
|
|
21d5fd |
return 0
|
|
|
21d5fd |
for dev in devs:
|
|
|
21d5fd |
- if key in get_registration_keys(options, dev):
|
|
|
21d5fd |
- logging.debug("key " + key + " registered with device " + dev)
|
|
|
21d5fd |
- return 0
|
|
|
21d5fd |
- else:
|
|
|
21d5fd |
- logging.debug("key " + key + " not registered with device " + dev)
|
|
|
21d5fd |
+ for n in range(int(options["retry"]) + 1):
|
|
|
21d5fd |
+ if n > 0:
|
|
|
21d5fd |
+ logging.debug("retry: " + str(n) + " of " + options["retry"])
|
|
|
21d5fd |
+ if key in get_registration_keys(options, dev, fail=False):
|
|
|
21d5fd |
+ logging.debug("key " + key + " registered with device " + dev)
|
|
|
21d5fd |
+ return 0
|
|
|
21d5fd |
+ else:
|
|
|
21d5fd |
+ logging.debug("key " + key + " not registered with device " + dev)
|
|
|
21d5fd |
+
|
|
|
21d5fd |
+ if n < int(options["retry"]):
|
|
|
21d5fd |
+ time.sleep(float(options["retry-sleep"]))
|
|
|
21d5fd |
+
|
|
|
21d5fd |
logging.debug("key " + key + " registered with any devices")
|
|
|
21d5fd |
|
|
|
21d5fd |
if hardreboot == True:
|
|
|
21d5fd |
@@ -452,7 +468,11 @@ def main():
|
|
|
21d5fd |
device(s). The result is that only registered nodes may write to the \
|
|
|
21d5fd |
device(s). When a node failure occurs, the fence_scsi agent will remove the \
|
|
|
21d5fd |
key belonging to the failed node from the device(s). The failed node will no \
|
|
|
21d5fd |
-longer be able to write to the device(s). A manual reboot is required."
|
|
|
21d5fd |
+longer be able to write to the device(s). A manual reboot is required.\
|
|
|
21d5fd |
+\n.P\n\
|
|
|
21d5fd |
+When used as a watchdog device you can define e.g. retry=1, retry-sleep=2 and \
|
|
|
21d5fd |
+verbose=yes parameters in /etc/sysconfig/stonith if you have issues with it \
|
|
|
21d5fd |
+failing."
|
|
|
21d5fd |
docs["vendorurl"] = ""
|
|
|
21d5fd |
show_docs(options, docs)
|
|
|
21d5fd |
|
|
|
21d5fd |
diff --git a/tests/data/metadata/fence_scsi.xml b/tests/data/metadata/fence_scsi.xml
|
|
|
21d5fd |
index 45a84168..b8cdabd1 100644
|
|
|
21d5fd |
--- a/tests/data/metadata/fence_scsi.xml
|
|
|
21d5fd |
+++ b/tests/data/metadata/fence_scsi.xml
|
|
|
21d5fd |
@@ -1,7 +1,9 @@
|
|
|
21d5fd |
|
|
|
21d5fd |
<resource-agent name="fence_scsi" shortdesc="Fence agent for SCSI persistent reservation" >
|
|
|
21d5fd |
<longdesc>fence_scsi is an I/O fencing agent that uses SCSI-3 persistent reservations to control access to shared storage devices. These devices must support SCSI-3 persistent reservations (SPC-3 or greater) as well as the "preempt-and-abort" subcommand.
|
|
|
21d5fd |
-The fence_scsi agent works by having each node in the cluster register a unique key with the SCSI device(s). Once registered, a single node will become the reservation holder by creating a "write exclusive, registrants only" reservation on the device(s). The result is that only registered nodes may write to the device(s). When a node failure occurs, the fence_scsi agent will remove the key belonging to the failed node from the device(s). The failed node will no longer be able to write to the device(s). A manual reboot is required.</longdesc>
|
|
|
21d5fd |
+The fence_scsi agent works by having each node in the cluster register a unique key with the SCSI device(s). Once registered, a single node will become the reservation holder by creating a "write exclusive, registrants only" reservation on the device(s). The result is that only registered nodes may write to the device(s). When a node failure occurs, the fence_scsi agent will remove the key belonging to the failed node from the device(s). The failed node will no longer be able to write to the device(s). A manual reboot is required.
|
|
|
21d5fd |
+
|
|
|
21d5fd |
+When used as a watchdog device you can define e.g. retry=1, retry-sleep=2 and verbose=yes parameters in /etc/sysconfig/stonith if you have issues with it failing.</longdesc>
|
|
|
21d5fd |
<vendor-url></vendor-url>
|
|
|
21d5fd |
<parameters>
|
|
|
21d5fd |
<parameter name="action" unique="0" required="1">
|