From 2d8bb4b8862d876ec69714771270193725c8290f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 01 2019 18:59:15 +0000 Subject: import fence-agents-4.2.1-28.el7 --- diff --git a/.fence-agents.metadata b/.fence-agents.metadata new file mode 100644 index 0000000..c2e8725 --- /dev/null +++ b/.fence-agents.metadata @@ -0,0 +1,12 @@ +b68122ef53a0857d020529ff85d14f0e905c327f SOURCES/aliyun-python-sdk-core-2.8.5.tar.gz +c2a98b9a1562d223a76514f05028488ca000c395 SOURCES/aliyun-python-sdk-ecs-4.9.3.tar.gz +f14647a4d37a9a254c4e711b95a7654fc418e41e SOURCES/aliyun-python-sdk-vpc-3.0.2.tar.gz +54edb660de002b23fc12f4c0cadb2cc4ac04a398 SOURCES/fasteners-0.9.0.tar.gz +e2561df8e7ff9113dab118a651371dd88dab0142 SOURCES/fence-agents-4.2.1.tar.gz +d6180c4c8ec815872ae4c79d031a38906a5989df SOURCES/google-api-python-client-1.6.3.tar.gz +26696e1a5d79ea6cd7cf3462540695f105d2259e SOURCES/httplib2-0.9.1.tar.gz +9214a01aad373e3f0637ff444f07f7aa48801540 SOURCES/keyring-5.0.zip +bdce685cd0586e03f75aa1963751373e3850eb79 SOURCES/oauth2client-4.0.0.tar.gz +326a73f58a62ebee00c11a12cfdd838b196e0e8e SOURCES/pycryptodome-3.6.4.tar.gz +db309e6964b102ff36de319ce551db512a78281e SOURCES/python-gflags-2.0.tar.gz +7933292fb56af9f22fb1460374dc4657c01aa3fb SOURCES/uritemplate-3.0.0.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f69c86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +SOURCES/aliyun-python-sdk-core-2.8.5.tar.gz +SOURCES/aliyun-python-sdk-ecs-4.9.3.tar.gz +SOURCES/aliyun-python-sdk-vpc-3.0.2.tar.gz +SOURCES/fasteners-0.9.0.tar.gz +SOURCES/fence-agents-4.2.1.tar.gz +SOURCES/google-api-python-client-1.6.3.tar.gz +SOURCES/httplib2-0.9.1.tar.gz +SOURCES/keyring-5.0.zip +SOURCES/oauth2client-4.0.0.tar.gz +SOURCES/pycryptodome-3.6.4.tar.gz +SOURCES/python-gflags-2.0.tar.gz +SOURCES/uritemplate-3.0.0.tar.gz diff --git a/SOURCES/bz1236395-1-fence_scsi-fence_scsi_check.pl-link.patch b/SOURCES/bz1236395-1-fence_scsi-fence_scsi_check.pl-link.patch new file mode 100644 index 0000000..507540b --- /dev/null +++ b/SOURCES/bz1236395-1-fence_scsi-fence_scsi_check.pl-link.patch @@ -0,0 +1,36 @@ +diff -uNr a/agents/Makefile.am b/agents/Makefile.am +--- a/agents/Makefile.am 2018-06-18 12:14:35.000000000 +0200 ++++ b/agents/Makefile.am 2018-06-28 12:50:17.193565151 +0200 +@@ -52,7 +52,7 @@ + + if BUILD_FENCE_SCSI + scsidatadir = $(CLUSTERDATA) +-scsidata_SCRIPTS = scsi/fence_scsi_check scsi/fence_scsi_check_hardreboot ++scsidata_SCRIPTS = scsi/fence_scsi_check scsi/fence_scsi_check_hardreboot scsi/fence_scsi_check.pl + endif + + FENCE_TEST_ARGS = \ +@@ -72,6 +72,9 @@ + -e 's#@clustervarrun@#${CLUSTERVARRUN}#g' \ + > $@ + ++scsi/fence_scsi_check.pl: scsi/fence_scsi ++ cp $^ $@ ++ + scsi/fence_scsi_check: scsi/fence_scsi + cp $^ $@ + +diff -uNr a/agents/scsi/fence_scsi.py b/agents/scsi/fence_scsi.py +--- a/agents/scsi/fence_scsi.py 2018-06-18 12:14:35.000000000 +0200 ++++ b/agents/scsi/fence_scsi.py 2018-06-28 12:34:24.319178921 +0200 +@@ -430,7 +430,9 @@ + ignored when used with the -k option." + + #fence_scsi_check +- if os.path.basename(sys.argv[0]) == "fence_scsi_check": ++ if os.path.basename(sys.argv[0]) == "fence_scsi_check.pl": ++ sys.exit(scsi_check()) ++ elif os.path.basename(sys.argv[0]) == "fence_scsi_check": + sys.exit(scsi_check()) + elif os.path.basename(sys.argv[0]) == "fence_scsi_check_hardreboot": + sys.exit(scsi_check(True)) diff --git a/SOURCES/bz1236395-2-fence_ilo3-fence_ipmilan-show-correct-default-method.patch b/SOURCES/bz1236395-2-fence_ilo3-fence_ipmilan-show-correct-default-method.patch new file mode 100644 index 0000000..677ebb1 --- /dev/null +++ b/SOURCES/bz1236395-2-fence_ilo3-fence_ipmilan-show-correct-default-method.patch @@ -0,0 +1,26 @@ +From bd1b11884f33f5fce5ca7618c9f87b540592e1b6 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 2 Jul 2018 16:36:41 +0200 +Subject: [PATCH] fence_ilo3/fence_ipmilan: show correct default method (onoff) + in help + +--- + agents/ipmilan/fence_ipmilan.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/ipmilan/fence_ipmilan.py b/agents/ipmilan/fence_ipmilan.py +index 453d7365..9610f1c6 100644 +--- a/agents/ipmilan/fence_ipmilan.py ++++ b/agents/ipmilan/fence_ipmilan.py +@@ -171,7 +171,7 @@ def main(): + all_opt["lanplus"]["default"] = "1" + + all_opt["ipport"]["default"] = "623" +- all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)\n" \ ++ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: onoff)\n" \ + "WARNING! This fence agent might report success before the node is powered off. " \ + "You should use -m/method onoff if your fence device works correctly with that option." + +-- +2.17.1 + diff --git a/SOURCES/bz1236395-3-fix-version.patch b/SOURCES/bz1236395-3-fix-version.patch new file mode 100644 index 0000000..dbb2fc2 --- /dev/null +++ b/SOURCES/bz1236395-3-fix-version.patch @@ -0,0 +1,10 @@ +diff -uNr a/.tarball-version b/.tarball-version +--- a/.tarball-version 1970-01-01 01:00:00.000000000 +0100 ++++ b/.tarball-version 2018-08-20 10:42:03.876068353 +0200 +@@ -0,0 +1 @@ ++4.2.1 +diff -uNr a/.version b/.version +--- a/.version 1970-01-01 01:00:00.000000000 +0100 ++++ b/.version 2018-08-20 10:52:35.712060731 +0200 +@@ -0,0 +1 @@ ++4.2.1 diff --git a/SOURCES/bz1350908-fence_vmware_soap-cleanup-sigterm.patch b/SOURCES/bz1350908-fence_vmware_soap-cleanup-sigterm.patch new file mode 100644 index 0000000..8d27ea4 --- /dev/null +++ b/SOURCES/bz1350908-fence_vmware_soap-cleanup-sigterm.patch @@ -0,0 +1,41 @@ +From 116fb7d1253ac31a8f174187dfe9f4a0c6546ade Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 7 Sep 2018 15:56:56 +0200 +Subject: [PATCH] fence_vmware_soap: cleanup when receiving SIGTERM + +--- + agents/vmware_soap/fence_vmware_soap.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/agents/vmware_soap/fence_vmware_soap.py b/agents/vmware_soap/fence_vmware_soap.py +index b90edc9b..dd1a4ed6 100644 +--- a/agents/vmware_soap/fence_vmware_soap.py ++++ b/agents/vmware_soap/fence_vmware_soap.py +@@ -3,7 +3,7 @@ + import sys + import shutil, tempfile, suds + import logging, requests +-import atexit ++import atexit, signal + sys.path.append("@FENCEAGENTSLIBDIR@") + + from suds.client import Client +@@ -211,6 +211,9 @@ def logout(): + except Exception: + pass + ++def signal_handler(signum, frame): ++ raise Exception("Signal \"%d\" received which has triggered an exit of the process." % signum) ++ + def main(): + global options_global + global conn_global +@@ -219,6 +222,8 @@ def main(): + atexit.register(atexit_handler) + atexit.register(logout) + ++ signal.signal(signal.SIGTERM, signal_handler) ++ + options_global = check_input(device_opt, process_input(device_opt)) + + ## diff --git a/SOURCES/bz1402862-fence_rhevm-RHEV-v4-API-support.patch b/SOURCES/bz1402862-fence_rhevm-RHEV-v4-API-support.patch new file mode 100644 index 0000000..6f115e8 --- /dev/null +++ b/SOURCES/bz1402862-fence_rhevm-RHEV-v4-API-support.patch @@ -0,0 +1,164 @@ +From a4e8b77ac51a0e4a6de489823ee1be47cbc7eb18 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 9 May 2019 12:09:48 +0200 +Subject: [PATCH] fence_rhevm: add RHEV v4 API support and auto-detection + +--- + agents/rhevm/fence_rhevm.py | 44 +++++++++++++++++++++++------ + tests/data/metadata/fence_rhevm.xml | 7 ++++- + 2 files changed, 41 insertions(+), 10 deletions(-) + +diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py +index a1cdaf605..6012c4239 100644 +--- a/agents/rhevm/fence_rhevm.py ++++ b/agents/rhevm/fence_rhevm.py +@@ -9,7 +9,8 @@ + from fencing import fail, EC_FETCH_VM_UUID, run_delay + + RE_GET_ID = re.compile("(.*?)", re.IGNORECASE) ++RE_STATUS = re.compile("(.*?)", re.IGNORECASE) ++RE_STATE = re.compile("(.*?)", re.IGNORECASE) + RE_GET_NAME = re.compile("(.*?)", re.IGNORECASE) + + def get_power_status(conn, options): +@@ -25,7 +26,10 @@ def get_power_status(conn, options): + + options["id"] = result.group(2) + +- result = RE_STATUS.search(res) ++ if tuple(map(int, options["--api-version"].split(".")))[0] > 3: ++ result = RE_STATUS.search(res) ++ else: ++ result = RE_STATE.search(res) + if result == None: + # We were able to parse ID so output is correct + # in some cases it is possible that RHEV-M output does not +@@ -59,7 +63,10 @@ def get_list(conn, options): + lines = res.split(" 3: ++ status = RE_STATUS.search(lines[i]).group(1) ++ else: ++ status = RE_STATE.search(lines[i]).group(1) + outlets[name] = ("", status) + except AttributeError: + return {} +@@ -69,6 +76,13 @@ def get_list(conn, options): + return outlets + + def send_command(opt, command, method="GET"): ++ if opt["--api-version"] == "auto": ++ opt["--api-version"] = "4" ++ res = send_command(opt, "") ++ if re.search("Error", res): ++ opt["--api-version"] = "3" ++ logging.debug("auto-detected API version: " + opt["--api-version"]) ++ + ## setup correct URL + if "--ssl" in opt or "--ssl-secure" in opt or "--ssl-insecure" in opt: + url = "https:" +@@ -90,7 +104,7 @@ def send_command(opt, command, method="GET"): + web_buffer = io.BytesIO() + conn.setopt(pycurl.URL, url.encode("UTF-8")) + conn.setopt(pycurl.HTTPHEADER, [ +- "Version: 3", ++ "Version: {}".format(opt["--api-version"]), + "Content-type: application/xml", + "Accept: application/xml", + "Prefer: persistent-auth", +@@ -130,8 +144,9 @@ def send_command(opt, command, method="GET"): + + result = web_buffer.getvalue().decode("UTF-8") + +- logging.debug("%s\n", command) +- logging.debug("%s\n", result) ++ logging.debug("url: %s\n", url) ++ logging.debug("command: %s\n", command) ++ logging.debug("result: %s\n", result) + + return result + +@@ -151,6 +166,15 @@ def define_new_opts(): + "required" : "0", + "shortdesc" : "Reuse cookies for authentication", + "order" : 1} ++ all_opt["api_version"] = { ++ "getopt" : ":", ++ "longopt" : "api-version", ++ "help" : "--api-version " ++ "Version of RHEV API (default: auto)", ++ "required" : "0", ++ "order" : 2, ++ "default" : "auto", ++ } + all_opt["api_path"] = { + "getopt" : ":", + "longopt" : "api-path", +@@ -158,20 +182,19 @@ def define_new_opts(): + "default" : "/ovirt-engine/api", + "required" : "0", + "shortdesc" : "The path part of the API URL", +- "order" : 2} ++ "order" : 3} + all_opt["disable_http_filter"] = { + "getopt" : "", + "longopt" : "disable-http-filter", + "help" : "--disable-http-filter Set HTTP Filter header to false", + "required" : "0", + "shortdesc" : "Set HTTP Filter header to false", +- "order" : 3} ++ "order" : 4} + + + def main(): + device_opt = [ + "ipaddr", +- "api_path", + "login", + "passwd", + "ssl", +@@ -179,6 +202,8 @@ def main(): + "web", + "port", + "use_cookies", ++ "api_version", ++ "api_path", + "disable_http_filter", + ] + +@@ -186,6 +211,7 @@ def main(): + define_new_opts() + + all_opt["power_wait"]["default"] = "1" ++ all_opt["shell_timeout"]["default"] = "5" + + options = check_input(device_opt, process_input(device_opt)) + +diff --git a/tests/data/metadata/fence_rhevm.xml b/tests/data/metadata/fence_rhevm.xml +index 6344db79f..c56cf64b6 100644 +--- a/tests/data/metadata/fence_rhevm.xml ++++ b/tests/data/metadata/fence_rhevm.xml +@@ -98,6 +98,11 @@ + + Login name + ++ ++ ++ ++ Version of RHEV API (default: auto) ++ + + + The path part of the API URL +@@ -164,7 +169,7 @@ + + + +- ++ + Wait X seconds for cmd prompt after issuing command + + diff --git a/SOURCES/bz1464933-1-fence_redfish.patch b/SOURCES/bz1464933-1-fence_redfish.patch new file mode 100644 index 0000000..c6f5dfd --- /dev/null +++ b/SOURCES/bz1464933-1-fence_redfish.patch @@ -0,0 +1,812 @@ +From 64e3f3ef4d0abefd2836fe015c87173310b1e130 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Mon, 3 Dec 2018 10:11:15 -0600 +Subject: [PATCH 1/8] Add new fence agent for Redfish + +- Agent works on all fence devices that implement the Redfish API specification +- Agent programatically finds the Systems Resouce URI if it's not provided +--- + agents/redfish/fence_redfish.py | 151 +++++++++++++++++++++ + tests/data/metadata/fence_redfish.xml | 181 ++++++++++++++++++++++++++ + 2 files changed, 332 insertions(+) + create mode 100644 agents/redfish/fence_redfish.py + create mode 100644 tests/data/metadata/fence_redfish.xml + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +new file mode 100644 +index 00000000..df7cf8c2 +--- /dev/null ++++ b/agents/redfish/fence_redfish.py +@@ -0,0 +1,151 @@ ++#!@PYTHON@ -tt ++ ++# Copyright (c) 2018 Dell Inc. or its subsidiaries. All Rights Reserved. ++ ++# Fence agent for devices that support the Redfish API Specification. ++ ++import sys ++import re ++import json ++import requests ++import atexit ++sys.path.append("@FENCEAGENTSLIBDIR@") ++ ++from requests.packages.urllib3.exceptions import InsecureRequestWarning ++from fencing import * ++from fencing import fail_usage ++ ++def get_power_status(conn, options): ++ uri = options["--systems-uri"] ++ response = send_get_request(options, uri) ++ if response['ret'] is False: ++ fail_usage("Couldn't get power information") ++ data = response['data'] ++ if data[u'PowerState'].strip() == "On": ++ return "on" ++ else: ++ return "off" ++ ++def set_power_status(conn, options): ++ action = { ++ 'on' : "On", ++ 'off': "ForceOff", ++ 'reboot': "GracefulRestart" ++ }[options["--action"]] ++ ++ payload = {'ResetType': action} ++ headers = {'content-type': 'application/json'} ++ ++ # Search for 'Actions' key and extract URI from it ++ uri = options["--systems-uri"] ++ response = send_get_request(options, uri) ++ if response['ret'] is False: ++ return {'ret': False} ++ data = response['data'] ++ uri = data["Actions"]["#ComputerSystem.Reset"]["target"] ++ ++ response = send_post_request(options, uri, payload, headers) ++ if response['ret'] is False: ++ fail_usage("Error sending power command") ++ return ++ ++def send_get_request(options, uri): ++ full_uri = "https://" + options["--ip"] + uri ++ try: ++ resp = requests.get(full_uri, verify=False, ++ auth=(options["--username"], options["--password"])) ++ data = resp.json() ++ except: ++ return {'ret': False} ++ return {'ret': True, 'data': data} ++ ++def send_post_request(options, uri, payload, headers): ++ full_uri = "https://" + options["--ip"] + uri ++ try: ++ requests.post(full_uri, data=json.dumps(payload), ++ headers=headers, verify=False, ++ auth=(options["--username"], options["--password"])) ++ except: ++ return {'ret': False} ++ return {'ret': True} ++ ++def find_systems_resource(options): ++ uri = options["--redfish-uri"] ++ response = send_get_request(options, uri) ++ if response['ret'] is False: ++ return {'ret': False} ++ data = response['data'] ++ ++ if 'Systems' not in data: ++ # Systems resource not found" ++ return {'ret': False} ++ else: ++ uri = data["Systems"]["@odata.id"] ++ response = send_get_request(options, uri) ++ if response['ret'] is False: ++ return {'ret': False} ++ data = response['data'] ++ ++ # need to be able to handle more than one entry ++ for member in data[u'Members']: ++ system_uri = member[u'@odata.id'] ++ return {'ret': True, 'uri': system_uri} ++ ++def define_new_opts(): ++ all_opt["redfish-uri"] = { ++ "getopt" : ":", ++ "longopt" : "redfish-uri", ++ "help" : "--redfish-uri=[uri] Base or starting Redifsh URI", ++ "required" : "0", ++ "default" : "/redfish/v1", ++ "shortdesc" : "Base or starting Redfish URI", ++ "order": 1 ++ } ++ all_opt["systems-uri"] = { ++ "getopt" : ":", ++ "longopt" : "systems-uri", ++ "help" : "--systems-uri=[uri] Redfish Systems resource URI", ++ "required" : "0", ++ "shortdesc" : "Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1", ++ "order": 1 ++ } ++ ++def main(): ++ atexit.register(atexit_handler) ++ device_opt = ["ipaddr", "login", "passwd", "redfish-uri", "systems-uri", "ssl"] ++ define_new_opts() ++ ++ opt = process_input(device_opt) ++ ++ all_opt["ipport"]["default"] = "443" ++ options = check_input(device_opt, opt) ++ ++ docs = {} ++ docs["shortdesc"] = "I/O Fencing agent for Redfish" ++ docs["longdesc"] = "fence_redfish is an I/O Fencing agent which can be used with \ ++Out-of-Band controllers that support Redfish APIs. These controllers provide remote \ ++access to control power on a server." ++ docs["vendorurl"] = "http://www.dmtf.org" ++ show_docs(options, docs) ++ ++ ## ++ ## Operate the fencing device ++ #### ++ ++ # Disable insecure-certificate-warning message ++ if "--ssl-insecure" in opt: ++ requests.packages.urllib3.disable_warnings(InsecureRequestWarning) ++ ++ if "--systems-uri" not in opt: ++ # Systems URI not provided, find it ++ sysresult = find_systems_resource(options) ++ if sysresult['ret'] is False: ++ sys.exit(1) ++ else: ++ options["--systems-uri"] = sysresult["uri"] ++ ++ result = fence_action(None, options, set_power_status, get_power_status, None) ++ sys.exit(result) ++ ++if __name__ == "__main__": ++ main() +diff --git a/tests/data/metadata/fence_redfish.xml b/tests/data/metadata/fence_redfish.xml +new file mode 100644 +index 00000000..43d447d0 +--- /dev/null ++++ b/tests/data/metadata/fence_redfish.xml +@@ -0,0 +1,181 @@ ++ ++ ++fence_redfish is an I/O Fencing agent which can be used with Out-of-Band controllers that support Redfish APIs. These controllers provide remote access to control power on a server. ++http://www.dmtf.org ++ ++ ++ ++ ++ TCP/UDP port to use for connection with device ++ ++ ++ ++ ++ SSL connection with verifying fence device's certificate ++ ++ ++ ++ ++ Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1 ++ ++ ++ ++ ++ Fencing Action ++ ++ ++ ++ ++ Forces agent to use IPv6 addresses only ++ ++ ++ ++ ++ IP Address or Hostname ++ ++ ++ ++ ++ IP address or hostname of fencing device (together with --port-as-ip) ++ ++ ++ ++ ++ Script to retrieve password ++ ++ ++ ++ ++ Forces agent to use IPv4 addresses only ++ ++ ++ ++ ++ Login password or passphrase ++ ++ ++ ++ ++ SSL connection ++ ++ ++ ++ ++ Base or starting Redfish URI ++ ++ ++ ++ ++ SSL connection without verifying fence device's certificate ++ ++ ++ ++ ++ Login Name ++ ++ ++ ++ ++ IP address or hostname of fencing device (together with --port-as-ip) ++ ++ ++ ++ ++ Login Name ++ ++ ++ ++ ++ Base or starting Redfish URI ++ ++ ++ ++ ++ IP Address or Hostname ++ ++ ++ ++ ++ Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1 ++ ++ ++ ++ ++ Login password or passphrase ++ ++ ++ ++ ++ Script to retrieve password ++ ++ ++ ++ ++ Verbose mode ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Display version information and exit ++ ++ ++ ++ ++ Display help and exit ++ ++ ++ ++ ++ Wait X seconds after issuing ON/OFF ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after login ++ ++ ++ ++ ++ Test X seconds for status change after ON/OFF ++ ++ ++ ++ ++ Wait X seconds before fencing is started ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after issuing command ++ ++ ++ ++ ++ Make "port/plug" to be an alias to IP address ++ ++ ++ ++ ++ Count of attempts to retry power on ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + +From 6921a34d64d098a7b1f32205e0be434438c36898 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Mon, 3 Dec 2018 10:46:52 -0600 +Subject: [PATCH 2/8] Updated fence_redfish.xml with make xml-upload + +--- + tests/data/metadata/fence_redfish.xml | 148 ++++++++++++++------------ + 1 file changed, 79 insertions(+), 69 deletions(-) + +diff --git a/tests/data/metadata/fence_redfish.xml b/tests/data/metadata/fence_redfish.xml +index 43d447d0..a39541e6 100644 +--- a/tests/data/metadata/fence_redfish.xml ++++ b/tests/data/metadata/fence_redfish.xml +@@ -3,110 +3,115 @@ + fence_redfish is an I/O Fencing agent which can be used with Out-of-Band controllers that support Redfish APIs. These controllers provide remote access to control power on a server. + http://www.dmtf.org + +- +- +- +- TCP/UDP port to use for connection with device +- +- +- +- +- SSL connection with verifying fence device's certificate +- +- +- +- +- Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1 +- + + + +- Fencing Action ++ Fencing action ++ ++ ++ ++ ++ Forces agent to use IPv4 addresses only + + + + + Forces agent to use IPv6 addresses only + +- ++ + + +- IP Address or Hostname ++ IP address or hostname of fencing device + +- +- ++ ++ + +- IP address or hostname of fencing device (together with --port-as-ip) ++ IP address or hostname of fencing device + +- +- +- +- Script to retrieve password ++ ++ ++ ++ TCP/UDP port to use for connection with device + +- +- +- +- Forces agent to use IPv4 addresses only ++ ++ ++ ++ Login name + + + + + Login password or passphrase + +- +- +- +- SSL connection +- +- +- +- +- Base or starting Redfish URI ++ ++ ++ ++ Script to run to retrieve password + +- +- +- +- SSL connection without verifying fence device's certificate ++ ++ ++ ++ Login password or passphrase + +- +- ++ ++ + +- Login Name ++ Script to run to retrieve password + + + + + IP address or hostname of fencing device (together with --port-as-ip) + +- +- ++ ++ + +- Login Name ++ IP address or hostname of fencing device (together with --port-as-ip) ++ ++ ++ ++ ++ Base or starting Redfish URI + + + + + Base or starting Redfish URI + +- +- ++ ++ ++ ++ Use SSL connection with verifying certificate ++ ++ ++ ++ ++ Use SSL connection without verifying certificate ++ ++ ++ ++ ++ Use SSL connection with verifying certificate ++ ++ ++ + +- IP Address or Hostname ++ Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1 + + + + + Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1 + +- +- ++ ++ + +- Login password or passphrase ++ Login name + +- +- +- +- Script to retrieve password ++ ++ ++ ++ Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. + + + +@@ -133,41 +138,45 @@ + + Display help and exit + +- +- ++ ++ + +- Wait X seconds after issuing ON/OFF ++ Wait X seconds before fencing is started + + + + + Wait X seconds for cmd prompt after login + ++ ++ ++ ++ Make "port/plug" to be an alias to IP address ++ + + + + Test X seconds for status change after ON/OFF + +- +- ++ ++ + +- Wait X seconds before fencing is started ++ Wait X seconds after issuing ON/OFF + + + + + Wait X seconds for cmd prompt after issuing command + +- +- +- +- Make "port/plug" to be an alias to IP address +- + + + + Count of attempts to retry power on + ++ ++ ++ Path to gnutls-cli binary ++ + + + +@@ -176,6 +185,7 @@ + + + ++ + + + + +From 755627fadd711848ea256d72f5e75f36f83b4d31 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Mon, 3 Dec 2018 11:55:23 -0600 +Subject: [PATCH 3/8] Added run_delay() + +--- + agents/redfish/fence_redfish.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index df7cf8c2..0e4a4f68 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -13,7 +13,7 @@ + + from requests.packages.urllib3.exceptions import InsecureRequestWarning + from fencing import * +-from fencing import fail_usage ++from fencing import fail_usage, run_delay + + def get_power_status(conn, options): + uri = options["--systems-uri"] +@@ -127,6 +127,7 @@ def main(): + access to control power on a server." + docs["vendorurl"] = "http://www.dmtf.org" + show_docs(options, docs) ++ run_delay(options) + + ## + ## Operate the fencing device + +From 15fef4c47f391a3f03c714d86c9670ea209dec99 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Tue, 4 Dec 2018 10:56:58 -0600 +Subject: [PATCH 4/8] Modify power status check + +- Only returns off if PowerState = Off +- Otherwise returns on +--- + agents/redfish/fence_redfish.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 0e4a4f68..7998fb1c 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -21,10 +21,10 @@ def get_power_status(conn, options): + if response['ret'] is False: + fail_usage("Couldn't get power information") + data = response['data'] +- if data[u'PowerState'].strip() == "On": +- return "on" +- else: ++ if data[u'PowerState'].strip() == "Off": + return "off" ++ else: ++ return "on" + + def set_power_status(conn, options): + action = { + +From acf70f4672be65562841227ab0b4cacb87965f44 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Wed, 5 Dec 2018 10:39:32 -0600 +Subject: [PATCH 5/8] Changed reboot type to ForceRestart + +--- + agents/redfish/fence_redfish.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 7998fb1c..3fe2bfc0 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -30,7 +30,7 @@ def set_power_status(conn, options): + action = { + 'on' : "On", + 'off': "ForceOff", +- 'reboot': "GracefulRestart" ++ 'reboot': "ForceRestart" + }[options["--action"]] + + payload = {'ResetType': action} + +From 56e3358d45050ac669c099c56873feefa1ecda38 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Wed, 5 Dec 2018 10:54:44 -0600 +Subject: [PATCH 6/8] Replaced default port 443 with default ssl enabled option + +--- + agents/redfish/fence_redfish.py | 2 +- + tests/data/metadata/fence_redfish.xml | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 3fe2bfc0..6a2dbb76 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -117,7 +117,7 @@ def main(): + + opt = process_input(device_opt) + +- all_opt["ipport"]["default"] = "443" ++ all_opt["ssl"]["default"] = "1" + options = check_input(device_opt, opt) + + docs = {} +diff --git a/tests/data/metadata/fence_redfish.xml b/tests/data/metadata/fence_redfish.xml +index a39541e6..e1c18584 100644 +--- a/tests/data/metadata/fence_redfish.xml ++++ b/tests/data/metadata/fence_redfish.xml +@@ -80,7 +80,7 @@ + + + +- ++ + Use SSL connection with verifying certificate + + + +From 5c25a85b22a17d6bbc3dcb47c99b76e3a99a5857 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Wed, 5 Dec 2018 13:29:42 -0600 +Subject: [PATCH 7/8] Renamed variable to avoid reusing variable name + +--- + agents/redfish/fence_redfish.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 6a2dbb76..1ea25cd8 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -42,9 +42,9 @@ def set_power_status(conn, options): + if response['ret'] is False: + return {'ret': False} + data = response['data'] +- uri = data["Actions"]["#ComputerSystem.Reset"]["target"] ++ action_uri = data["Actions"]["#ComputerSystem.Reset"]["target"] + +- response = send_post_request(options, uri, payload, headers) ++ response = send_post_request(options, action_uri, payload, headers) + if response['ret'] is False: + fail_usage("Error sending power command") + return + +From 7dce8b1e22d57fec0d34e91a99fab9d8a06f1303 Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Thu, 6 Dec 2018 10:33:06 -0600 +Subject: [PATCH 8/8] Removed unnecessary variable assignments to simplify code + +--- + agents/redfish/fence_redfish.py | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 1ea25cd8..67ef67ab 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -16,8 +16,7 @@ + from fencing import fail_usage, run_delay + + def get_power_status(conn, options): +- uri = options["--systems-uri"] +- response = send_get_request(options, uri) ++ response = send_get_request(options, options["--systems-uri"]) + if response['ret'] is False: + fail_usage("Couldn't get power information") + data = response['data'] +@@ -37,8 +36,7 @@ def set_power_status(conn, options): + headers = {'content-type': 'application/json'} + + # Search for 'Actions' key and extract URI from it +- uri = options["--systems-uri"] +- response = send_get_request(options, uri) ++ response = send_get_request(options, options["--systems-uri"]) + if response['ret'] is False: + return {'ret': False} + data = response['data'] +@@ -70,8 +68,7 @@ def send_post_request(options, uri, payload, headers): + return {'ret': True} + + def find_systems_resource(options): +- uri = options["--redfish-uri"] +- response = send_get_request(options, uri) ++ response = send_get_request(options, options["--redfish-uri"]) + if response['ret'] is False: + return {'ret': False} + data = response['data'] +@@ -80,8 +77,7 @@ def find_systems_resource(options): + # Systems resource not found" + return {'ret': False} + else: +- uri = data["Systems"]["@odata.id"] +- response = send_get_request(options, uri) ++ response = send_get_request(options, data["Systems"]["@odata.id"]) + if response['ret'] is False: + return {'ret': False} + data = response['data'] diff --git a/SOURCES/bz1464933-2-fence_redfish-fail-invalid-cert.patch b/SOURCES/bz1464933-2-fence_redfish-fail-invalid-cert.patch new file mode 100644 index 0000000..a834644 --- /dev/null +++ b/SOURCES/bz1464933-2-fence_redfish-fail-invalid-cert.patch @@ -0,0 +1,60 @@ +From 7aa3c50d1d02dd26bdeac99c49ada72f842d88e8 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 17 Jan 2019 16:52:52 +0100 +Subject: [PATCH] fence_redfish: fail when using invalid cert without + --ssl-insecure + +--- + agents/redfish/fence_redfish.py | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 67ef67ab..5b719d4b 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -6,6 +6,7 @@ + + import sys + import re ++import logging + import json + import requests + import atexit +@@ -20,6 +21,9 @@ def get_power_status(conn, options): + if response['ret'] is False: + fail_usage("Couldn't get power information") + data = response['data'] ++ ++ logging.debug("PowerState is: " + data[u'PowerState']) ++ + if data[u'PowerState'].strip() == "Off": + return "off" + else: +@@ -50,21 +54,21 @@ def set_power_status(conn, options): + def send_get_request(options, uri): + full_uri = "https://" + options["--ip"] + uri + try: +- resp = requests.get(full_uri, verify=False, ++ resp = requests.get(full_uri, verify=not "--ssl-insecure" in options, + auth=(options["--username"], options["--password"])) + data = resp.json() +- except: +- return {'ret': False} ++ except Exception as e: ++ fail_usage("Failed: send_get_request: " + str(e)) + return {'ret': True, 'data': data} + + def send_post_request(options, uri, payload, headers): + full_uri = "https://" + options["--ip"] + uri + try: + requests.post(full_uri, data=json.dumps(payload), +- headers=headers, verify=False, ++ headers=headers, verify=not "--ssl-insecure" in options, + auth=(options["--username"], options["--password"])) +- except: +- return {'ret': False} ++ except Exception as e: ++ fail_usage("Failed: send_post_request: " + str(e)) + return {'ret': True} + + def find_systems_resource(options): diff --git a/SOURCES/bz1504202-fence_mpath-watchdog-support.patch b/SOURCES/bz1504202-fence_mpath-watchdog-support.patch new file mode 100644 index 0000000..c2f0122 --- /dev/null +++ b/SOURCES/bz1504202-fence_mpath-watchdog-support.patch @@ -0,0 +1,176 @@ +From 199b1efee0ba1f01c27ca689a15465cf4a258ee6 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 22 Jan 2018 11:27:28 +0100 +Subject: [PATCH] fence_mpath: add watchdog support + +--- + agents/Makefile.am | 11 ++++++++ + agents/mpath/fence_mpath.py | 50 ++++++++++++++++++++++++++++++++++--- + configure.ac | 6 +++++ + make/fencebuild.mk | 2 +- + tests/data/metadata/fence_mpath.xml | 2 +- + 5 files changed, 66 insertions(+), 5 deletions(-) + +diff --git a/agents/Makefile.am b/agents/Makefile.am +index 2524a3ab..833d2af5 100644 +--- a/agents/Makefile.am ++++ b/agents/Makefile.am +@@ -50,6 +50,11 @@ zvm_fence_zvm_SOURCES = zvm/fence_zvm.c + zvm_fence_zvm_CFLAGS = -D_GNU_SOURCE -Izvm + endif + ++if BUILD_FENCE_MPATH ++mpathdatadir = $(CLUSTERDATA) ++mpathdata_SCRIPTS = mpath/fence_mpath_check mpath/fence_mpath_check_hardreboot ++endif ++ + if BUILD_FENCE_SCSI + scsidatadir = $(CLUSTERDATA) + scsidata_SCRIPTS = scsi/fence_scsi_check scsi/fence_scsi_check_hardreboot +@@ -72,6 +77,12 @@ manual/fence_ack_manual: manual/fence_ack_manual.in + -e 's#@clustervarrun@#${CLUSTERVARRUN}#g' \ + > $@ + ++mpath/fence_mpath_check: mpath/fence_mpath ++ cp $^ $@ ++ ++mpath/fence_mpath_check_hardreboot: mpath/fence_mpath ++ cp $^ $@ ++ + scsi/fence_scsi_check: scsi/fence_scsi + cp $^ $@ + +diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py +index ac5bc794..d9ac2ef5 100644 +--- a/agents/mpath/fence_mpath.py ++++ b/agents/mpath/fence_mpath.py +@@ -143,25 +143,63 @@ def dev_write(options, dev): + store_fh.write(dev + "\t" + options["--key"] + "\n") + store_fh.close() + +-def dev_read(options): ++def dev_read(options, fail=True): + dev_key = {} + file_path = options["--store-path"] + "/mpath.devices" + try: + store_fh = open(file_path, "r") + except IOError: +- fail_usage("Failed: Cannot open file \"" + file_path + "\"") ++ if fail: ++ fail_usage("Failed: Cannot open file \"" + file_path + "\"") ++ else: ++ return None + # get not empty lines from file + for (device, key) in [line.strip().split() for line in store_fh if line.strip()]: + dev_key[device] = key + store_fh.close() + return dev_key + ++def mpath_check_get_verbose(): ++ try: ++ f = open("/etc/sysconfig/watchdog", "r") ++ except IOError: ++ return False ++ match = re.search(r"^\s*verbose=yes", "".join(f.readlines()), re.MULTILINE) ++ f.close() ++ return bool(match) ++ ++def mpath_check(hardreboot=False): ++ if len(sys.argv) >= 3 and sys.argv[1] == "repair": ++ return int(sys.argv[2]) ++ options = {} ++ options["--mpathpersist-path"] = "/usr/sbin/mpathpersist" ++ options["--store-path"] = "/var/run/cluster" ++ options["--power-timeout"] = "5" ++ if mpath_check_get_verbose(): ++ logging.getLogger().setLevel(logging.DEBUG) ++ devs = dev_read(options, fail=False) ++ if not devs: ++ logging.error("No devices found") ++ return 0 ++ for dev, key in list(devs.items()): ++ if key in get_registration_keys(options, dev): ++ logging.debug("key " + key + " registered with device " + dev) ++ return 0 ++ else: ++ logging.debug("key " + key + " not registered with device " + dev) ++ logging.debug("key " + key + " registered with any devices") ++ ++ if hardreboot == True: ++ libc = ctypes.cdll['libc.so.6'] ++ libc.reboot(0x1234567) ++ return 2 ++ + def define_new_opts(): + all_opt["devices"] = { + "getopt" : "d:", + "longopt" : "devices", + "help" : "-d, --devices=[devices] List of devices to use for current operation", +- "required" : "1", ++ "required" : "0", + "shortdesc" : "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.", +@@ -205,6 +243,12 @@ def main(): + + define_new_opts() + ++ # fence_mpath_check ++ if os.path.basename(sys.argv[0]) == "fence_mpath_check": ++ sys.exit(mpath_check()) ++ elif os.path.basename(sys.argv[0]) == "fence_mpath_check_hardreboot": ++ sys.exit(mpath_check(hardreboot=True)) ++ + options = check_input(device_opt, process_input(device_opt), other_conditions=True) + + docs = {} +diff --git a/configure.ac b/configure.ac +index e8b24211..24b857b3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -148,6 +148,11 @@ if echo "$AGENTS_LIST" | grep -q -E "all|manual"; then + AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/manual( |$)//") + fi + ++FENCE_MPATH=0 ++if echo "$AGENTS_LIST" | grep -q -E "all|mpath"; then ++ FENCE_MPATH=1 ++fi ++ + FENCE_SCSI=0 + if echo "$AGENTS_LIST" | grep -q -E "all|scsi"; then + FENCE_SCSI=1 +@@ -312,6 +317,7 @@ AC_SUBST([SNMPBIN]) + AC_SUBST([AGENTS_LIST]) + AM_CONDITIONAL(BUILD_FENCE_KDUMP, test $FENCE_KDUMP -eq 1) + AM_CONDITIONAL(BUILD_FENCE_MANUAL, test $FENCE_MANUAL -eq 1) ++AM_CONDITIONAL(BUILD_FENCE_MPATH, test $FENCE_MPATH -eq 1) + AM_CONDITIONAL(BUILD_FENCE_SCSI, test $FENCE_SCSI -eq 1) + AM_CONDITIONAL(BUILD_FENCE_ZVM, test $FENCE_ZVM -eq 1) + AM_CONDITIONAL(BUILD_XENAPILIB, test $XENAPILIB -eq 1) +diff --git a/make/fencebuild.mk b/make/fencebuild.mk +index e08d5200..6a7c6f63 100644 +--- a/make/fencebuild.mk ++++ b/make/fencebuild.mk +@@ -51,7 +51,7 @@ $(TARGET): + $(call gen_agent_from_py) + + clean: clean-man +- rm -f $(CLEAN_TARGET:%.8=%) $(CLEAN_TARGET_ADDITIONAL) $(scsidata_SCRIPTS) */*.pyc *.pyc */*.wiki ++ rm -f $(CLEAN_TARGET:%.8=%) $(CLEAN_TARGET_ADDITIONAL) $(mpathdata_SCRIPTS) $(scsidata_SCRIPTS) */*.pyc */*.wiki + + if [ "$(abs_builddir)" = "$(abs_top_builddir)/lib" ]; then \ + rm -f $(TARGET); \ +diff --git a/tests/data/metadata/fence_mpath.xml b/tests/data/metadata/fence_mpath.xml +index f384e50b..bbe9ad2b 100644 +--- a/tests/data/metadata/fence_mpath.xml ++++ b/tests/data/metadata/fence_mpath.xml +@@ -9,7 +9,7 @@ The fence_mpath agent works by having a unique key for each node that has to be + + Fencing action + +- ++ + + + 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. diff --git a/SOURCES/bz1549699-1-fence_evacuate-fix-evacuable-tag-mix-issue.patch b/SOURCES/bz1549699-1-fence_evacuate-fix-evacuable-tag-mix-issue.patch new file mode 100644 index 0000000..a83ff74 --- /dev/null +++ b/SOURCES/bz1549699-1-fence_evacuate-fix-evacuable-tag-mix-issue.patch @@ -0,0 +1,20 @@ +diff -uNr a/agents/evacuate/fence_evacuate.py b/agents/evacuate/fence_evacuate.py +--- a/agents/evacuate/fence_evacuate.py 2018-06-28 14:24:54.000000000 +0200 ++++ b/agents/evacuate/fence_evacuate.py 2018-07-11 09:08:56.975072003 +0200 +@@ -74,12 +74,15 @@ + } + + def _is_server_evacuable(server, evac_flavors, evac_images): ++ reason = "flavor "+server.flavor.get('id') + if server.flavor.get('id') in evac_flavors: + return True + if hasattr(server.image, 'get'): + if server.image.get('id') in evac_images: + return True +- logging.debug("Instance %s is not evacuable" % server.image.get('id')) ++ reason = reason +" and image "+server.image.get('id') ++ ++ logging.debug("Instance is not evacuable: no match for %s" % reason) + return False + + def _get_evacuable_flavors(connection): diff --git a/SOURCES/bz1549699-2-fence_compute-fence_evacuate-fix-compute-domain.patch b/SOURCES/bz1549699-2-fence_compute-fence_evacuate-fix-compute-domain.patch new file mode 100644 index 0000000..3ae0ae8 --- /dev/null +++ b/SOURCES/bz1549699-2-fence_compute-fence_evacuate-fix-compute-domain.patch @@ -0,0 +1,232 @@ +From 15635df9d12ce693f473d5ebcd5b7cacb81e2295 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 16 Jul 2018 11:14:16 +0200 +Subject: [PATCH] fence_compute/fence_evacuate: workaround for compute-domain + regression + +--- + agents/compute/fence_compute.py | 24 +++++++++++++++++++----- + agents/evacuate/fence_evacuate.py | 24 +++++++++++++++++++----- + tests/data/metadata/fence_compute.xml | 24 ++++++++++++++++++++++-- + tests/data/metadata/fence_evacuate.xml | 24 ++++++++++++++++++++++-- + 4 files changed, 82 insertions(+), 14 deletions(-) + +diff --git a/agents/compute/fence_compute.py b/agents/compute/fence_compute.py +index ec2d093c..aac9b296 100644 +--- a/agents/compute/fence_compute.py ++++ b/agents/compute/fence_compute.py +@@ -353,7 +353,7 @@ def define_new_opts(): + "default" : "", + "order": 1, + } +- all_opt["user_domain"] = { ++ all_opt["user-domain"] = { + "getopt" : "u:", + "longopt" : "user-domain", + "help" : "-u, --user-domain=[name] Keystone v3 User Domain", +@@ -362,7 +362,7 @@ def define_new_opts(): + "default" : "Default", + "order": 2, + } +- all_opt["project_domain"] = { ++ all_opt["project-domain"] = { + "getopt" : "P:", + "longopt" : "project-domain", + "help" : "-d, --project-domain=[name] Keystone v3 Project Domain", +@@ -433,6 +433,14 @@ def define_new_opts(): + "default" : "False", + "order": 5, + } ++ all_opt["compute-domain"] = { ++ "getopt" : ":", ++ "longopt" : "compute-domain", ++ "help" : "--compute-domain=[string] Replaced by --domain", ++ "required" : "0", ++ "shortdesc" : "Replaced by domain", ++ "order": 6, ++ } + + def set_multi_power_fn(connection, options, set_power_fn, get_power_fn, retry_attempts=1): + for _ in range(retry_attempts): +@@ -450,9 +458,10 @@ def main(): + global override_status + atexit.register(atexit_handler) + +- device_opt = ["login", "passwd", "tenant_name", "auth_url", "fabric_fencing", +- "no_login", "no_password", "port", "domain", "project_domain", "user_domain", +- "no_shared_storage", "endpoint_type", "record_only", "instance_filtering", "insecure", "region_name"] ++ device_opt = ["login", "passwd", "tenant_name", "auth_url", "fabric_fencing", "no_login", ++ "no_password", "port", "domain", "compute-domain", "project-domain", ++ "user-domain", "no_shared_storage", "endpoint_type", "record_only", ++ "instance_filtering", "insecure", "region_name"] + define_new_opts() + all_opt["shell_timeout"]["default"] = "180" + +@@ -470,6 +479,11 @@ def main(): + + run_delay(options) + ++ # workaround to avoid regressions ++ if "--compute-domain" in options and options["--compute-domain"]: ++ options["--domain"] = options["--compute-domain"] ++ del options["--domain"] ++ + logging.debug("Running "+options["--action"]) + connection = create_nova_connection(options) + +diff --git a/agents/evacuate/fence_evacuate.py b/agents/evacuate/fence_evacuate.py +index 615dede7..529a60dd 100644 +--- a/agents/evacuate/fence_evacuate.py ++++ b/agents/evacuate/fence_evacuate.py +@@ -287,7 +287,7 @@ def define_new_opts(): + "default" : "", + "order": 1, + } +- all_opt["user_domain"] = { ++ all_opt["user-domain"] = { + "getopt" : "u:", + "longopt" : "user-domain", + "help" : "-u, --user-domain=[name] Keystone v3 User Domain", +@@ -296,7 +296,7 @@ def define_new_opts(): + "default" : "Default", + "order": 2, + } +- all_opt["project_domain"] = { ++ all_opt["project-domain"] = { + "getopt" : "P:", + "longopt" : "project-domain", + "help" : "-d, --project-domain=[name] Keystone v3 Project Domain", +@@ -358,14 +358,22 @@ def define_new_opts(): + "default" : "False", + "order": 5, + } ++ all_opt["compute-domain"] = { ++ "getopt" : ":", ++ "longopt" : "compute-domain", ++ "help" : "--compute-domain=[string] Replaced by --domain", ++ "required" : "0", ++ "shortdesc" : "Replaced by domain", ++ "order": 6, ++ } + + def main(): + atexit.register(atexit_handler) + + device_opt = ["login", "passwd", "tenant_name", "auth_url", +- "no_login", "no_password", "port", "domain", "project_domain", +- "user_domain", "no_shared_storage", "endpoint_type", +- "instance_filtering", "insecure", "region_name"] ++ "no_login", "no_password", "port", "domain", "compute-domain", ++ "project-domain", "user-domain", "no_shared_storage", ++ "endpoint_type", "instance_filtering", "insecure", "region_name"] + define_new_opts() + all_opt["shell_timeout"]["default"] = "180" + +@@ -380,6 +388,12 @@ def main(): + + run_delay(options) + ++ # workaround to avoid regressions ++ if "--compute-domain" in options and options["--compute-domain"]: ++ options["--domain"] = options["--compute-domain"] ++ del options["--domain"] ++ ++ + connection = create_nova_connection(options) + + # Un-evacuating a server doesn't make sense +diff --git a/tests/data/metadata/fence_compute.xml b/tests/data/metadata/fence_compute.xml +index e1dac97c..1dcbfc54 100644 +--- a/tests/data/metadata/fence_compute.xml ++++ b/tests/data/metadata/fence_compute.xml +@@ -73,12 +73,22 @@ + + Allow Insecure TLS Requests + +- ++ + + + Keystone v3 Project Domain + +- ++ ++ ++ ++ Keystone v3 Project Domain ++ ++ ++ ++ ++ Keystone v3 User Domain ++ ++ + + + Keystone v3 User Domain +@@ -103,6 +113,16 @@ + + Only record the target as needing evacuation + ++ ++ ++ ++ Replaced by domain ++ ++ ++ ++ ++ Replaced by domain ++ + + + +diff --git a/tests/data/metadata/fence_evacuate.xml b/tests/data/metadata/fence_evacuate.xml +index 6f8bd0a4..4f1f6a58 100644 +--- a/tests/data/metadata/fence_evacuate.xml ++++ b/tests/data/metadata/fence_evacuate.xml +@@ -73,12 +73,22 @@ + + Allow Insecure TLS Requests + +- ++ + + + Keystone v3 Project Domain + +- ++ ++ ++ ++ Keystone v3 Project Domain ++ ++ ++ ++ ++ Keystone v3 User Domain ++ ++ + + + Keystone v3 User Domain +@@ -98,6 +108,16 @@ + + Disable functionality for dealing with shared storage + ++ ++ ++ ++ Replaced by domain ++ ++ ++ ++ ++ Replaced by domain ++ + + + +-- +2.17.1 + diff --git a/SOURCES/bz1568742-1-fence_aliyun.patch b/SOURCES/bz1568742-1-fence_aliyun.patch new file mode 100644 index 0000000..c5f656b --- /dev/null +++ b/SOURCES/bz1568742-1-fence_aliyun.patch @@ -0,0 +1,344 @@ +From 418df5845d1781e18e300cf17b2de714e4ff09d1 Mon Sep 17 00:00:00 2001 +From: "feng.changf1" +Date: Tue, 24 Jul 2018 15:56:50 +0800 +Subject: [PATCH 1/3] Add Aliyun fence agent. + +--- + agents/aliyun/fence_aliyun.py | 146 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 146 insertions(+) + create mode 100644 agents/aliyun/fence_aliyun.py + +diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +new file mode 100644 +index 00000000..ec7d2316 +--- /dev/null ++++ b/agents/aliyun/fence_aliyun.py +@@ -0,0 +1,146 @@ ++#!/usr/bin/python -tt ++ ++import sys, re ++import logging ++import atexit ++import json ++sys.path.append("@FENCEAGENTSLIBDIR@") ++from fencing import * ++from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay ++ ++from aliyunsdkcore import client ++ ++from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest ++from aliyunsdkecs.request.v20140526.StartInstanceRequest import StartInstanceRequest ++from aliyunsdkecs.request.v20140526.StopInstanceRequest import StopInstanceRequest ++from aliyunsdkecs.request.v20140526.RebootInstanceRequest import RebootInstanceRequest ++ ++def _send_request(conn, request): ++ request.set_accept_format('json') ++ try: ++ response_str = conn.do_action_with_exception(request) ++ response_detail = json.loads(response_str) ++ return response_detail ++ except Exception as e: ++ fail_usage("Failed: _send_request failed") ++ ++def start_instance(conn, instance_id): ++ request = StartInstanceRequest() ++ request.set_InstanceId(instance_id) ++ _send_request(conn, request) ++ ++def stop_instance(conn, instance_id): ++ request = StopInstanceRequest() ++ request.set_InstanceId(instance_id) ++ request.set_ForceStop('true') ++ _send_request(conn, request) ++ ++def reboot_instance(conn, instance_id): ++ request = RebootInstanceRequest() ++ request.set_InstanceId(instance_id) ++ request.set_ForceStop('true') ++ _send_request(conn, request) ++ ++def get_status(conn, instance_id): ++ request = DescribeInstancesRequest() ++ request.set_InstanceIds(json.dumps([instance_id])) ++ response = _send_request(conn, request) ++ instance_status = None ++ if response is not None: ++ instance_list = response.get('Instances').get('Instance') ++ for item in instance_list: ++ instance_status = item.get('Status') ++ return instance_status ++ ++def get_nodes_list(conn, options): ++ result = {} ++ request = DescribeInstancesRequest() ++ response = _send_request(conn, request) ++ instance_status = None ++ if response is not None: ++ instance_list = response.get('Instances').get('Instance') ++ for item in instance_list: ++ instance_id = item.get('InstanceId') ++ result[instance_id] = ("", None) ++ return result ++ ++def get_power_status(conn, options): ++ state = get_status(conn, options["--plug"]) ++ if state == "Running": ++ return "on" ++ elif state == "Stopped": ++ return "off" ++ else: ++ return "unknown" ++ ++ ++def set_power_status(conn, options): ++ if (options["--action"]=="off"): ++ stop_instance(conn, options["--plug"]) ++ elif (options["--action"]=="on"): ++ start_instance(conn, options["--plug"]) ++ elif (options["--action"]=="reboot"): ++ reboot_instance(conn, options["--plug"]) ++ ++ ++def define_new_opts(): ++ all_opt["region"] = { ++ "getopt" : "r:", ++ "longopt" : "region", ++ "help" : "-r, --region=[name] Region, e.g. cn-hangzhou", ++ "shortdesc" : "Region.", ++ "required" : "0", ++ "order" : 2 ++ } ++ all_opt["access_key"] = { ++ "getopt" : "a:", ++ "longopt" : "access-key", ++ "help" : "-a, --access-key=[name] Access Key", ++ "shortdesc" : "Access Key.", ++ "required" : "0", ++ "order" : 3 ++ } ++ all_opt["secret_key"] = { ++ "getopt" : "s:", ++ "longopt" : "secret-key", ++ "help" : "-s, --secret-key=[name] Secret Key", ++ "shortdesc" : "Secret Key.", ++ "required" : "0", ++ "order" : 4 ++ } ++ ++# Main agent method ++def main(): ++ conn = None ++ ++ device_opt = ["port", "no_password", "region", "access_key", "secret_key"] ++ ++ atexit.register(atexit_handler) ++ ++ define_new_opts() ++ ++ all_opt["power_timeout"]["default"] = "60" ++ ++ options = check_input(device_opt, process_input(device_opt)) ++ ++ docs = {} ++ docs["shortdesc"] = "Fence agent for Aliyun (Aliyun Web Services)" ++ docs["longdesc"] = "fence_aliyun is an I/O Fencing agent for Aliyun" ++ docs["vendorurl"] = "http://www.aliyun.com" ++ show_docs(options, docs) ++ ++ run_delay(options) ++ ++ if "--region" in options and "--access-key" in options and "--secret-key" in options: ++ region = options["--region"] ++ access_key = options["--access-key"] ++ secret_key = options["--secret-key"] ++ conn = client.AcsClient(access_key, secret_key, region) ++ ++ ++ # Operate the fencing device ++ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) ++ sys.exit(result) ++ ++if __name__ == "__main__": ++ main() + +From 28b55555abda9b6c278a7f082bb22c4f6f1e2474 Mon Sep 17 00:00:00 2001 +From: "feng.changf1" +Date: Tue, 24 Jul 2018 17:18:53 +0800 +Subject: [PATCH 2/3] Add Aliyun fence agent. + +--- + tests/data/metadata/fence_aliyun.xml | 113 +++++++++++++++++++++++++++++++++++ + 1 file changed, 113 insertions(+) + create mode 100644 tests/data/metadata/fence_aliyun.xml + +diff --git a/tests/data/metadata/fence_aliyun.xml b/tests/data/metadata/fence_aliyun.xml +new file mode 100644 +index 00000000..1db692ee +--- /dev/null ++++ b/tests/data/metadata/fence_aliyun.xml +@@ -0,0 +1,113 @@ ++ ++ ++fence_aliyun is an I/O Fencing agent for Aliyun ++http://www.aliyun.com ++ ++ ++ ++ ++ Fencing action ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Region. ++ ++ ++ ++ ++ Access Key. ++ ++ ++ ++ ++ Secret Key. ++ ++ ++ ++ ++ Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. ++ ++ ++ ++ ++ Verbose mode ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ 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 ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after issuing command ++ ++ ++ ++ ++ Count of attempts to retry power on ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + +From 53bbd91e91c231c89ae8981238bb15d85d02207b Mon Sep 17 00:00:00 2001 +From: "feng.changf1" +Date: Tue, 24 Jul 2018 17:26:45 +0800 +Subject: [PATCH 3/3] Fix CI error. + +--- + agents/aliyun/fence_aliyun.py | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +index ec7d2316..0f24b83e 100644 +--- a/agents/aliyun/fence_aliyun.py ++++ b/agents/aliyun/fence_aliyun.py +@@ -1,20 +1,22 @@ + #!/usr/bin/python -tt + +-import sys, re +-import logging +-import atexit +-import json +-sys.path.append("@FENCEAGENTSLIBDIR@") +-from fencing import * +-from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay +- +-from aliyunsdkcore import client +- +-from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest +-from aliyunsdkecs.request.v20140526.StartInstanceRequest import StartInstanceRequest +-from aliyunsdkecs.request.v20140526.StopInstanceRequest import StopInstanceRequest +-from aliyunsdkecs.request.v20140526.RebootInstanceRequest import RebootInstanceRequest +- ++try: ++ import sys, re ++ import logging ++ import atexit ++ import json ++ sys.path.append("@FENCEAGENTSLIBDIR@") ++ from fencing import * ++ from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay ++ ++ from aliyunsdkcore import client ++ ++ from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest ++ from aliyunsdkecs.request.v20140526.StartInstanceRequest import StartInstanceRequest ++ from aliyunsdkecs.request.v20140526.StopInstanceRequest import StopInstanceRequest ++ from aliyunsdkecs.request.v20140526.RebootInstanceRequest import RebootInstanceRequest ++except ImportError: ++ pass + def _send_request(conn, request): + request.set_accept_format('json') + try: diff --git a/SOURCES/bz1568742-2-fence_aliyun.patch b/SOURCES/bz1568742-2-fence_aliyun.patch new file mode 100644 index 0000000..eb4c735 --- /dev/null +++ b/SOURCES/bz1568742-2-fence_aliyun.patch @@ -0,0 +1,58 @@ +From 8db45537fb470624a754ea1243cc4f349a9b413d Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 24 Jul 2018 13:10:41 +0200 +Subject: [PATCH] fence_aliyun: fix CI and add Python detection + +--- + agents/aliyun/fence_aliyun.py | 19 ++++++++++--------- + tests/data/metadata/fence_aliyun.xml | 1 + + 2 files changed, 11 insertions(+), 9 deletions(-) + +diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +index 0f24b83e..aa6c0acf 100644 +--- a/agents/aliyun/fence_aliyun.py ++++ b/agents/aliyun/fence_aliyun.py +@@ -1,14 +1,14 @@ +-#!/usr/bin/python -tt ++#!@PYTHON@ -tt + +-try: +- import sys, re +- import logging +- import atexit +- import json +- sys.path.append("@FENCEAGENTSLIBDIR@") +- from fencing import * +- from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay ++import sys, re ++import logging ++import atexit ++import json ++sys.path.append("@FENCEAGENTSLIBDIR@") ++from fencing import * ++from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay + ++try: + from aliyunsdkcore import client + + from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest +@@ -17,6 +17,7 @@ + from aliyunsdkecs.request.v20140526.RebootInstanceRequest import RebootInstanceRequest + except ImportError: + pass ++ + def _send_request(conn, request): + request.set_accept_format('json') + try: +diff --git a/tests/data/metadata/fence_aliyun.xml b/tests/data/metadata/fence_aliyun.xml +index 1db692ee..b41d82bf 100644 +--- a/tests/data/metadata/fence_aliyun.xml ++++ b/tests/data/metadata/fence_aliyun.xml +@@ -108,6 +108,7 @@ + + + ++ + + + diff --git a/SOURCES/bz1568742-3-fence_aliyun-logging.patch b/SOURCES/bz1568742-3-fence_aliyun-logging.patch new file mode 100644 index 0000000..52c2dca --- /dev/null +++ b/SOURCES/bz1568742-3-fence_aliyun-logging.patch @@ -0,0 +1,51 @@ +From 790cbaa66f3927a84739af4a1f0e8bba295cdc36 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 30 Jul 2018 10:43:04 +0200 +Subject: [PATCH] fence_aliyun: add logging + +--- + agents/aliyun/fence_aliyun.py | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +index aa6c0acf..2cda6b7f 100644 +--- a/agents/aliyun/fence_aliyun.py ++++ b/agents/aliyun/fence_aliyun.py +@@ -23,9 +23,10 @@ def _send_request(conn, request): + try: + response_str = conn.do_action_with_exception(request) + response_detail = json.loads(response_str) ++ logging.debug("_send_request reponse: %s" % response_detail) + return response_detail + except Exception as e: +- fail_usage("Failed: _send_request failed") ++ fail_usage("Failed: _send_request failed: %s" % e) + + def start_instance(conn, instance_id): + request = StartInstanceRequest() +@@ -69,15 +70,22 @@ def get_nodes_list(conn, options): + + def get_power_status(conn, options): + state = get_status(conn, options["--plug"]) ++ + if state == "Running": +- return "on" ++ status = "on" + elif state == "Stopped": +- return "off" ++ status = "off" + else: +- return "unknown" ++ status = "unknown" ++ ++ logging.info("get_power_status: %s" % status) ++ ++ return status + + + def set_power_status(conn, options): ++ logging.info("set_power_status: %s" % options["--action"]) ++ + if (options["--action"]=="off"): + stop_instance(conn, options["--plug"]) + elif (options["--action"]=="on"): diff --git a/SOURCES/bz1568742-4-fence_aliyun-bundled.patch b/SOURCES/bz1568742-4-fence_aliyun-bundled.patch new file mode 100644 index 0000000..99a0b50 --- /dev/null +++ b/SOURCES/bz1568742-4-fence_aliyun-bundled.patch @@ -0,0 +1,11 @@ +diff -uNr a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +--- a/agents/aliyun/fence_aliyun.py 2018-07-24 14:30:29.030311806 +0200 ++++ b/agents/aliyun/fence_aliyun.py 2018-07-24 14:31:10.023884949 +0200 +@@ -9,6 +9,7 @@ + from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay + + try: ++ sys.path.insert(0, '/usr/lib/fence-agents/bundled/aliyun') + from aliyunsdkcore import client + + from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest diff --git a/SOURCES/bz1568753-1-fence_gce-stackdriver-logging-default-method-cycle.patch b/SOURCES/bz1568753-1-fence_gce-stackdriver-logging-default-method-cycle.patch new file mode 100644 index 0000000..bafa753 --- /dev/null +++ b/SOURCES/bz1568753-1-fence_gce-stackdriver-logging-default-method-cycle.patch @@ -0,0 +1,674 @@ +From 59ae9d00060da5329d7ca538974498292bbe1d91 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Tue, 26 Jun 2018 10:18:29 -0300 +Subject: [PATCH 1/7] fence_gce: add support for stackdriver logging + +Add --logging option to enable sending logs to google stackdriver +--- + agents/gce/fence_gce.py | 65 +++++++++++++++++++++++++++++++++++++-- + tests/data/metadata/fence_gce.xml | 5 +++ + 2 files changed, 67 insertions(+), 3 deletions(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index 3abb5207..3af5bfc8 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -1,12 +1,19 @@ + #!@PYTHON@ -tt + + import atexit ++import logging ++import platform + import sys ++import time + sys.path.append("@FENCEAGENTSLIBDIR@") + + import googleapiclient.discovery + from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action + ++ ++LOGGER = logging ++ ++ + def translate_status(instance_status): + "Returns on | off | unknown." + if instance_status == "RUNNING": +@@ -27,6 +34,7 @@ def get_nodes_list(conn, options): + + return result + ++ + def get_power_status(conn, options): + try: + instance = conn.instances().get( +@@ -38,18 +46,37 @@ def get_power_status(conn, options): + fail_usage("Failed: get_power_status: {}".format(str(err))) + + ++def wait_for_operation(conn, project, zone, operation): ++ while True: ++ result = conn.zoneOperations().get( ++ project=project, ++ zone=zone, ++ operation=operation['name']).execute() ++ if result['status'] == 'DONE': ++ if 'error' in result: ++ raise Exception(result['error']) ++ return ++ time.sleep(1) ++ ++ + def set_power_status(conn, options): + try: + if options["--action"] == "off": +- conn.instances().stop( ++ LOGGER.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"])) ++ operation = conn.instances().stop( + project=options["--project"], + zone=options["--zone"], + instance=options["--plug"]).execute() ++ wait_for_operation(conn, options["--project"], options["--zone"], operation) ++ LOGGER.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"])) + elif options["--action"] == "on": +- conn.instances().start( ++ LOGGER.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"])) ++ operation = conn.instances().start( + project=options["--project"], + zone=options["--zone"], + instance=options["--plug"]).execute() ++ wait_for_operation(conn, options["--project"], options["--zone"], operation) ++ LOGGER.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"])) + except Exception as err: + fail_usage("Failed: set_power_status: {}".format(str(err))) + +@@ -71,11 +98,24 @@ def define_new_opts(): + "required" : "1", + "order" : 3 + } ++ all_opt["logging"] = { ++ "getopt" : ":", ++ "longopt" : "logging", ++ "help" : "--logging=[bool] Logging, true/false", ++ "shortdesc" : "Stackdriver-logging support.", ++ "longdesc" : "If enabled (set to true), IP failover logs will be posted to stackdriver logging.", ++ "required" : "0", ++ "default" : "false", ++ "order" : 4 ++ } + + def main(): + conn = None ++ global LOGGER ++ ++ hostname = platform.node() + +- device_opt = ["port", "no_password", "zone", "project"] ++ device_opt = ["port", "no_password", "zone", "project", "logging"] + + atexit.register(atexit_handler) + +@@ -97,6 +137,25 @@ def main(): + + run_delay(options) + ++ # Prepare logging ++ logging_env = options.get('--logging') ++ if logging_env: ++ logging_env = logging_env.lower() ++ if any(x in logging_env for x in ['yes', 'true', 'enabled']): ++ try: ++ import google.cloud.logging.handlers ++ client = google.cloud.logging.Client() ++ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname) ++ formatter = logging.Formatter('gcp:stonish "%(message)s"') ++ LOGGER = logging.getLogger(hostname) ++ handler.setFormatter(formatter) ++ LOGGER.addHandler(handler) ++ LOGGER.setLevel(logging.INFO) ++ except ImportError: ++ LOGGER.error('Couldn\'t import google.cloud.logging, ' ++ 'disabling Stackdriver-logging support') ++ ++ # Prepare cli + try: + credentials = None + if tuple(googleapiclient.__version__) < tuple("1.6.0"): +diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml +index 2a147f21..805ecc6b 100644 +--- a/tests/data/metadata/fence_gce.xml ++++ b/tests/data/metadata/fence_gce.xml +@@ -30,6 +30,11 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui + + Project ID. + ++ ++ ++ ++ Stackdriver-logging support. ++ + + + + +From bb34acd8b0b150599c393d56dd81a7d8185b27d3 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Tue, 26 Jun 2018 10:44:41 -0300 +Subject: [PATCH 2/7] fence_gce: set project and zone as not required + +Try to retrieve the GCE project if the script is being executed inside a +GCE machine if --project is not provided. +Try to retrieve the zone automatically from GCE if --zone is not +provided. +--- + agents/gce/fence_gce.py | 63 +++++++++++++++++++++++++++++++++++++-- + tests/data/metadata/fence_gce.xml | 4 +-- + 2 files changed, 63 insertions(+), 4 deletions(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index 3af5bfc8..e53dc5a6 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -12,6 +12,8 @@ + + + LOGGER = logging ++METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/' ++METADATA_HEADERS = {'Metadata-Flavor': 'Google'} + + + def translate_status(instance_status): +@@ -81,13 +83,56 @@ def set_power_status(conn, options): + fail_usage("Failed: set_power_status: {}".format(str(err))) + + ++def get_instance(conn, project, zone, instance): ++ request = conn.instances().get( ++ project=project, zone=zone, instance=instance) ++ return request.execute() ++ ++ ++def get_zone(conn, project, instance): ++ request = conn.instances().aggregatedList(project=project) ++ while request is not None: ++ response = request.execute() ++ zones = response.get('items', {}) ++ for zone in zones.values(): ++ for inst in zone.get('instances', []): ++ if inst['name'] == instance: ++ return inst['zone'].split("/")[-1] ++ request = conn.instances().aggregatedList_next( ++ previous_request=request, previous_response=response) ++ raise Exception("Unable to find instance %s" % (instance)) ++ ++ ++def get_metadata(metadata_key, params=None, timeout=None): ++ """Performs a GET request with the metadata headers. ++ ++ Args: ++ metadata_key: string, the metadata to perform a GET request on. ++ params: dictionary, the query parameters in the GET request. ++ timeout: int, timeout in seconds for metadata requests. ++ ++ Returns: ++ HTTP response from the GET request. ++ ++ Raises: ++ urlerror.HTTPError: raises when the GET request fails. ++ """ ++ timeout = timeout or 60 ++ metadata_url = os.path.join(METADATA_SERVER, metadata_key) ++ params = urlparse.urlencode(params or {}) ++ url = '%s?%s' % (metadata_url, params) ++ request = urlrequest.Request(url, headers=METADATA_HEADERS) ++ request_opener = urlrequest.build_opener(urlrequest.ProxyHandler({})) ++ return request_opener.open(request, timeout=timeout * 1.1).read() ++ ++ + def define_new_opts(): + all_opt["zone"] = { + "getopt" : ":", + "longopt" : "zone", + "help" : "--zone=[name] Zone, e.g. us-central1-b", + "shortdesc" : "Zone.", +- "required" : "1", ++ "required" : "0", + "order" : 2 + } + all_opt["project"] = { +@@ -95,7 +140,7 @@ def define_new_opts(): + "longopt" : "project", + "help" : "--project=[name] Project ID", + "shortdesc" : "Project ID.", +- "required" : "1", ++ "required" : "0", + "order" : 3 + } + all_opt["logging"] = { +@@ -109,6 +154,7 @@ def define_new_opts(): + "order" : 4 + } + ++ + def main(): + conn = None + global LOGGER +@@ -165,6 +211,19 @@ def main(): + except Exception as err: + fail_usage("Failed: Create GCE compute v1 connection: {}".format(str(err))) + ++ # Get project and zone ++ if not options.get("--project"): ++ try: ++ options["--project"] = get_metadata('project/project-id') ++ except Exception as err: ++ fail_usage("Failed retrieving GCE project. Please provide --project option: {}".format(str(err))) ++ ++ if not options.get("--zone"): ++ try: ++ options["--zone"] = get_zone(conn, options['--project'], options['--plug']) ++ except Exception as err: ++ fail_usage("Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err))) ++ + # Operate the fencing device + result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) + sys.exit(result) +diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml +index 805ecc6b..507b8385 100644 +--- a/tests/data/metadata/fence_gce.xml ++++ b/tests/data/metadata/fence_gce.xml +@@ -20,12 +20,12 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui + + Physical plug number on device, UUID or identification of machine + +- ++ + + + Zone. + +- ++ + + + Project ID. + +From 8ae1af8068d1718a861a25bf954e14392384fa55 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Wed, 4 Jul 2018 09:25:46 -0300 +Subject: [PATCH 3/7] fence_gce: add power cycle as default method + +Add function to power cycle an instance and set cycle as the default +method to reboot. +--- + agents/gce/fence_gce.py | 21 +++++++++++++++++++-- + tests/data/metadata/fence_gce.xml | 8 ++++++++ + 2 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index e53dc5a6..3f77dc24 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -83,6 +83,21 @@ def set_power_status(conn, options): + fail_usage("Failed: set_power_status: {}".format(str(err))) + + ++def power_cycle(conn, options): ++ try: ++ LOGGER.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"])) ++ operation = conn.instances().reset( ++ project=options["--project"], ++ zone=options["--zone"], ++ instance=options["--plug"]).execute() ++ wait_for_operation(conn, options["--project"], options["--zone"], operation) ++ LOGGER.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"])) ++ return True ++ except Exception as err: ++ LOGGER.error("Failed: power_cycle: {}".format(str(err))) ++ return False ++ ++ + def get_instance(conn, project, zone, instance): + request = conn.instances().get( + project=project, zone=zone, instance=instance) +@@ -161,13 +176,15 @@ def main(): + + hostname = platform.node() + +- device_opt = ["port", "no_password", "zone", "project", "logging"] ++ device_opt = ["port", "no_password", "zone", "project", "logging", "method"] + + atexit.register(atexit_handler) + + define_new_opts() + + all_opt["power_timeout"]["default"] = "60" ++ 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)) + +@@ -225,7 +242,7 @@ def main(): + fail_usage("Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err))) + + # Operate the fencing device +- result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) ++ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list, power_cycle) + sys.exit(result) + + if __name__ == "__main__": +diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml +index 507b8385..f522550f 100644 +--- a/tests/data/metadata/fence_gce.xml ++++ b/tests/data/metadata/fence_gce.xml +@@ -10,6 +10,14 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui + + Fencing action + ++ ++ ++ ++ ++ Method to fence ++ + + + + +From 68644764695b79a3b75826fe009ea7da675677f7 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Thu, 5 Jul 2018 11:04:32 -0300 +Subject: [PATCH 4/7] fence_gce: add missing imports to retrieve the project + +--- + agents/gce/fence_gce.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index 3f77dc24..9b7b5e55 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -2,9 +2,18 @@ + + import atexit + import logging ++import os + import platform + import sys + import time ++if sys.version_info >= (3, 0): ++ # Python 3 imports. ++ import urllib.parse as urlparse ++ import urllib.request as urlrequest ++else: ++ # Python 2 imports. ++ import urllib as urlparse ++ import urllib2 as urlrequest + sys.path.append("@FENCEAGENTSLIBDIR@") + + import googleapiclient.discovery + +From f8f3f11187341622c26e4e439dfda6a37ad660b0 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Thu, 5 Jul 2018 11:05:32 -0300 +Subject: [PATCH 5/7] fence_gce: s/--loging/--stackdriver-logging/ + +--- + agents/gce/fence_gce.py | 42 ++++++++++++++++++--------------------- + tests/data/metadata/fence_gce.xml | 11 +++++++--- + 2 files changed, 27 insertions(+), 26 deletions(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index 9b7b5e55..a6befe39 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -167,14 +167,13 @@ def define_new_opts(): + "required" : "0", + "order" : 3 + } +- all_opt["logging"] = { +- "getopt" : ":", +- "longopt" : "logging", +- "help" : "--logging=[bool] Logging, true/false", ++ all_opt["stackdriver-logging"] = { ++ "getopt" : "", ++ "longopt" : "stackdriver-logging", ++ "help" : "--stackdriver-logging Enable Logging to Stackdriver", + "shortdesc" : "Stackdriver-logging support.", +- "longdesc" : "If enabled (set to true), IP failover logs will be posted to stackdriver logging.", ++ "longdesc" : "If enabled IP failover logs will be posted to stackdriver logging.", + "required" : "0", +- "default" : "false", + "order" : 4 + } + +@@ -185,7 +184,7 @@ def main(): + + hostname = platform.node() + +- device_opt = ["port", "no_password", "zone", "project", "logging", "method"] ++ device_opt = ["port", "no_password", "zone", "project", "stackdriver-logging", "method"] + + atexit.register(atexit_handler) + +@@ -210,22 +209,19 @@ def main(): + run_delay(options) + + # Prepare logging +- logging_env = options.get('--logging') +- if logging_env: +- logging_env = logging_env.lower() +- if any(x in logging_env for x in ['yes', 'true', 'enabled']): +- try: +- import google.cloud.logging.handlers +- client = google.cloud.logging.Client() +- handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname) +- formatter = logging.Formatter('gcp:stonish "%(message)s"') +- LOGGER = logging.getLogger(hostname) +- handler.setFormatter(formatter) +- LOGGER.addHandler(handler) +- LOGGER.setLevel(logging.INFO) +- except ImportError: +- LOGGER.error('Couldn\'t import google.cloud.logging, ' +- 'disabling Stackdriver-logging support') ++ if options.get('--stackdriver-logging'): ++ try: ++ import google.cloud.logging.handlers ++ client = google.cloud.logging.Client() ++ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname) ++ formatter = logging.Formatter('gcp:stonish "%(message)s"') ++ LOGGER = logging.getLogger(hostname) ++ handler.setFormatter(formatter) ++ LOGGER.addHandler(handler) ++ LOGGER.setLevel(logging.INFO) ++ except ImportError: ++ LOGGER.error('Couldn\'t import google.cloud.logging, ' ++ 'disabling Stackdriver-logging support') + + # Prepare cli + try: +diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml +index f522550f..79b82ebb 100644 +--- a/tests/data/metadata/fence_gce.xml ++++ b/tests/data/metadata/fence_gce.xml +@@ -38,9 +38,14 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui + + Project ID. + +- +- +- ++ ++ ++ ++ Stackdriver-logging support. ++ ++ ++ ++ + Stackdriver-logging support. + + + +From 9ae0a072424fa982e1d18a2cb661628c38601c3a Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Sat, 7 Jul 2018 18:42:01 -0300 +Subject: [PATCH 6/7] fence_gce: use root logger for stackdriver + +--- + agents/gce/fence_gce.py | 29 +++++++++++++++-------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index a6befe39..1d5095ae 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -20,7 +20,6 @@ + from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action + + +-LOGGER = logging + METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/' + METADATA_HEADERS = {'Metadata-Flavor': 'Google'} + +@@ -73,37 +72,37 @@ def wait_for_operation(conn, project, zone, operation): + def set_power_status(conn, options): + try: + if options["--action"] == "off": +- LOGGER.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"])) ++ logging.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"])) + operation = conn.instances().stop( + project=options["--project"], + zone=options["--zone"], + instance=options["--plug"]).execute() + wait_for_operation(conn, options["--project"], options["--zone"], operation) +- LOGGER.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"])) ++ logging.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"])) + elif options["--action"] == "on": +- LOGGER.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"])) ++ logging.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"])) + operation = conn.instances().start( + project=options["--project"], + zone=options["--zone"], + instance=options["--plug"]).execute() + wait_for_operation(conn, options["--project"], options["--zone"], operation) +- LOGGER.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"])) ++ logging.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"])) + except Exception as err: + fail_usage("Failed: set_power_status: {}".format(str(err))) + + + def power_cycle(conn, options): + try: +- LOGGER.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"])) ++ logging.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"])) + operation = conn.instances().reset( + project=options["--project"], + zone=options["--zone"], + instance=options["--plug"]).execute() + wait_for_operation(conn, options["--project"], options["--zone"], operation) +- LOGGER.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"])) ++ logging.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"])) + return True + except Exception as err: +- LOGGER.error("Failed: power_cycle: {}".format(str(err))) ++ logging.error("Failed: power_cycle: {}".format(str(err))) + return False + + +@@ -180,7 +179,6 @@ def define_new_opts(): + + def main(): + conn = None +- global LOGGER + + hostname = platform.node() + +@@ -209,18 +207,21 @@ def main(): + run_delay(options) + + # Prepare logging +- if options.get('--stackdriver-logging'): ++ if options.get('--stackdriver-logging') is not None: + try: + import google.cloud.logging.handlers + client = google.cloud.logging.Client() + handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname) ++ handler.setLevel(logging.INFO) + formatter = logging.Formatter('gcp:stonish "%(message)s"') +- LOGGER = logging.getLogger(hostname) + handler.setFormatter(formatter) +- LOGGER.addHandler(handler) +- LOGGER.setLevel(logging.INFO) ++ root_logger = logging.getLogger() ++ if options.get('--verbose') is None: ++ root_logger.setLevel(logging.INFO) ++ logging.getLogger("googleapiclient").setLevel(logging.ERROR) ++ root_logger.addHandler(handler) + except ImportError: +- LOGGER.error('Couldn\'t import google.cloud.logging, ' ++ logging.error('Couldn\'t import google.cloud.logging, ' + 'disabling Stackdriver-logging support') + + # Prepare cli + +From a52e643708908539d6e5fdb5d36a6cea935e4481 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Wed, 11 Jul 2018 17:16:49 -0300 +Subject: [PATCH 7/7] fence_gce: minor changes in logging + +- Remove hostname (use --plug instead). +- Supress messages from googleapiclient and oauth2client if not error in +non verbose mode. +- s/stonish/stonith +--- + agents/gce/fence_gce.py | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index 1d5095ae..3eca0139 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -3,7 +3,6 @@ + import atexit + import logging + import os +-import platform + import sys + import time + if sys.version_info >= (3, 0): +@@ -180,8 +179,6 @@ def define_new_opts(): + def main(): + conn = None + +- hostname = platform.node() +- + device_opt = ["port", "no_password", "zone", "project", "stackdriver-logging", "method"] + + atexit.register(atexit_handler) +@@ -207,18 +204,20 @@ def main(): + run_delay(options) + + # Prepare logging +- if options.get('--stackdriver-logging') is not None: ++ if options.get('--verbose') is None: ++ logging.getLogger('googleapiclient').setLevel(logging.ERROR) ++ logging.getLogger('oauth2client').setLevel(logging.ERROR) ++ if options.get('--stackdriver-logging') is not None and options.get('--plug'): + try: + import google.cloud.logging.handlers + client = google.cloud.logging.Client() +- handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname) ++ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=options['--plug']) + handler.setLevel(logging.INFO) +- formatter = logging.Formatter('gcp:stonish "%(message)s"') ++ formatter = logging.Formatter('gcp:stonith "%(message)s"') + handler.setFormatter(formatter) + root_logger = logging.getLogger() + if options.get('--verbose') is None: + root_logger.setLevel(logging.INFO) +- logging.getLogger("googleapiclient").setLevel(logging.ERROR) + root_logger.addHandler(handler) + except ImportError: + logging.error('Couldn\'t import google.cloud.logging, ' diff --git a/SOURCES/bz1568753-2-fence_gce-filter-aggregatedlist.patch b/SOURCES/bz1568753-2-fence_gce-filter-aggregatedlist.patch new file mode 100644 index 0000000..29b7203 --- /dev/null +++ b/SOURCES/bz1568753-2-fence_gce-filter-aggregatedlist.patch @@ -0,0 +1,25 @@ +From 8e801d513b9a500ac0d717476aadc1cdabc0a92e Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Thu, 19 Jul 2018 13:13:53 -0300 +Subject: [PATCH] fence_gce: filter call to aggregatedList + +Don't list all the instances in the project, filter only the one we are +interested in. +--- + agents/gce/fence_gce.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +index 3eca0139..93cd1180 100644 +--- a/agents/gce/fence_gce.py ++++ b/agents/gce/fence_gce.py +@@ -112,7 +112,8 @@ def get_instance(conn, project, zone, instance): + + + def get_zone(conn, project, instance): +- request = conn.instances().aggregatedList(project=project) ++ fl = 'name="%s"' % instance ++ request = conn.instances().aggregatedList(project=project, filter=fl) + while request is not None: + response = request.execute() + zones = response.get('items', {}) diff --git a/SOURCES/bz1568753-3-fence_gce-stackdriver-logging-note.patch b/SOURCES/bz1568753-3-fence_gce-stackdriver-logging-note.patch new file mode 100644 index 0000000..8589b77 --- /dev/null +++ b/SOURCES/bz1568753-3-fence_gce-stackdriver-logging-note.patch @@ -0,0 +1,34 @@ +diff -uNr a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +--- a/agents/gce/fence_gce.py 2018-07-30 16:09:45.811531118 +0200 ++++ b/agents/gce/fence_gce.py 2018-07-30 16:31:28.970202508 +0200 +@@ -174,9 +174,9 @@ + all_opt["stackdriver-logging"] = { + "getopt" : "", + "longopt" : "stackdriver-logging", +- "help" : "--stackdriver-logging Enable Logging to Stackdriver", +- "shortdesc" : "Stackdriver-logging support.", +- "longdesc" : "If enabled IP failover logs will be posted to stackdriver logging.", ++ "help" : "--stackdriver-logging Enable Logging to Stackdriver. Using stackdriver logging requires additional libraries (google-cloud-logging).", ++ "shortdesc" : "Stackdriver-logging support. Requires additional libraries (google-cloud-logging).", ++ "longdesc" : "If enabled IP failover logs will be posted to stackdriver logging. Using stackdriver logging requires additional libraries (google-cloud-logging).", + "required" : "0", + "order" : 4 + } +diff -uNr a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml +--- a/tests/data/metadata/fence_gce.xml 2018-07-30 16:09:45.548532576 +0200 ++++ b/tests/data/metadata/fence_gce.xml 2018-07-30 16:32:05.392988450 +0200 +@@ -41,12 +41,12 @@ + + + +- Stackdriver-logging support. ++ Stackdriver-logging support. Requires additional libraries (google-cloud-logging). + + + + +- Stackdriver-logging support. ++ Stackdriver-logging support. Requires additional libraries (google-cloud-logging). + + + diff --git a/SOURCES/bz1568753-4-fence_gce-bundled-libs.patch b/SOURCES/bz1568753-4-fence_gce-bundled-libs.patch new file mode 100644 index 0000000..05edddf --- /dev/null +++ b/SOURCES/bz1568753-4-fence_gce-bundled-libs.patch @@ -0,0 +1,19 @@ +diff -uNr a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +--- a/agents/gce/fence_gce.py 2018-07-12 09:54:53.121993715 +0200 ++++ b/agents/gce/fence_gce.py 2018-07-12 09:57:42.580699588 +0200 +@@ -15,9 +15,14 @@ + import urllib2 as urlrequest + sys.path.append("@FENCEAGENTSLIBDIR@") + +-import googleapiclient.discovery + from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action + ++try: ++ sys.path.insert(0, '/usr/lib/fence-agents/bundled/gce') ++ import googleapiclient.discovery ++except ImportError: ++ pass ++ + + METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/' + METADATA_HEADERS = {'Metadata-Flavor': 'Google'} diff --git a/SOURCES/bz1568753-5-oauth2client-docs-build-fix.patch b/SOURCES/bz1568753-5-oauth2client-docs-build-fix.patch new file mode 100644 index 0000000..f8e8a9f --- /dev/null +++ b/SOURCES/bz1568753-5-oauth2client-docs-build-fix.patch @@ -0,0 +1,27 @@ +diff -up oauth2client-3.0.0/docs/conf.py.doc oauth2client-3.0.0/docs/conf.py +--- oauth2client-3.0.0/docs/conf.py.doc 2016-12-27 17:01:44.043275431 +0100 ++++ oauth2client-3.0.0/docs/conf.py 2016-12-27 17:02:14.024315815 +0100 +@@ -64,9 +64,9 @@ project = u'oauth2client' + copyright = u'2014, Google, Inc' + + # Version info +-distro = get_distribution('oauth2client') +-version = distro.version +-release = distro.version ++#distro = get_distribution('oauth2client') ++version = '3.0.0' ++release = '3.0.0' + + exclude_patterns = ['_build'] + +diff -up oauth2client-3.0.0/docs/source/oauth2client.contrib.rst.doc oauth2client-3.0.0/docs/source/oauth2client.contrib.rst +--- oauth2client-3.0.0/docs/source/oauth2client.contrib.rst.doc 2016-07-28 20:50:44.000000000 +0200 ++++ oauth2client-3.0.0/docs/source/oauth2client.contrib.rst 2016-12-27 17:01:29.849256312 +0100 +@@ -13,7 +13,6 @@ Submodules + + .. toctree:: + +- oauth2client.contrib.appengine + oauth2client.contrib.devshell + oauth2client.contrib.dictionary_storage + oauth2client.contrib.flask_util diff --git a/SOURCES/bz1568753-6-oauth2client-python-rsa-to-cryptography.patch b/SOURCES/bz1568753-6-oauth2client-python-rsa-to-cryptography.patch new file mode 100644 index 0000000..54fb3cb --- /dev/null +++ b/SOURCES/bz1568753-6-oauth2client-python-rsa-to-cryptography.patch @@ -0,0 +1,101 @@ +diff -uNr a/oauth2client/_pure_python_crypt.py b/oauth2client/_pure_python_crypt.py +--- a/oauth2client/_pure_python_crypt.py 2016-10-14 19:53:53.000000000 +0200 ++++ b/oauth2client/_pure_python_crypt.py 2018-06-21 15:40:25.216478384 +0200 +@@ -23,7 +23,10 @@ + from pyasn1_modules import pem + from pyasn1_modules.rfc2459 import Certificate + from pyasn1_modules.rfc5208 import PrivateKeyInfo +-import rsa ++from cryptography.hazmat.primitives import serialization, hashes ++from cryptography.hazmat.primitives.asymmetric import padding ++from cryptography import x509 ++from cryptography.hazmat.backends import default_backend + import six + + from oauth2client import _helpers +@@ -70,7 +73,8 @@ + """ + + def __init__(self, pubkey): +- self._pubkey = pubkey ++ self._pubkey = serialization.load_pem_public_key(pubkey, ++ backend=default_backend()) + + def verify(self, message, signature): + """Verifies a message against a signature. +@@ -87,8 +91,9 @@ + """ + message = _helpers._to_bytes(message, encoding='utf-8') + try: +- return rsa.pkcs1.verify(message, signature, self._pubkey) +- except (ValueError, rsa.pkcs1.VerificationError): ++ return self._pubkey.verify(signature, message, padding.PKCS1v15(), ++ hashes.SHA256()) ++ except (ValueError, TypeError, InvalidSignature): + return False + + @classmethod +@@ -112,16 +117,18 @@ + """ + key_pem = _helpers._to_bytes(key_pem) + if is_x509_cert: +- der = rsa.pem.load_pem(key_pem, 'CERTIFICATE') ++ der = x509.load_pem_x509_certificate(pem_data, default_backend()) + asn1_cert, remaining = decoder.decode(der, asn1Spec=Certificate()) + if remaining != b'': + raise ValueError('Unused bytes', remaining) + + cert_info = asn1_cert['tbsCertificate']['subjectPublicKeyInfo'] + key_bytes = _bit_list_to_bytes(cert_info['subjectPublicKey']) +- pubkey = rsa.PublicKey.load_pkcs1(key_bytes, 'DER') ++ pubkey = serialization.load_der_public_key(decoded_key, ++ backend=default_backend()) + else: +- pubkey = rsa.PublicKey.load_pkcs1(key_pem, 'PEM') ++ pubkey = serialization.load_pem_public_key(decoded_key, ++ backend=default_backend()) + return cls(pubkey) + + +@@ -134,6 +141,8 @@ + + def __init__(self, pkey): + self._key = pkey ++ self._pubkey = serialization.load_pem_private_key(pkey, ++ backend=default_backend()) + + def sign(self, message): + """Signs a message. +@@ -145,7 +154,7 @@ + string, The signature of the message for the given key. + """ + message = _helpers._to_bytes(message, encoding='utf-8') +- return rsa.pkcs1.sign(message, self._key, 'SHA-256') ++ return self._key.sign(message, padding.PKCS1v15(), hashes.SHA256()) + + @classmethod + def from_string(cls, key, password='notasecret'): +@@ -168,16 +177,19 @@ + six.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER) + + if marker_id == 0: +- pkey = rsa.key.PrivateKey.load_pkcs1(key_bytes, +- format='DER') ++ pkey = serialization.load_der_private_key( ++ key_bytes, password=None, ++ backend=default_backend()) ++ + elif marker_id == 1: + key_info, remaining = decoder.decode( + key_bytes, asn1Spec=_PKCS8_SPEC) + if remaining != b'': + raise ValueError('Unused bytes', remaining) + pkey_info = key_info.getComponentByName('privateKey') +- pkey = rsa.key.PrivateKey.load_pkcs1(pkey_info.asOctets(), +- format='DER') ++ pkey = serialization.load_der_private_key( ++ pkey_info.asOctets(), password=None, ++ backend=default_backend()) + else: + raise ValueError('No key could be detected.') + diff --git a/SOURCES/bz1568753-7-keyring-fix-gnome-version-warning.patch b/SOURCES/bz1568753-7-keyring-fix-gnome-version-warning.patch new file mode 100644 index 0000000..baa8377 --- /dev/null +++ b/SOURCES/bz1568753-7-keyring-fix-gnome-version-warning.patch @@ -0,0 +1,11 @@ +--- a/keyring/backends/Gnome.py 2017-10-11 17:28:14.061370016 -0400 ++++ b/keyring/backends/Gnome.py 2017-10-11 17:30:16.426342684 -0400 +@@ -3,6 +3,7 @@ + try: +- from gi import Repository ++ from gi import Repository, require_version + if Repository.get_default().enumerate_versions('GnomeKeyring'): ++ require_version('GnomeKeyring', '1.0') + from gi.repository import GnomeKeyring + except ImportError: + pass diff --git a/SOURCES/bz1579391-fence_impilan-fence_ilo_ssh-add-ilo5-support.patch b/SOURCES/bz1579391-fence_impilan-fence_ilo_ssh-add-ilo5-support.patch new file mode 100644 index 0000000..8e23e64 --- /dev/null +++ b/SOURCES/bz1579391-fence_impilan-fence_ilo_ssh-add-ilo5-support.patch @@ -0,0 +1,33 @@ +diff -uNr a/agents/ilo_ssh/fence_ilo_ssh.py b/agents/ilo_ssh/fence_ilo_ssh.py +--- a/agents/ilo_ssh/fence_ilo_ssh.py 2018-06-18 12:14:35.000000000 +0200 ++++ b/agents/ilo_ssh/fence_ilo_ssh.py 2018-06-28 12:26:14.274615003 +0200 +@@ -54,7 +54,8 @@ + device via ssh and reboot a specified outlet. " + docs["vendorurl"] = "http://www.hp.com" + docs["symlink"] = [("fence_ilo3_ssh", "Fence agent for HP iLO3 over SSH"), +- ("fence_ilo4_ssh", "Fence agent for HP iLO4 over SSH")] ++ ("fence_ilo4_ssh", "Fence agent for HP iLO4 over SSH"), ++ ("fence_ilo5_ssh", "Fence agent for HP iLO5 over SSH")] + show_docs(options, docs) + + options["eol"] = "\r" +diff -uNr a/agents/ipmilan/fence_ipmilan.py b/agents/ipmilan/fence_ipmilan.py +--- a/agents/ipmilan/fence_ipmilan.py 2018-06-18 12:14:35.000000000 +0200 ++++ b/agents/ipmilan/fence_ipmilan.py 2018-06-28 12:26:14.275614990 +0200 +@@ -169,6 +169,8 @@ + all_opt["lanplus"]["default"] = "1" + elif os.path.basename(sys.argv[0]) == "fence_ilo4": + all_opt["lanplus"]["default"] = "1" ++ elif os.path.basename(sys.argv[0]) == "fence_ilo5": ++ all_opt["lanplus"]["default"] = "1" + + all_opt["ipport"]["default"] = "623" + all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)\n" \ +@@ -187,6 +189,7 @@ + docs["vendorurl"] = "" + docs["symlink"] = [("fence_ilo3", "Fence agent for HP iLO3"), + ("fence_ilo4", "Fence agent for HP iLO4"), ++ ("fence_ilo5", "Fence agent for HP iLO5"), + ("fence_imm", "Fence agent for IBM Integrated Management Module"), + ("fence_idrac", "Fence agent for Dell iDRAC")] + show_docs(options, docs) diff --git a/SOURCES/bz1608550-fence_dump-validate-all.patch b/SOURCES/bz1608550-fence_dump-validate-all.patch new file mode 100644 index 0000000..69143e8 --- /dev/null +++ b/SOURCES/bz1608550-fence_dump-validate-all.patch @@ -0,0 +1,62 @@ +From 0dc5bcf0ee82f6d6dc42a92e6564b93740b3c7ee Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 3 Sep 2018 15:29:19 +0200 +Subject: [PATCH] fence_kdump: add validate-all action + +--- + agents/kdump/fence_kdump.c | 6 +++++- + agents/kdump/options.h | 3 +++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/agents/kdump/fence_kdump.c b/agents/kdump/fence_kdump.c +index 768a9344..4ab2dd9b 100644 +--- a/agents/kdump/fence_kdump.c ++++ b/agents/kdump/fence_kdump.c +@@ -295,6 +295,7 @@ do_action_metadata (const char *self) + fprintf (stdout, "\t\n"); + fprintf (stdout, "\t\n"); + fprintf (stdout, "\t\n"); ++ fprintf (stdout, "\t\n"); + fprintf (stdout, "\n"); + + fprintf (stdout, "\n"); +@@ -316,7 +317,7 @@ print_usage (const char *self) + fprintf (stdout, "%s\n", + " -f, --family=FAMILY Network family: ([auto], ipv4, ipv6)"); + fprintf (stdout, "%s\n", +- " -o, --action=ACTION Fencing action: ([off], monitor, metadata)"); ++ " -o, --action=ACTION Fencing action: ([off], monitor, metadata, validate-all)"); + fprintf (stdout, "%s\n", + " -t, --timeout=TIMEOUT Timeout in seconds (default: 60)"); + fprintf (stdout, "%s\n", +@@ -556,6 +557,9 @@ main (int argc, char **argv) + case FENCE_KDUMP_ACTION_MONITOR: + error = do_action_monitor (); + break; ++ case FENCE_KDUMP_ACTION_VALIDATE: ++ error = 0; ++ break; + default: + break; + } +diff --git a/agents/kdump/options.h b/agents/kdump/options.h +index 22731d7c..6d774e5a 100644 +--- a/agents/kdump/options.h ++++ b/agents/kdump/options.h +@@ -36,6 +36,7 @@ enum { + FENCE_KDUMP_ACTION_LIST = 4, + FENCE_KDUMP_ACTION_MONITOR = 5, + FENCE_KDUMP_ACTION_METADATA = 6, ++ FENCE_KDUMP_ACTION_VALIDATE = 7, + }; + + enum { +@@ -191,6 +192,8 @@ set_option_action (fence_kdump_opts_t *opts, const char *arg) + opts->action = FENCE_KDUMP_ACTION_METADATA; + } else if (!strcasecmp (arg, "monitor")) { + opts->action = FENCE_KDUMP_ACTION_MONITOR; ++ } else if (!strcasecmp (arg, "validate-all")) { ++ opts->action = FENCE_KDUMP_ACTION_VALIDATE; + } else { + fprintf (stderr, "[error]: unsupported action '%s'\n", arg); + exit (1); diff --git a/SOURCES/bz1622229-1-fence_aliyun-list-instance-names.patch b/SOURCES/bz1622229-1-fence_aliyun-list-instance-names.patch new file mode 100644 index 0000000..40bebac --- /dev/null +++ b/SOURCES/bz1622229-1-fence_aliyun-list-instance-names.patch @@ -0,0 +1,31 @@ +From c21d60fbcf0b11dcbf4f70006c8ffaeac4ca7dbd Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 28 Aug 2018 15:20:10 +0200 +Subject: [PATCH] fence_aliyun: list instance names and show up to 100 + instances + +--- + agents/aliyun/fence_aliyun.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +index 2cda6b7f..b3aca12f 100644 +--- a/agents/aliyun/fence_aliyun.py ++++ b/agents/aliyun/fence_aliyun.py +@@ -59,13 +59,15 @@ def get_status(conn, instance_id): + def get_nodes_list(conn, options): + result = {} + request = DescribeInstancesRequest() ++ request.set_PageSize(100) + response = _send_request(conn, request) + instance_status = None + if response is not None: + instance_list = response.get('Instances').get('Instance') + for item in instance_list: + instance_id = item.get('InstanceId') +- result[instance_id] = ("", None) ++ instance_name = item.get('InstanceName') ++ result[instance_id] = (instance_name, None) + return result + + def get_power_status(conn, options): diff --git a/SOURCES/bz1622229-2-fence_aliyun-correct-help-indentation.patch b/SOURCES/bz1622229-2-fence_aliyun-correct-help-indentation.patch new file mode 100644 index 0000000..39b1551 --- /dev/null +++ b/SOURCES/bz1622229-2-fence_aliyun-correct-help-indentation.patch @@ -0,0 +1,31 @@ +From 588f935b1f79c8355d461fe9f8597151fbcd7fa2 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 30 Aug 2018 09:11:58 +0200 +Subject: [PATCH] fence_aliyun: correct indentation for *key in help + +--- + agents/aliyun/fence_aliyun.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py +index 2cda6b7f..7d04c5bb 100644 +--- a/agents/aliyun/fence_aliyun.py ++++ b/agents/aliyun/fence_aliyun.py +@@ -106,7 +106,7 @@ def define_new_opts(): + all_opt["access_key"] = { + "getopt" : "a:", + "longopt" : "access-key", +- "help" : "-a, --access-key=[name] Access Key", ++ "help" : "-a, --access-key=[name] Access Key", + "shortdesc" : "Access Key.", + "required" : "0", + "order" : 3 +@@ -114,7 +114,7 @@ def define_new_opts(): + all_opt["secret_key"] = { + "getopt" : "s:", + "longopt" : "secret-key", +- "help" : "-s, --secret-key=[name] Secret Key", ++ "help" : "-s, --secret-key=[name] Secret Key", + "shortdesc" : "Secret Key.", + "required" : "0", + "order" : 4 diff --git a/SOURCES/bz1625164-fence_cisco_ucs-encode-POSTFIELDS.patch b/SOURCES/bz1625164-fence_cisco_ucs-encode-POSTFIELDS.patch new file mode 100644 index 0000000..6515deb --- /dev/null +++ b/SOURCES/bz1625164-fence_cisco_ucs-encode-POSTFIELDS.patch @@ -0,0 +1,22 @@ +From 70bd4ffa245ef7e8b7698228bab3b41c240d50d2 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 4 Sep 2018 12:35:07 +0200 +Subject: [PATCH] fence_cisco_ucs: encode POSTFIELDS + +--- + agents/cisco_ucs/fence_cisco_ucs.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/cisco_ucs/fence_cisco_ucs.py b/agents/cisco_ucs/fence_cisco_ucs.py +index d509b3e0..ec311754 100644 +--- a/agents/cisco_ucs/fence_cisco_ucs.py ++++ b/agents/cisco_ucs/fence_cisco_ucs.py +@@ -111,7 +111,7 @@ def send_command(opt, command, timeout): + web_buffer = io.BytesIO() + conn.setopt(pycurl.URL, url.encode("ascii")) + conn.setopt(pycurl.HTTPHEADER, ["Content-type: text/xml"]) +- conn.setopt(pycurl.POSTFIELDS, command) ++ conn.setopt(pycurl.POSTFIELDS, command.encode("ascii")) + conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write) + conn.setopt(pycurl.TIMEOUT, timeout) + if "--ssl" in opt or "--ssl-secure" in opt: diff --git a/SOURCES/bz1645170-fence_scsi-fix-incorrect-SCSI-key-node-ID-10-or-higher.patch b/SOURCES/bz1645170-fence_scsi-fix-incorrect-SCSI-key-node-ID-10-or-higher.patch new file mode 100644 index 0000000..9560368 --- /dev/null +++ b/SOURCES/bz1645170-fence_scsi-fix-incorrect-SCSI-key-node-ID-10-or-higher.patch @@ -0,0 +1,24 @@ +From f77297b654586bf539e78957f26cae1d22c6f081 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 2 Nov 2018 09:24:56 +0100 +Subject: [PATCH] fence_scsi: fix incorrect SCSI key when node ID is 10 or + higher + + The last four digits of the SCSI key will be zero padded digit between 0000-0009. +--- + agents/scsi/fence_scsi.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/scsi/fence_scsi.py b/agents/scsi/fence_scsi.py +index 2180d0c9..79ada4fa 100644 +--- a/agents/scsi/fence_scsi.py ++++ b/agents/scsi/fence_scsi.py +@@ -191,7 +191,7 @@ def get_cluster_id(options): + def get_node_id(options): + cmd = options["--corosync-cmap-path"] + " nodelist" + +- match = re.search(r".(\d).ring._addr \(str\) = " + options["--plug"] + "\n", run_cmd(options, cmd)["out"]) ++ match = re.search(r".(\d+).ring._addr \(str\) = " + options["--plug"] + "\n", run_cmd(options, cmd)["out"]) + return match.group(1) if match else fail_usage("Failed: unable to parse output of corosync-cmapctl or node does not exist") + + diff --git a/SOURCES/bz1650526-fence_hpblade-fix-log_expect_syntax.patch b/SOURCES/bz1650526-fence_hpblade-fix-log_expect_syntax.patch new file mode 100644 index 0000000..bb239b1 --- /dev/null +++ b/SOURCES/bz1650526-fence_hpblade-fix-log_expect_syntax.patch @@ -0,0 +1,50 @@ +From 342570c5a5af4c277be283507ef7898a078e2df9 Mon Sep 17 00:00:00 2001 +From: mmartinv <32071463+mmartinv@users.noreply.github.com> +Date: Fri, 16 Nov 2018 12:55:58 +0100 +Subject: [PATCH] Fix 'log_expect' in fence_hpblade.py + +Update the 'log_expect' call to the new method definition. +--- + agents/hpblade/fence_hpblade.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/agents/hpblade/fence_hpblade.py b/agents/hpblade/fence_hpblade.py +index b2cc94a3..fbc89f61 100644 +--- a/agents/hpblade/fence_hpblade.py ++++ b/agents/hpblade/fence_hpblade.py +@@ -16,7 +16,7 @@ + + def get_enclosure_type(conn, options): + conn.send_eol("show enclosure info") +- conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"])) ++ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) + + type_re=re.compile(r"^\s*Enclosure Type: (\w+)(.*?)\s*$") + enclosure="unknown" +@@ -39,7 +39,7 @@ def get_power_status(conn, options): + powrestr = "^\\s*Power: (.*?)\\s*$" + + conn.send_eol(cmd_send) +- conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"])) ++ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) + + power_re = re.compile(powrestr) + status = "unknown" +@@ -72,7 +72,7 @@ def set_power_status(conn, options): + conn.send_eol("poweron " + dev + options["--plug"]) + elif options["--action"] == "off": + conn.send_eol("poweroff " + dev + options["--plug"] + " force") +- conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"])) ++ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) + + def get_instances_list(conn, options): + outlets = {} +@@ -84,7 +84,7 @@ def get_instances_list(conn, options): + listrestr = "^\\s*(\\d+)\\s+(.*?)\\s+(.*?)\\s+OK\\s+(.*?)\\s+(.*?)\\s*$" + + conn.send_eol(cmd_send) +- conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"])) ++ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) + + list_re = re.compile(listrestr) + for line in conn.before.splitlines(): diff --git a/SOURCES/bz1653700-1-fence_scsi-watchdog-retry-support.patch b/SOURCES/bz1653700-1-fence_scsi-watchdog-retry-support.patch new file mode 100644 index 0000000..276c439 --- /dev/null +++ b/SOURCES/bz1653700-1-fence_scsi-watchdog-retry-support.patch @@ -0,0 +1,146 @@ +From 11a63822fbdc0a9ebe1b668b26a59f1cc9649f6c Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 24 Oct 2018 14:51:27 +0200 +Subject: [PATCH] fence_scsi: watchdog retries support + +--- + agents/scsi/fence_scsi.py | 60 ++++++++++++++++++++---------- + tests/data/metadata/fence_scsi.xml | 4 +- + 2 files changed, 43 insertions(+), 21 deletions(-) + +diff --git a/agents/scsi/fence_scsi.py b/agents/scsi/fence_scsi.py +index 79ada4fa..8a1e4c77 100644 +--- a/agents/scsi/fence_scsi.py ++++ b/agents/scsi/fence_scsi.py +@@ -158,13 +158,15 @@ def get_reservation_key(options, dev): + return match.group(1) if match else None + + +-def get_registration_keys(options, dev): ++def get_registration_keys(options, dev, fail=True): + reset_dev(options,dev) + keys = [] + cmd = options["--sg_persist-path"] + " -n -i -k -d " + dev + out = run_cmd(options, cmd) + if out["err"]: +- fail_usage("Cannot get registration keys") ++ fail_usage("Cannot get registration keys", fail) ++ if not fail: ++ return [] + for line in out["out"].split("\n"): + match = re.search(r"\s+0x(\S+)\s*", line) + if match: +@@ -218,9 +220,8 @@ def get_key(fail=True): + try: + f = open(file_path, "r") + except IOError: +- if fail: +- fail_usage("Failed: Cannot open file \""+ file_path + "\"") +- else: ++ fail_usage("Failed: Cannot open file \""+ file_path + "\"", fail) ++ if not fail: + return None + return f.readline().strip().lower() + +@@ -244,9 +245,8 @@ def dev_read(fail=True): + try: + f = open(file_path, "r") + except IOError: +- if fail: +- fail_usage("Failed: Cannot open file \"" + file_path + "\"") +- else: ++ fail_usage("Failed: Cannot open file \"" + file_path + "\"", fail) ++ if not fail: + return None + # get not empty lines from file + devs = [line.strip() for line in f if line.strip()] +@@ -371,14 +371,20 @@ def define_new_opts(): + } + + +-def scsi_check_get_verbose(): ++def scsi_check_get_options(options): + try: +- f = open("/etc/sysconfig/watchdog", "r") ++ f = open("/etc/sysconfig/stonith", "r") + except IOError: +- return False +- match = re.search(r"^\s*verbose=yes", "".join(f.readlines()), re.MULTILINE) ++ return options ++ ++ match = re.findall(r"^\s*(\S*)\s*=\s*(\S*)\s*", "".join(f.readlines()), re.MULTILINE) ++ ++ for m in match: ++ options[m[0].lower()] = m[1].lower() ++ + f.close() +- return bool(match) ++ ++ return options + + + def scsi_check(hardreboot=False): +@@ -388,7 +394,10 @@ def scsi_check(hardreboot=False): + options["--sg_turs-path"] = "@SG_TURS_PATH@" + options["--sg_persist-path"] = "@SG_PERSIST_PATH@" + options["--power-timeout"] = "5" +- if scsi_check_get_verbose(): ++ options["retry"] = "0" ++ options["retry-sleep"] = "1" ++ options = scsi_check_get_options(options) ++ if "verbose" in options and options["verbose"] == "yes": + logging.getLogger().setLevel(logging.DEBUG) + devs = dev_read(fail=False) + if not devs: +@@ -399,11 +408,18 @@ def scsi_check(hardreboot=False): + logging.error("Key not found") + return 0 + for dev in devs: +- if key in get_registration_keys(options, dev): +- logging.debug("key " + key + " registered with device " + dev) +- return 0 +- else: +- logging.debug("key " + key + " not registered with device " + dev) ++ for n in range(int(options["retry"]) + 1): ++ if n > 0: ++ logging.debug("retry: " + str(n) + " of " + options["retry"]) ++ if key in get_registration_keys(options, dev, fail=False): ++ logging.debug("key " + key + " registered with device " + dev) ++ return 0 ++ else: ++ logging.debug("key " + key + " not registered with device " + dev) ++ ++ if n < int(options["retry"]): ++ time.sleep(float(options["retry-sleep"])) ++ + logging.debug("key " + key + " registered with any devices") + + if hardreboot == True: +@@ -452,7 +468,11 @@ def main(): + 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." ++longer be able to write to the device(s). A manual reboot is required.\ ++\n.P\n\ ++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." + docs["vendorurl"] = "" + show_docs(options, docs) + +diff --git a/tests/data/metadata/fence_scsi.xml b/tests/data/metadata/fence_scsi.xml +index 45a84168..b8cdabd1 100644 +--- a/tests/data/metadata/fence_scsi.xml ++++ b/tests/data/metadata/fence_scsi.xml +@@ -1,7 +1,9 @@ + + + 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. +-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. ++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. ++ ++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. + + + diff --git a/SOURCES/bz1653700-2-build-fix-check_used_options.patch b/SOURCES/bz1653700-2-build-fix-check_used_options.patch new file mode 100644 index 0000000..068375d --- /dev/null +++ b/SOURCES/bz1653700-2-build-fix-check_used_options.patch @@ -0,0 +1,23 @@ +From 267afc5caa0580cc483220e671cda094413a4e16 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 28 Nov 2018 09:54:16 +0100 +Subject: [PATCH] build: fix if-redirection to make check_used_options run for + the agents as intended + +--- + make/fencebuild.mk | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/make/fencebuild.mk b/make/fencebuild.mk +index 9e8bd692..143082f0 100644 +--- a/make/fencebuild.mk ++++ b/make/fencebuild.mk +@@ -33,7 +33,7 @@ define gen_agent_from_py + -e 's#@''PING4_CMD@#${PING4_CMD}#g' \ + > $@ + +- if [ 0 -eq `echo "$(@)" | grep fence_ 2>&1 /dev/null; echo $$?` ]; then \ ++ if [ 0 -eq `echo "$(@)" | grep fence_ > /dev/null 2>&1; echo $$?` ]; then \ + PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(top_srcdir)/lib/check_used_options.py $@; \ + else true ; fi + diff --git a/SOURCES/bz1653700-3-fence_scsi-watchdog-fix-retry-failing-on-first-try.patch b/SOURCES/bz1653700-3-fence_scsi-watchdog-fix-retry-failing-on-first-try.patch new file mode 100644 index 0000000..010fc00 --- /dev/null +++ b/SOURCES/bz1653700-3-fence_scsi-watchdog-fix-retry-failing-on-first-try.patch @@ -0,0 +1,42 @@ +From 418b3a36c8a7de0e984a0cd4707f2b90f279c4ce Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 13 Jun 2019 11:29:25 +0200 +Subject: [PATCH] fence_scsi watchdog: dont exit when command fails using retry + parameter + +--- + lib/fencing.py.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index 8cd0a813..6f2526a9 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -530,7 +530,7 @@ def fail_usage(message="", stop=True): + logging.error("Please use '-h' for usage\n") + sys.exit(EC_GENERIC_ERROR) + +-def fail(error_code): ++def fail(error_code, stop=True): + message = { + EC_LOGIN_DENIED : "Unable to connect/login to fencing device", + EC_CONNECTION_LOST : "Connection lost", +@@ -546,7 +546,8 @@ def fail(error_code): + + }[error_code] + "\n" + logging.error("%s\n", message) +- sys.exit(EC_GENERIC_ERROR) ++ if stop: ++ sys.exit(EC_GENERIC_ERROR) + + def usage(avail_opt): + print("Usage:") +@@ -1009,7 +1010,7 @@ def run_command(options, command, timeout=None, env=None, log_command=None): + thread.join(timeout) + if thread.is_alive(): + process.kill() +- fail(EC_TIMED_OUT) ++ fail(EC_TIMED_OUT, stop=(int(options.get("retry", 0)) < 1)) + + status = process.wait() + diff --git a/SOURCES/bz1670460-fence_rhevm-1-use-UTF8-encoding.patch b/SOURCES/bz1670460-fence_rhevm-1-use-UTF8-encoding.patch new file mode 100644 index 0000000..281e006 --- /dev/null +++ b/SOURCES/bz1670460-fence_rhevm-1-use-UTF8-encoding.patch @@ -0,0 +1,32 @@ +From a77165d7c8caadf514462d359c6d564048c2c33a Mon Sep 17 00:00:00 2001 +From: Sandro <42254081+Numblesix@users.noreply.github.com> +Date: Tue, 29 Jan 2019 13:29:52 +0100 +Subject: [PATCH] Changed Encoding to UTF-8 + +Starting from RHV/Ovirt 4.2 we saw issues with the agent(unable to fence) after switching to UTF-8 all worked again. +--- + agents/rhevm/fence_rhevm.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py +index 2a5107cc6..a1cdaf605 100644 +--- a/agents/rhevm/fence_rhevm.py ++++ b/agents/rhevm/fence_rhevm.py +@@ -88,7 +88,7 @@ def send_command(opt, command, method="GET"): + ## send command through pycurl + conn = pycurl.Curl() + web_buffer = io.BytesIO() +- conn.setopt(pycurl.URL, url.encode("ascii")) ++ conn.setopt(pycurl.URL, url.encode("UTF-8")) + conn.setopt(pycurl.HTTPHEADER, [ + "Version: 3", + "Content-type: application/xml", +@@ -128,7 +128,7 @@ def send_command(opt, command, method="GET"): + + opt["cookie"] = cookie + +- result = web_buffer.getvalue().decode() ++ result = web_buffer.getvalue().decode("UTF-8") + + logging.debug("%s\n", command) + logging.debug("%s\n", result) diff --git a/SOURCES/bz1670460-fence_rhevm-2-fix-debug-encoding-issues.patch b/SOURCES/bz1670460-fence_rhevm-2-fix-debug-encoding-issues.patch new file mode 100644 index 0000000..9603498 --- /dev/null +++ b/SOURCES/bz1670460-fence_rhevm-2-fix-debug-encoding-issues.patch @@ -0,0 +1,31 @@ +From 965924fe8bf7dcd0bc15fb0e9265ab49bb8a5dd8 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 20 May 2019 15:49:39 +0200 +Subject: [PATCH] fence_rhevm: fix debug encoding issues + +Tested with UTF-8 encoded comment in result, which caused this issue, +and added to command and url in case they are in UTF-8 decoded state. +--- + agents/rhevm/fence_rhevm.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py +index 6012c423..9e4650cd 100644 +--- a/agents/rhevm/fence_rhevm.py ++++ b/agents/rhevm/fence_rhevm.py +@@ -144,9 +144,9 @@ def send_command(opt, command, method="GET"): + + result = web_buffer.getvalue().decode("UTF-8") + +- logging.debug("url: %s\n", url) +- logging.debug("command: %s\n", command) +- logging.debug("result: %s\n", result) ++ logging.debug("url: %s\n", url.encode("UTF-8")) ++ logging.debug("command: %s\n", command.encode("UTF-8")) ++ logging.debug("result: %s\n", result.encode("UTF-8")) + + return result + +-- +2.21.0 + diff --git a/SOURCES/bz1677023-1-fence_redfish-use-ipport-parameter.patch b/SOURCES/bz1677023-1-fence_redfish-use-ipport-parameter.patch new file mode 100644 index 0000000..e2514f1 --- /dev/null +++ b/SOURCES/bz1677023-1-fence_redfish-use-ipport-parameter.patch @@ -0,0 +1,43 @@ +From 9ebd2e2e36ae0de5c9164f4ac3fd29bdac0cab61 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 14 Feb 2019 10:03:33 +0100 +Subject: [PATCH] fence_redfish: use "ipport" parameter and improve logging + +--- + agents/redfish/fence_redfish.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 5b719d4b..28840058 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -22,7 +22,10 @@ def get_power_status(conn, options): + fail_usage("Couldn't get power information") + data = response['data'] + +- logging.debug("PowerState is: " + data[u'PowerState']) ++ try: ++ logging.debug("PowerState is: " + data[u'PowerState']) ++ except Exception: ++ fail_usage("Unable to get PowerState: " + "https://" + options["--ip"] + ":" + str(options["--ipport"]) + options["--systems-uri"]) + + if data[u'PowerState'].strip() == "Off": + return "off" +@@ -52,7 +55,7 @@ def set_power_status(conn, options): + return + + def send_get_request(options, uri): +- full_uri = "https://" + options["--ip"] + uri ++ full_uri = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + uri + try: + resp = requests.get(full_uri, verify=not "--ssl-insecure" in options, + auth=(options["--username"], options["--password"])) +@@ -62,7 +65,7 @@ def send_get_request(options, uri): + return {'ret': True, 'data': data} + + def send_post_request(options, uri, payload, headers): +- full_uri = "https://" + options["--ip"] + uri ++ full_uri = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + uri + try: + requests.post(full_uri, data=json.dumps(payload), + headers=headers, verify=not "--ssl-insecure" in options, diff --git a/SOURCES/bz1677023-2-fence_redfish-ip-parameter-backward-compatibility.patch b/SOURCES/bz1677023-2-fence_redfish-ip-parameter-backward-compatibility.patch new file mode 100644 index 0000000..3d97c4e --- /dev/null +++ b/SOURCES/bz1677023-2-fence_redfish-ip-parameter-backward-compatibility.patch @@ -0,0 +1,24 @@ +From 21898e45ca2624546de99086a27a14dd1ff86a2b Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 21 Feb 2019 09:08:03 +0100 +Subject: [PATCH] fence_redfish: backwards compatibility for : + +--- + agents/redfish/fence_redfish.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index 28840058..f1424232 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -140,6 +140,10 @@ def main(): + if "--ssl-insecure" in opt: + requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + ++ # backwards compatibility for : ++ if options["--ip"].count(":") == 1: ++ (options["--ip"], options["--ipport"]) = options["--ip"].split(":") ++ + if "--systems-uri" not in opt: + # Systems URI not provided, find it + sysresult = find_systems_resource(options) diff --git a/SOURCES/bz1700544-fence_azure_arm-skip_shutdown.patch b/SOURCES/bz1700544-fence_azure_arm-skip_shutdown.patch new file mode 100644 index 0000000..708eb84 --- /dev/null +++ b/SOURCES/bz1700544-fence_azure_arm-skip_shutdown.patch @@ -0,0 +1,48 @@ +From 1b3e548fcc0bd427dade178fa260567047ff3a0e Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 6 May 2019 13:24:18 +0200 +Subject: [PATCH] fence_azure_arm: use skip_shutdown feature when available + +The "skip_shutdown" parameter is ignored in older Azure SDK, so there's +no need for a fallback option. +--- + agents/azure_arm/fence_azure_arm.py | 6 +++--- + tests/data/metadata/fence_azure_arm.xml | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/agents/azure_arm/fence_azure_arm.py b/agents/azure_arm/fence_azure_arm.py +index 58b9eeb13..be0d40345 100755 +--- a/agents/azure_arm/fence_azure_arm.py ++++ b/agents/azure_arm/fence_azure_arm.py +@@ -114,8 +114,8 @@ def set_power_status(clients, options): + azure_fence.set_network_state(compute_client, network_client, rgName, vmName, "unblock") + + if (options["--action"]=="off"): +- logging.info("Deallocating " + vmName + " in resource group " + rgName) +- compute_client.virtual_machines.deallocate(rgName, vmName) ++ logging.info("Poweroff " + vmName + " in resource group " + rgName) ++ compute_client.virtual_machines.power_off(rgName, vmName, skip_shutdown=True) + elif (options["--action"]=="on"): + logging.info("Starting " + vmName + " in resource group " + rgName) + compute_client.virtual_machines.start(rgName, vmName) +@@ -199,7 +199,7 @@ def main(): + + docs = {} + docs["shortdesc"] = "Fence agent for Azure Resource Manager" +- docs["longdesc"] = "Used to deallocate virtual machines and to report power state of virtual machines running in Azure. It uses Azure SDK for Python to connect to Azure.\ ++ docs["longdesc"] = "fence_azure_arm is an I/O Fencing agent for Azure Resource Manager. It uses Azure SDK for Python to connect to Azure.\ + \n.P\n\ + For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal\ + \n.P\n\ +diff --git a/tests/data/metadata/fence_azure_arm.xml b/tests/data/metadata/fence_azure_arm.xml +index 1c0b6cc6b..97ecfdba4 100644 +--- a/tests/data/metadata/fence_azure_arm.xml ++++ b/tests/data/metadata/fence_azure_arm.xml +@@ -1,6 +1,6 @@ + + +-Used to deallocate virtual machines and to report power state of virtual machines running in Azure. It uses Azure SDK for Python to connect to Azure. ++fence_azure_arm is an I/O Fencing agent for Azure Resource Manager. It uses Azure SDK for Python to connect to Azure. + + For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal + diff --git a/SOURCES/bz1709879-fence_mpath-fix-watchdog-hardreboot.patch b/SOURCES/bz1709879-fence_mpath-fix-watchdog-hardreboot.patch new file mode 100644 index 0000000..2b187c2 --- /dev/null +++ b/SOURCES/bz1709879-fence_mpath-fix-watchdog-hardreboot.patch @@ -0,0 +1,21 @@ +From e5c6c2e134fd397ffe3319adc7afb8b633a251b2 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 14 May 2019 16:44:59 +0200 +Subject: [PATCH] fence_mpath: import ctypes to fix watchdog hardreboot + +--- + agents/mpath/fence_mpath.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py +index d9ac2ef54..e4f598361 100644 +--- a/agents/mpath/fence_mpath.py ++++ b/agents/mpath/fence_mpath.py +@@ -6,6 +6,7 @@ + import os + import logging + import atexit ++import ctypes + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import fail_usage, run_command, atexit_handler, check_input, process_input, show_docs + from fencing import fence_action, all_opt, run_delay diff --git a/SOURCES/bz1713665-fence_redfish-full-redfish-spec-compliance.patch b/SOURCES/bz1713665-fence_redfish-full-redfish-spec-compliance.patch new file mode 100644 index 0000000..3b8ba13 --- /dev/null +++ b/SOURCES/bz1713665-fence_redfish-full-redfish-spec-compliance.patch @@ -0,0 +1,65 @@ +From 75a74debba2205547d8eefae221221c2c71d99ce Mon Sep 17 00:00:00 2001 +From: Jose Delarosa +Date: Mon, 15 Apr 2019 12:46:42 -0500 +Subject: [PATCH] fence_redfish: add headers to HTTP methods + +* Needed for full compliance with Redfish spec. +* May cause errors in some devices if not sent. +--- + agents/redfish/fence_redfish.py | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py +index f1424232..390a4827 100644 +--- a/agents/redfish/fence_redfish.py ++++ b/agents/redfish/fence_redfish.py +@@ -16,6 +16,11 @@ + from fencing import * + from fencing import fail_usage, run_delay + ++GET_HEADERS = {'accept': 'application/json', 'OData-Version': '4.0'} ++POST_HEADERS = {'content-type': 'application/json', 'accept': 'application/json', ++ 'OData-Version': '4.0'} ++ ++ + def get_power_status(conn, options): + response = send_get_request(options, options["--systems-uri"]) + if response['ret'] is False: +@@ -40,7 +45,6 @@ def set_power_status(conn, options): + }[options["--action"]] + + payload = {'ResetType': action} +- headers = {'content-type': 'application/json'} + + # Search for 'Actions' key and extract URI from it + response = send_get_request(options, options["--systems-uri"]) +@@ -49,7 +53,7 @@ def set_power_status(conn, options): + data = response['data'] + action_uri = data["Actions"]["#ComputerSystem.Reset"]["target"] + +- response = send_post_request(options, action_uri, payload, headers) ++ response = send_post_request(options, action_uri, payload) + if response['ret'] is False: + fail_usage("Error sending power command") + return +@@ -58,17 +62,18 @@ def send_get_request(options, uri): + full_uri = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + uri + try: + resp = requests.get(full_uri, verify=not "--ssl-insecure" in options, ++ headers=GET_HEADERS, + auth=(options["--username"], options["--password"])) + data = resp.json() + except Exception as e: + fail_usage("Failed: send_get_request: " + str(e)) + return {'ret': True, 'data': data} + +-def send_post_request(options, uri, payload, headers): ++def send_post_request(options, uri, payload): + full_uri = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + uri + try: + requests.post(full_uri, data=json.dumps(payload), +- headers=headers, verify=not "--ssl-insecure" in options, ++ headers=POST_HEADERS, verify=not "--ssl-insecure" in options, + auth=(options["--username"], options["--password"])) + except Exception as e: + fail_usage("Failed: send_post_request: " + str(e)) diff --git a/SOURCES/bz1734812-fence_iloX_ssh-monitor-timeout-warning.patch b/SOURCES/bz1734812-fence_iloX_ssh-monitor-timeout-warning.patch new file mode 100644 index 0000000..ba26ed3 --- /dev/null +++ b/SOURCES/bz1734812-fence_iloX_ssh-monitor-timeout-warning.patch @@ -0,0 +1,25 @@ +From 7c1348d53aa8080f2fcfc344a2f4a2372739a62c Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 6 Aug 2019 13:06:13 +0200 +Subject: [PATCH] fence_ilo_ssh*: add timeout warning in metadata/manpage + +--- + agents/ilo_ssh/fence_ilo_ssh.py | 5 ++++- + 5 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/agents/ilo_ssh/fence_ilo_ssh.py b/agents/ilo_ssh/fence_ilo_ssh.py +index 88f13d17..a27e3418 100644 +--- a/agents/ilo_ssh/fence_ilo_ssh.py ++++ b/agents/ilo_ssh/fence_ilo_ssh.py +@@ -51,7 +51,10 @@ def main(): + docs = {} + docs["shortdesc"] = "Fence agent for HP iLO over SSH" + docs["longdesc"] = "fence_ilo_ssh is a fence agent that connects to iLO device. It logs into \ +-device via ssh and reboot a specified outlet. " ++device via ssh and reboot a specified outlet.\ ++\n.P\n\ ++WARNING: The monitor-action is prone to timeouts. Use the fence_ilo-equivalent \ ++to avoid this issue." + docs["vendorurl"] = "http://www.hp.com" + docs["symlink"] = [("fence_ilo3_ssh", "Fence agent for HP iLO3 over SSH"), + ("fence_ilo4_ssh", "Fence agent for HP iLO4 over SSH"), diff --git a/SOURCES/bz1751702-fence_mpath-fix-watchdog-trigger-multipath-disconnect.patch b/SOURCES/bz1751702-fence_mpath-fix-watchdog-trigger-multipath-disconnect.patch new file mode 100644 index 0000000..8c804c2 --- /dev/null +++ b/SOURCES/bz1751702-fence_mpath-fix-watchdog-trigger-multipath-disconnect.patch @@ -0,0 +1,40 @@ +From 2df8abf25eddc8da71c193ca29f6be51e66b02f0 Mon Sep 17 00:00:00 2001 +From: Hideo Yamauchi +Date: Thu, 12 Sep 2019 08:44:49 +0900 +Subject: [PATCH] High: mpath: Correction of failure detection behavior from + watchdog service. + +--- + agents/mpath/fence_mpath.py | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py +index e4f59836..b17388eb 100644 +--- a/agents/mpath/fence_mpath.py ++++ b/agents/mpath/fence_mpath.py +@@ -117,12 +117,14 @@ def get_reservation_key(options, dev): + match = re.search(r"\s+key\s*=\s*0x(\S+)\s+", out["out"], re.IGNORECASE) + return match.group(1) if match else None + +-def get_registration_keys(options, dev): ++def get_registration_keys(options, dev, fail=True): + keys = [] + cmd = options["--mpathpersist-path"] + " -i -k -d " + dev + out = run_cmd(options, cmd) + if out["err"]: +- fail_usage("Cannot get registration keys") ++ fail_usage("Cannot get registration keys", fail) ++ if not fail: ++ return [] + for line in out["out"].split("\n"): + match = re.search(r"\s+0x(\S+)\s*", line) + if match: +@@ -183,7 +185,7 @@ def mpath_check(hardreboot=False): + logging.error("No devices found") + return 0 + for dev, key in list(devs.items()): +- if key in get_registration_keys(options, dev): ++ if key in get_registration_keys(options, dev, fail=False): + logging.debug("key " + key + " registered with device " + dev) + return 0 + else: diff --git a/SOURCES/bz1753229-fence_mpath-1-add-plug-parameter-support.patch b/SOURCES/bz1753229-fence_mpath-1-add-plug-parameter-support.patch new file mode 100644 index 0000000..216f48c --- /dev/null +++ b/SOURCES/bz1753229-fence_mpath-1-add-plug-parameter-support.patch @@ -0,0 +1,197 @@ +From d866e11213ebeab8da280b41371a968ae12410bd Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 13 Sep 2019 12:48:46 +0200 +Subject: [PATCH] fence_mpath: use -n/--plug/port parameter to be able to use + pcmk_host_map + +--- + agents/mpath/fence_mpath.py | 63 +++++++++++++++++------------ + tests/data/metadata/fence_mpath.xml | 12 +++++- + 2 files changed, 49 insertions(+), 26 deletions(-) + +diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py +index e4f59836..dfc5657b 100644 +--- a/agents/mpath/fence_mpath.py ++++ b/agents/mpath/fence_mpath.py +@@ -16,11 +16,11 @@ def get_status(conn, options): + status = "off" + for dev in options["devices"]: + is_block_device(dev) +- if options["--key"] in get_registration_keys(options, dev): ++ if options["--plug"] in get_registration_keys(options, dev): + status = "on" + else: + logging.debug("No registration for key "\ +- + options["--key"] + " on device " + dev + "\n") ++ + options["--plug"] + " on device " + dev + "\n") + + if options["--action"] == "monitor": + dev_read(options) +@@ -36,10 +36,10 @@ def set_status(conn, options): + is_block_device(dev) + + register_dev(options, dev) +- if options["--key"] not in get_registration_keys(options, dev): ++ if options["--plug"] not in get_registration_keys(options, dev): + count += 1 + logging.debug("Failed to register key "\ +- + options["--key"] + "on device " + dev + "\n") ++ + options["--plug"] + "on device " + dev + "\n") + continue + dev_write(options, dev) + +@@ -48,7 +48,7 @@ def set_status(conn, options): + and get_reservation_key(options, dev) is None: + count += 1 + logging.debug("Failed to create reservation (key="\ +- + options["--key"] + ", device=" + dev + ")\n") ++ + options["--plug"] + ", device=" + dev + ")\n") + + else: + dev_keys = dev_read(options) +@@ -56,14 +56,14 @@ def set_status(conn, options): + for dev in options["devices"]: + is_block_device(dev) + +- if options["--key"] in get_registration_keys(options, dev): ++ if options["--plug"] in get_registration_keys(options, dev): + preempt_abort(options, dev_keys[dev], dev) + + for dev in options["devices"]: +- if options["--key"] in get_registration_keys(options, dev): ++ if options["--plug"] in get_registration_keys(options, dev): + count += 1 + logging.debug("Failed to remove key "\ +- + options["--key"] + " on device " + dev + "\n") ++ + options["--plug"] + " on device " + dev + "\n") + continue + + if not get_reservation_key(options, dev): +@@ -97,16 +97,16 @@ def is_block_device(dev): + + # cancel registration + def preempt_abort(options, host, dev): +- cmd = options["--mpathpersist-path"] + " -o --preempt-abort --prout-type=5 --param-rk=" + host +" --param-sark=" + options["--key"] +" -d " + dev ++ cmd = options["--mpathpersist-path"] + " -o --preempt-abort --prout-type=5 --param-rk=" + host +" --param-sark=" + options["--plug"] +" -d " + dev + return not bool(run_cmd(options, cmd)["err"]) + + def register_dev(options, dev): +- cmd = options["--mpathpersist-path"] + " -o --register --param-sark=" + options["--key"] + " -d " + dev ++ cmd = options["--mpathpersist-path"] + " -o --register --param-sark=" + options["--plug"] + " -d " + dev + #cmd return code != 0 but registration can be successful + return not bool(run_cmd(options, cmd)["err"]) + + def reserve_dev(options, dev): +- cmd = options["--mpathpersist-path"] + " -o --reserv --prout-type=5 --param-rk=" + options["--key"] + " -d " + dev ++ cmd = options["--mpathpersist-path"] + " -o --reserv --prout-type=5 --param-rk=" + options["--plug"] + " -d " + dev + return not bool(run_cmd(options, cmd)["err"]) + + def get_reservation_key(options, dev): +@@ -141,7 +141,7 @@ def dev_write(options, dev): + fail_usage("Failed: Cannot open file \""+ file_path + "\"") + out = store_fh.read() + if not re.search(r"^" + dev + r"\s+", out): +- store_fh.write(dev + "\t" + options["--key"] + "\n") ++ store_fh.write(dev + "\t" + options["--plug"] + "\n") + store_fh.close() + + def dev_read(options, fail=True): +@@ -209,12 +209,9 @@ def define_new_opts(): + all_opt["key"] = { + "getopt" : "k:", + "longopt" : "key", +- "help" : "-k, --key=[key] Key to use for the current operation", +- "required" : "1", +- "shortdesc" : "Key to use for the current operation. This key should be \ +-unique to a node and have to be written in /etc/multipath.conf. For the \"on\" action, the key specifies the key use to \ +-register the local node. For the \"off\" action, this key specifies the key to \ +-be removed from the device(s).", ++ "help" : "-k, --key=[key] Replaced by -n, --plug", ++ "required" : "0", ++ "shortdesc" : "Replaced by -n, --plug", + "order": 1 + } + all_opt["mpathpersist_path"] = { +@@ -240,10 +237,18 @@ def main(): + atexit.register(atexit_handler) + + device_opt = ["no_login", "no_password", "devices", "key", "sudo", \ +- "fabric_fencing", "on_target", "store_path", "mpathpersist_path", "force_on"] ++ "fabric_fencing", "on_target", "store_path", \ ++ "mpathpersist_path", "force_on", "port", "no_port"] + + define_new_opts() + ++ all_opt["port"]["help"] = "Key to use for the current operation" ++ all_opt["port"]["shortdesc"] = "Key to use for the current operation. \ ++This key should be unique to a node and have to be written in \ ++/etc/multipath.conf. For the \"on\" action, the key specifies the key use to \ ++register the local node. For the \"off\" action, this key specifies the key to \ ++be removed from the device(s)." ++ + # fence_mpath_check + if os.path.basename(sys.argv[0]) == "fence_mpath_check": + sys.exit(mpath_check()) +@@ -252,6 +257,17 @@ def main(): + + options = check_input(device_opt, process_input(device_opt), other_conditions=True) + ++ # hack to remove list/list-status actions which are not supported ++ options["device_opt"] = [ o for o in options["device_opt"] if o != "separator" ] ++ ++ # workaround to avoid regressions ++ if "--key" in options: ++ options["--plug"] = options["--key"] ++ del options["--key"] ++ elif options["--action"] in ["off", "on", "reboot", "status"] \ ++ and "--plug" not in options: ++ fail_usage("Failed: You have to enter plug number or machine identification", stop) ++ + docs = {} + docs["shortdesc"] = "Fence agent for multipath persistent reservation" + docs["longdesc"] = "fence_mpath is an I/O fencing agent that uses SCSI-3 \ +@@ -271,16 +287,13 @@ def main(): + run_delay(options) + + # Input control BEGIN +- if not "--key" in options: +- fail_usage("Failed: key is required") +- + if options["--action"] == "validate-all": + sys.exit(0) + +- options["devices"] = options["--devices"].split(",") +- +- if not options["devices"]: ++ if not ("--devices" in options and options["--devices"]): + fail_usage("Failed: No devices found") ++ ++ options["devices"] = options["--devices"].split(",") + # Input control END + + result = fence_action(None, options, set_status, get_status) +diff --git a/tests/data/metadata/fence_mpath.xml b/tests/data/metadata/fence_mpath.xml +index bbe9ad2b..fe9378df 100644 +--- a/tests/data/metadata/fence_mpath.xml ++++ b/tests/data/metadata/fence_mpath.xml +@@ -14,9 +14,19 @@ The fence_mpath agent works by having a unique key for each node that has to be + + 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. + +- ++ + + ++ Replaced by -n, --plug ++ ++ ++ ++ ++ Key to use for the current operation. This key should be unique to a node and have to be written in /etc/multipath.conf. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s). ++ ++ ++ ++ + Key to use for the current operation. This key should be unique to a node and have to be written in /etc/multipath.conf. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s). + + diff --git a/SOURCES/bz1753229-fence_mpath-2-fix-plug-parameter-issues.patch b/SOURCES/bz1753229-fence_mpath-2-fix-plug-parameter-issues.patch new file mode 100644 index 0000000..d668e27 --- /dev/null +++ b/SOURCES/bz1753229-fence_mpath-2-fix-plug-parameter-issues.patch @@ -0,0 +1,73 @@ +From 868c494d17952eecc6736683c6df04aa9d3a3199 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 20 Sep 2019 12:06:55 +0200 +Subject: [PATCH] fence_mpath: fix fail_usage() issue and a couple of other + minor issues w/the newly added plug/port parameter + +--- + agents/mpath/fence_mpath.py | 12 +++++++----- + tests/data/metadata/fence_mpath.xml | 10 +++++----- + 2 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py +index 25aeb052..73517851 100644 +--- a/agents/mpath/fence_mpath.py ++++ b/agents/mpath/fence_mpath.py +@@ -213,7 +213,7 @@ def define_new_opts(): + "longopt" : "key", + "help" : "-k, --key=[key] Replaced by -n, --plug", + "required" : "0", +- "shortdesc" : "Replaced by -n, --plug", ++ "shortdesc" : "Replaced by port/-n/--plug", + "order": 1 + } + all_opt["mpathpersist_path"] = { +@@ -244,7 +244,8 @@ def main(): + + define_new_opts() + +- all_opt["port"]["help"] = "Key to use for the current operation" ++ all_opt["port"]["required"] = "0" ++ all_opt["port"]["help"] = "-n, --plug=[key] Key to use for the current operation" + all_opt["port"]["shortdesc"] = "Key to use for the current operation. \ + This key should be unique to a node and have to be written in \ + /etc/multipath.conf. For the \"on\" action, the key specifies the key use to \ +@@ -266,9 +267,10 @@ def main(): + if "--key" in options: + options["--plug"] = options["--key"] + del options["--key"] +- elif options["--action"] in ["off", "on", "reboot", "status"] \ +- and "--plug" not in options: +- fail_usage("Failed: You have to enter plug number or machine identification", stop) ++ elif "--help" not in options and options["--action"] in ["off", "on", \ ++ "reboot", "status", "validate-all"] and "--plug" not in options: ++ stop_after_error = False if options["--action"] == "validate-all" else True ++ fail_usage("Failed: You have to enter plug number or machine identification", stop_after_error) + + docs = {} + docs["shortdesc"] = "Fence agent for multipath persistent reservation" +diff --git a/tests/data/metadata/fence_mpath.xml b/tests/data/metadata/fence_mpath.xml +index fe9378df..f5e60823 100644 +--- a/tests/data/metadata/fence_mpath.xml ++++ b/tests/data/metadata/fence_mpath.xml +@@ -17,15 +17,15 @@ The fence_mpath agent works by having a unique key for each node that has to be + + + +- Replaced by -n, --plug ++ Replaced by port/-n/--plug + +- +- ++ ++ + + Key to use for the current operation. This key should be unique to a node and have to be written in /etc/multipath.conf. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s). + +- +- ++ ++ + + Key to use for the current operation. This key should be unique to a node and have to be written in /etc/multipath.conf. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s). + diff --git a/SOURCES/python-httplib2-0.9-cve-2013-2037.patch b/SOURCES/python-httplib2-0.9-cve-2013-2037.patch new file mode 100644 index 0000000..6a09337 --- /dev/null +++ b/SOURCES/python-httplib2-0.9-cve-2013-2037.patch @@ -0,0 +1,21 @@ +diff -Nur httplib2-0.9.orig/python2/httplib2/__init__.py httplib2-0.9/python2/httplib2/__init__.py +--- httplib2-0.9.orig/python2/httplib2/__init__.py 2015-04-03 13:10:43.401035131 -0600 ++++ httplib2-0.9/python2/httplib2/__init__.py 2015-04-03 13:10:08.470685647 -0600 +@@ -1042,7 +1042,7 @@ + raise CertificateHostnameMismatch( + 'Server presented certificate that does not match ' + 'host %s: %s' % (hostname, cert), hostname, cert) +- except ssl_SSLError, e: ++ except (ssl_SSLError, CertificateHostnameMismatch), e: + if sock: + sock.close() + if self.sock: +@@ -1052,7 +1052,7 @@ + # to get at more detailed error information, in particular + # whether the error is due to certificate validation or + # something else (such as SSL protocol mismatch). +- if e.errno == ssl.SSL_ERROR_SSL: ++ if hasattr(e, 'errno') and e.errno == ssl.SSL_ERROR_SSL: + raise SSLHandshakeError(e) + else: + raise diff --git a/SOURCES/python-httplib2-0.9-proxy-http.patch b/SOURCES/python-httplib2-0.9-proxy-http.patch new file mode 100644 index 0000000..0d55002 --- /dev/null +++ b/SOURCES/python-httplib2-0.9-proxy-http.patch @@ -0,0 +1,16 @@ +diff -Nur httplib2-0.9.orig/python2/httplib2/__init__.py httplib2-0.9/python2/httplib2/__init__.py +--- httplib2-0.9.orig/python2/httplib2/__init__.py 2015-04-03 12:56:04.834370332 -0600 ++++ httplib2-0.9/python2/httplib2/__init__.py 2015-04-03 12:58:16.441925454 -0600 +@@ -838,7 +838,11 @@ + else: + port = dict(https=443, http=80)[method] + +- proxy_type = 3 # socks.PROXY_TYPE_HTTP ++ if method == 'http': ++ proxy_type = 4 # socks.PROXY_TYPE_HTTP_NO_TUNNEL ++ else: ++ proxy_type = 3 # socks.PROXY_TYPE_HTTP ++ + return ProxyInfo( + proxy_type = proxy_type, + proxy_host = host, diff --git a/SOURCES/python-httplib2.certfile.patch b/SOURCES/python-httplib2.certfile.patch new file mode 100644 index 0000000..e351169 --- /dev/null +++ b/SOURCES/python-httplib2.certfile.patch @@ -0,0 +1,31 @@ +diff -Nur httplib2-0.9.orig/python2/httplib2/__init__.py httplib2-0.9/python2/httplib2/__init__.py +--- httplib2-0.9.orig/python2/httplib2/__init__.py 2014-04-14 06:52:57.000000000 -0600 ++++ httplib2-0.9/python2/httplib2/__init__.py 2014-05-23 21:17:02.082118837 -0600 +@@ -191,8 +191,10 @@ + CA_CERTS = ca_certs_locater.get() + except ImportError: + # Default CA certificates file bundled with httplib2. +- CA_CERTS = os.path.join( +- os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") ++# CA_CERTS = os.path.join( ++# os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") ++# Use Fedora system-wide shared certificate store for security, consistency. ++ CA_CERTS = "/etc/pki/tls/certs/ca-bundle.crt" + + # Which headers are hop-by-hop headers by default + HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] +--- httplib2-0.9/python3/httplib2/__init__.py 2014-04-14 05:52:57.000000000 -0700 ++++ httplib2-0.9/python3/httplib2/__init__.py.new 2015-01-12 17:22:19.815505848 -0800 +@@ -124,8 +124,10 @@ + HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] + + # Default CA certificates file bundled with httplib2. +-CA_CERTS = os.path.join( +- os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") ++#CA_CERTS = os.path.join( ++# os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") ++# Use Fedora system-wide shared certificate store for security, consistency. ++CA_CERTS = "/etc/pki/tls/certs/ca-bundle.crt" + + def _get_end2end_headers(response): + hopbyhop = list(HOP_BY_HOP) diff --git a/SOURCES/python-httplib2.getCertHost.patch b/SOURCES/python-httplib2.getCertHost.patch new file mode 100644 index 0000000..f9c53de --- /dev/null +++ b/SOURCES/python-httplib2.getCertHost.patch @@ -0,0 +1,21 @@ +diff -up ./python2/httplib2/__init__.py.getCertHost ./python2/httplib2/__init__.py +--- ./python2/httplib2/__init__.py.getCertHost 2012-05-03 17:16:33.834155219 +1000 ++++ ./python2/httplib2/__init__.py 2012-06-21 18:19:33.804660257 +1000 +@@ -942,11 +942,12 @@ class HTTPSConnectionWithTimeout(httplib + list: A list of valid host globs. + """ + if 'subjectAltName' in cert: +- return [x[1] for x in cert['subjectAltName'] +- if x[0].lower() == 'dns'] +- else: +- return [x[0][1] for x in cert['subject'] +- if x[0][0].lower() == 'commonname'] ++ # Patch from richardfearn@gmail.com ++ return [x[1] for x in cert['subjectAltName'] ++ if x[0].lower() == "dns"] ++ ++ return [x[0][1] for x in cert['subject'] ++ if x[0][0].lower() == 'commonname'] + + def _ValidateCertificateHostname(self, cert, hostname): + """Validates that a given hostname is valid for an SSL certificate. diff --git a/SOURCES/python-httplib2.rfc2459.patch b/SOURCES/python-httplib2.rfc2459.patch new file mode 100644 index 0000000..523129e --- /dev/null +++ b/SOURCES/python-httplib2.rfc2459.patch @@ -0,0 +1,19 @@ +diff -up ./python2/httplib2/__init__.py.orig ./python2/httplib2/__init__.py +--- ./python2/httplib2/__init__.py.orig 2012-07-27 18:35:59.215300471 +1000 ++++ ./python2/httplib2/__init__.py 2012-07-27 18:36:30.697287505 +1000 +@@ -943,8 +943,13 @@ class HTTPSConnectionWithTimeout(httplib + """ + if 'subjectAltName' in cert: + # Patch from richardfearn@gmail.com +- return [x[1] for x in cert['subjectAltName'] ++ # RFC 2459 states that subjectAltName may contain: ++ # either DNS, email, IP or URI ++ # email, URI, ++ hosts=[x[1] for x in cert['subjectAltName'] + if x[0].lower() == "dns"] ++ if hosts: ++ return hosts + + return [x[0][1] for x in cert['subject'] + if x[0][0].lower() == 'commonname'] + diff --git a/SPECS/fence-agents.spec b/SPECS/fence-agents.spec new file mode 100644 index 0000000..0d8db4e --- /dev/null +++ b/SPECS/fence-agents.spec @@ -0,0 +1,1783 @@ +############################################################################### +############################################################################### +## +## Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. +## +## This copyrighted material is made available to anyone wishing to use, +## modify, copy, or redistribute it subject to the terms and conditions +## of the GNU General Public License v.2. +## +############################################################################### +############################################################################### + +# keep around ready for later user +## global alphatag git0a6184070 + +%global bundled_lib_dir bundled + +# google cloud +# python-google-api-client bundle +%global googleapiclient google-api-python-client +%global googleapiclient_version 1.6.3 +%global googleapiclient_dir %{bundled_lib_dir}/gce/%{googleapiclient} +# python-oauth2client bundle +%global oauth2client oauth2client +%global oauth2client_version 4.0.0 +%global oauth2client_dir %{bundled_lib_dir}/gce/%{oauth2client} +# python-httplib2 bundle +%global httplib2 httplib2 +%global httplib2_version 0.9.1 +%global httplib2_dir %{bundled_lib_dir}/gce/%{httplib2} +# python-fasteners bundle +%global fasteners fasteners +%global fasteners_version 0.9.0 +%global fasteners_dir %{bundled_lib_dir}/gce/%{fasteners} +# python-keyring bundle +%global keyring keyring +%global keyring_version 5.0 +%global keyring_dir %{bundled_lib_dir}/gce/%{keyring} +# python-gflags bundle +%global gflags gflags +%global gflags_version 2.0 +%global gflags_dir %{bundled_lib_dir}/gce/%{gflags} +# python-uritemplate bundle +%global uritemplate uritemplate +%global uritemplate_version 3.0.0 +%global uritemplate_dir %{bundled_lib_dir}/gce/%{uritemplate} + +# alibaba +# python-pycryptodome bundle +%global pycryptodome pycryptodome +%global pycryptodome_version 3.6.4 +%global pycryptodome_dir %{bundled_lib_dir}/aliyun/%{pycryptodome} +# python-aliyun-sdk-core bundle +%global aliyunsdkcore aliyun-python-sdk-core +%global aliyunsdkcore_version 2.8.5 +%global aliyunsdkcore_dir %{bundled_lib_dir}/aliyun/%{aliyunsdkcore} +# python-aliyun-sdk-ecs bundle +%global aliyunsdkecs aliyun-python-sdk-ecs +%global aliyunsdkecs_version 4.9.3 +%global aliyunsdkecs_dir %{bundled_lib_dir}/aliyun/%{aliyunsdkecs} +# python-aliyun-sdk-vpc bundle +%global aliyunsdkvpc aliyun-python-sdk-vpc +%global aliyunsdkvpc_version 3.0.2 +%global aliyunsdkvpc_dir %{bundled_lib_dir}/aliyun/%{aliyunsdkvpc} + +Name: fence-agents +Summary: Fence Agents for Red Hat Cluster +Version: 4.2.1 +Release: 28%{?alphatag:.%{alphatag}}%{?dist} +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +URL: https://github.com/ClusterLabs/fence-agents +Source0: https://fedorahosted.org/releases/f/e/fence-agents/%{name}-%{version}.tar.gz +Source1: https://pypi.python.org/packages/16/00/a6913a2e6eb3d5b1cc3538c3492ccd2b39a6d79367432d46cea1ec74170d/%{googleapiclient}-%{googleapiclient_version}.tar.gz +Source2: https://github.com/google/%{oauth2client}/archive/v%{oauth2client_version}.tar.gz#/%{oauth2client}-%{oauth2client_version}.tar.gz +Source3: https://pypi.python.org/packages/source/h/%{httplib2}/%{httplib2}-%{httplib2_version}.tar.gz +Source4: https://codeload.github.com/harlowja/fasteners/tar.gz/%{fasteners_version}#/%{fasteners}-%{fasteners_version}.tar.gz +Source5: http://pypi.python.org/packages/source/k/keyring/%{keyring}-%{keyring_version}.zip +Source6: https://github.com/gflags/python-gflags/archive/python-%{gflags}-%{gflags_version}.tar.gz#/python-%{gflags}-%{gflags_version}.tar.gz +Source7: https://github.com/sigmavirus24/%{uritemplate}/archive/%{uritemplate_version}/%{uritemplate}-%{uritemplate_version}.tar.gz +Source8: %{pycryptodome}-%{pycryptodome_version}.tar.gz +Source9: %{aliyunsdkcore}-%{aliyunsdkcore_version}.tar.gz +Source10: %{aliyunsdkecs}-%{aliyunsdkecs_version}.tar.gz +Source11: %{aliyunsdkvpc}-%{aliyunsdkvpc_version}.tar.gz +Patch0: bz1579391-fence_impilan-fence_ilo_ssh-add-ilo5-support.patch +Patch1: bz1504202-fence_mpath-watchdog-support.patch +Patch2: bz1236395-1-fence_scsi-fence_scsi_check.pl-link.patch +Patch3: bz1236395-2-fence_ilo3-fence_ipmilan-show-correct-default-method.patch +Patch4: bz1549699-1-fence_evacuate-fix-evacuable-tag-mix-issue.patch +Patch5: bz1549699-2-fence_compute-fence_evacuate-fix-compute-domain.patch +Patch6: bz1568753-1-fence_gce-stackdriver-logging-default-method-cycle.patch +Patch7: bz1568753-2-fence_gce-filter-aggregatedlist.patch +Patch8: bz1568753-3-fence_gce-stackdriver-logging-note.patch +Patch9: bz1568742-1-fence_aliyun.patch +Patch10: bz1568742-2-fence_aliyun.patch +Patch11: bz1568742-3-fence_aliyun-logging.patch +Patch12: bz1568742-4-fence_aliyun-bundled.patch +Patch13: bz1236395-3-fix-version.patch +Patch14: bz1622229-1-fence_aliyun-list-instance-names.patch +Patch15: bz1622229-2-fence_aliyun-correct-help-indentation.patch +Patch16: bz1625164-fence_cisco_ucs-encode-POSTFIELDS.patch +Patch17: bz1645170-fence_scsi-fix-incorrect-SCSI-key-node-ID-10-or-higher.patch +Patch18: bz1653700-1-fence_scsi-watchdog-retry-support.patch +Patch19: bz1653700-2-build-fix-check_used_options.patch +Patch20: bz1650526-fence_hpblade-fix-log_expect_syntax.patch +Patch21: bz1350908-fence_vmware_soap-cleanup-sigterm.patch +Patch22: bz1464933-1-fence_redfish.patch +Patch23: bz1464933-2-fence_redfish-fail-invalid-cert.patch +Patch24: bz1608550-fence_dump-validate-all.patch +Patch25: bz1677023-1-fence_redfish-use-ipport-parameter.patch +Patch26: bz1677023-2-fence_redfish-ip-parameter-backward-compatibility.patch +Patch27: bz1670460-fence_rhevm-1-use-UTF8-encoding.patch +Patch28: bz1402862-fence_rhevm-RHEV-v4-API-support.patch +Patch29: bz1700544-fence_azure_arm-skip_shutdown.patch +Patch30: bz1670460-fence_rhevm-2-fix-debug-encoding-issues.patch +Patch31: bz1709879-fence_mpath-fix-watchdog-hardreboot.patch +Patch32: bz1713665-fence_redfish-full-redfish-spec-compliance.patch +Patch33: bz1653700-3-fence_scsi-watchdog-fix-retry-failing-on-first-try.patch +Patch34: bz1734812-fence_iloX_ssh-monitor-timeout-warning.patch +Patch35: bz1751702-fence_mpath-fix-watchdog-trigger-multipath-disconnect.patch +Patch36: bz1753229-fence_mpath-1-add-plug-parameter-support.patch +Patch37: bz1753229-fence_mpath-2-fix-plug-parameter-issues.patch +# bundle patches +Patch1000: bz1568753-4-fence_gce-bundled-libs.patch +Patch1001: bz1568753-5-%{oauth2client}-docs-build-fix.patch +Patch1002: bz1568753-6-%{oauth2client}-python-rsa-to-cryptography.patch +Patch1003: python-%{httplib2}.certfile.patch +Patch1004: python-%{httplib2}.getCertHost.patch +Patch1005: python-%{httplib2}.rfc2459.patch +Patch1006: python-%{httplib2}-0.9-proxy-http.patch +Patch1007: python-%{httplib2}-0.9-cve-2013-2037.patch +Patch1008: bz1568753-7-%{keyring}-fix-gnome-version-warning.patch + +%if 0%{?rhel} +%global supportedagents amt_ws apc apc_snmp bladecenter brocade cisco_mds cisco_ucs compute drac5 eaton_snmp emerson eps evacuate hpblade ibmblade ifmib ilo ilo_moonshot ilo_mp ilo_ssh intelmodular ipdu ipmilan mpath kdump redfish rhevm rsa rsb sbd scsi vmware_rest vmware_soap wti +%ifarch x86_64 +%global testagents virsh heuristics_ping aliyun aws azure_arm gce +%endif +%ifarch ppc64le +%global testagents virsh lpar heuristics_ping +%endif +%ifarch s390x +%global testagents virsh zvm heuristics_ping +%endif +%ifnarch x86_64 ppc64le s390x +%global testagents virsh heuristics_ping +%endif + +%global allfenceagents fence-agents-amt-ws fence-agents-apc fence-agents-apc-snmp fence-agents-bladecenter fence-agents-brocade fence-agents-cisco-mds fence-agents-cisco-ucs fence-agents-compute fence-agents-drac5 fence-agents-eaton-snmp fence-agents-emerson fence-agents-eps fence-agents-heuristics-ping fence-agents-hpblade fence-agents-ibmblade fence-agents-ifmib fence-agents-ilo2 fence-agents-ilo-moonshot fence-agents-ilo-mp fence-agents-ilo-ssh fence-agents-intelmodular fence-agents-ipdu fence-agents-ipmilan fence-agents-mpath fence-agents-kdump fence-agents-redfish fence-agents-rhevm fence-agents-rsa fence-agents-rsb fence-agents-sbd fence-agents-scsi fence-agents-vmware-rest fence-agents-vmware-soap fence-agents-wti +%endif + +## Setup/build bits + +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +# Build dependencies +BuildRequires: glibc-devel +BuildRequires: gnutls-utils +BuildRequires: libxslt +BuildRequires: python pexpect python-pycurl python-suds python-requests python-boto3 +BuildRequires: net-snmp-utils +BuildRequires: autoconf automake libtool +BuildRequires: iputils + +# python-google-api-client bundle +BuildRequires: python-devel >= 2.7 +BuildRequires: python-setuptools +BuildRequires: python-six >= 1.6.1 + +%prep +%setup -q -n %{name}-%{version} +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 -F2 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 -F1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 -F1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 + +%ifarch x86_64 +# bundles +mkdir -p %{bundled_lib_dir}/aliyun +mkdir -p %{bundled_lib_dir}/gce + +# python-google-api-client bundle +tar -xzf %SOURCE1 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{googleapiclient}-%{googleapiclient_version} %{googleapiclient_dir} +cp %{googleapiclient_dir}/LICENSE %{googleapiclient}_LICENSE + +# python-oauth2client bundle +tar -xzf %SOURCE2 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{oauth2client}-%{oauth2client_version} %{oauth2client_dir} +cp %{oauth2client_dir}/LICENSE %{oauth2client}_LICENSE +cp %{oauth2client_dir}/README.md %{oauth2client}_README.md + +# python-httplib2 bundle +tar -xzf %SOURCE3 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{httplib2}-%{httplib2_version} %{httplib2_dir} + +# python-fasteners bundle +tar -xzf %SOURCE4 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{fasteners}-%{fasteners_version} %{fasteners_dir} +cp %{fasteners_dir}/LICENSE %{fasteners}_LICENSE +cp %{fasteners_dir}/README.rst %{fasteners}_README.rst + +# python-keyring bundle +unzip %SOURCE5 -d %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{keyring}-%{keyring_version} %{keyring_dir} +cp %{keyring_dir}/README.rst %{keyring}_README.rst + +# python-gflags bundle +tar -xzf %SOURCE6 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/python-%{gflags}-%{gflags_version} %{gflags_dir} +cp %{gflags_dir}/README %{gflags}_README + +# python-uritemplate bundle +tar -xzf %SOURCE7 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{uritemplate}-%{uritemplate_version} %{uritemplate_dir} +cp %{uritemplate_dir}/LICENSE %{uritemplate}_LICENSE +cp %{uritemplate_dir}/LICENSE.APACHE %{uritemplate}_LICENSE.APACHE +cp %{uritemplate_dir}/LICENSE.BSD %{uritemplate}_LICENSE.BSD +cp %{uritemplate_dir}/README.rst %{uritemplate}_README.rst + +# python-pycryptodome bundle +tar -xzf %SOURCE8 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{pycryptodome}-%{pycryptodome_version} %{pycryptodome_dir} +cp %{pycryptodome_dir}/README.rst %{pycryptodome}_README.rst +cp %{pycryptodome_dir}/LICENSE.rst %{pycryptodome}_LICENSE.rst + +# python-aliyun-sdk-core bundle +tar -xzf %SOURCE9 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{aliyunsdkcore}-%{aliyunsdkcore_version} %{aliyunsdkcore_dir} +cp %{aliyunsdkcore_dir}/README.rst %{aliyunsdkcore}_README.rst + +# python-aliyun-sdk-ecs bundle +tar -xzf %SOURCE10 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{aliyunsdkecs}-%{aliyunsdkecs_version} %{aliyunsdkecs_dir} +cp %{aliyunsdkecs_dir}/README.rst %{aliyunsdkecs}_README.rst + +# python-aliyun-sdk-vpc bundle +tar -xzf %SOURCE11 -C %{bundled_lib_dir} +mv %{bundled_lib_dir}/%{aliyunsdkvpc}-%{aliyunsdkvpc_version} %{aliyunsdkvpc_dir} +cp %{aliyunsdkvpc_dir}/README.rst %{aliyunsdkvpc}_README.rst + +# fence_gce: append bundled-directory to search path +%patch1000 -p1 + +# python-google-api-client bundle +pushd %{googleapiclient_dir} +# remove egg info +rm -rf google_api_python_client.egg-info +# remove shebang without touching timestamp +for lib in googleapiclient/*.py; do + sed '1{\@^#!/usr/bin/python@d}' $lib > $lib.new && + touch -r $lib $lib.new && + mv $lib.new $lib +done +popd + +# python-oauth2client bundle +pushd %{oauth2client_dir} +%patch1001 -p1 -b .doc +# replace python-rsa with python-cryptography +%patch1002 -p1 + +# Remove the version constraint on httplib2. From reading upstream's git log, +# it seems the only reason they require a new version is to force python3 +# support. That doesn't affect us on EPEL7, so we can loosen the constraint. +sed -i 's/httplib2>=0.9.1/httplib2/' setup.py + +# We do not have the package for google.appengine support +# This is removed because it breaks the docs build otherwise +rm -f docs/source/oauth2client.contrib.appengine.rst oauth2client/appengine.py +popd + +# python-httplib2 bundle +pushd %{httplib2_dir} +%patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 +%patch1006 -p1 +%patch1007 -p1 +popd + +# python-keyring bundle +pushd %{keyring_dir} +%patch1008 -p1 +rm -frv keyring.egg-info +# Drop redundant shebangs. +sed -i '1{\@^#!/usr/bin/env python@d}' keyring/cli.py +# Drop slags from upstream of using his own versioning system. +sed -i -e "\@use_vcs_version@s/^.*$/\tversion = \"%{version}\",/g" \ + -e "/'hgtools'/d" setup.py +popd + +# python-gflags bundle +pushd %{gflags_dir} +sed -i '1s|^#!/usr/bin/env python$|#!%{__python2}|' gflags2man.py +sed -i '/^#!\/usr\/bin\/env python$/,+1 d' gflags*.py +popd + +# python-uritemplate bundle +pushd %{uritemplate_dir} +# remove egg info +rm -rf uritemplate.egg-info +popd +%endif + +%build +./autogen.sh +%{configure} --with-agents='%{supportedagents} %{testagents}' +CFLAGS="$(echo '%{optflags}')" make %{_smp_mflags} + +%ifarch x86_64 +# python-google-api-client bundle +pushd %{googleapiclient_dir} +%{__python2} setup.py build +popd + +# python-oauth2client bundle +pushd %{oauth2client_dir} +%{__python2} setup.py build +popd + +# python-httplib2 bundle +pushd %{httplib2_dir} +%{__python2} setup.py build +popd + +# python-fasteners bundle +pushd %{fasteners_dir} +%{__python2} setup.py build +popd + +# python-keyring bundle +pushd %{keyring_dir} +%{__python2} setup.py build +popd + +# python-gflags bundle +pushd %{gflags_dir} +%{__python2} setup.py build +popd + +# python-uritemplate bundle +pushd %{uritemplate_dir} +%{__python2} setup.py build +popd + +# python-pycryptodome bundle +pushd %{pycryptodome_dir} +%{__python2} setup.py build +popd + +# python-aliyun-sdk-core bundle +pushd %{aliyunsdkcore_dir} +%{__python2} setup.py build +popd + +# python-aliyun-sdk-ecs bundle +pushd %{aliyunsdkecs_dir} +%{__python2} setup.py build +popd + +# python-aliyun-sdk-vpc bundle +pushd %{aliyunsdkvpc_dir} +%{__python2} setup.py build +popd +%endif + +%install +rm -rf %{buildroot} +make install DESTDIR=%{buildroot} + +%ifarch x86_64 +# python-google-api-client bundle +pushd %{googleapiclient_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +popd + +# python-oauth2client bundle +pushd %{oauth2client_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +popd + +# python-httplib2 bundle +pushd %{httplib2_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +popd + +# python-fasteners bundle +pushd %{fasteners_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +popd + +# python-keyring bundle +pushd %{keyring_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +popd + +# python-gflags bundle +pushd %{gflags_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +mv %{buildroot}%{_bindir}/gflags2man.py %{buildroot}%{_bindir}/gflags2man +chmod +x %{buildroot}%{_bindir}/gflags2man +popd + +# python-uritemplate bundle +pushd %{uritemplate_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/gce +popd + +# python-pycryptodome bundle +pushd %{pycryptodome_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/aliyun +popd + +# python-aliyun-sdk-core bundle +pushd %{aliyunsdkcore_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/aliyun +popd + +# python-aliyun-sdk-ecs bundle +pushd %{aliyunsdkecs_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/aliyun +popd + +# python-aliyun-sdk-vpc bundle +pushd %{aliyunsdkvpc_dir} +%{__python2} setup.py install -O1 --skip-build --root %{buildroot} --install-lib /usr/lib/fence-agents/%{bundled_lib_dir}/aliyun +popd +%endif + +## tree fix up +# remove docs +rm -rf %{buildroot}/usr/share/doc/fence-agents + +%clean +rm -rf %{buildroot} + +%description +Red Hat Fence Agents is a collection of scripts to handle remote +power management for several devices. + +%package common +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Common utilities for fence agents +Requires: python pexpect python-pycurl policycoreutils-python selinux-policy-targeted +%description common +Red Hat Fence Agents is a collection of scripts and libraries to handle remote power management for various devices. +%post common +/usr/sbin/semanage boolean -S targeted -N -m --on fenced_can_ssh +/usr/sbin/semanage boolean -S targeted -N -m --on fenced_can_network_connect +%files common +%defattr(-,root,root,-) +%doc doc/COPYING.* doc/COPYRIGHT doc/README.licence +%{_datadir}/fence +%{_datadir}/cluster +%exclude %{_datadir}/cluster/fence_mpath_check* +%exclude %{_datadir}/cluster/fence_scsi_check* +%exclude %{_sbindir}/fence_tripplite_snmp +%exclude %{_mandir}/man8/fence_tripplite_snmp.8.gz + +%package all +License: GPLv2+ and LGPLv2+ and ASL 2.0 +Group: System Environment/Base +Summary: Fence agents +Requires: %(echo "%{allfenceagents}" | sed "s/\( \|$\)/ >= %{version}-%{release}\1/g") +%ifarch i686 x86_64 +Requires: fence-virt +%endif +%ifarch ppc64le +Requires: fence-agents-lpar >= %{version}-%{release} +%endif +%ifarch s390x +Requires: fence-agents-zvm >= %{version}-%{release} +%endif +Provides: fence-agents = %{version}-%{release} +Obsoletes: fence-agents < 3.1.13 +%description all +Red Hat Fence Agents is a collection of all supported fence agents. +%files all + +%ifarch x86_64 +%package aliyun +License: GPLv2+ and LGPLv2+ and ASL 2.0 and BSD and MIT +Group: System Environment/Base +Summary: Fence agent for Alibaba Cloud (Aliyun) +Requires: fence-agents-common >= %{version}-%{release} +# python-pycryptodome bundle +Provides: bundled(python-%{pycryptodome}) = %{pycryptodome_version} +# python-aliyun-sdk-core bundle +Provides: bundled(python-aliyun-sdk-core) = %{aliyunsdkcore_version} +# python-aliyun-sdk-ecs bundle +Provides: bundled(python-aliyun-sdk-ecs) = %{aliyunsdkecs_version} +# python-aliyun-sdk-vpc bundle +Provides: bundled(python-aliyun-sdk-vpc) = %{aliyunsdkvpc_version} +Obsoletes: fence-agents +%description aliyun +The fence-agents-aliyun package contains a fence agent for Alibaba Cloud (Aliyun) instances. +%files aliyun +%defattr(-,root,root,-) +# bundled libraries +%doc pycryptodome_README.rst aliyun*_README* +%license pycryptodome_LICENSE.rst +%{_sbindir}/fence_aliyun +%{_mandir}/man8/fence_aliyun.8* +# bundled libraries +/usr/lib/fence-agents/%{bundled_lib_dir}/aliyun +%endif + +%package amt-ws +License: ASL 2.0 +Group: System Environment/Base +Summary: Fence agent for AMT (WS-Man) devices +Requires: fence-agents-common >= %{version}-%{release} +Requires: openwsman-python >= 2.6.3-1.git4391e5c.el7 +Obsoletes: fence-agents +%description amt-ws +The fence-agents-amt-ws package contains a fence agent for AMT (WS-Man) devices. +%files amt-ws +%defattr(-,root,root,-) +%{_sbindir}/fence_amt_ws +%{_mandir}/man8/fence_amt_ws.8* + +%package apc +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for APC devices +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description apc +The fence-agents-apc package contains a fence agent for APC devices that are accessed via telnet or SSH. +%files apc +%defattr(-,root,root,-) +%{_sbindir}/fence_apc +%{_mandir}/man8/fence_apc.8* + +%package apc-snmp +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for APC devices (SNMP) +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description apc-snmp +The fence-agents-apc-snmp package contains a fence agent for APC devices that are accessed via the SNMP protocol. +%files apc-snmp +%defattr(-,root,root,-) +%{_sbindir}/fence_apc_snmp +%{_mandir}/man8/fence_apc_snmp.8* + +%ifarch x86_64 +%package aws +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Amazon AWS +Requires: fence-agents-common >= %{version}-%{release} +Requires: python-boto3 +Obsoletes: fence-agents +%description aws +The fence-agents-aws package contains a fence agent for Amazon AWS instances. +%files aws +%defattr(-,root,root,-) +%{_sbindir}/fence_aws +%{_mandir}/man8/fence_aws.8* +%endif + +%ifarch x86_64 +%package azure-arm +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Azure Resource Manager +Requires: fence-agents-common >= %{version}-%{release} +Requires: python-azure-sdk >= 4.0.0 +Obsoletes: fence-agents +%description azure-arm +The fence-agents-azure-arm package contains a fence agent for Azure instances. +%files azure-arm +%defattr(-,root,root,-) +%{_sbindir}/fence_azure_arm +%{_mandir}/man8/fence_azure_arm.8* +%{_datadir}/fence/azure_fence.py +%endif + +%package bladecenter +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for IBM BladeCenter +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description bladecenter +The fence-agents-bladecenter package contains a fence agent for IBM BladeCenter devices that are accessed via telnet or SSH. +%files bladecenter +%defattr(-,root,root,-) +%{_sbindir}/fence_bladecenter +%{_mandir}/man8/fence_bladecenter.8* + +%package brocade +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for HP Brocade +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description brocade +The fence-agents-brocade package contains a fence agent for HP Brocade devices that are accessed via telnet or SSH. +%files brocade +%defattr(-,root,root,-) +%{_sbindir}/fence_brocade +%{_mandir}/man8/fence_brocade.8* + +%package cisco-mds +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Cisco MDS 9000 series +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description cisco-mds +The fence-agents-cisco-mds package contains a fence agent for Cisco MDS 9000 series devices that are accessed via the SNMP protocol. +%files cisco-mds +%defattr(-,root,root,-) +%{_sbindir}/fence_cisco_mds +%{_mandir}/man8/fence_cisco_mds.8* + +%package cisco-ucs +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Cisco UCS series +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description cisco-ucs +The fence-agents-cisco-ucs package contains a fence agent for Cisco UCS series devices that are accessed via the SNMP protocol. +%files cisco-ucs +%defattr(-,root,root,-) +%{_sbindir}/fence_cisco_ucs +%{_mandir}/man8/fence_cisco_ucs.8* + +%package compute +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Nova compute nodes +Requires: fence-agents-common >= %{version}-%{release} +Requires: python-requests +Obsoletes: fence-agents +%description compute +The fence-agents-compute package contains a fence agent for Nova compute nodes. +%files compute +%defattr(-,root,root,-) +%{_sbindir}/fence_compute +%{_sbindir}/fence_evacuate +%{_mandir}/man8/fence_compute.8* +%{_mandir}/man8/fence_evacuate.8* + +%package drac5 +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Dell DRAC 5 +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description drac5 +The fence-agents-drac5 package contains a fence agent for Dell DRAC 5 series devices that are accessed via telnet or SSH. +%files drac5 +%defattr(-,root,root,-) +%{_sbindir}/fence_drac5 +%{_mandir}/man8/fence_drac5.8* + +%package eaton-snmp +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Eaton network power switches +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description eaton-snmp +The fence-agents-eaton-snmp package contains a fence agent for Eaton network power switches that are accessed via the SNMP protocol. +%files eaton-snmp +%defattr(-,root,root,-) +%{_sbindir}/fence_eaton_snmp +%{_mandir}/man8/fence_eaton_snmp.8* + +%package emerson +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Emerson devices (SNMP) +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description emerson +The fence-agents-emerson package contains a fence agent for Emerson devices that are accessed via the SNMP protocol. +%files emerson +%defattr(-,root,root,-) +%{_sbindir}/fence_emerson +%{_mandir}/man8/fence_emerson.8* + +%package eps +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for ePowerSwitch 8M+ power switches +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description eps +The fence-agents-eps package contains a fence agent for ePowerSwitch 8M+ power switches that are accessed via the HTTP(s) protocol. +%files eps +%defattr(-,root,root,-) +%{_sbindir}/fence_eps +%{_mandir}/man8/fence_eps.8* + +%ifarch x86_64 +%package gce +License: GPLv2+ and LGPLv2+ and ASL 2.0 and BSD and MIT +Group: System Environment/Base +Summary: Fence agent for GCE (Google Cloud Engine) +Requires: fence-agents-common >= %{version}-%{release} +Requires: python-cryptography >= 1.7.2 +# python-google-api-client bundle +Provides: bundled(python-google-api-client) = %{googleapiclient_version} +# python-oauth2client bundle +Provides: bundled(python-%{oauth2client}) = %{oauth2client_version} +# python-httplib2 bundle +Provides: bundled(python-%{httplib2}) = %{httplib2_version} +# python-fasteners bundle +Provides: bundled(python-%{fasteners}) = %{fasteners_version} +# python-keyring bundle +Provides: bundled(python-%{keyring}) = %{keyring_version} +# python-uritemplate bundle +Provides: bundled(python-%{uritemplate}) = %{uritemplate_version} +Obsoletes: fence-agents +%description gce +The fence-agents-gce package contains a fence agent for GCE (Google Cloud Engine) instances. +%files gce +%defattr(-,root,root,-) +# bundled libraries +%doc %{oauth2client}_README.md %{fasteners}_README.rst %{keyring}_README.rst %{gflags}_README %{uritemplate}_README.rst +%license %{googleapiclient}_LICENSE %{oauth2client}_LICENSE %{fasteners}_LICENSE %{uritemplate}_LICENSE* +%{_sbindir}/fence_gce +%{_mandir}/man8/fence_gce.8* +# bundled libraries +/usr/lib/fence-agents/%{bundled_lib_dir}/gce +%exclude %{_bindir}/keyring +%exclude %{_bindir}/gflags2man +%endif + +%package heuristics-ping +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent used to control other fence agents based on ping-heuristics +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description heuristics-ping + +The fence-agents-heuristics-ping package contains fence agent used to control other fence agents based on ping-heuristics +%files heuristics-ping +%defattr(-,root,root,-) +%{_sbindir}/fence_heuristics_ping +%{_mandir}/man8/fence_heuristics_ping.8* + +%package hpblade +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for HP BladeSystem devices +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description hpblade +The fence-agents-hpblade package contains a fence agent for HP BladeSystem devices that are accessed via telnet or SSH. +%files hpblade +%defattr(-,root,root,-) +%{_sbindir}/fence_hpblade +%{_mandir}/man8/fence_hpblade.8* + +%package ibmblade +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for IBM BladeCenter +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description ibmblade +The fence-agents-ibmblade package contains a fence agent for IBM BladeCenter devices that are accessed via the SNMP protocol. +%files ibmblade +%defattr(-,root,root,-) +%{_sbindir}/fence_ibmblade +%{_mandir}/man8/fence_ibmblade.8* + +%package ifmib +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for devices with IF-MIB interfaces +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description ifmib +The fence-agents-ifmib package contains a fence agent for IF-MIB interfaces that are accessed via the SNMP protocol. +%files ifmib +%defattr(-,root,root,-) +%{_sbindir}/fence_ifmib +%{_mandir}/man8/fence_ifmib.8* + +%package ilo2 +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for HP iLO2 devices +Requires: fence-agents-common >= %{version}-%{release} +Requires: gnutls-utils +Obsoletes: fence-agents +%description ilo2 +The fence-agents-ilo2 package contains a fence agent for HP iLO2 devices that are accessed via the HTTP(s) protocol. +%files ilo2 +%defattr(-,root,root,-) +%{_sbindir}/fence_ilo +%{_sbindir}/fence_ilo2 +%{_mandir}/man8/fence_ilo.8* +%{_mandir}/man8/fence_ilo2.8* + +%package ilo-moonshot +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for HP iLO Moonshot devices +Requires: telnet openssh-clients +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description ilo-moonshot +The fence-agents-ilo-moonshot package contains a fence agent for HP iLO Moonshot devices that are accessed via telnet or SSH. +%files ilo-moonshot +%defattr(-,root,root,-) +%{_sbindir}/fence_ilo_moonshot +%{_mandir}/man8/fence_ilo_moonshot.8* + +%package ilo-mp +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for HP iLO MP devices +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description ilo-mp +The fence-agents-ilo-mp package contains a fence agent for HP iLO MP devices that are accessed via telnet or SSH. +%files ilo-mp +%defattr(-,root,root,-) +%{_sbindir}/fence_ilo_mp +%{_mandir}/man8/fence_ilo_mp.8* + +%package ilo-ssh +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for HP iLO devices via SSH +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description ilo-ssh +The fence-agents-ilo-ssh package contains a fence agent for HP iLO devices that are accessed via SSH. +%files ilo-ssh +%defattr(-,root,root,-) +%{_sbindir}/fence_ilo_ssh +%{_mandir}/man8/fence_ilo_ssh.8* +%{_sbindir}/fence_ilo3_ssh +%{_mandir}/man8/fence_ilo3_ssh.8* +%{_sbindir}/fence_ilo4_ssh +%{_mandir}/man8/fence_ilo4_ssh.8* +%{_sbindir}/fence_ilo5_ssh +%{_mandir}/man8/fence_ilo5_ssh.8* + +%package intelmodular +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for devices with Intel Modular interfaces +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description intelmodular +The fence-agents-intelmodular package contains a fence agent for Intel Modular interfaces that are accessed via the SNMP protocol. +%files intelmodular +%defattr(-,root,root,-) +%{_sbindir}/fence_intelmodular +%{_mandir}/man8/fence_intelmodular.8* + +%package ipdu +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for IBM iPDU network power switches +Requires: fence-agents-common >= %{version}-%{release} +Requires: net-snmp-utils +Obsoletes: fence-agents +%description ipdu +The fence-agents-ipdu package contains a fence agent for IBM iPDU network power switches that are accessed via the SNMP protocol. +%files ipdu +%defattr(-,root,root,-) +%{_sbindir}/fence_ipdu +%{_mandir}/man8/fence_ipdu.8* + +%package ipmilan +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for devices with IPMI interface +Requires: fence-agents-common >= %{version}-%{release} +Requires: /usr/bin/ipmitool +Obsoletes: fence-agents +%description ipmilan +The fence-agents-ipmilan package contains a fence agent for devices with IPMI interface. +%files ipmilan +%defattr(-,root,root,-) +%{_sbindir}/fence_ipmilan +%{_mandir}/man8/fence_ipmilan.8* +%{_sbindir}/fence_idrac +%{_mandir}/man8/fence_idrac.8* +%{_sbindir}/fence_ilo3 +%{_mandir}/man8/fence_ilo3.8* +%{_sbindir}/fence_ilo4 +%{_mandir}/man8/fence_ilo4.8* +%{_sbindir}/fence_ilo5 +%{_mandir}/man8/fence_ilo5.8* +%{_sbindir}/fence_imm +%{_mandir}/man8/fence_imm.8* + +%package mpath +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for reservations over Device Mapper Multipath +Requires: fence-agents-common >= %{version}-%{release} +Requires: device-mapper-multipath +Obsoletes: fence-agents +%description mpath +The fence-agents-mpath package contains fence agent for SCSI persistent reservation over Device Mapper Multipath +%files mpath +%defattr(-,root,root,-) +%{_sbindir}/fence_mpath +%{_datadir}/cluster/fence_mpath_check* +%{_mandir}/man8/fence_mpath.8* + +%package kdump +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for use with kdump crash recovery service +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description kdump +The fence-agents-kdump package contains a fence agent for use with kdump crash recovery service. +%files kdump +%defattr(-,root,root,-) +%{_sbindir}/fence_kdump +%{_libexecdir}/fence_kdump_send +%{_mandir}/man8/fence_kdump.8* +%{_mandir}/man8/fence_kdump_send.8* + +%ifarch ppc64le +%package lpar +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for IBM LPAR +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description lpar +The fence-agents-lpar package contains a fence agent for IBM LPAR devices that are accessed via telnet or SSH. +%files lpar +%defattr(-,root,root,-) +%{_sbindir}/fence_lpar +%{_mandir}/man8/fence_lpar.8* +%endif + +%package redfish +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Redfish +Requires: fence-agents-common >= %{version}-%{release} +Requires: python-requests +Obsoletes: fence-agents +%description redfish +The fence-agents-redfish package contains a fence agent for Redfish +%files redfish +%defattr(-,root,root,-) +%{_sbindir}/fence_redfish +%{_mandir}/man8/fence_redfish.8* + +%package rhevm +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for RHEV-M +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description rhevm +The fence-agents-rhevm package contains a fence agent for RHEV-M via REST API +%files rhevm +%defattr(-,root,root,-) +%{_sbindir}/fence_rhevm +%{_mandir}/man8/fence_rhevm.8* + +%package rsa +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for IBM RSA II +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description rsa +The fence-agents-rsa package contains a fence agent for IBM RSA II devices that are accessed via telnet or SSH. +%files rsa +%defattr(-,root,root,-) +%{_sbindir}/fence_rsa +%{_mandir}/man8/fence_rsa.8* + +%package rsb +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Fujitsu RSB +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description rsb +The fence-agents-rsb package contains a fence agent for Fujitsu RSB devices that are accessed via telnet or SSH. +%files rsb +%defattr(-,root,root,-) +%{_sbindir}/fence_rsb +%{_mandir}/man8/fence_rsb.8* + +%if 0 +%package sanbox2 +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for QLogic SANBox2 FC switches +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet +Obsoletes: fence-agents +%description sanbox2 +The fence-agents-sanbox2 package contains a fence agent for QLogic SANBox2 switches that are accessed via telnet. +%files sanbox2 +%defattr(-,root,root,-) +%{_sbindir}/fence_sanbox2 +%{_mandir}/man8/fence_sanbox2.8* +%endif + +%package sbd +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for SBD (storage-based death) +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description sbd +The fence-agents-sbd package contains fence agent for SBD (storage-based death) +%files sbd +%defattr(-,root,root,-) +%{_sbindir}/fence_sbd +%{_mandir}/man8/fence_sbd.8* + +%package scsi +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for SCSI persistent reservations +Requires: sg3_utils fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description scsi +The fence-agents-scsi package contains fence agent for SCSI persistent reservations +%files scsi +%defattr(-,root,root,-) +%{_sbindir}/fence_scsi +%{_datadir}/cluster/fence_scsi_check.pl +%{_datadir}/cluster/fence_scsi_check +%{_datadir}/cluster/fence_scsi_check_hardreboot +%{_mandir}/man8/fence_scsi.8* + +%package virsh +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for virtual machines based on libvirt +Requires: fence-agents-common >= %{version}-%{release} +Requires: openssh-clients /usr/bin/virsh +Obsoletes: fence-agents +%description virsh +The fence-agents-virsh package contains a fence agent for virtual machines that are accessed via SSH. +%files virsh +%defattr(-,root,root,-) +%{_sbindir}/fence_virsh +%{_mandir}/man8/fence_virsh.8* + +%package vmware-rest +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for VMWare with REST API +Requires: fence-agents-common >= %{version}-%{release} +Obsoletes: fence-agents +%description vmware-rest +The fence-agents-vmware-rest package contains a fence agent for VMWare with REST API +%files vmware-rest +%defattr(-,root,root,-) +%{_sbindir}/fence_vmware_rest +%{_mandir}/man8/fence_vmware_rest.8* + +%package vmware-soap +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for VMWare with SOAP API v4.1+ +Requires: fence-agents-common >= %{version}-%{release} +Requires: python-suds python-requests +Obsoletes: fence-agents +%description vmware-soap +The fence-agents-vmware-soap package contains a fence agent for VMWare with SOAP API v4.1+ +%files vmware-soap +%defattr(-,root,root,-) +%{_sbindir}/fence_vmware_soap +%{_mandir}/man8/fence_vmware_soap.8* + +%package wti +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for WTI Network power switches +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description wti +The fence-agents-wti package contains a fence agent for WTI network power switches that are accessed via telnet or SSH. +%files wti +%defattr(-,root,root,-) +%{_sbindir}/fence_wti +%{_mandir}/man8/fence_wti.8* + +%ifarch s390x +%package zvm +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for z/VM hypervisors +Requires: fence-agents-common >= %{version}-%{release} +Requires: telnet openssh-clients +Obsoletes: fence-agents +%description zvm +The fence-agents-zvm package contains a fence agent for z/VM hypervisors +%files zvm +%defattr(-,root,root,-) +%{_sbindir}/fence_zvmip +%{_mandir}/man8/fence_zvmip.8* +%exclude %{_sbindir}/fence_zvm +%exclude %{_mandir}/man8/fence_zvm.8* +%endif + +%changelog +* Fri Sep 20 2019 Oyvind Albrigtsen - 4.2.1-28 +- fence_mpath: add plug parameter support to be able to use pcmk_host_map + Resolves: rhbz#1753229 + +* Thu Sep 12 2019 Oyvind Albrigtsen - 4.2.1-26 +- fence_mpath: fix watchdog reboot not triggered when multipath + disconnected + Resolves: rhbz#1751702 + +* Wed Aug 21 2019 Oyvind Albrigtsen - 4.2.1-25 +- fence_ilo4_ssh/fence_ilo5_ssh: add monitor timeout warning + Resolves: rhbz#1734812 + +* Thu Jun 13 2019 Oyvind Albrigtsen - 4.2.1-24 +- fence_scsi watchdog: fix failing on first try when using retry + Resolves: rhbz#1653700 + +* Tue May 28 2019 Oyvind Albrigtsen - 4.2.1-22 +- fence_redfish: add header for full Redfish spec compliance + Resolves: rhbz#1713665 + +* Tue May 21 2019 Oyvind Albrigtsen - 4.2.1-21 +- fence_rhevm: fix encoding issues + Resolves: rhbz#1670460 + +* Mon May 20 2019 Oyvind Albrigtsen - 4.2.1-20 +- fence_mpath: fix watchdog hardreboot + Resolves: rhbz#1709879 + +* Tue May 14 2019 Oyvind Albrigtsen - 4.2.1-18 +- fence_rhevm: add RHEV v4 API support and auto-detection + Resolves: rhbz#1402862 +- fence_azure_arm: use skip_shutdown feature + Resolves: rhbz#1700544 + +* Thu Feb 21 2019 Oyvind Albrigtsen - 4.2.1-16 +- fence_redfish: use ipport parameter + Resolves: rhbz#1677023 + +* Tue Feb 5 2019 Oyvind Albrigtsen - 4.2.1-15 +- fence_dump: add validate-all action + Resolves: rhbz#1608550 + +* Fri Jan 18 2019 Oyvind Albrigtsen - 4.2.1-14 +- fence_redfish: new fence agent + Resolves: rhbz#1464933, rhbz#1631492 + +* Tue Jan 8 2019 Oyvind Albrigtsen - 4.2.1-13 +- fence_scsi: add watchdog retry support + Resolves: rhbz#1653700 + +* Thu Nov 29 2018 Oyvind Albrigtsen - 4.2.1-12 +- fence_scsi: fix incorrect SCSI-key when node ID is 10 or higher + Resolves: rhbz#1645170 +- fence_hpblade: fix log_expect syntax + Resolves: rhbz#1650526 +- fence_vmware_soap: cleanup when receiving SIGTERM + Resolves: rhbz#1350908 + +* Tue Sep 4 2018 Oyvind Albrigtsen - 4.2.1-11 +- fence_cisco_ucs: fix missing encode for POSTFIELDS + Resolves: rhbz#1625164 + +* Thu Aug 30 2018 Oyvind Albrigtsen - 4.2.1-10 +- fence_aliyun: show instances names in list-action + Resolves: rhbz#1622229 + +* Mon Aug 20 2018 Oyvind Albrigtsen - 4.2.1-9 +- Fix --version + Resolves: rhbz#1236395 + +* Tue Aug 14 2018 Oyvind Albrigtsen - 4.2.1-8 +- fence_aliyun: add logging + Resolves: rhbz#1568742 +- fence_gce: add stackdriver-logging support, improve logging and + set default mode to cycle + Resolves: rhbz#1568753 + +* Tue Jul 24 2018 Oyvind Albrigtsen - 4.2.1-5 +- fence_aliyun: new fence agent + Resolves: rhbz#1568742 + +* Mon Jul 16 2018 Oyvind Albrigtsen - 4.2.1-3 +- fence_evacuate: fix evacuable tag mix issue + Resolves: rhbz#1549699 + +* Thu Jun 28 2018 Oyvind Albrigtsen - 4.2.1-1 +- rebase to v4.2.1 + Resolves: rhbz#1236395 +- fence_mpath: add watchdog support + Resolves: rhbz#1504202 + +* Mon Jun 25 2018 Oyvind Albrigtsen - 4.0.11-90 +- fence_gce: new fence agent + Resolves: rhbz#1568753 +- fence_rhevm: dont require --ssl parameter when using --ssl-insecure + Resolves: rhbz#1544093 +- fence_mpath: fix preemptive abort + Resolves: rhbz#1556857 +- fence-agents-all: dont show manpage-tags in metadata + Resolves: rhbz#1553908 +- fence_scsi: dont write duplicates to .dev-file + Resolves: rhbz#1575973 +- fence_impilan: add iLO5-support + Resolves: rhbz#1579391 + +* Thu Apr 12 2018 Oyvind Albrigtsen - 4.0.11-88 +- fence_azure_arm: fix subscriptionId from metadata + Resolves: rhbz#1566154 + +* Tue Apr 10 2018 Oyvind Albrigtsen - 4.0.11-87 +- fence_azure_arm: add network-fencing + Resolves: rhbz#1553904 +- fence_compute/fence_evacuate: fix parameters + Resolves: rhbz#1559977 + +* Wed Feb 7 2018 Oyvind Albrigtsen - 4.0.11-86 +- fence-agents-all: remove fence-agents-aws and fence-agents-azure-arm + dependencies + Resolves: rhbz#1476009 + +* Tue Feb 6 2018 Oyvind Albrigtsen - 4.0.11-85 +- fence_aws: add python-boto3 dependency + Resolves: rhbz#1540700 + +* Mon Jan 22 2018 Oyvind Albrigtsen - 4.0.11-84 +- fence_azure_arm: new fence agent + Resolves: rhbz#1476009 + +* Thu Jan 11 2018 Oyvind Albrigtsen - 4.0.11-83 +- fence_compute/fence_evacuate: add support for keystone v3 authentication + Resolves: rhbz#1533170 +- fence_ilo3: default to onoff + Resolves: rhbz#1519370 + +* Tue Nov 28 2017 Oyvind Albrigtsen - 4.0.11-82 +- fence_vmware_rest: new fence agent + Resolves: rhbz#1396050 + +* Tue Nov 7 2017 Oyvind Albrigtsen - 4.0.11-81 +- common: add selinux-policy-targeted dependency + Resolves: rhbz#1509327 + +* Fri Nov 3 2017 Oyvind Albrigtsen - 4.0.11-80 +- fence_ipmilan: fix default method inconsistency (help/man page) + Resolves: rhbz#1465436 + +* Wed Nov 1 2017 Oyvind Albrigtsen - 4.0.11-78 +- fence_heuristics_ping: new fence agent + Resolves: rhbz#1476401 + +* Thu Oct 26 2017 Oyvind Albrigtsen - 4.0.11-77 +- fence_ilo_ssh: fix "hard reset" + Resolves: rhbz#1490475 + +* Wed Oct 25 2017 Oyvind Albrigtsen - 4.0.11-76 +- fence_ipmilan: add support for hexadecimal key authentication + Resolves: rhbz#1449183 + +* Tue Oct 24 2017 Oyvind Albrigtsen - 4.0.11-75 +- fence_aws: new fence agent + Resolves: rhbz#1451776 + +* Fri Oct 6 2017 Oyvind Albrigtsen - 4.0.11-72 +- fence_amt_ws: new fence agent + Resolves: rhbz#1296201 + +* Fri Sep 29 2017 Oyvind Albrigtsen - 4.0.11-70 +- fence-agents-all: require agents to be the same version + Resolves: rhbz#1484128 + +* Fri Sep 29 2017 Oyvind Albrigtsen - 4.0.11-69 +- fence_scsi: add FIPS support + Resolves: rhbz#1455383 + +* Thu Sep 28 2017 Oyvind Albrigtsen - 4.0.11-68 +- fence_compute/fence_scsi: fix issue with some parameters + Resolves: rhbz#1473860 +- fence_compute/fence_evacuate: changes to support Instance HA on OSP12 + Resolves: rhbz#1496390 +- fence-agents-common: remove fence_scsi_check-files that should only be in + the scsi subpackage + Resolves: rhbz#1484128 + +* Wed Aug 2 2017 Oyvind Albrigtsen - 4.0.11-67 +- Remove "list" when not supported + Resolves: rhbz#1461854 + +* Fri Jun 16 2017 Marek Grac - 4.0.11-66 +- Set SELinux booleans even when SELinux is disabled + Resolves: rhbz#1457887 + +* Thu Jun 15 2017 Marek Grac - 4.0.11-65 +- Set SELinux booleans even when SELinux is disabled + Resolves: rhbz#1457887 + +* Wed Jun 7 2017 Oyvind Albrigtsen - 4.0.11-64 +- fence_vmware_soap: fix for self-signed certificates + Resolves: rhbz#1459199 + +* Tue May 30 2017 Marek Grac - 4.0.11-63 +- Add dependencies on policycoreutils + Resolves: rhbz#1427986 + +* Wed May 17 2017 Marek Grac - 4.0.11-62 +- Set SELinux booleans required for fence agent integration with cluster + Resolves: rhbz#1427986 + +* Thu May 4 2017 Oyvind Albrigtsen - 4.0.11-61 +- fence_ipmilan: add target (ipmilan -t ) support + Resolves: rhbz#1377389 + +* Mon Apr 3 2017 Oyvind Albrigtsen - 4.0.11-60 +- fence_compute: fix project_id changed to project_name in Nova API + Resolves: rhbz#1426693 + +* Thu Mar 23 2017 Oyvind Albrigtsen - 4.0.11-58 +- CI: dont test paths in metadata + Resolves: rhbz#1377972 + +* Wed Mar 22 2017 Marek Grac - 4.0.11-57 +- Set SELinux booleans required for fence agent integration with cluster + Resolves: rhbz#1427986 +- Add consistency of parameters between STDIN and command-line + Resolves: rhbz#1403028 + +* Tue Mar 21 2017 Oyvind Albrigtsen - 4.0.11-56 +- fencing: add validate-all action + Resolves: rhbz#1433948 +- fence_rhevm: add "--disable-http-filter" to be able to explicitly + use oVirt API version 3 + Resolves: rhbz#1422499 + +* Wed Mar 01 2017 Marek Grac - 4.0.11-54 +- fence_lpar: Fix monitor action on IVM systems + Resolves: rhbz#1376481 + +* Tue Feb 21 2017 Oyvind Albrigtsen - 4.0.11-53 +- fence_compute: Improved FQDN and Nova handling + Resolves: rhbz#1387590 + +* Tue Feb 14 2017 Oyvind Albrigtsen - 4.0.11-52 +- fence_compute: fix ConnectionError + Resolves: rhbz#1384073 +- fence_lpar: add IVM support and improve error handling + Resolves: rhbz#1376481 +- fence_vmware_soap: suppress warning for --ssl-insecure + Resolves: rhbz#1393962 +- Add support for "s" for seconds for delay, *_timeout, *_wait parameters + Resolves: rhbz#1377928 +- fence-agents-zvm: add to fence-agents-all dependencies for s390x + Resolves: rhbz#1255700 +- Build for ppc64le + Resolves: rhbz#1402566 + +* Mon Jan 23 2017 Marek Grac +- fence_cisco_ucs: Change commands send to UCS + Resolves: rhbz#1410881 + +* Wed Jan 11 2017 Oyvind Albrigtsen - 4.0.11-50 +- fence_sbd: new fence agent + Resolves: rhbz#1337236 + +* Wed Nov 23 2016 Marek Grac - 4.0.11-49 +- fencing: Fix 'monitor' action for devices with --port-as-ip + Resolves: rhbz#1390915 + +* Wed Aug 31 2016 Oyvind Albrigtsen - 4.0.11-47 +- fence_rhevm: fix issues on RHEV 4 + Resolves: rhbz#1287059 + +* Thu Aug 25 2016 Oyvind Albrigtsen - 4.0.11-46 + Resolves: rhbz#1298430 + +* Thu Aug 25 2016 Marek Grac - 4.0.11-45 +- fence_cisco_ucs: Change method for obtaining status + Resolves: rhbz#1298430 + +* Wed Aug 17 2016 Oyvind Albrigtsen - 4.0.11-44 +- fence_mpath: update info to say unique key per node instead of per + node/device + Resolves: rhbz#1280151 + +* Tue Jul 12 2016 Marek Grac - 4.0.11-43 +- change in spec file + Resolves: rhbz#1353221 + +* Thu Jul 7 2016 Oyvind Albrigtsen - 4.0.11-42 +- fence-agents-common: add dependency on python-pycurl + Resolves: rhbz#1353221 + +* Wed Jul 6 2016 Oyvind Albrigtsen - 4.0.11-41 +- fence_compute: perform real status operation in record-only mode + Resolves: rhbz#1287311 + +* Mon Jul 4 2016 Oyvind Albrigtsen - 4.0.11-40 +- fence_compute: improved FQDN handling + Resolves: rhbz#1334162 + +* Wed Jun 22 2016 Oyvind Albrigtsen - 4.0.11-39 +- fence_apc: fix "Connection timed out" issue + Resolves: rhbz#1342584 + +* Wed Jun 15 2016 Oyvind Albrigtsen - 4.0.11-38 +- fence_compute: advertise as fabric device + Resolves: rhbz#1287301 + +* Tue Jun 14 2016 Oyvind Albrigtsen - 4.0.11-37 +- fence_compute: add taggable instance support + Resolves: rhbz#1285523 + +* Tue May 31 2016 Oyvind Albrigtsen - 4.0.11-34 +- fence_virsh: add --missing-as-off + Resolves: rhbz#1254821 +- fence_ipmilan: fix power_wait regression + Resolves: rhbz#1275250 +- fence_ipmilan: add diag action + Resolves: rhbz#1286045 +- fence_ipmilan: warn that cycle method can report success before node + is powered off + Resolves: rhbz#1271780 +- fence_scsi: fix persistentl typo in short desc + Resolves: rhbz#1280139 +- fence_scsi: remove /dev/dm-X reference + Resolves: rhbz#1280151 +- fence_rhevm: add Filter header + Resolves: rhbz#1287059 +- fence_compute: fix to locate all instances to be evacuated + Resolves: rhbz#1313561 + +* Mon Feb 22 2016 Marek Grac - 4.0.11-33 +- fence_cisco_ucs: Obtain status from different attribute + Resolves: rhbz#1298430 + +* Tue Feb 09 2016 Marek Grac - 4.0.11-32 +- fence_cisco_ucs: Obtain status from different endpoint + Resolves: rhbz#1298430 + +* Mon Feb 01 2016 Marek Grac - 4.0.11-31 +- fence_cisco_ucs: Obtain status from different endpoint + Resolves: rhbz#1298430 + +* Wed Jan 20 2016 Marek Grac - 4.0.11-30 +- fence_compute: Replace with current implementation + Resolves: rhbz#1283084 + +* Wed Dec 16 2015 Marek Grac - 4.0.11-28 +- fence_scsi: Add fence_scsi_check_hardreboot + Resolves: rhbz#bz1265426 + +* Mon Oct 26 2015 Marek Grac - 4.0.11-27 +- fence_brocade: Fix return status in get_power_status + Resolves: rhbz#1274431 + +* Thu Sep 17 2015 Marek Grac - 4.0.11-26 +- fence_ipmilan: Fix -i attribute + Resolves: rhbz#1257137 + +* Mon Sep 14 2015 Marek Grac - 4.0.11-25 +- fence_apc: Support for v6.x + Resolves: rhbz#1259319 + +* Wed Sep 02 2015 Marek Grac - 4.0.11-24 +- fence_ipmilan: Add removed attributes -i & timeout + Resolves: rhbz#1257137 +- fence_ipmilan: Do not print password in verbose mode + Resolves: rhbz#1241648 +- fence_ilo: Negotiation of TLS1.0 is more automatic + Resolves: rhbz#1256908 + +* Mon Aug 17 2015 Marek Grac - 4.0.11-23 +- fence_scsi: Fix watchdog script broken by more strict 'monitor' + Resolves: 1243485 + +* Wed Aug 12 2015 Marek Grac - 4.0.11-21 +- fence_mpath: Fix unfencing after non-cluster reboot + Resolves: 1102727 +- manual pages now describe 'list-status' properly + +bz1102727-3-fence_mpath.patch bz1250586-2-list_status.patch +* Tue Aug 11 2015 Marek Grac - 4.0.11-20 +- fencing: Fix place where --plug + --port-as-ip are tested + Resolves: rhbz#1214522 + +* Mon Aug 10 2015 Marek Grac - 4.0.11-19 +- fencing: do not fail when state is None + Resolves: rhbz#1251491 + +* Wed Aug 05 2015 Marek Grac - 4.0.11-18 +- fence_rsa: Fix login issue + Resolves: rhbz#1185329 +- fencing: support for list-status + Resolves: rhbz#1250586 +- fencing: Fix support for --port-as-ip + Resolves: rhbz#1214522 + +* Thu Jul 16 2015 Marek Grac - 4.0.11-17 +- fence_scsi: Improve monitoring and add option to force ON + Resolves: rhbz#1243485 + +* Mon Jun 29 2015 Marek Grac - 4.0.11-16 +- fence_compute: Agent cleanup + Resolves: rhbz#1214359 +- fence_hpblade: Add support for HP Integrity Superdome + Resolves: rhbz#1216997 +- fence_zvmip: Add --missing-as-off and change monitor/status actions + Resolves: rhbz#1188750 +- fence_mpath: new fence agent + Resolves: rhbz#1102727 +- fencing: Option --port-as-ip + Resolves: rhbz#1214522 + +* Mon Jun 22 2015 Marek Grac - 4.0.11-15 +- fence_zvmip: Connection timeout issues + Resolves: rhbz#1188750 + +* Thu Jun 18 2015 Marek Grac - 4.0.11-14 +- fence_rhevm: Add authentication via cookies + Resolves: rhbz#1145769 +- fence_ilo_moonshot: New fence agent + Resolves: rhbz#1152917 +- fence_emerson: New fence agent + Resolves: rhbz#1171732 +- fence_rsa: New fence agent + Resolves: rhbz#1185329 + +* Wed Jun 17 2015 Marek Grac - 4.0.11-13 +- fence_scsi: Add monitor operation + Resolves: rhbz#1213571 +- fence_scsi: Force unfence if any of paths is off + Resolves: rhbz#1214919 +- fence_cisco_ucs: Fix https:// prefix with --ssl-(in)secure + Resolves: rhbz#1165591 +- fence_kdump: Add monitor operation + Resolves: rhbz#1196068 +- fence2rng: Fix problem with quotes + Resolves: rhbz#1207982 + +* Mon Jun 08 2015 Marek Grac - 4.0.11-12 +- New fence agent fence_compute + Resolves: rhbz#1214359 + +* Wed Mar 25 2015 Marek Grac - 4.0.11-11 +- fence_ipmilan: Unset default cipher + Resolves: rhbz#1203877 +- fence_ilo2: Add --tls1.0 + Resolves: rhbz#1199970 +- update scripts so 'make check' is working again + +* Mon Jan 05 2015 Marek Grac - 4.0.11-10 +- fence_zvmip: Add fence_zvmip ported to fencing library + Resolves: rhbz#1173178 + +* Mon Dec 01 2014 Marek Grac - 4.0.11-9 +- fence_ilo_ssh: Fix EOL issue, syslog problem and add fence_ilo_[34]_ssh symlink + Resolves: rhbz#1121122 + +* Wed Nov 12 2014 Marek Grac - 4.0.11-8 +- fence_zvm: Add 'monitor' support for fence_zvmip + Resolves: rhbz#1140921 + +* Mon Nov 10 2014 Marek Grac - 4.0.11-7 +- HTTPS connection do not validate certificate (introduced with rebase) + Resolves: rhbz#1162092 + +* Thu Oct 16 2014 Marek Grac - 4.0.11-6 +- fence_cisco_ucs and fence_vmware_soap should logout even in case of failure + Resolves: rhbz#1111599 +- fence_vmware_soap: Fix issue with import of fail_usage + Resolves: rhbz#1153059 + +* Thu Oct 02 2014 Marek Grac - 4.0.11-5 +- fence_wti: Fix problem with EOL introduced by rebase + Resolves: rhbz#1148762 +- fence_rsb: Fix issue with new firmware + Resolves: rhbz#1111597 + +* Sat Sep 20 2014 Fabio M. Di Nitto - 4.0.11-4 +- add initial support for IBM z/VM + Resolves: rhbz#1140921 + +* Mon Sep 15 2014 Marek Grac - 4.0.11-3 +- temporary removes fence-agents-amt because amtterm is missing + +* Wed Sep 03 2014 Marek Grac - 4.0.11-2 +- add a fence agents for AMT and iLO-ssh + Resolves: rhbz#1121122 rhbz#1107439 + +* Wed Sep 03 2014 Marek Grac - 4.0.11-1 +- rebase of fence agents + Resolves: rhbz#1120682 +- INFO: fence_scsi_check.pl is now a python script + +* Wed Mar 19 2014 Marek Grac - 4.0.2-21 +- fencing: Add --ssl-secure and --ssl-insecure for fence_vmware_soap + Resolves: rhbz#1072564 + +* Fri Mar 07 2014 Marek Grac - 4.0.2-20 +- fencing: Add --ssl-secure and --ssl-insecure for fence_vmware_soap + Resolves: rhbz#1072564 + +* Wed Mar 05 2014 Marek Grac - 4.0.2-19 +- fencing: Add --ssl-secure and --ssl-insecure + Resolves: rhbz#1072564 + +* Thu Feb 27 2014 Fabio M. Di Nitto - 4.0.2-18 +- fence_vmware_soap: fix short/long option parsing traceback + Resolves: rhbz#1018780 + +* Wed Feb 26 2014 Fabio M. Di Nitto - 4.0.2-17 +- Fix fence-agents-* Requires on proper fence-agents-common and silence + suds error + Resolves: rhbz#1018780 + +* Thu Feb 20 2014 Fabio M. Di Nitto - 4.0.2-16 +- Allow ssl connections to disable TLS negotiation with "notls" option. + Resolves: rhbz#990539 + +* Wed Feb 19 2014 Marek Grac - 4.0.2-15 +- Fix dependencies issues + +* Mon Feb 17 2014 Marek Grac - 4.0.2-14 +- fence_vmware_soap: Fix unexpected exception + Resolves: rhbz#1018780 +- nss_wrapper was replaced by gnutls-cli + Resolves: rhbz#990539 + +* Wed Jan 29 2014 Marek Grac - 4.0.2-13 +- fencing: Do not use public key if identity file is not defined + Resolves: rhbz#1048843 +- fence_vmware_soap: Add support for --delay option + Resolves: rhbz#1057299 +- fence_wti: Add support for named groups (also for firmware 1.43) + Resolves: rhbz#1022536 + +* Fri Jan 24 2014 Daniel Mach - 4.0.2-12 +- Mass rebuild 2014-01-24 + +* Thu Jan 23 2014 Marek Grac - 4.0.2-11 +- fencing: Ensure validity of XML metadata using Relax NG + Resolves: rhbz#1022529 + +* Thu Jan 23 2014 Marek Grac - 4.0.2-10 +- fix default action for fabric fencing agents + Resolves: rhbz#1021392 +- modify key generation in fence_scsi to support pacemaker/corosync cluster + Resolves: rhbz#994466 + +* Fri Dec 27 2013 Daniel Mach - 4.0.2-9 +- Mass rebuild 2013-12-27 + +* Wed Nov 20 2013 Marek Grac - 4.0.2-8 +- fence-agents-all now includes fence-virt which is not available everywhere + Resolves: rhbz#1028940 + +* Tue Nov 12 2013 Marek Grac - 4.0.2-7 +- fence-agents-all now includes fence-virt + Resolves: rhbz#1028940 + +* Mon Nov 04 2013 Marek Grac - 4.0.2-6 +- fencing: Ensure validity of XML metadata using Relax NG + Resolves: rhbz#1022529 +- fencing: Fix invalid use of options[".."] + Resolves: rhbz#1022533 +- fence_brocade: Add fence agent + Resolves: rhbz#1021392 + +* Mon Nov 04 2013 Marek Grac - 4.0.2-5 +- fence_vmware_soap: Report if user privileges are not enough for given operation + Resolves: rhbz#1018780 +- fence_wti: Add support for named groups + Resolves: rhbz#1022536 +- fence_rsb: Update regular expression to match newer firmware version + Resolves: rhbz#1022538 + +* Mon Nov 04 2013 Marek Grac - 4.0.2-4 +- fence_vmware_soap: Disable cache in SUDS library to resolve SELinux problems + Resolves: rhbz#1022528 +- fencing: Add information that operation 'unfence' should be run automatically after start of the cluster + Resolves: rhbz#1012994 +- Aligned to upstream 4.0.4 + +* Mon Sep 02 2013 Marek Grac - 4.0.2-3 +- fence_bladecenter: Fix telnet login failure +- fence_brocade: Rewrite to fencing library +- fencing_snmp: Fix 'KeyError --a' +- fence_scsi: Fix XML metadata +- fence_scsi: Add a documentation of "delay" +- fence_ilo2: Unable to login when password contains " + +* Tue Jul 30 2013 Marek Grac - 4.0.2-2 +- new upstream release + +* Tue Jul 09 2013 Marek Grac - 4.0.1-1 +- new upstream release + +* Mon Jun 24 2013 Marek Grac - 4.0.0-5 +- fence-agents-all should provide fence-agent for clean update path + +* Wed Apr 03 2013 Marek Grac - 4.0.0-4 +- minor changes in spec file + +* Thu Mar 21 2013 Marek Grac - 4.0.0-3 +- minor changes in spec file + +* Mon Mar 18 2013 Marek Grac - 4.0.0-2 +- minor changes in spec file + +* Mon Mar 11 2013 Marek Grac - 4.0.0-1 +- new upstream release +- introducing subpackages + +