diff --git a/SOURCES/bz1654058-fence_vmware_rest-1-add-filter-parameter.patch b/SOURCES/bz1654058-fence_vmware_rest-1-add-filter-parameter.patch new file mode 100644 index 0000000..33ef692 --- /dev/null +++ b/SOURCES/bz1654058-fence_vmware_rest-1-add-filter-parameter.patch @@ -0,0 +1,133 @@ +From ab193580dcdd810b7bef69cc04cebef315f4781d Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 23 Apr 2020 15:55:11 +0200 +Subject: [PATCH] fence_vmware_rest: add filter parameter + +--- + agents/vmware_rest/fence_vmware_rest.py | 24 ++++++++++++++++++++--- + tests/data/metadata/fence_vmware_rest.xml | 9 ++++++++- + 2 files changed, 29 insertions(+), 4 deletions(-) + +--- a/agents/vmware_rest/fence_vmware_rest.py 2020-04-24 14:28:04.674694199 +0200 ++++ b/agents/vmware_rest/fence_vmware_rest.py 2020-04-24 13:02:25.001890003 +0200 +@@ -8,10 +8,14 @@ + from fencing import * + from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS + +-state = {"POWERED_ON": "on", 'POWERED_OFF': "off"} ++state = {"POWERED_ON": "on", 'POWERED_OFF': "off", 'SUSPENDED': "off"} + + def get_power_status(conn, options): +- res = send_command(conn, "vcenter/vm?filter.names={}".format(options["--plug"]))["value"] ++ try: ++ res = send_command(conn, "vcenter/vm?filter.names={}".format(options["--plug"]))["value"] ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) ++ fail(EC_STATUS) + + if len(res) == 0: + fail(EC_STATUS) +@@ -28,12 +32,23 @@ + "off" : "stop" + }[options["--action"]] + +- send_command(conn, "vcenter/vm/{}/power/{}".format(options["id"], action), "POST") ++ try: ++ send_command(conn, "vcenter/vm/{}/power/{}".format(options["id"], action), "POST") ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) ++ fail(EC_STATUS) + + def get_list(conn, options): + outlets = {} + +- res = send_command(conn, "vcenter/vm") ++ try: ++ command = "vcenter/vm" ++ if "--filter" in options: ++ command = command + "?" + options["--filter"] ++ res = send_command(conn, command) ++ except: ++ logging.debug("Failed: {}".format(e)) ++ fail(EC_STATUS) + + for r in res["value"]: + outlets[r["name"]] = ("", state[r["power_state"]]) +@@ -87,7 +102,10 @@ + return conn + + def disconnect(conn): +- send_command(conn, "com/vmware/cis/session", "DELETE") ++ try: ++ send_command(conn, "com/vmware/cis/session", "DELETE") ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) + conn.close() + + def send_command(conn, command, method="GET"): +@@ -142,6 +160,16 @@ + "required" : "0", + "shortdesc" : "The path part of the API URL", + "order" : 2} ++ all_opt["filter"] = { ++ "getopt" : ":", ++ "longopt" : "filter", ++ "help" : "--filter=[filter] Filter to only return relevant VMs" ++ " (e.g. \"filter.names=node1&filter.names=node2\").", ++ "default" : "", ++ "required" : "0", ++ "shortdesc" : "Filter to only return relevant VMs. It can be used to avoid " ++ "the agent failing when more than 1000 VMs should be returned.", ++ "order" : 2} + + + def main(): +@@ -154,6 +182,7 @@ + "notls", + "web", + "port", ++ "filter", + ] + + atexit.register(atexit_handler) +@@ -166,8 +195,12 @@ + + docs = {} + docs["shortdesc"] = "Fence agent for VMware REST API" +- docs["longdesc"] = "fence_vmware_rest is an I/O Fencing agent which can be \ +-used with VMware API to fence virtual machines." ++ docs["longdesc"] = """fence_vmware_rest is an I/O Fencing agent which can be \ ++used with VMware API to fence virtual machines. ++ ++NOTE: If there's more than 1000 VMs there is a filter parameter to work around \ ++the API limit. See https://code.vmware.com/apis/62/vcenter-management#/VM%20/get_vcenter_vm \ ++for full list of filters.""" + docs["vendorurl"] = "https://www.vmware.com" + show_docs(options, docs) + +diff --git a/tests/data/metadata/fence_vmware_rest.xml b/tests/data/metadata/fence_vmware_rest.xml +index 5b497a6a..d60c8775 100644 +--- a/tests/data/metadata/fence_vmware_rest.xml ++++ b/tests/data/metadata/fence_vmware_rest.xml +@@ -1,6 +1,8 @@ + + +-fence_vmware_rest is an I/O Fencing agent which can be used with VMware API to fence virtual machines. ++fence_vmware_rest is an I/O Fencing agent which can be used with VMware API to fence virtual machines. ++ ++NOTE: If there's more than 1000 VMs there is a filter parameter to work around the API limit. See https://code.vmware.com/apis/62/vcenter-management#/VM%20/get_vcenter_vm for full list of filters. + https://www.vmware.com + + +@@ -87,6 +89,11 @@ + + The path part of the API URL + ++ ++ ++ ++ Filter to only return relevant VMs. It can be used to avoid the agent failing when more than 1000 VMs should be returned. ++ + + + diff --git a/SOURCES/bz1654058-fence_vmware_rest-2-fix-1000-VM-monitor-error.patch b/SOURCES/bz1654058-fence_vmware_rest-2-fix-1000-VM-monitor-error.patch new file mode 100644 index 0000000..0f83fa7 --- /dev/null +++ b/SOURCES/bz1654058-fence_vmware_rest-2-fix-1000-VM-monitor-error.patch @@ -0,0 +1,76 @@ +From 0296bc8512e37b8b935bc342b6493ed4fa8aa001 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 14 May 2020 13:17:04 +0200 +Subject: [PATCH 1/2] fence_vmware_rest: fix exception and remove default value + for filter parameter (which was shown in the manpage) + +--- + agents/vmware_rest/fence_vmware_rest.py | 3 +-- + tests/data/metadata/fence_vmware_rest.xml | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index 6daff121..2635ae07 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -46,7 +46,7 @@ def get_list(conn, options): + if "--filter" in options: + command = command + "?" + options["--filter"] + res = send_command(conn, command) +- except: ++ except Exception as e: + logging.debug("Failed: {}".format(e)) + fail(EC_STATUS) + +@@ -165,7 +165,6 @@ def define_new_opts(): + "longopt" : "filter", + "help" : "--filter=[filter] Filter to only return relevant VMs" + " (e.g. \"filter.names=node1&filter.names=node2\").", +- "default" : "", + "required" : "0", + "shortdesc" : "Filter to only return relevant VMs. It can be used to avoid " + "the agent failing when more than 1000 VMs should be returned.", +diff --git a/tests/data/metadata/fence_vmware_rest.xml b/tests/data/metadata/fence_vmware_rest.xml +index d60c8775..830b6a21 100644 +--- a/tests/data/metadata/fence_vmware_rest.xml ++++ b/tests/data/metadata/fence_vmware_rest.xml +@@ -91,7 +91,7 @@ NOTE: If there's more than 1000 VMs there is a filter parameter to work around t + + + +- ++ + Filter to only return relevant VMs. It can be used to avoid the agent failing when more than 1000 VMs should be returned. + + + +From 7420cf9f11568be7239956bed4631cdbaa6fb87c Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 14 May 2020 14:17:03 +0200 +Subject: [PATCH 2/2] fence_vmware_rest: dont fail when receiving more than + 1000 VM error during monitor-action + +--- + agents/vmware_rest/fence_vmware_rest.py | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index 2635ae07..675de246 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -48,7 +48,14 @@ def get_list(conn, options): + res = send_command(conn, command) + except Exception as e: + logging.debug("Failed: {}".format(e)) +- fail(EC_STATUS) ++ if str(e).startswith("400"): ++ if options.get("--original-action") == "monitor": ++ return outlets ++ else: ++ logging.error("More than 1000 VMs returned. Use --filter parameter to limit which VMs to list.") ++ fail(EC_STATUS) ++ else: ++ fail(EC_STATUS) + + for r in res["value"]: + outlets[r["name"]] = ("", state[r["power_state"]]) diff --git a/SOURCES/bz1673468-fence_aws-improve-parameter-logic.patch b/SOURCES/bz1673468-fence_aws-improve-parameter-logic.patch new file mode 100644 index 0000000..5b01675 --- /dev/null +++ b/SOURCES/bz1673468-fence_aws-improve-parameter-logic.patch @@ -0,0 +1,48 @@ +From 1c2f791b6b2be13bcceaa096df52654164b1f6cb Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 5 Mar 2020 14:10:29 +0100 +Subject: [PATCH] fence_aws: improve connect parameter logic, so region can be + specified as parameter, while using role or keys from ~/.aws/config + +--- + agents/aws/fence_aws.py | 27 +++++++++------------------ + 1 file changed, 9 insertions(+), 18 deletions(-) + +diff --git a/agents/aws/fence_aws.py b/agents/aws/fence_aws.py +index 74321e8e..4a4d9de2 100644 +--- a/agents/aws/fence_aws.py ++++ b/agents/aws/fence_aws.py +@@ -99,24 +99,15 @@ + + 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"] +- try: +- conn = boto3.resource('ec2', region_name=region, +- aws_access_key_id=access_key, +- aws_secret_access_key=secret_key) +- except: +- fail_usage("Failed: Unable to connect to AWS. Check your configuration.") +- else: +- # If setup with "aws configure" or manually in +- # ~/.aws/credentials +- try: +- conn = boto3.resource('ec2') +- except: +- # If any of region/access/secret are missing +- fail_usage("Failed: Unable to connect to AWS. Check your configuration.") ++ region = options.get("--region") ++ access_key = options.get("--access-key") ++ secret_key = options.get("--secret-key") ++ try: ++ conn = boto3.resource('ec2', region_name=region, ++ aws_access_key_id=access_key, ++ aws_secret_access_key=secret_key) ++ except: ++ fail_usage("Failed: Unable to connect to AWS. Check your configuration.") + + # Operate the fencing device + result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) diff --git a/SOURCES/bz1760203-fence_compute-fence_evacuate-1-fix-region_name-type.patch b/SOURCES/bz1760203-fence_compute-fence_evacuate-1-fix-region_name-type.patch new file mode 100644 index 0000000..2d8ba1c --- /dev/null +++ b/SOURCES/bz1760203-fence_compute-fence_evacuate-1-fix-region_name-type.patch @@ -0,0 +1,66 @@ +From 32d2aa2cea22bb38fc3eeded1f6682daad097908 Mon Sep 17 00:00:00 2001 +From: Gauvain Pocentek +Date: Tue, 13 Aug 2019 20:11:21 +0200 +Subject: [PATCH] Fix argument parsing for region_name + +The region_name attribute for fence_compute and fence_evacuate is not a boolean +and should expect a string argument. +--- + agents/compute/fence_compute.py | 2 +- + agents/evacuate/fence_evacuate.py | 2 +- + tests/data/metadata/fence_compute.xml | 2 +- + tests/data/metadata/fence_evacuate.xml | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/agents/compute/fence_compute.py b/agents/compute/fence_compute.py +index 0e6c8044..a94bdc46 100644 +--- a/agents/compute/fence_compute.py ++++ b/agents/compute/fence_compute.py +@@ -381,7 +381,7 @@ def define_new_opts(): + "order": 1, + } + all_opt["region_name"] = { +- "getopt" : "", ++ "getopt" : ":", + "longopt" : "region-name", + "help" : "--region-name=[region] Region Name", + "required" : "0", +diff --git a/agents/evacuate/fence_evacuate.py b/agents/evacuate/fence_evacuate.py +index 2b9af273..76e78b87 100644 +--- a/agents/evacuate/fence_evacuate.py ++++ b/agents/evacuate/fence_evacuate.py +@@ -318,7 +318,7 @@ def define_new_opts(): + "order": 1, + } + all_opt["region_name"] = { +- "getopt" : "", ++ "getopt" : ":", + "longopt" : "region-name", + "help" : "--region-name=[region] Region Name", + "required" : "0", +diff --git a/tests/data/metadata/fence_compute.xml b/tests/data/metadata/fence_compute.xml +index 1dcbfc54..abc276ca 100644 +--- a/tests/data/metadata/fence_compute.xml ++++ b/tests/data/metadata/fence_compute.xml +@@ -55,7 +55,7 @@ + + + +- ++ + Region Name + + +diff --git a/tests/data/metadata/fence_evacuate.xml b/tests/data/metadata/fence_evacuate.xml +index 4f1f6a58..7decb05c 100644 +--- a/tests/data/metadata/fence_evacuate.xml ++++ b/tests/data/metadata/fence_evacuate.xml +@@ -55,7 +55,7 @@ + + + +- ++ + Region Name + + diff --git a/SOURCES/bz1760203-fence_compute-fence_evacuate-2-fix-project-shortopt.patch b/SOURCES/bz1760203-fence_compute-fence_evacuate-2-fix-project-shortopt.patch new file mode 100644 index 0000000..1458956 --- /dev/null +++ b/SOURCES/bz1760203-fence_compute-fence_evacuate-2-fix-project-shortopt.patch @@ -0,0 +1,77 @@ +From 708d0a8e4e45d4f4a6bee67f0a9ebc0ff573e1ff Mon Sep 17 00:00:00 2001 +From: Kumabuchi Kenji +Date: Fri, 25 Oct 2019 16:34:40 +0900 +Subject: [PATCH] fix shortopt in fence-compute / fence_evacuate help messages + +Signed-off-by: Kumabuchi Kenji +--- + agents/compute/fence_compute.py | 2 +- + agents/evacuate/fence_evacuate.py | 2 +- + tests/data/metadata/fence_compute.xml | 4 ++-- + tests/data/metadata/fence_evacuate.xml | 4 ++-- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/agents/compute/fence_compute.py b/agents/compute/fence_compute.py +index c08a9dbe..d0e012e6 100644 +--- a/agents/compute/fence_compute.py ++++ b/agents/compute/fence_compute.py +@@ -365,7 +365,7 @@ def define_new_opts(): + all_opt["project-domain"] = { + "getopt" : "P:", + "longopt" : "project-domain", +- "help" : "-d, --project-domain=[name] Keystone v3 Project Domain", ++ "help" : "-P, --project-domain=[name] Keystone v3 Project Domain", + "required" : "0", + "shortdesc" : "Keystone v3 Project Domain", + "default" : "Default", +diff --git a/agents/evacuate/fence_evacuate.py b/agents/evacuate/fence_evacuate.py +index 76e78b87..60bb130e 100644 +--- a/agents/evacuate/fence_evacuate.py ++++ b/agents/evacuate/fence_evacuate.py +@@ -302,7 +302,7 @@ def define_new_opts(): + all_opt["project-domain"] = { + "getopt" : "P:", + "longopt" : "project-domain", +- "help" : "-d, --project-domain=[name] Keystone v3 Project Domain", ++ "help" : "-P, --project-domain=[name] Keystone v3 Project Domain", + "required" : "0", + "shortdesc" : "Keystone v3 Project Domain", + "default" : "Default", +diff --git a/tests/data/metadata/fence_compute.xml b/tests/data/metadata/fence_compute.xml +index abc276ca..99d56af0 100644 +--- a/tests/data/metadata/fence_compute.xml ++++ b/tests/data/metadata/fence_compute.xml +@@ -74,12 +74,12 @@ + Allow Insecure TLS Requests + + +- ++ + + Keystone v3 Project Domain + + +- ++ + + Keystone v3 Project Domain + +diff --git a/tests/data/metadata/fence_evacuate.xml b/tests/data/metadata/fence_evacuate.xml +index 7decb05c..8c720b80 100644 +--- a/tests/data/metadata/fence_evacuate.xml ++++ b/tests/data/metadata/fence_evacuate.xml +@@ -74,12 +74,12 @@ + Allow Insecure TLS Requests + + +- ++ + + Keystone v3 Project Domain + + +- ++ + + Keystone v3 Project Domain + diff --git a/SOURCES/bz1763675-fence_rhevm-add-cookie-support.patch b/SOURCES/bz1763675-fence_rhevm-add-cookie-support.patch new file mode 100644 index 0000000..d4f7be9 --- /dev/null +++ b/SOURCES/bz1763675-fence_rhevm-add-cookie-support.patch @@ -0,0 +1,109 @@ +From b885e0f65af626154096a49554e9765e18bfbbd9 Mon Sep 17 00:00:00 2001 +From: Frank Toth +Date: Wed, 16 Oct 2019 13:58:50 +0800 +Subject: [PATCH 1/3] Added cookie file management to properly reuse session + and do not create new one every time. + +--- + agents/rhevm/fence_rhevm.py | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py +index 9e4650cd..defa35e6 100644 +--- a/agents/rhevm/fence_rhevm.py ++++ b/agents/rhevm/fence_rhevm.py +@@ -117,7 +117,12 @@ def send_command(opt, command, method="GET"): + conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC) + conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"]) + if "--use-cookies" in opt: +- conn.setopt(pycurl.COOKIEFILE, "") ++ if "--cookie-file" in opt: ++ cookie_file = opt["--cookie-file"] ++ else: ++ cookie_file = "/tmp/fence_rhevm_" + opt["--ip"] + "_" + opt["--username"] + "_cookie.dat" ++ conn.setopt(pycurl.COOKIEFILE, cookie_file) ++ conn.setopt(pycurl.COOKIEJAR, cookie_file) + + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) + if "--ssl" in opt or "--ssl-secure" in opt: +@@ -166,6 +171,14 @@ def define_new_opts(): + "required" : "0", + "shortdesc" : "Reuse cookies for authentication", + "order" : 1} ++ all_opt["cookie_file"] = { ++ "getopt" : ":", ++ "longopt" : "cookie-file", ++ "help" : "--cookie-file Path to cookie file for authentication\n" ++ "\t\t\t\t (Default: /tmp/fence_rhevm_ip_username_cookie.dat)", ++ "required" : "0", ++ "shortdesc" : "Path to cookie file for authentication", ++ "order" : 2} + all_opt["api_version"] = { + "getopt" : ":", + "longopt" : "api-version", + +From 874344acbfee5f774b320e384a46e1ce953a34ce Mon Sep 17 00:00:00 2001 +From: Frank Toth +Date: Wed, 16 Oct 2019 23:41:50 +0800 +Subject: [PATCH 2/3] Added cookie_file to device_opt array. Use + tempfile.gettempdir() to get the TMP dir instead of hardcoded /tmp + +--- + agents/rhevm/fence_rhevm.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py +index defa35e6..25aecbe5 100644 +--- a/agents/rhevm/fence_rhevm.py ++++ b/agents/rhevm/fence_rhevm.py +@@ -4,6 +4,7 @@ + import pycurl, io + import logging + import atexit ++import tempfile + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * + from fencing import fail, EC_FETCH_VM_UUID, run_delay +@@ -120,7 +121,7 @@ def send_command(opt, command, method="GET"): + if "--cookie-file" in opt: + cookie_file = opt["--cookie-file"] + else: +- cookie_file = "/tmp/fence_rhevm_" + opt["--ip"] + "_" + opt["--username"] + "_cookie.dat" ++ cookie_file = tempfile.gettempdir() + "/fence_rhevm_" + opt["--ip"] + "_" + opt["--username"] + "_cookie.dat" + conn.setopt(pycurl.COOKIEFILE, cookie_file) + conn.setopt(pycurl.COOKIEJAR, cookie_file) + +@@ -215,6 +216,7 @@ def main(): + "web", + "port", + "use_cookies", ++ "cookie_file", + "api_version", + "api_path", + "disable_http_filter", + +From 196513cfc0edfd28f483a00b4adfa230b666a47d Mon Sep 17 00:00:00 2001 +From: Frank Toth +Date: Fri, 18 Oct 2019 05:16:18 +0200 +Subject: [PATCH 3/3] After 'make xml-upload' + +--- + tests/data/metadata/fence_rhevm.xml | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tests/data/metadata/fence_rhevm.xml b/tests/data/metadata/fence_rhevm.xml +index c56cf64b..2b6b02b2 100644 +--- a/tests/data/metadata/fence_rhevm.xml ++++ b/tests/data/metadata/fence_rhevm.xml +@@ -103,6 +103,11 @@ + + Version of RHEV API (default: auto) + ++ ++ ++ ++ Path to cookie file for authentication ++ + + + The path part of the API URL diff --git a/SOURCES/bz1769784-fencing-improve-stdin-quote-parsing.patch b/SOURCES/bz1769784-fencing-improve-stdin-quote-parsing.patch new file mode 100644 index 0000000..adf0754 --- /dev/null +++ b/SOURCES/bz1769784-fencing-improve-stdin-quote-parsing.patch @@ -0,0 +1,23 @@ +From 82626dbdb12519e95a5df70ae6ae21bc17112f43 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 13 Feb 2019 13:28:25 +0100 +Subject: [PATCH] fencing: improve stdin parse function + +- Remove quotes around stdin parameters for consistency with CLI +parameters and to be able to quote number and time parameters +--- + lib/fencing.py.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index 287cd01f..8cd0a813 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -1389,6 +1389,7 @@ def _parse_input_stdin(avail_opt): + + (name, value) = (line + "=").split("=", 1) + value = value[:-1] ++ value = re.sub("^\"(.*)\"$", "\\1", value) + + if name.replace("-", "_") in mapping_longopt_names: + name = mapping_longopt_names[name.replace("-", "_")] diff --git a/SOURCES/bz1793738-fence_vmware_rest-1-fix-encoding.patch b/SOURCES/bz1793738-fence_vmware_rest-1-fix-encoding.patch new file mode 100644 index 0000000..c215ab1 --- /dev/null +++ b/SOURCES/bz1793738-fence_vmware_rest-1-fix-encoding.patch @@ -0,0 +1,23 @@ +From 06cba4aa30322f410b0b2fec5785be39d0953433 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 12 Feb 2020 14:21:54 +0100 +Subject: [PATCH] fence_vmware_rest: fix encoding to avoid issues with UTF-8 + encoded comments + +--- + agents/vmware_rest/fence_vmware_rest.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index cd99b4ac..d07bc10d 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -127,7 +127,7 @@ def send_command(conn, command, method="GET"): + raise Exception(e[1]) + + rc = conn.getinfo(pycurl.HTTP_CODE) +- result = web_buffer.getvalue().decode() ++ result = web_buffer.getvalue().decode("UTF-8") + + web_buffer.close() + diff --git a/SOURCES/bz1793738-fence_vmware_rest-2-support-utf-8-vm-names.patch b/SOURCES/bz1793738-fence_vmware_rest-2-support-utf-8-vm-names.patch new file mode 100644 index 0000000..ce113af --- /dev/null +++ b/SOURCES/bz1793738-fence_vmware_rest-2-support-utf-8-vm-names.patch @@ -0,0 +1,38 @@ +From 80aea3942aaca881349230a32b5dcc06c57de98a Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 19 May 2020 15:10:16 +0200 +Subject: [PATCH] fence_vmware_rest: support UTF-8 VM names + +--- + agents/vmware_rest/fence_vmware_rest.py | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index 675de246..a038a096 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -8,11 +8,14 @@ + from fencing import * + from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS + ++if sys.version_info[0] > 2: import urllib.parse as urllib ++else: import urllib ++ + state = {"POWERED_ON": "on", 'POWERED_OFF': "off", 'SUSPENDED': "off"} + + def get_power_status(conn, options): + try: +- res = send_command(conn, "vcenter/vm?filter.names={}".format(options["--plug"]))["value"] ++ res = send_command(conn, "vcenter/vm?filter.names={}".format(urllib.quote(options["--plug"])))["value"] + except Exception as e: + logging.debug("Failed: {}".format(e)) + fail(EC_STATUS) +@@ -58,7 +61,7 @@ def get_list(conn, options): + fail(EC_STATUS) + + for r in res["value"]: +- outlets[r["name"]] = ("", state[r["power_state"]]) ++ outlets[r["name"].encode("UTF-8")] = ("", state[r["power_state"]]) + + return outlets + diff --git a/SOURCES/bz1816205-fence_aws-fix-race-condition.patch b/SOURCES/bz1816205-fence_aws-fix-race-condition.patch new file mode 100644 index 0000000..7ddfae8 --- /dev/null +++ b/SOURCES/bz1816205-fence_aws-fix-race-condition.patch @@ -0,0 +1,202 @@ +--- a/agents/aws/fence_aws.py 2020-03-26 10:31:03.653171381 +0100 ++++ b/agents/aws/fence_aws.py 2020-03-24 16:21:16.942155519 +0100 +@@ -3,14 +3,33 @@ + import sys, re + import logging + import atexit ++import requests + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +-from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay ++from fencing import fail, fail_usage, run_delay, EC_STATUS, SyslogLibHandler + + import boto3 + from botocore.exceptions import ClientError, EndpointConnectionError, NoRegionError + ++logger = logging.getLogger("fence_aws") ++logger.propagate = False ++logger.setLevel(logging.INFO) ++logger.addHandler(SyslogLibHandler()) ++logging.getLogger('botocore.vendored').propagate = False ++ ++def get_instance_id(): ++ try: ++ r = requests.get('http://169.254.169.254/latest/meta-data/instance-id') ++ return r.content.decode("UTF-8") ++ except HTTPError as http_err: ++ logger.error('HTTP error occurred while trying to access EC2 metadata server: %s', http_err) ++ except Exception as err: ++ logger.error('A fatal error occurred while trying to access EC2 metadata server: %s', err) ++ return None ++ ++ + def get_nodes_list(conn, options): ++ logger.info("Starting monitor operation") + result = {} + try: + for instance in conn.instances.all(): +@@ -19,13 +38,17 @@ + fail_usage("Failed: Incorrect Access Key or Secret Key.") + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") +- ++ except Exception as e: ++ logger.error("Failed to get node list: %s", e) ++ logger.debug("Monitor operation OK: %s",result) + return result + + def get_power_status(conn, options): ++ logger.debug("Starting status operation") + try: + instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [options["--plug"]]}]) + state = list(instance)[0].state["Name"] ++ logger.info("Status operation for EC2 instance %s returned state: %s",options["--plug"],state.upper()) + if state == "running": + return "on" + elif state == "stopped": +@@ -38,20 +61,49 @@ + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") + except IndexError: ++ fail(EC_STATUS) ++ except Exception as e: ++ logging.error("Failed to get power status: %s", e) ++ fail(EC_STATUS) ++ ++def get_self_power_status(conn, instance_id): ++ try: ++ instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [instance_id]}]) ++ state = list(instance)[0].state["Name"] ++ if state == "running": ++ logging.debug("Captured my (%s) state and it %s - returning OK - Proceeding with fencing",instance_id,state.upper()) ++ return "ok" ++ else: ++ logging.debug("Captured my (%s) state it is %s - returning Alert - Unable to fence other nodes",instance_id,state.upper()) ++ return "alert" ++ ++ except ClientError: ++ fail_usage("Failed: Incorrect Access Key or Secret Key.") ++ except EndpointConnectionError: ++ fail_usage("Failed: Incorrect Region.") ++ except IndexError: + return "fail" + + def set_power_status(conn, options): +- if (options["--action"]=="off"): +- conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True) +- elif (options["--action"]=="on"): +- conn.instances.filter(InstanceIds=[options["--plug"]]).start() +- ++ my_instance = get_instance_id() ++ try: ++ if (options["--action"]=="off"): ++ if (get_self_power_status(conn,my_instance) == "ok"): ++ conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True) ++ logger.info("Called StopInstance API call for %s", options["--plug"]) ++ else: ++ logger.info("Skipping fencing as instance is not in running status") ++ elif (options["--action"]=="on"): ++ conn.instances.filter(InstanceIds=[options["--plug"]]).start() ++ except Exception as e: ++ logger.error("Failed to power %s %s: %s", \ ++ options["--action"], options["--plug"], e) + + def define_new_opts(): + all_opt["region"] = { + "getopt" : "r:", + "longopt" : "region", +- "help" : "-r, --region=[name] Region, e.g. us-east-1", ++ "help" : "-r, --region=[region] Region, e.g. us-east-1", + "shortdesc" : "Region.", + "required" : "0", + "order" : 2 +@@ -59,7 +111,7 @@ + all_opt["access_key"] = { + "getopt" : "a:", + "longopt" : "access-key", +- "help" : "-a, --access-key=[name] Access Key", ++ "help" : "-a, --access-key=[key] Access Key", + "shortdesc" : "Access Key.", + "required" : "0", + "order" : 3 +@@ -67,23 +119,32 @@ + all_opt["secret_key"] = { + "getopt" : "s:", + "longopt" : "secret-key", +- "help" : "-s, --secret-key=[name] Secret Key", ++ "help" : "-s, --secret-key=[key] Secret Key", + "shortdesc" : "Secret Key.", + "required" : "0", + "order" : 4 + } ++ all_opt["boto3_debug"] = { ++ "getopt" : "b:", ++ "longopt" : "boto3_debug", ++ "help" : "-b, --boto3_debug=[option] Boto3 and Botocore library debug logging", ++ "shortdesc": "Boto Lib debug", ++ "required": "0", ++ "order": 5 ++ } + + # Main agent method + def main(): + conn = None + +- device_opt = ["port", "no_password", "region", "access_key", "secret_key"] ++ device_opt = ["port", "no_password", "region", "access_key", "secret_key", "boto3_debug"] + + atexit.register(atexit_handler) + + define_new_opts() + + all_opt["power_timeout"]["default"] = "60" ++ all_opt["boto3_debug"]["default"] = "off" + + options = check_input(device_opt, process_input(device_opt)) + +@@ -99,6 +160,28 @@ + + run_delay(options) + ++ if options.get("--verbose") is not None: ++ lh = logging.FileHandler('/var/log/fence_aws_debug.log') ++ logger.addHandler(lh) ++ lhf = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ++ lh.setFormatter(lhf) ++ logger.setLevel(logging.DEBUG) ++ ++ if options["--boto3_debug"] != "on": ++ boto3.set_stream_logger('boto3',logging.INFO) ++ boto3.set_stream_logger('botocore',logging.INFO) ++ logging.getLogger('botocore').propagate = False ++ logging.getLogger('boto3').propagate = False ++ else: ++ log_format = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') ++ logging.getLogger('botocore').propagate = False ++ logging.getLogger('boto3').propagate = False ++ fdh = logging.FileHandler('/var/log/fence_aws_boto3.log') ++ fdh.setFormatter(log_format) ++ logging.getLogger('boto3').addHandler(fdh) ++ logging.getLogger('botocore').addHandler(fdh) ++ logging.debug("Boto debug level is %s and sending debug info to /var/log/fence_aws_boto3.log", options["--boto3_debug"]) ++ + region = options.get("--region") + access_key = options.get("--access-key") + secret_key = options.get("--secret-key") +@@ -106,12 +189,12 @@ + conn = boto3.resource('ec2', region_name=region, + aws_access_key_id=access_key, + aws_secret_access_key=secret_key) +- except: +- fail_usage("Failed: Unable to connect to AWS. Check your configuration.") ++ except Exception as e: ++ fail_usage("Failed: Unable to connect to AWS: " + str(e)) + + # 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() ++ main() +\ No newline at end of file diff --git a/SOURCES/bz1827561-fence_vmware_rest-improve-exception-handling.patch b/SOURCES/bz1827561-fence_vmware_rest-improve-exception-handling.patch new file mode 100644 index 0000000..1c61b35 --- /dev/null +++ b/SOURCES/bz1827561-fence_vmware_rest-improve-exception-handling.patch @@ -0,0 +1,44 @@ +From 020f48a309bcad659dc493960d2b39e8e1243085 Mon Sep 17 00:00:00 2001 +From: Thomas Abraham +Date: Mon, 20 Apr 2020 20:28:43 -0400 +Subject: [PATCH] fence_vmware_rest: improve exception handling in + send_command() + +If an exception occurs, simply raise it. pycurl's perform() method can +generate a pycurl.error object, which does not support indexing and +attempting to do so will generate an exception that hides the original +exception. + +Also, don't assume that the remote will return a JSON formatted response. +If it doesn't, a exception will occur accessing result which will not +raise the intended exception. +--- + agents/vmware_rest/fence_vmware_rest.py | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index d07bc10d..1505ffe6 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -124,7 +124,7 @@ def send_command(conn, command, method="GET"): + try: + conn.perform() + except Exception as e: +- raise Exception(e[1]) ++ raise(e) + + rc = conn.getinfo(pycurl.HTTP_CODE) + result = web_buffer.getvalue().decode("UTF-8") +@@ -135,7 +135,11 @@ def send_command(conn, command, method="GET"): + result = json.loads(result) + + if rc != 200: +- raise Exception("{}: {}".format(rc, result["value"]["messages"][0]["default_message"])) ++ if len(result) > 0: ++ raise Exception("{}: {}".format(rc, ++ result["value"]["messages"][0]["default_message"])) ++ else: ++ raise Exception("Remote returned {} for request to {}".format(rc, url)) + + logging.debug("url: {}".format(url)) + logging.debug("method: {}".format(method)) diff --git a/SOURCES/bz1832289-fence_aws-improve-catch-connectionerror.patch b/SOURCES/bz1832289-fence_aws-improve-catch-connectionerror.patch new file mode 100644 index 0000000..674586e --- /dev/null +++ b/SOURCES/bz1832289-fence_aws-improve-catch-connectionerror.patch @@ -0,0 +1,95 @@ +From be20615859c518b3161b08ee63f5da5213eba91d Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 25 May 2020 14:03:53 +0200 +Subject: [PATCH 1/2] fence_aws: catch ConnectionError and suppress traceback + for caught exceptions + +--- + agents/aws/fence_aws.py | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/agents/aws/fence_aws.py b/agents/aws/fence_aws.py +index 17c2fedb..191f5de1 100644 +--- a/agents/aws/fence_aws.py ++++ b/agents/aws/fence_aws.py +@@ -9,14 +9,14 @@ + from fencing import fail, fail_usage, run_delay, EC_STATUS, SyslogLibHandler + + import boto3 +-from botocore.exceptions import ClientError, EndpointConnectionError, NoRegionError ++from botocore.exceptions import ConnectionError, ClientError, EndpointConnectionError, NoRegionError + + logger = logging.getLogger("fence_aws") + logger.propagate = False + logger.setLevel(logging.INFO) + logger.addHandler(SyslogLibHandler()) + logging.getLogger('botocore.vendored').propagate = False +- ++ + def get_instance_id(): + try: + r = requests.get('http://169.254.169.254/latest/meta-data/instance-id') +@@ -38,6 +38,8 @@ def get_nodes_list(conn, options): + fail_usage("Failed: Incorrect Access Key or Secret Key.") + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") ++ except ConnectionError as e: ++ fail_usage("Failed: Unable to connect to AWS: " + str(e)) + except Exception as e: + logger.error("Failed to get node list: %s", e) + logger.debug("Monitor operation OK: %s",result) +@@ -169,7 +171,7 @@ def main(): + + if options["--boto3_debug"] != "on": + boto3.set_stream_logger('boto3',logging.INFO) +- boto3.set_stream_logger('botocore',logging.INFO) ++ boto3.set_stream_logger('botocore',logging.CRITICAL) + logging.getLogger('botocore').propagate = False + logging.getLogger('boto3').propagate = False + else: +@@ -197,4 +199,4 @@ def main(): + sys.exit(result) + + if __name__ == "__main__": +- main() +\ No newline at end of file ++ main() + +From 50772024cffa60d05938d328bbd5cffd930f6b42 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 25 May 2020 14:07:14 +0200 +Subject: [PATCH 2/2] fence_aws: improve boto3_debug boolean handling + +--- + agents/aws/fence_aws.py | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/agents/aws/fence_aws.py b/agents/aws/fence_aws.py +index 191f5de1..483a2991 100644 +--- a/agents/aws/fence_aws.py ++++ b/agents/aws/fence_aws.py +@@ -132,6 +132,7 @@ def define_new_opts(): + "help" : "-b, --boto3_debug=[option] Boto3 and Botocore library debug logging", + "shortdesc": "Boto Lib debug", + "required": "0", ++ "default": "False", + "order": 5 + } + +@@ -146,7 +147,6 @@ def main(): + define_new_opts() + + all_opt["power_timeout"]["default"] = "60" +- all_opt["boto3_debug"]["default"] = "off" + + options = check_input(device_opt, process_input(device_opt)) + +@@ -169,7 +169,7 @@ def main(): + lh.setFormatter(lhf) + logger.setLevel(logging.DEBUG) + +- if options["--boto3_debug"] != "on": ++ if options["--boto3_debug"].lower() not in ["1", "yes", "on", "true"]: + boto3.set_stream_logger('boto3',logging.INFO) + boto3.set_stream_logger('botocore',logging.CRITICAL) + logging.getLogger('botocore').propagate = False diff --git a/SOURCES/bz1834193-1-fence_aws-improve-parameter-logic.patch b/SOURCES/bz1834193-1-fence_aws-improve-parameter-logic.patch deleted file mode 100644 index 5b01675..0000000 --- a/SOURCES/bz1834193-1-fence_aws-improve-parameter-logic.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 1c2f791b6b2be13bcceaa096df52654164b1f6cb Mon Sep 17 00:00:00 2001 -From: Oyvind Albrigtsen -Date: Thu, 5 Mar 2020 14:10:29 +0100 -Subject: [PATCH] fence_aws: improve connect parameter logic, so region can be - specified as parameter, while using role or keys from ~/.aws/config - ---- - agents/aws/fence_aws.py | 27 +++++++++------------------ - 1 file changed, 9 insertions(+), 18 deletions(-) - -diff --git a/agents/aws/fence_aws.py b/agents/aws/fence_aws.py -index 74321e8e..4a4d9de2 100644 ---- a/agents/aws/fence_aws.py -+++ b/agents/aws/fence_aws.py -@@ -99,24 +99,15 @@ - - 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"] -- try: -- conn = boto3.resource('ec2', region_name=region, -- aws_access_key_id=access_key, -- aws_secret_access_key=secret_key) -- except: -- fail_usage("Failed: Unable to connect to AWS. Check your configuration.") -- else: -- # If setup with "aws configure" or manually in -- # ~/.aws/credentials -- try: -- conn = boto3.resource('ec2') -- except: -- # If any of region/access/secret are missing -- fail_usage("Failed: Unable to connect to AWS. Check your configuration.") -+ region = options.get("--region") -+ access_key = options.get("--access-key") -+ secret_key = options.get("--secret-key") -+ try: -+ conn = boto3.resource('ec2', region_name=region, -+ aws_access_key_id=access_key, -+ aws_secret_access_key=secret_key) -+ except: -+ fail_usage("Failed: Unable to connect to AWS. Check your configuration.") - - # Operate the fencing device - result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) diff --git a/SOURCES/bz1834193-2-fence_aws-fix-race-condition.patch b/SOURCES/bz1834193-2-fence_aws-fix-race-condition.patch deleted file mode 100644 index 7ddfae8..0000000 --- a/SOURCES/bz1834193-2-fence_aws-fix-race-condition.patch +++ /dev/null @@ -1,202 +0,0 @@ ---- a/agents/aws/fence_aws.py 2020-03-26 10:31:03.653171381 +0100 -+++ b/agents/aws/fence_aws.py 2020-03-24 16:21:16.942155519 +0100 -@@ -3,14 +3,33 @@ - import sys, re - import logging - import atexit -+import requests - sys.path.append("@FENCEAGENTSLIBDIR@") - from fencing import * --from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay -+from fencing import fail, fail_usage, run_delay, EC_STATUS, SyslogLibHandler - - import boto3 - from botocore.exceptions import ClientError, EndpointConnectionError, NoRegionError - -+logger = logging.getLogger("fence_aws") -+logger.propagate = False -+logger.setLevel(logging.INFO) -+logger.addHandler(SyslogLibHandler()) -+logging.getLogger('botocore.vendored').propagate = False -+ -+def get_instance_id(): -+ try: -+ r = requests.get('http://169.254.169.254/latest/meta-data/instance-id') -+ return r.content.decode("UTF-8") -+ except HTTPError as http_err: -+ logger.error('HTTP error occurred while trying to access EC2 metadata server: %s', http_err) -+ except Exception as err: -+ logger.error('A fatal error occurred while trying to access EC2 metadata server: %s', err) -+ return None -+ -+ - def get_nodes_list(conn, options): -+ logger.info("Starting monitor operation") - result = {} - try: - for instance in conn.instances.all(): -@@ -19,13 +38,17 @@ - fail_usage("Failed: Incorrect Access Key or Secret Key.") - except EndpointConnectionError: - fail_usage("Failed: Incorrect Region.") -- -+ except Exception as e: -+ logger.error("Failed to get node list: %s", e) -+ logger.debug("Monitor operation OK: %s",result) - return result - - def get_power_status(conn, options): -+ logger.debug("Starting status operation") - try: - instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [options["--plug"]]}]) - state = list(instance)[0].state["Name"] -+ logger.info("Status operation for EC2 instance %s returned state: %s",options["--plug"],state.upper()) - if state == "running": - return "on" - elif state == "stopped": -@@ -38,20 +61,49 @@ - except EndpointConnectionError: - fail_usage("Failed: Incorrect Region.") - except IndexError: -+ fail(EC_STATUS) -+ except Exception as e: -+ logging.error("Failed to get power status: %s", e) -+ fail(EC_STATUS) -+ -+def get_self_power_status(conn, instance_id): -+ try: -+ instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [instance_id]}]) -+ state = list(instance)[0].state["Name"] -+ if state == "running": -+ logging.debug("Captured my (%s) state and it %s - returning OK - Proceeding with fencing",instance_id,state.upper()) -+ return "ok" -+ else: -+ logging.debug("Captured my (%s) state it is %s - returning Alert - Unable to fence other nodes",instance_id,state.upper()) -+ return "alert" -+ -+ except ClientError: -+ fail_usage("Failed: Incorrect Access Key or Secret Key.") -+ except EndpointConnectionError: -+ fail_usage("Failed: Incorrect Region.") -+ except IndexError: - return "fail" - - def set_power_status(conn, options): -- if (options["--action"]=="off"): -- conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True) -- elif (options["--action"]=="on"): -- conn.instances.filter(InstanceIds=[options["--plug"]]).start() -- -+ my_instance = get_instance_id() -+ try: -+ if (options["--action"]=="off"): -+ if (get_self_power_status(conn,my_instance) == "ok"): -+ conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True) -+ logger.info("Called StopInstance API call for %s", options["--plug"]) -+ else: -+ logger.info("Skipping fencing as instance is not in running status") -+ elif (options["--action"]=="on"): -+ conn.instances.filter(InstanceIds=[options["--plug"]]).start() -+ except Exception as e: -+ logger.error("Failed to power %s %s: %s", \ -+ options["--action"], options["--plug"], e) - - def define_new_opts(): - all_opt["region"] = { - "getopt" : "r:", - "longopt" : "region", -- "help" : "-r, --region=[name] Region, e.g. us-east-1", -+ "help" : "-r, --region=[region] Region, e.g. us-east-1", - "shortdesc" : "Region.", - "required" : "0", - "order" : 2 -@@ -59,7 +111,7 @@ - all_opt["access_key"] = { - "getopt" : "a:", - "longopt" : "access-key", -- "help" : "-a, --access-key=[name] Access Key", -+ "help" : "-a, --access-key=[key] Access Key", - "shortdesc" : "Access Key.", - "required" : "0", - "order" : 3 -@@ -67,23 +119,32 @@ - all_opt["secret_key"] = { - "getopt" : "s:", - "longopt" : "secret-key", -- "help" : "-s, --secret-key=[name] Secret Key", -+ "help" : "-s, --secret-key=[key] Secret Key", - "shortdesc" : "Secret Key.", - "required" : "0", - "order" : 4 - } -+ all_opt["boto3_debug"] = { -+ "getopt" : "b:", -+ "longopt" : "boto3_debug", -+ "help" : "-b, --boto3_debug=[option] Boto3 and Botocore library debug logging", -+ "shortdesc": "Boto Lib debug", -+ "required": "0", -+ "order": 5 -+ } - - # Main agent method - def main(): - conn = None - -- device_opt = ["port", "no_password", "region", "access_key", "secret_key"] -+ device_opt = ["port", "no_password", "region", "access_key", "secret_key", "boto3_debug"] - - atexit.register(atexit_handler) - - define_new_opts() - - all_opt["power_timeout"]["default"] = "60" -+ all_opt["boto3_debug"]["default"] = "off" - - options = check_input(device_opt, process_input(device_opt)) - -@@ -99,6 +160,28 @@ - - run_delay(options) - -+ if options.get("--verbose") is not None: -+ lh = logging.FileHandler('/var/log/fence_aws_debug.log') -+ logger.addHandler(lh) -+ lhf = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') -+ lh.setFormatter(lhf) -+ logger.setLevel(logging.DEBUG) -+ -+ if options["--boto3_debug"] != "on": -+ boto3.set_stream_logger('boto3',logging.INFO) -+ boto3.set_stream_logger('botocore',logging.INFO) -+ logging.getLogger('botocore').propagate = False -+ logging.getLogger('boto3').propagate = False -+ else: -+ log_format = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') -+ logging.getLogger('botocore').propagate = False -+ logging.getLogger('boto3').propagate = False -+ fdh = logging.FileHandler('/var/log/fence_aws_boto3.log') -+ fdh.setFormatter(log_format) -+ logging.getLogger('boto3').addHandler(fdh) -+ logging.getLogger('botocore').addHandler(fdh) -+ logging.debug("Boto debug level is %s and sending debug info to /var/log/fence_aws_boto3.log", options["--boto3_debug"]) -+ - region = options.get("--region") - access_key = options.get("--access-key") - secret_key = options.get("--secret-key") -@@ -106,12 +189,12 @@ - conn = boto3.resource('ec2', region_name=region, - aws_access_key_id=access_key, - aws_secret_access_key=secret_key) -- except: -- fail_usage("Failed: Unable to connect to AWS. Check your configuration.") -+ except Exception as e: -+ fail_usage("Failed: Unable to connect to AWS: " + str(e)) - - # 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() -+ main() -\ No newline at end of file diff --git a/SOURCES/bz1854310-fence_vmware_rest-1-fix-encoding.patch b/SOURCES/bz1854310-fence_vmware_rest-1-fix-encoding.patch deleted file mode 100644 index c215ab1..0000000 --- a/SOURCES/bz1854310-fence_vmware_rest-1-fix-encoding.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 06cba4aa30322f410b0b2fec5785be39d0953433 Mon Sep 17 00:00:00 2001 -From: Oyvind Albrigtsen -Date: Wed, 12 Feb 2020 14:21:54 +0100 -Subject: [PATCH] fence_vmware_rest: fix encoding to avoid issues with UTF-8 - encoded comments - ---- - agents/vmware_rest/fence_vmware_rest.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py -index cd99b4ac..d07bc10d 100644 ---- a/agents/vmware_rest/fence_vmware_rest.py -+++ b/agents/vmware_rest/fence_vmware_rest.py -@@ -127,7 +127,7 @@ def send_command(conn, command, method="GET"): - raise Exception(e[1]) - - rc = conn.getinfo(pycurl.HTTP_CODE) -- result = web_buffer.getvalue().decode() -+ result = web_buffer.getvalue().decode("UTF-8") - - web_buffer.close() - diff --git a/SOURCES/bz1854310-fence_vmware_rest-2-support-utf-8-vm-names.patch b/SOURCES/bz1854310-fence_vmware_rest-2-support-utf-8-vm-names.patch deleted file mode 100644 index 18f1569..0000000 --- a/SOURCES/bz1854310-fence_vmware_rest-2-support-utf-8-vm-names.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/agents/vmware_rest/fence_vmware_rest.py 2020-07-03 15:09:59.307198567 +0200 -+++ b/agents/vmware_rest/fence_vmware_rest.py 2020-07-03 15:09:52.331210984 +0200 -@@ -8,10 +8,13 @@ - from fencing import * - from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS - -+if sys.version_info[0] > 2: import urllib.parse as urllib -+else: import urllib -+ - state = {"POWERED_ON": "on", 'POWERED_OFF': "off"} - - def get_power_status(conn, options): -- res = send_command(conn, "vcenter/vm?filter.names={}".format(options["--plug"]))["value"] -+ res = send_command(conn, "vcenter/vm?filter.names={}".format(urllib.quote(options["--plug"])))["value"] - - if len(res) == 0: - fail(EC_STATUS) -@@ -36,7 +39,7 @@ - res = send_command(conn, "vcenter/vm") - - for r in res["value"]: -- outlets[r["name"]] = ("", state[r["power_state"]]) -+ outlets[r["name"].encode("UTF-8")] = ("", state[r["power_state"]]) - - return outlets - diff --git a/SPECS/fence-agents.spec b/SPECS/fence-agents.spec index a35e205..e67821c 100644 --- a/SPECS/fence-agents.spec +++ b/SPECS/fence-agents.spec @@ -13,6 +13,7 @@ # keep around ready for later user ## global alphatag git0a6184070 +# bundles %global bundled_lib_dir bundled # google cloud @@ -66,7 +67,7 @@ Name: fence-agents Summary: Fence Agents for Red Hat Cluster Version: 4.2.1 -Release: 30%{?alphatag:.%{alphatag}}%{?dist}.2 +Release: 41%{?alphatag:.%{alphatag}}%{?dist} License: GPLv2+ and LGPLv2+ Group: System Environment/Base URL: https://github.com/ClusterLabs/fence-agents @@ -122,10 +123,18 @@ Patch36: bz1753229-fence_mpath-1-add-plug-parameter-support.patch Patch37: bz1753229-fence_mpath-2-fix-plug-parameter-issues.patch Patch38: bz1722004-1-fencing-inetX_only-SSH-fence_zvmip.patch Patch39: bz1722004-2-fence_redfish-fence_vmware_soap-suppress-warning.patch -Patch40: bz1834193-1-fence_aws-improve-parameter-logic.patch -Patch41: bz1834193-2-fence_aws-fix-race-condition.patch -Patch42: bz1854310-fence_vmware_rest-1-fix-encoding.patch -Patch43: bz1854310-fence_vmware_rest-2-support-utf-8-vm-names.patch +Patch40: bz1760203-fence_compute-fence_evacuate-1-fix-region_name-type.patch +Patch41: bz1760203-fence_compute-fence_evacuate-2-fix-project-shortopt.patch +Patch42: bz1763675-fence_rhevm-add-cookie-support.patch +Patch43: bz1769784-fencing-improve-stdin-quote-parsing.patch +Patch44: bz1793738-fence_vmware_rest-1-fix-encoding.patch +Patch45: bz1673468-fence_aws-improve-parameter-logic.patch +Patch58: bz1816205-fence_aws-fix-race-condition.patch +Patch59: bz1827561-fence_vmware_rest-improve-exception-handling.patch +Patch60: bz1654058-fence_vmware_rest-1-add-filter-parameter.patch +Patch61: bz1654058-fence_vmware_rest-2-fix-1000-VM-monitor-error.patch +Patch62: bz1793738-fence_vmware_rest-2-support-utf-8-vm-names.patch +Patch63: bz1832289-fence_aws-improve-catch-connectionerror.patch # bundle patches Patch1000: bz1568753-4-fence_gce-bundled-libs.patch Patch1001: bz1568753-5-%{oauth2client}-docs-build-fix.patch @@ -138,12 +147,12 @@ 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 +%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 lpar 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 +%global testagents virsh heuristics_ping %endif %ifarch s390x %global testagents virsh zvm heuristics_ping @@ -217,8 +226,19 @@ BuildRequires: python-six >= 1.6.1 %patch39 -p1 %patch40 -p1 %patch41 -p1 -%patch42 -p1 +%patch42 -p1 -F1 %patch43 -p1 +%patch44 -p1 +%patch45 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 + +# prevent compilation of something that won't get used anyway +sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac %ifarch x86_64 # bundles @@ -990,7 +1010,6 @@ The fence-agents-kdump package contains a fence agent for use with kdump crash r %{_mandir}/man8/fence_kdump.8* %{_mandir}/man8/fence_kdump_send.8* -%ifarch ppc64le %package lpar License: GPLv2+ and LGPLv2+ Group: System Environment/Base @@ -1004,7 +1023,6 @@ The fence-agents-lpar package contains a fence agent for IBM LPAR devices that a %defattr(-,root,root,-) %{_sbindir}/fence_lpar %{_mandir}/man8/fence_lpar.8* -%endif %package redfish License: GPLv2+ and LGPLv2+ @@ -1175,18 +1193,47 @@ The fence-agents-zvm package contains a fence agent for z/VM hypervisors %defattr(-,root,root,-) %{_sbindir}/fence_zvmip %{_mandir}/man8/fence_zvmip.8* -%exclude %{_sbindir}/fence_zvm -%exclude %{_mandir}/man8/fence_zvm.8* %endif %changelog -* Tue Jul 7 2020 Oyvind Albrigtsen - 4.2.1-30.2 +* Mon May 25 2020 Oyvind Albrigtsen - 4.2.1-41 +- fence_aws: improve logging and metadata/usage text + Resolves: rhbz#1832289 + +* Tue May 19 2020 Oyvind Albrigtsen - 4.2.1-40 - fence_vmware_rest: fix encoding issues - Resolves: rhbz#1854310 + Resolves: rhbz#1793738 + +* Fri May 15 2020 Oyvind Albrigtsen - 4.2.1-39 +- fence_vmware_rest: add filter parameter to avoid 1000 VM API limit + and avoid failing when hitting it during the monitor-action + Resolves: rhbz#1654058 + +* Fri Apr 24 2020 Oyvind Albrigtsen - 4.2.1-36 +- fence_vmware_rest: improve exception handling + Resolves: rhbz#1827561 -* Tue May 12 2020 Oyvind Albrigtsen - 4.2.1-30.1 +* Thu Mar 26 2020 Oyvind Albrigtsen - 4.2.1-35 - fence_aws: fix possible race condition - Resolves: rhbz#1834193 + Resolves: rhbz#1816205 + +* Tue Mar 10 2020 Oyvind Albrigtsen - 4.2.1-34 +- fence_aws: improve parameter logic to allow setting region parameter + while using credentials from ~/.aws/config + Resolves: rhbz#1673468 +- +* Tue Feb 25 2020 Oyvind Albrigtsen - 4.2.1-33 +- fence-agents-lpar: build on non-ppc64le arch's + Resolves: rhbz#1801818 + +* Wed Jan 15 2020 Oyvind Albrigtsen - 4.2.1-31 +- fence_compute/fence_evacuate: fix region_name content type and + project shortopt in usage text and project-domain shortopt + Resolves: rhbz#1760203 +- fence_rhevm: add cookie support + Resolves: rhbz#1763675 +- fencing: improve stdin quote parsing + Resolves: rhbz#1769784 * Tue Nov 26 2019 Oyvind Albrigtsen - 4.2.1-30 - fencing: only use inetX_only parameters for SSH based agents and