diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:50:17 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:50:17 +0000 |
commit | 86ed03f8adee56c050c73018537371c230a664a6 (patch) | |
tree | eae3d04cdf1c49848e5a671327ab38297f4acb0d /agents/crosslink/fence_crosslink.py | |
parent | Initial commit. (diff) | |
download | fence-agents-86ed03f8adee56c050c73018537371c230a664a6.tar.xz fence-agents-86ed03f8adee56c050c73018537371c230a664a6.zip |
Adding upstream version 4.12.1.upstream/4.12.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-x | agents/crosslink/fence_crosslink.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/agents/crosslink/fence_crosslink.py b/agents/crosslink/fence_crosslink.py new file mode 100755 index 0000000..7cfc90c --- /dev/null +++ b/agents/crosslink/fence_crosslink.py @@ -0,0 +1,113 @@ +#!@PYTHON@ -tt + +# Copyright (c) 2020 Red Hat +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see +# <http://www.gnu.org/licenses/>. + +import atexit +import logging +import sys +sys.path.append("@FENCEAGENTSLIBDIR@") +from fencing import (all_opt, atexit_handler, check_input, # noqa: E402 + fence_action, process_input, run_command, run_delay, + show_docs) + +logger = logging.getLogger(__name__) +logger.setLevel("WARNING") + + +def get_power_status(conn, options): + logger.debug("get_power_status(): %s" % options) + ip = options['--crosscableip'] + timeout = options['--timeout'] + # This returns 'off' if not a single ICMP packet gets answered during the + # whole timeout window. (the ping executable will return 1 in such case and + # 0 if even a single packet gets replied to) + (status, stdout, stderr) = run_command(options, "ping -w%s -n %s" % + (timeout, ip)) + logger.debug("get_power_status(): %s - Stdout: %s - Stderr: %s" % + (status, stdout, stderr)) + if status == 0: + return "on" + else: + return "off" + + +def set_power_status(conn, options): + logger.debug("set_power_status(): %s" % options) + # If we got here it means the previous call to get_power_status() returned + # on At this point we've been invoked but the node is still reachable over + # the cross connect, so we can just error out. + ip = options['--crosscableip'] + if options['--action'] == 'off': + logger.error("We've been asked to turn off the node at %s but the " + "cross-cable link is up so erroring out" % ip) + sys.exit(1) + elif options['--action'] == 'on': + logger.error("We've been asked to turn on the node at %s but the " + "cross-cable link is off so erroring out" % ip) + sys.exit(1) + else: + logger.error("set_power_status() was called with action %s which " + "is not supported" % options['--action']) + sys.exit(1) + + +def define_new_opts(): + all_opt["crosscableip"] = { + "getopt": "a:", + "longopt": "crosscableip", + "help": "-a, --crosscableip=[IP] IP over the cross-cable link", + "required": "1", + "shortdesc": "Cross-cable IP", + "order": 1 + } + all_opt["timeout"] = { + "getopt": "T:", + "longopt": "timeout", + "help": "-T, --timeout=[seconds] timeout in seconds", + "required": "0", + "shortdesc": "No ICMP reply in 5 seconds -> Node is considered dead", + "default": "5", + "order": 1 + } + + +def main(): + atexit.register(atexit_handler) + + device_opt = ["crosscableip", "timeout", "no_password", "no_login", "port"] + define_new_opts() + + options = check_input(device_opt, process_input(device_opt)) + + docs = {} + docs["shortdesc"] = "Fence agent for cross-link two-node clusters" + docs["longdesc"] = "This agent helps two-node clusters to tackle the " \ + "situation where one node lost power, cannot be " \ + "fenced by telling pacemaker that if the node is not " \ + "reachable over the crosslink cable, we can assume " \ + "it is dead" + docs["vendorurl"] = "" + show_docs(options, docs) + + run_delay(options) + + result = fence_action(None, options, set_power_status, get_power_status) + sys.exit(result) + + +if __name__ == "__main__": + main() |