diff --git a/0001-attr-filter-uses-env.getattr.patch b/0001-attr-filter-uses-env.getattr.patch deleted file mode 100644 index 7933b82116cda14b88981a3655876d160627eaeb..0000000000000000000000000000000000000000 --- a/0001-attr-filter-uses-env.getattr.patch +++ /dev/null @@ -1,80 +0,0 @@ -diff --git a/Jinja2-3.1.3/src/jinja2/filters.py b/Jinja2-3.1.3/src/jinja2/filters.py -index e5b5a00c..2bcba4fb 100644 ---- a/Jinja2-3.1.3/src/jinja2/filters.py -+++ b/Jinja2-3.1.3/src/jinja2/filters.py -@@ -6,6 +6,7 @@ import re - import typing - import typing as t - from collections import abc -+from inspect import getattr_static - from itertools import chain - from itertools import groupby - -@@ -1411,31 +1412,25 @@ def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V] - def do_attr( - environment: "Environment", obj: t.Any, name: str - ) -> t.Union[Undefined, t.Any]: -- """Get an attribute of an object. ``foo|attr("bar")`` works like -- ``foo.bar`` just that always an attribute is returned and items are not -- looked up. -+ """Get an attribute of an object. ``foo|attr("bar")`` works like -+ ``foo.bar``, but returns undefined instead of falling back to ``foo["bar"]`` -+ if the attribute doesn't exist. - - See :ref:`Notes on subscriptions ` for more details. - """ -+ # Environment.getattr will fall back to obj[name] if obj.name doesn't exist. -+ # But we want to call env.getattr to get behavior such as sandboxing. -+ # Determine if the attr exists first, so we know the fallback won't trigger. - try: -- name = str(name) -- except UnicodeError: -- pass -- else: -- try: -- value = getattr(obj, name) -- except AttributeError: -- pass -- else: -- if environment.sandboxed: -- environment = t.cast("SandboxedEnvironment", environment) -- -- if not environment.is_safe_attribute(obj, name, value): -- return environment.unsafe_undefined(obj, name) -- -- return value -- -- return environment.undefined(obj=obj, name=name) -+ # This avoids executing properties/descriptors, but misses __getattr__ -+ # and __getattribute__ dynamic attrs. -+ getattr_static(obj, name) -+ except AttributeError: -+ # This finds dynamic attrs, and we know it's not a descriptor at this point. -+ if not hasattr(obj, name): -+ return environment.undefined(obj=obj, name=name) -+ -+ return environment.getattr(obj, name) - - - @typing.overload -diff --git a/Jinja2-3.1.3/tests/test_security.py b/Jinja2-3.1.3/tests/test_security.py -index 864d5f7f..3a137819 100644 ---- a/Jinja2-3.1.3/tests/test_security.py -+++ b/Jinja2-3.1.3/tests/test_security.py -@@ -190,3 +190,13 @@ class TestStringFormatMap: - - with pytest.raises(SecurityError): - t.render() -+ -+ def test_attr_filter(self) -> None: -+ env = SandboxedEnvironment() -+ t = env.from_string( -+ """{{ "{0.__call__.__builtins__[__import__]}" -+ | attr("format")(not_here) }}""" -+ ) -+ -+ with pytest.raises(SecurityError): -+ t.render() --- -2.43.0 - diff --git a/0001-fix-f-string-syntax-error-in-code-generation.patch b/0001-fix-f-string-syntax-error-in-code-generation.patch deleted file mode 100644 index d982e8189703eeecaf49ee00513ee3ca8b8f5cbc..0000000000000000000000000000000000000000 --- a/0001-fix-f-string-syntax-error-in-code-generation.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/Jinja2-3.1.3/src/jinja2/compiler.py b/Jinja2-3.1.3/src/jinja2/compiler.py -index ff95c80..1ebdcd9 100644 ---- a/Jinja2-3.1.3/src/jinja2/compiler.py -+++ b/Jinja2-3.1.3/src/jinja2/compiler.py -@@ -1121,9 +1121,14 @@ class CodeGenerator(NodeVisitor): - ) - self.writeline(f"if {frame.symbols.ref(alias)} is missing:") - self.indent() -+ # The position will contain the template name, and will be formatted -+ # into a string that will be compiled into an f-string. Curly braces -+ # in the name must be replaced with escapes so that they will not be -+ # executed as part of the f-string. -+ position = self.position(node).replace("{", "{{").replace("}", "}}") - message = ( - "the template {included_template.__name__!r}" -- f" (imported on {self.position(node)})" -+ f" (imported on {position})" - f" does not export the requested name {name!r}" - ) - self.writeline( -diff --git a/Jinja2-3.1.3/tests/test_compile.py b/Jinja2-3.1.3/tests/test_compile.py -index 42a773f..19df4db 100644 ---- a/Jinja2-3.1.3/tests/test_compile.py -+++ b/Jinja2-3.1.3/tests/test_compile.py -@@ -1,6 +1,9 @@ - import os - import re - -+import pytest -+ -+from jinja2 import UndefinedError - from jinja2.environment import Environment - from jinja2.loaders import DictLoader - -@@ -26,3 +29,18 @@ def test_import_as_with_context_deterministic(tmp_path): - expect = [f"'bar{i}': " for i in range(10)] - found = re.findall(r"'bar\d': ", content)[:10] - assert found == expect -+ -+def test_undefined_import_curly_name(): -+ env = Environment( -+ loader=DictLoader( -+ { -+ "{bad}": "{% from 'macro' import m %}{{ m() }}", -+ "macro": "", -+ } -+ ) -+ ) -+ -+ # Must not raise `NameError: 'bad' is not defined`, as that would indicate -+ # that `{bad}` is being interpreted as an f-string. It must be escaped. -+ with pytest.raises(UndefinedError): -+ env.get_template("{bad}").render() diff --git a/0001-sandbox-indirect-calls-to-str.format.patch b/0001-sandbox-indirect-calls-to-str.format.patch deleted file mode 100644 index 83bf43750af9f00d60cc5ae44c513f8df4bd12ec..0000000000000000000000000000000000000000 --- a/0001-sandbox-indirect-calls-to-str.format.patch +++ /dev/null @@ -1,150 +0,0 @@ -diff --git a/Jinja2-3.1.3/src/jinja2/sandbox.py b/Jinja2-3.1.3/src/jinja2/sandbox.py -index 06d7414..7d90951 100644 ---- a/Jinja2-3.1.3/src/jinja2/sandbox.py -+++ b/Jinja2-3.1.3/src/jinja2/sandbox.py -@@ -80,20 +80,6 @@ _mutable_spec: t.Tuple[t.Tuple[t.Type, t.FrozenSet[str]], ...] = ( - ) - - --def inspect_format_method(callable: t.Callable) -> t.Optional[str]: -- if not isinstance( -- callable, (types.MethodType, types.BuiltinMethodType) -- ) or callable.__name__ not in ("format", "format_map"): -- return None -- -- obj = callable.__self__ -- -- if isinstance(obj, str): -- return obj -- -- return None -- -- - def safe_range(*args: int) -> range: - """A range that can't generate ranges with a length of more than - MAX_RANGE items. -@@ -313,6 +299,9 @@ class SandboxedEnvironment(Environment): - except AttributeError: - pass - else: -+ fmt = self.wrap_str_format(value) -+ if fmt is not None: -+ return fmt - if self.is_safe_attribute(obj, argument, value): - return value - return self.unsafe_undefined(obj, argument) -@@ -330,6 +319,9 @@ class SandboxedEnvironment(Environment): - except (TypeError, LookupError): - pass - else: -+ fmt = self.wrap_str_format(value) -+ if fmt is not None: -+ return fmt - if self.is_safe_attribute(obj, attribute, value): - return value - return self.unsafe_undefined(obj, attribute) -@@ -345,34 +337,48 @@ class SandboxedEnvironment(Environment): - exc=SecurityError, - ) - -- def format_string( -- self, -- s: str, -- args: t.Tuple[t.Any, ...], -- kwargs: t.Dict[str, t.Any], -- format_func: t.Optional[t.Callable] = None, -- ) -> str: -- """If a format call is detected, then this is routed through this -- method so that our safety sandbox can be used for it. -+ def wrap_str_format(self, value: t.Any) -> t.Optional[t.Callable[..., str]]: -+ """If the given value is a ``str.format`` or ``str.format_map`` method, -+ return a new function than handles sandboxing. This is done at access -+ rather than in :meth:`call`, so that calls made without ``call`` are -+ also sandboxed. - """ -+ if not isinstance( -+ value, (types.MethodType, types.BuiltinMethodType) -+ ) or value.__name__ not in ("format", "format_map"): -+ return None -+ -+ f_self: t.Any = value.__self__ -+ -+ if not isinstance(f_self, str): -+ return None -+ -+ str_type: t.Type[str] = type(f_self) -+ is_format_map = value.__name__ == "format_map" - formatter: SandboxedFormatter -- if isinstance(s, Markup): -- formatter = SandboxedEscapeFormatter(self, escape=s.escape) -+ -+ -+ if isinstance(f_self, Markup): -+ formatter = SandboxedEscapeFormatter(self, escape=f_self.escape) - else: - formatter = SandboxedFormatter(self) - -- if format_func is not None and format_func.__name__ == "format_map": -- if len(args) != 1 or kwargs: -- raise TypeError( -- "format_map() takes exactly one argument" -- f" {len(args) + (kwargs is not None)} given" -- ) -+ vformat = formatter.vformat -+ -+ def wrapper(*args: t.Any, **kwargs: t.Any) -> str: -+ if is_format_map: -+ if kwargs: -+ raise TypeError("format_map() takes no keyword arguments") -+ -+ if len(args) != 1: -+ raise TypeError( -+ f"format_map() takes exactly one argument ({len(args)} given)" -+ ) - -- kwargs = args[0] -- args = () -+ kwargs = args[0] -+ args = () - -- rv = formatter.vformat(s, args, kwargs) -- return type(s)(rv) -+ return update_wrapper(wrapper, value) - - def call( - __self, # noqa: B902 -@@ -382,9 +388,6 @@ class SandboxedEnvironment(Environment): - **kwargs: t.Any, - ) -> t.Any: - """Call an object from sandboxed code.""" -- fmt = inspect_format_method(__obj) -- if fmt is not None: -- return __self.format_string(fmt, args, kwargs, __obj) - - # the double prefixes are to avoid double keyword argument - # errors when proxying the call. -diff --git a/Jinja2-3.1.3/tests/test_security.py b/Jinja2-3.1.3/tests/test_security.py -index 0e8dc5c..81a32ae 100644 ---- a/Jinja2-3.1.3/tests/test_security.py -+++ b/Jinja2-3.1.3/tests/test_security.py -@@ -171,3 +171,20 @@ class TestStringFormatMap: - '{{ ("a{x.foo}b{y}"|safe).format_map({"x":{"foo": 42}, "y":""}) }}' - ) - assert t.render() == "a42b<foo>" -+ -+ def test_indirect_call(self): -+ def run(value, arg): -+ return value.run(arg) -+ -+ env = SandboxedEnvironment() -+ env.filters["run"] = run -+ t = env.from_string( -+ """{% set -+ ns = namespace(run="{0.__call__.__builtins__[__import__]}".format) -+ %} -+ {{ ns | run(not_here) }} -+ """ -+ ) -+ -+ with pytest.raises(SecurityError): -+ t.render() diff --git a/MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl b/MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl deleted file mode 100644 index 46dbca2f1dc1896100f87c556a0b685e14eca668..0000000000000000000000000000000000000000 Binary files a/MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl and /dev/null differ diff --git a/RHEL-35649-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch b/RHEL-35649-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch deleted file mode 100644 index 700ab80a0f3b5b13aeb71d4ae91a2d4c388ec797..0000000000000000000000000000000000000000 --- a/RHEL-35649-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch +++ /dev/null @@ -1,65 +0,0 @@ -From d655030770081e2dfe46f90e27620472a502289d Mon Sep 17 00:00:00 2001 -From: David Lord -Date: Thu, 2 May 2024 09:14:00 -0700 -Subject: [PATCH] disallow invalid characters in keys to xmlattr filter - ---- - CHANGES.rst | 6 ++++++ - src/jinja2/filters.py | 22 +++++++++++++++++----- - tests/test_filters.py | 11 ++++++----- - 3 files changed, 29 insertions(+), 10 deletions(-) - -diff --git a/kubevirt/jinja2/filters.py b/kubevirt/jinja2/filters.py -index 4cf3c11fb..acd11976e 100644 ---- a/kubevirt/jinja2/filters.py -+++ b/kubevirt/jinja2/filters.py -@@ -250,7 +250,9 @@ def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K - yield from value.items() - - --_space_re = re.compile(r"\s", flags=re.ASCII) -+# Check for characters that would move the parser state from key to value. -+# https://html.spec.whatwg.org/#attribute-name-state -+_attr_key_re = re.compile(r"[\s/>=]", flags=re.ASCII) - - - @pass_eval_context -@@ -259,8 +261,14 @@ def do_xmlattr( - ) -> str: - """Create an SGML/XML attribute string based on the items in a dict. - -- If any key contains a space, this fails with a ``ValueError``. Values that -- are neither ``none`` nor ``undefined`` are automatically escaped. -+ **Values** that are neither ``none`` nor ``undefined`` are automatically -+ escaped, safely allowing untrusted user input. -+ -+ User input should not be used as **keys** to this filter. If any key -+ contains a space, ``/`` solidus, ``>`` greater-than sign, or ``=`` equals -+ sign, this fails with a ``ValueError``. Regardless of this, user input -+ should never be used as keys to this filter, or must be separately validated -+ first. - - .. sourcecode:: html+jinja - -@@ -280,6 +288,10 @@ def do_xmlattr( - As you can see it automatically prepends a space in front of the item - if the filter returned something unless the second parameter is false. - -+ .. versionchanged:: 3.1.4 -+ Keys with ``/`` solidus, ``>`` greater-than sign, or ``=`` equals sign -+ are not allowed. -+ - .. versionchanged:: 3.1.3 - Keys with spaces are not allowed. - """ -@@ -289,8 +301,8 @@ def do_xmlattr( - if value is None or isinstance(value, Undefined): - continue - -- if _space_re.search(key) is not None: -- raise ValueError(f"Spaces are not allowed in attributes: '{key}'") -+ if _attr_key_re.search(key) is not None: -+ raise ValueError(f"Invalid character in attribute name: {key!r}") - - items.append(f'{escape(key)}="{escape(value)}"') - diff --git a/RHEL-43562-fix-bundled-urllib3-CVE-2024-37891.patch b/RHEL-43562-fix-bundled-urllib3-CVE-2024-37891.patch index 2c2de0eac873fcffc81fb55a3591903f99c7ebf8..88258d48392123d040b7726c79437041d5863fd6 100644 --- a/RHEL-43562-fix-bundled-urllib3-CVE-2024-37891.patch +++ b/RHEL-43562-fix-bundled-urllib3-CVE-2024-37891.patch @@ -15,22 +15,6 @@ Subject: [PATCH] Merge pull request from GHSA-34jh-p97f-mpxf test/with_dummyserver/test_poolmanager.py | 27 ++++++++++++++++++++--- 4 files changed, 37 insertions(+), 5 deletions(-) -diff --git a/awscli/urllib3/util/retry.py b/awscli/urllib3/util/retry.py -index 7a76a4a6ad..0456cceba4 100644 ---- a/awscli/urllib3/util/retry.py -+++ b/awscli/urllib3/util/retry.py -@@ -189,7 +189,9 @@ class Retry: - RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) - - #: Default headers to be used for ``remove_headers_on_redirect`` -- DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Cookie", "Authorization"]) -+ DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset( -+ ["Cookie", "Authorization", "Proxy-Authorization"] -+ ) - - #: Default maximum backoff time. - DEFAULT_BACKOFF_MAX = 120 - diff --git a/aws/urllib3/util/retry.py b/aws/urllib3/util/retry.py index 7a76a4a6ad..0456cceba4 100644 --- a/aws/urllib3/util/retry.py diff --git a/RHEL-56138-fence_mpath-1-support-hex-key-format.patch b/RHEL-56138-fence_mpath-1-support-hex-key-format.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b2cd5a073a8fcf96f8801f7ad7227cdb2486ada --- /dev/null +++ b/RHEL-56138-fence_mpath-1-support-hex-key-format.patch @@ -0,0 +1,10 @@ +--- a/agents/mpath/fence_mpath.py 2024-10-09 14:56:07.688665678 +0200 ++++ b/agents/mpath/fence_mpath.py 2024-10-09 14:56:12.639780798 +0200 +@@ -323,6 +323,7 @@ + fail_usage("Failed: No devices found") + + options["devices"] = [d for d in re.split("\s*,\s*|\s+", options["--devices"].strip()) if d] ++ options["--plug"] = re.sub(r"^0x0*|^0+", "", options["--plug"]) + # Input control END + + result = fence_action(None, options, set_status, get_status) diff --git a/RHEL-56138-fence_mpath-2-fix-unfencing-issue-use-MULTILINE-avoid-duplicates.patch b/RHEL-56138-fence_mpath-2-fix-unfencing-issue-use-MULTILINE-avoid-duplicates.patch new file mode 100644 index 0000000000000000000000000000000000000000..051fa1d9e6f6de23394ff5c17950a80257d1af3d --- /dev/null +++ b/RHEL-56138-fence_mpath-2-fix-unfencing-issue-use-MULTILINE-avoid-duplicates.patch @@ -0,0 +1,44 @@ +From 99c5c3289b23064441f998949808a0b3569c2e3b Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 10 Oct 2024 09:55:16 +0200 +Subject: [PATCH] fence_mpath: fix 0x-format patch causing unfencing issue, and + use re.MULTILINE to avoid duplicating device dev/key lines in + /run/cluster/mpath.devices + +--- + agents/mpath/fence_mpath.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py +index 2d8601497..2a4a58b36 100644 +--- a/agents/mpath/fence_mpath.py ++++ b/agents/mpath/fence_mpath.py +@@ -40,7 +40,7 @@ def set_status(conn, options): + if options["--plug"] not in get_registration_keys(options, dev): + count += 1 + logging.debug("Failed to register key "\ +- + options["--plug"] + "on device " + dev + "\n") ++ + options["--plug"] + " on device " + dev + "\n") + continue + dev_write(options, dev) + +@@ -147,8 +147,9 @@ def dev_write(options, dev): + store_fh = open(file_path, "a+") + except IOError: + fail_usage("Failed: Cannot open file \""+ file_path + "\"") ++ store_fh.seek(0) + out = store_fh.read() +- if not re.search(r"^" + dev + r"\s+", out): ++ if not re.search(r"^{}\s+{}$".format(dev, options["--plug"]), out, flags=re.MULTILINE): + store_fh.write(dev + "\t" + options["--plug"] + "\n") + store_fh.close() + +@@ -332,7 +333,7 @@ def main(): + fail_usage("Failed: No devices found") + + options["devices"] = [d for d in re.split("\s*,\s*|\s+", options["--devices"].strip()) if d] +- options["--plug"] = re.sub(r"^0x0*|^0+", "", options["--plug"]) ++ options["--plug"] = re.sub(r"^0x0*|^0+", "", options.get("--plug", "")) + # Input control END + + result = fence_action(None, options, set_status, get_status) diff --git a/RHEL-59882-fence_scsi-only-preempt-once-for-mpath-devices.patch b/RHEL-59878-fence_scsi-only-preempt-once-for-mpath-devices.patch similarity index 100% rename from RHEL-59882-fence_scsi-only-preempt-once-for-mpath-devices.patch rename to RHEL-59878-fence_scsi-only-preempt-once-for-mpath-devices.patch diff --git a/RHEL-62206-fence_ibm_powervs-add-private-endpoint-and-token-file-support.patch b/RHEL-62206-fence_ibm_powervs-add-private-endpoint-and-token-file-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..af3ea5f781201e89fefbc951b2247da265e95ad5 --- /dev/null +++ b/RHEL-62206-fence_ibm_powervs-add-private-endpoint-and-token-file-support.patch @@ -0,0 +1,120 @@ +--- a/agents/ibm_powervs/fence_ibm_powervs.py 2024-10-18 10:30:40.651200620 +0200 ++++ b/agents/ibm_powervs/fence_ibm_powervs.py 2024-10-18 10:30:35.157070713 +0200 +@@ -1,13 +1,14 @@ + #!@PYTHON@ -tt + + import sys +-import pycurl, io, json ++import pycurl ++import io ++import json + import logging + import atexit +-import time ++ + sys.path.append("@FENCEAGENTSLIBDIR@") +-from fencing import * +-from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS ++from fencing import all_opt, atexit_handler, check_input, process_input, show_docs, fence_action, fail, run_delay, EC_STATUS + + state = { + "ACTIVE": "on", +@@ -18,15 +19,35 @@ + } + + def get_token(conn, options): +- try: +- command = "identity/token" +- action = "grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(options["--token"]) +- res = send_command(conn, command, "POST", action, printResult=False) +- except Exception as e: +- logging.debug("Failed: {}".format(e)) +- return "TOKEN_IS_MISSING_OR_WRONG" +- +- return res["access_token"] ++ try: ++ if options["--token"][0] == '@': ++ key_file = options["--token"][1:] ++ try: ++ # read the API key from a file ++ with open(key_file, "r") as f: ++ try: ++ keys = json.loads(f.read()) ++ # data seems to be in json format ++ # return the value of the item with the key 'Apikey' ++ api_key = keys.get("Apikey", "") ++ if not api_key: ++ # backward compatibility: former key name was 'apikey' ++ api_key = keys.get("apikey", "") ++ # data is text, return as is ++ except ValueError: ++ api_key = f.read().strip() ++ except FileNotFoundError: ++ logging.debug("Failed: Cannot open file {}".format(key_file)) ++ return "TOKEN_IS_MISSING_OR_WRONG" ++ else: ++ api_key = options["--token"] ++ command = "identity/token" ++ action = "grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(api_key) ++ res = send_command(conn, command, "POST", action, printResult=False) ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) ++ return "TOKEN_IS_MISSING_OR_WRONG" ++ return res["access_token"] + + def get_list(conn, options): + outlets = {} +@@ -41,7 +62,7 @@ + for r in res["pvmInstances"]: + if options["--verbose-level"] > 1: + logging.debug(json.dumps(r, indent=2)) +- outlets[r["pvmInstanceID"]] = (r["serverName"], state[r["status"]]) ++ outlets[r["pvmInstanceID"]] = (r["serverName"], state.get(r["status"], "unknown")) + + return outlets + +@@ -97,7 +118,7 @@ + else: + logging.debug("Failed: Unable to cycle with {} for {}".format(options["--action"], e)) + fail(EC_STATUS) +- return True ++ return True + + def connect(opt, token): + conn = pycurl.Curl() +@@ -130,7 +151,10 @@ + conn = pycurl.Curl() + + # setup correct URL +- conn.base_url = "https://iam.cloud.ibm.com/" ++ if opt["--api-type"] == "private": ++ conn.base_url = "https://private.iam.cloud.ibm.com/" ++ else: ++ conn.base_url = "https://iam.cloud.ibm.com/" + + if opt["--verbose-level"] > 1: + conn.setopt(pycurl.VERBOSE, 1) +@@ -265,9 +289,9 @@ + define_new_opts() + + all_opt["shell_timeout"]["default"] = "500" +- all_opt["power_timeout"]["default"] = "30" +- all_opt["power_wait"]["default"] = "1" +- all_opt["stonith_status_sleep"]["default"] = "2" ++ all_opt["power_timeout"]["default"] = "120" ++ all_opt["power_wait"]["default"] = "15" ++ all_opt["stonith_status_sleep"]["default"] = "10" + all_opt["api-type"]["default"] = "private" + all_opt["proxy"]["default"] = "" + +@@ -275,8 +299,8 @@ + + docs = {} + docs["shortdesc"] = "Fence agent for IBM PowerVS" +- docs["longdesc"] = """fence_ibm_powervs is a Power Fencing agent which can be \ +-used with IBM PowerVS to fence virtual machines.""" ++ docs["longdesc"] = """fence_ibm_powervs is a power fencing agent for \ ++IBM Power Virtual Server (IBM PowerVS) to fence virtual server instances.""" + docs["vendorurl"] = "https://www.ibm.com" + show_docs(options, docs) + diff --git a/RHEL-76493-fence_azure_arm-use-azure-identity.patch b/RHEL-76493-fence_azure_arm-use-azure-identity.patch new file mode 100644 index 0000000000000000000000000000000000000000..081d1cd1a2a7aaab5f3bb06d2066f4ab761d9fc9 --- /dev/null +++ b/RHEL-76493-fence_azure_arm-use-azure-identity.patch @@ -0,0 +1,472 @@ +--- a/lib/azure_fence.py.py 2025-01-30 14:59:48.211366580 +0100 ++++ b/lib/azure_fence.py.py 2025-01-30 12:06:10.847889534 +0100 +@@ -1,9 +1,6 @@ + import logging, re, time + from fencing import fail_usage + +-import sys +-sys.path.insert(0, '/usr/lib/fence-agents/support/azure') +- + FENCE_SUBNET_NAME = "fence-subnet" + FENCE_INBOUND_RULE_NAME = "FENCE_DENY_ALL_INBOUND" + FENCE_INBOUND_RULE_DIRECTION = "Inbound" +@@ -17,6 +14,9 @@ + IP_TYPE_DYNAMIC = "Dynamic" + MAX_RETRY = 10 + RETRY_WAIT = 5 ++NETWORK_MGMT_CLIENT_API_VERSION = "2021-05-01" ++AZURE_RHEL8_COMPUTE_VERSION = "27.2.0" ++AZURE_COMPUTE_VERSION_5 = "5.0.0" + + class AzureSubResource: + Type = None +@@ -52,7 +52,7 @@ + return None + + def get_azure_resource(id): +- match = re.match('(/subscriptions/([^/]*)/resourceGroups/([^/]*))(/providers/([^/]*/[^/]*)/([^/]*))?((/([^/]*)/([^/]*))*)', id) ++ match = re.match(r'(/subscriptions/([^/]*)/resourceGroups/([^/]*))(/providers/([^/]*/[^/]*)/([^/]*))?((/([^/]*)/([^/]*))*)', id) + if not match: + fail_usage("{get_azure_resource} cannot parse resource id %s" % id) + +@@ -89,6 +89,59 @@ + + return resource + ++def azure_dep_versions(v): ++ return tuple(map(int, (v.split(".")))) ++ ++# Do azure API call to list all virtual machines in a resource group ++def get_vm_list(compute_client,rgName): ++ return compute_client.virtual_machines.list(rgName) ++ ++# Do azue API call to shutdown a virtual machine ++def do_vm_power_off(compute_client,rgName,vmName, skipShutdown): ++ try: ++ # Version is not available in azure-mgmt-compute version 14.0.0 until 27.2.0 ++ from azure.mgmt.compute import __version__ ++ except ImportError: ++ __version__ = "0.0.0" ++ ++ # use different implementation call based on used version ++ if (azure_dep_versions(__version__) == azure_dep_versions(AZURE_COMPUTE_VERSION_5)): ++ logging.debug("{do_vm_power_off} azure.mgtm.compute version is to old to use 'begin_power_off' use 'power_off' function") ++ compute_client.virtual_machines.power_off(rgName, vmName, skip_shutdown=skipShutdown) ++ return ++ ++ compute_client.virtual_machines.begin_power_off(rgName, vmName, skip_shutdown=skipShutdown) ++ ++# Do azure API call to start a virtual machine ++def do_vm_start(compute_client,rgName,vmName): ++ try: ++ # Version is not available in azure-mgmt-compute version 14.0.0 until 27.2.0 ++ from azure.mgmt.compute import __version__ ++ except ImportError: ++ __version__ = "0.0.0" ++ ++ # use different implementation call based on used version ++ if (azure_dep_versions(__version__) == azure_dep_versions(AZURE_COMPUTE_VERSION_5)): ++ logging.debug("{do_vm_start} azure.mgtm.compute version is to old to use 'begin_start' use 'start' function") ++ compute_client.virtual_machines.start(rgName, vmName) ++ return ++ ++ compute_client.virtual_machines.begin_start(rgName, vmName) ++ ++def get_vm_resource(compute_client, rgName, vmName): ++ try: ++ # Version is not available in azure-mgmt-compute version 14.0.0 until 27.2.0 ++ from azure.mgmt.compute import __version__ ++ except ImportError: ++ __version__ = "0.0.0" ++ ++ # use different implementation call based on used version ++ if (azure_dep_versions(__version__) <= azure_dep_versions(AZURE_RHEL8_COMPUTE_VERSION)): ++ return compute_client.virtual_machines.get(rgName, vmName, "instanceView") ++ ++ return compute_client.virtual_machines.get(resource_group_name=rgName, vm_name=vmName,expand="instanceView") ++ ++ + def get_fence_subnet_for_config(ipConfig, network_client): + subnetResource = get_azure_resource(ipConfig.subnet.id) + logging.debug("{get_fence_subnet_for_config} testing virtual network %s in resource group %s for a fence subnet" %(subnetResource.ResourceName, subnetResource.ResourceGroupName)) +@@ -155,7 +208,7 @@ + result = FENCE_STATE_ON + + try: +- vm = compute_client.virtual_machines.get(rgName, vmName, "instanceView") ++ vm = get_vm_resource(compute_client, rgName, vmName) + + allNICOK = True + for nicRef in vm.network_profile.network_interfaces: +@@ -182,7 +235,7 @@ + import msrestazure.azure_exceptions + logging.info("{set_network_state} Setting state %s for %s in resource group %s" % (operation, vmName, rgName)) + +- vm = compute_client.virtual_machines.get(rgName, vmName, "instanceView") ++ vm = get_vm_resource(compute_client,rgName, vmName) + + operations = [] + for nicRef in vm.network_profile.network_interfaces: +@@ -271,10 +324,72 @@ + + return config + ++# Function to fetch endpoints from metadata endpoint for azure_stack ++def get_cloud_from_arm_metadata_endpoint(arm_endpoint): ++ try: ++ import requests ++ session = requests.Session() ++ metadata_endpoint = arm_endpoint + "/metadata/endpoints?api-version=2015-01-01" ++ response = session.get(metadata_endpoint) ++ if response.status_code == 200: ++ metadata = response.json() ++ return { ++ "resource_manager": arm_endpoint, ++ "credential_scopes": [metadata.get("graphEndpoint") + "/.default"], ++ "authority_hosts": metadata['authentication'].get('loginEndpoint').replace("https://","") ++ } ++ else: ++ fail_usage("Failed to get cloud from metadata endpoint: %s - %s" % arm_endpoint, e) ++ except Exception as e: ++ fail_usage("Failed to get cloud from metadata endpoint: %s - %s" % arm_endpoint, e) ++ ++def get_azure_arm_endpoints(cloudName, authority): ++ cloudEnvironment = { ++ "authority_hosts": authority ++ } ++ ++ if cloudName == "AZURE_CHINA_CLOUD": ++ cloudEnvironment["resource_manager"] = "https://management.chinacloudapi.cn/" ++ cloudEnvironment["credential_scopes"] = ["https://management.chinacloudapi.cn/.default"] ++ return cloudEnvironment ++ ++ if cloudName == "AZURE_US_GOV_CLOUD": ++ cloudEnvironment["resource_manager"] = "https://management.usgovcloudapi.net/" ++ cloudEnvironment["credential_scopes"] = ["https://management.core.usgovcloudapi.net/.default"] ++ return cloudEnvironment ++ ++ if cloudName == "AZURE_PUBLIC_CLOUD": ++ cloudEnvironment["resource_manager"] = "https://management.azure.com/" ++ cloudEnvironment["credential_scopes"] = ["https://management.azure.com/.default"] ++ return cloudEnvironment ++ ++ + def get_azure_cloud_environment(config): +- cloud_environment = None +- if config.Cloud: ++ if (config.Cloud is None): ++ config.Cloud = "public" ++ ++ try: ++ from azure.identity import AzureAuthorityHosts ++ ++ azureCloudName = "AZURE_PUBLIC_CLOUD" ++ authorityHosts = AzureAuthorityHosts.AZURE_PUBLIC_CLOUD + if (config.Cloud.lower() == "china"): ++ azureCloudName = "AZURE_CHINA_CLOUD" ++ authorityHosts = AzureAuthorityHosts.AZURE_CHINA ++ elif (config.Cloud.lower() == "usgov"): ++ azureCloudName = "AZURE_US_GOV_CLOUD" ++ authorityHosts = AzureAuthorityHosts.AZURE_GOVERNMENT ++ elif (config.Cloud.lower() == "stack"): ++ # use custom function to call the azuer stack metadata endpoint to get required configuration. ++ return get_cloud_from_arm_metadata_endpoint(config.MetadataEndpoint) ++ ++ return get_azure_arm_endpoints(azureCloudName, authorityHosts) ++ ++ except ImportError: ++ if (config.Cloud.lower() == "public"): ++ from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD ++ cloud_environment = AZURE_PUBLIC_CLOUD ++ elif (config.Cloud.lower() == "china"): + from msrestazure.azure_cloud import AZURE_CHINA_CLOUD + cloud_environment = AZURE_CHINA_CLOUD + elif (config.Cloud.lower() == "germany"): +@@ -287,61 +402,44 @@ + from msrestazure.azure_cloud import get_cloud_from_metadata_endpoint + cloud_environment = get_cloud_from_metadata_endpoint(config.MetadataEndpoint) + +- return cloud_environment ++ authority_hosts = cloud_environment.endpoints.active_directory.replace("http://","") ++ return { ++ "resource_manager": cloud_environment.endpoints.resource_manager, ++ "credential_scopes": [cloud_environment.endpoints.active_directory_resource_id + "/.default"], ++ "authority_hosts": authority_hosts, ++ "cloud_environment": cloud_environment, ++ } + + def get_azure_credentials(config): + credentials = None + cloud_environment = get_azure_cloud_environment(config) +- if config.UseMSI and cloud_environment: +- try: +- from azure.identity import ManagedIdentityCredential +- credentials = ManagedIdentityCredential(cloud_environment=cloud_environment) +- except ImportError: +- from msrestazure.azure_active_directory import MSIAuthentication +- credentials = MSIAuthentication(cloud_environment=cloud_environment) +- elif config.UseMSI: ++ if config.UseMSI: + try: + from azure.identity import ManagedIdentityCredential +- credentials = ManagedIdentityCredential() ++ credentials = ManagedIdentityCredential(authority=cloud_environment["authority_hosts"]) + except ImportError: + from msrestazure.azure_active_directory import MSIAuthentication +- credentials = MSIAuthentication() +- elif cloud_environment: +- try: +- # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core) +- from azure.identity import ClientSecretCredential +- credentials = ClientSecretCredential( +- client_id = config.ApplicationId, +- client_secret = config.ApplicationKey, +- tenant_id = config.Tenantid, +- cloud_environment=cloud_environment +- ) +- except ImportError: +- # use old libraries ServicePrincipalCredentials (azure.common) if new one is not available +- from azure.common.credentials import ServicePrincipalCredentials +- credentials = ServicePrincipalCredentials( +- client_id = config.ApplicationId, +- secret = config.ApplicationKey, +- tenant = config.Tenantid, +- cloud_environment=cloud_environment +- ) +- else: +- try: +- # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core) +- from azure.identity import ClientSecretCredential +- credentials = ClientSecretCredential( +- client_id = config.ApplicationId, +- client_secret = config.ApplicationKey, +- tenant_id = config.Tenantid +- ) +- except ImportError: +- # use old libraries ServicePrincipalCredentials (azure.common) if new one is not available +- from azure.common.credentials import ServicePrincipalCredentials +- credentials = ServicePrincipalCredentials( +- client_id = config.ApplicationId, +- secret = config.ApplicationKey, +- tenant = config.Tenantid +- ) ++ credentials = MSIAuthentication(cloud_environment=cloud_environment["cloud_environment"]) ++ return credentials ++ ++ try: ++ # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core) ++ from azure.identity import ClientSecretCredential ++ credentials = ClientSecretCredential( ++ client_id = config.ApplicationId, ++ client_secret = config.ApplicationKey, ++ tenant_id = config.Tenantid, ++ authority=cloud_environment["authority_hosts"] ++ ) ++ except ImportError: ++ # use old libraries ServicePrincipalCredentials (azure.common) if new one is not available ++ from azure.common.credentials import ServicePrincipalCredentials ++ credentials = ServicePrincipalCredentials( ++ client_id = config.ApplicationId, ++ secret = config.ApplicationKey, ++ tenant = config.Tenantid, ++ cloud_environment=cloud_environment["cloud_environment"] ++ ) + + return credentials + +@@ -351,36 +449,40 @@ + cloud_environment = get_azure_cloud_environment(config) + credentials = get_azure_credentials(config) + +- if cloud_environment: +- if (config.Cloud.lower() == "stack") and not config.MetadataEndpoint: +- fail_usage("metadata-endpoint not specified") ++ # Try to read the default used api version from the installed package. ++ try: ++ compute_api_version = ComputeManagementClient.LATEST_PROFILE.get_profile_dict()["azure.mgmt.compute.ComputeManagementClient"]["virtual_machines"] ++ except Exception as e: ++ compute_api_version = ComputeManagementClient.DEFAULT_API_VERSION ++ logging.debug("{get_azure_compute_client} Failed to get the latest profile: %s using the default api version %s" % (e, compute_api_version)) + +- try: +- from azure.profiles import KnownProfiles +- if (config.Cloud.lower() == "stack"): +- client_profile = KnownProfiles.v2020_09_01_hybrid +- credential_scope = cloud_environment.endpoints.active_directory_resource_id + "/.default" +- else: +- client_profile = KnownProfiles.default +- credential_scope = cloud_environment.endpoints.resource_manager + "/.default" +- compute_client = ComputeManagementClient( +- credentials, +- config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager, +- profile=client_profile, +- credential_scopes=[credential_scope], +- ) +- except TypeError: +- compute_client = ComputeManagementClient( +- credentials, +- config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager +- ) +- else: ++ logging.debug("{get_azure_compute_client} use virtual_machine api version: %s" %(compute_api_version)) ++ ++ if (config.Cloud.lower() == "stack") and not config.MetadataEndpoint: ++ fail_usage("metadata-endpoint not specified") ++ ++ try: ++ from azure.profiles import KnownProfiles ++ if (config.Cloud.lower() == "stack"): ++ client_profile = KnownProfiles.v2020_09_01_hybrid ++ else: ++ client_profile = KnownProfiles.default + compute_client = ComputeManagementClient( + credentials, +- config.SubscriptionId ++ config.SubscriptionId, ++ base_url=cloud_environment["resource_manager"], ++ profile=client_profile, ++ credential_scopes=cloud_environment["credential_scopes"], ++ api_version=compute_api_version + ) ++ except TypeError: ++ compute_client = ComputeManagementClient( ++ credentials, ++ config.SubscriptionId, ++ base_url=cloud_environment["resource_manager"], ++ api_version=compute_api_version ++ ) ++ + return compute_client + + def get_azure_network_client(config): +@@ -389,34 +491,31 @@ + cloud_environment = get_azure_cloud_environment(config) + credentials = get_azure_credentials(config) + +- if cloud_environment: +- if (config.Cloud.lower() == "stack") and not config.MetadataEndpoint: +- fail_usage("metadata-endpoint not specified") ++ if (config.Cloud.lower() == "stack") and not config.MetadataEndpoint: ++ fail_usage("metadata-endpoint not specified") + +- try: +- from azure.profiles import KnownProfiles +- if (config.Cloud.lower() == "stack"): +- client_profile = KnownProfiles.v2020_09_01_hybrid +- credential_scope = cloud_environment.endpoints.active_directory_resource_id + "/.default" +- else: +- client_profile = KnownProfiles.default +- credential_scope = cloud_environment.endpoints.resource_manager + "/.default" +- network_client = NetworkManagementClient( +- credentials, +- config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager, +- profile=client_profile, +- credential_scopes=[credential_scope], +- ) +- except TypeError: +- network_client = NetworkManagementClient( +- credentials, +- config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager +- ) ++ ++ from azure.profiles import KnownProfiles ++ ++ if (config.Cloud.lower() == "stack"): ++ client_profile = KnownProfiles.v2020_09_01_hybrid + else: ++ client_profile = KnownProfiles.default ++ ++ try: ++ network_client = NetworkManagementClient( ++ credentials, ++ config.SubscriptionId, ++ base_url=cloud_environment["resource_manager"], ++ profile=client_profile, ++ credential_scopes=cloud_environment["credential_scopes"], ++ api_version=NETWORK_MGMT_CLIENT_API_VERSION ++ ) ++ except TypeError: + network_client = NetworkManagementClient( + credentials, +- config.SubscriptionId ++ config.SubscriptionId, ++ base_url=cloud_environment["resource_manager"], ++ api_version=NETWORK_MGMT_CLIENT_API_VERSION + ) + return network_client +--- a/agents/azure_arm/fence_azure_arm.py 2025-01-30 14:59:48.218366743 +0100 ++++ b/agents/azure_arm/fence_azure_arm.py 2025-01-28 13:12:00.758567141 +0100 +@@ -2,6 +2,7 @@ + + import sys, re + sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++sys.path.insert(1, '/usr/lib/fence-agents/support/azure') + try: + import pexpect + except: +@@ -20,7 +21,7 @@ + if clients: + compute_client = clients[0] + rgName = options["--resourceGroup"] +- vms = compute_client.virtual_machines.list(rgName) ++ vms = azure_fence.get_vm_list(compute_client,rgName) + try: + for vm in vms: + result[vm.name] = ("", None) +@@ -36,7 +37,7 @@ + rgName = options["--resourceGroup"] + + try: +- vms = compute_client.virtual_machines.list(rgName) ++ vms = azure_fence.get_vm_list(compute_client,rgName) + except Exception as e: + fail_usage("Failed: %s" % e) + +@@ -77,7 +78,7 @@ + + powerState = "unknown" + try: +- vmStatus = compute_client.virtual_machines.get(rgName, vmName, "instanceView") ++ vmStatus = azure_fence.get_vm_resource(compute_client, rgName, vmName) + except Exception as e: + fail_usage("Failed: %s" % e) + +@@ -120,23 +121,10 @@ + + if (options["--action"]=="off"): + logging.info("Poweroff " + vmName + " in resource group " + rgName) +- try: +- # try new API version first +- compute_client.virtual_machines.begin_power_off(rgName, vmName, skip_shutdown=True) +- except AttributeError: +- # use older API verson if it fails +- logging.debug("Poweroff " + vmName + " did not work via 'virtual_machines.begin_power_off. Trying virtual_machines.power_off'.") +- compute_client.virtual_machines.power_off(rgName, vmName, skip_shutdown=True) ++ azure_fence.do_vm_power_off(compute_client, rgName, vmName, True) + elif (options["--action"]=="on"): + logging.info("Starting " + vmName + " in resource group " + rgName) +- try: +- # try new API version first +- compute_client.virtual_machines.begin_start(rgName, vmName) +- except AttributeError: +- # use older API verson if it fails +- logging.debug("Starting " + vmName + " did not work via 'virtual_machines.begin_start. Trying virtual_machines.start'.") +- compute_client.virtual_machines.start(rgName, vmName) +- ++ azure_fence.do_vm_start(compute_client, rgName, vmName) + + def define_new_opts(): + all_opt["resourceGroup"] = { +@@ -256,7 +244,7 @@ + except ImportError: + fail_usage("Azure Resource Manager Python SDK not found or not accessible") + except Exception as e: +- fail_usage("Failed: %s" % re.sub("^, ", "", str(e))) ++ fail_usage("Failed: %s" % re.sub(r"^, ", r"", str(e))) + + if "--network-fencing" in options: + # use off-action to quickly return off once network is fenced instead of diff --git a/RHEL-83488-fence_ibm_vpc-refresh-bearer-token.patch b/RHEL-83488-fence_ibm_vpc-refresh-bearer-token.patch new file mode 100644 index 0000000000000000000000000000000000000000..eb8568f30a484483d8b419a22684e1b438f3d5f8 --- /dev/null +++ b/RHEL-83488-fence_ibm_vpc-refresh-bearer-token.patch @@ -0,0 +1,38 @@ +From 293b3961149f680ead9028e6719c405957abc6b7 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 13 Mar 2025 16:40:30 +0100 +Subject: [PATCH] fence_ibm_vpc: refresh bearer-token in connect() if token + data is corrupt, and avoid edge-case of writing empty token file + +--- + agents/ibm_vpc/fence_ibm_vpc.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/agents/ibm_vpc/fence_ibm_vpc.py b/agents/ibm_vpc/fence_ibm_vpc.py +index 035a3235a..efda5eed7 100755 +--- a/agents/ibm_vpc/fence_ibm_vpc.py ++++ b/agents/ibm_vpc/fence_ibm_vpc.py +@@ -105,6 +105,8 @@ def get_bearer_token(conn, options): + except Exception as e: + logging.error("Failed: Unable to authenticate: {}".format(e)) + fail(EC_LOGIN_DENIED) ++ if len(token) < 1: ++ fail(EC_LOGIN_DENIED) + file_obj.write(token) + finally: + os.umask(oldumask) +@@ -152,6 +154,14 @@ def connect(opt): + # set auth token for later requests + conn = set_bearer_token(conn, bearer_token) + ++ try: ++ command = "instances?version=2021-05-25&generation=2&limit=1" ++ res = send_command(conn, opt, command) ++ except Exception as e: ++ logging.warning("Failed to login/connect. Updating bearer-token.") ++ bearer_token = get_bearer_token(conn, opt) ++ conn = set_bearer_token(conn, bearer_token) ++ + return conn + + def disconnect(conn): diff --git a/RHEL-92695-1-fence_sbd-improve-error-handling.patch b/RHEL-92695-1-fence_sbd-improve-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..c9ab5ad2c495393e08657554c4f34c4e5cc1ffb1 --- /dev/null +++ b/RHEL-92695-1-fence_sbd-improve-error-handling.patch @@ -0,0 +1,296 @@ +From ab1de07902d9f380c10405d6ddac3aeb43838c86 Mon Sep 17 00:00:00 2001 +From: Klaus Wenninger +Date: Thu, 28 Jul 2022 15:33:12 +0200 +Subject: [PATCH] fence_sbd: improve error handling + +basically when using 3 disks be happy with 2 answers +but give it 5s at least to collect all answers +increase default power-timeout to 30s so that waiting +those 5s still allows us to get done sending the +reboot + +RHBZ#2033671 +--- + agents/sbd/fence_sbd.py | 77 +++++++++++++-------- + lib/fencing.py.py | 109 ++++++++++++++++++++++++++++++ + tests/data/metadata/fence_sbd.xml | 2 +- + 3 files changed, 158 insertions(+), 30 deletions(-) + +diff --git a/agents/sbd/fence_sbd.py b/agents/sbd/fence_sbd.py +index 0c876b16e..2b0127d55 100644 +--- a/agents/sbd/fence_sbd.py ++++ b/agents/sbd/fence_sbd.py +@@ -5,7 +5,7 @@ + import os + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") +-from fencing import fail_usage, run_command, fence_action, all_opt ++from fencing import fail_usage, run_commands, fence_action, all_opt + from fencing import atexit_handler, check_input, process_input, show_docs + from fencing import run_delay + import itertools +@@ -81,7 +81,7 @@ def check_sbd_device(options, device_path): + + cmd = "%s -d %s dump" % (options["--sbd-path"], device_path) + +- (return_code, out, err) = run_command(options, cmd) ++ (return_code, out, err) = run_commands(options, [ cmd ]) + + for line in itertools.chain(out.split("\n"), err.split("\n")): + if len(line) == 0: +@@ -94,21 +94,35 @@ def check_sbd_device(options, device_path): + + return DEVICE_INIT + ++ + def generate_sbd_command(options, command, arguments=None): + """Generates a sbd command based on given arguments. + + Return Value: +- generated sbd command (string) ++ generated list of sbd commands (strings) depending ++ on command multiple commands with a device each ++ or a single command with multiple devices + """ +- cmd = options["--sbd-path"] ++ cmds = [] ++ ++ if not command in ["list", "dump"]: ++ cmd = options["--sbd-path"] + +- # add "-d" for each sbd device +- for device in parse_sbd_devices(options): +- cmd += " -d %s" % device ++ # add "-d" for each sbd device ++ for device in parse_sbd_devices(options): ++ cmd += " -d %s" % device + +- cmd += " %s %s" % (command, arguments) ++ cmd += " %s %s" % (command, arguments) ++ cmds.append(cmd) ++ ++ else: ++ for device in parse_sbd_devices(options): ++ cmd = options["--sbd-path"] ++ cmd += " -d %s" % device ++ cmd += " %s %s" % (command, arguments) ++ cmds.append(cmd) + +- return cmd ++ return cmds + + def send_sbd_message(conn, options, plug, message): + """Sends a message to all sbd devices. +@@ -128,7 +142,7 @@ def send_sbd_message(conn, options, plug, message): + arguments = "%s %s" % (plug, message) + cmd = generate_sbd_command(options, "message", arguments) + +- (return_code, out, err) = run_command(options, cmd) ++ (return_code, out, err) = run_commands(options, cmd) + + return (return_code, out, err) + +@@ -147,7 +161,7 @@ def get_msg_timeout(options): + + cmd = generate_sbd_command(options, "dump") + +- (return_code, out, err) = run_command(options, cmd) ++ (return_code, out, err) = run_commands(options, cmd) + + for line in itertools.chain(out.split("\n"), err.split("\n")): + if len(line) == 0: +@@ -288,7 +302,7 @@ def get_node_list(conn, options): + + cmd = generate_sbd_command(options, "list") + +- (return_code, out, err) = run_command(options, cmd) ++ (return_code, out, err) = run_commands(options, cmd) + + for line in out.split("\n"): + if len(line) == 0: +@@ -356,6 +370,7 @@ def main(): + + all_opt["method"]["default"] = "cycle" + all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)" ++ all_opt["power_timeout"]["default"] = "30" + + options = check_input(device_opt, process_input(device_opt)) + +@@ -376,23 +391,27 @@ def main(): + + # We need to check if the provided sbd_devices exists. We need to do + # that for every given device. +- for device_path in parse_sbd_devices(options): +- logging.debug("check device \"%s\"", device_path) +- +- return_code = check_sbd_device(options, device_path) +- if PATH_NOT_EXISTS == return_code: +- logging.error("\"%s\" does not exist", device_path) +- elif PATH_NOT_BLOCK == return_code: +- logging.error("\"%s\" is not a valid block device", device_path) +- elif DEVICE_NOT_INIT == return_code: +- logging.error("\"%s\" is not initialized", device_path) +- elif DEVICE_INIT != return_code: +- logging.error("UNKNOWN error while checking \"%s\"", device_path) +- +- # If we get any error while checking the device we need to exit at this +- # point. +- if DEVICE_INIT != return_code: +- exit(return_code) ++ # Just for the case we are really rebooting / powering off a device ++ # (pacemaker as well uses the list command to generate a dynamic list) ++ # we leave it to sbd to try and decide if it was successful ++ if not options["--action"] in ["reboot", "off", "list"]: ++ for device_path in parse_sbd_devices(options): ++ logging.debug("check device \"%s\"", device_path) ++ ++ return_code = check_sbd_device(options, device_path) ++ if PATH_NOT_EXISTS == return_code: ++ logging.error("\"%s\" does not exist", device_path) ++ elif PATH_NOT_BLOCK == return_code: ++ logging.error("\"%s\" is not a valid block device", device_path) ++ elif DEVICE_NOT_INIT == return_code: ++ logging.error("\"%s\" is not initialized", device_path) ++ elif DEVICE_INIT != return_code: ++ logging.error("UNKNOWN error while checking \"%s\"", device_path) ++ ++ # If we get any error while checking the device we need to exit at this ++ # point. ++ if DEVICE_INIT != return_code: ++ exit(return_code) + + # we check against the defined timeouts. If the pacemaker timeout is smaller + # then that defined within sbd we should report this. +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index b746ede8b..fc3679e33 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -1088,6 +1088,115 @@ def is_executable(path): + return True + return False + ++def run_commands(options, commands, timeout=None, env=None, log_command=None): ++ # inspired by psutils.wait_procs (BSD License) ++ def check_gone(proc, timeout): ++ try: ++ returncode = proc.wait(timeout=timeout) ++ except subprocess.TimeoutExpired: ++ pass ++ else: ++ if returncode is not None or not proc.is_running(): ++ proc.returncode = returncode ++ gone.add(proc) ++ ++ if timeout is None and "--power-timeout" in options: ++ timeout = options["--power-timeout"] ++ if timeout == 0: ++ timeout = None ++ if timeout is not None: ++ timeout = float(timeout) ++ ++ time_start = time.time() ++ procs = [] ++ status = None ++ pipe_stdout = "" ++ pipe_stderr = "" ++ ++ for command in commands: ++ logging.info("Executing: %s\n", log_command or command) ++ ++ try: ++ process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, ++ # decodes newlines and in python3 also converts bytes to str ++ universal_newlines=(sys.version_info[0] > 2)) ++ except OSError: ++ fail_usage("Unable to run %s\n" % command) ++ ++ procs.append(process) ++ ++ gone = set() ++ alive = set(procs) ++ ++ while True: ++ if alive: ++ max_timeout = 2.0 / len(alive) ++ for proc in alive: ++ if timeout is not None: ++ if time.time()-time_start >= timeout: ++ # quickly go over the rest ++ max_timeout = 0 ++ check_gone(proc, max_timeout) ++ alive = alive - gone ++ ++ if not alive: ++ break ++ ++ if time.time()-time_start < 5.0: ++ # give it at least 5s to get a complete answer ++ # afterwards we're OK with a quorate answer ++ continue ++ ++ if len(gone) > len(alive): ++ good_cnt = 0 ++ for proc in gone: ++ if proc.returncode == 0: ++ good_cnt += 1 ++ # a positive result from more than half is fine ++ if good_cnt > len(procs)/2: ++ break ++ ++ if timeout is not None: ++ if time.time() - time_start >= timeout: ++ logging.debug("Stop waiting after %s\n", str(timeout)) ++ break ++ ++ logging.debug("Done: %d gone, %d alive\n", len(gone), len(alive)) ++ ++ for proc in gone: ++ if (status != 0): ++ status = proc.returncode ++ # hand over the best status we have ++ # but still collect as much stdout/stderr feedback ++ # avoid communicate as we know already process ++ # is gone and it seems to block when there ++ # are D state children we don't get rid off ++ os.set_blocking(proc.stdout.fileno(), False) ++ os.set_blocking(proc.stderr.fileno(), False) ++ try: ++ pipe_stdout += proc.stdout.read() ++ except: ++ pass ++ try: ++ pipe_stderr += proc.stderr.read() ++ except: ++ pass ++ proc.stdout.close() ++ proc.stderr.close() ++ ++ for proc in alive: ++ proc.kill() ++ ++ if status is None: ++ fail(EC_TIMED_OUT, stop=(int(options.get("retry", 0)) < 1)) ++ status = EC_TIMED_OUT ++ pipe_stdout = "" ++ pipe_stderr = "timed out" ++ ++ logging.debug("%s %s %s\n", str(status), str(pipe_stdout), str(pipe_stderr)) ++ ++ return (status, pipe_stdout, pipe_stderr) ++ + def run_command(options, command, timeout=None, env=None, log_command=None): + if timeout is None and "--power-timeout" in options: + timeout = options["--power-timeout"] +diff --git a/tests/data/metadata/fence_sbd.xml b/tests/data/metadata/fence_sbd.xml +index 516370c40..7248b864a 100644 +--- a/tests/data/metadata/fence_sbd.xml ++++ b/tests/data/metadata/fence_sbd.xml +@@ -87,7 +87,7 @@ + + + +- ++ + Test X seconds for status change after ON/OFF + + diff --git a/RHEL-92695-2-fence_sbd-get-devices-from-SBD_DEVICE-if-devices-parameter-isnt-set.patch b/RHEL-92695-2-fence_sbd-get-devices-from-SBD_DEVICE-if-devices-parameter-isnt-set.patch new file mode 100644 index 0000000000000000000000000000000000000000..f68fe0bbaf6f790e2f7775fa0a507a67d85e213d --- /dev/null +++ b/RHEL-92695-2-fence_sbd-get-devices-from-SBD_DEVICE-if-devices-parameter-isnt-set.patch @@ -0,0 +1,160 @@ +From f73b6b4465de1bf2b2887efd3b9767d3f36abd24 Mon Sep 17 00:00:00 2001 +From: xin liang +Date: Fri, 26 Jul 2024 10:49:55 +0800 +Subject: [PATCH 1/3] fence_sbd: if sbd devices are not specified with option, + read SBD_DEVICE + +from environment +--- + agents/sbd/fence_sbd.py | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/agents/sbd/fence_sbd.py b/agents/sbd/fence_sbd.py +index bf95bb72e..c36220295 100644 +--- a/agents/sbd/fence_sbd.py ++++ b/agents/sbd/fence_sbd.py +@@ -342,7 +342,7 @@ def define_new_opts(): + "longopt" : "devices", + "help":"--devices=[device_a,device_b] \ + Comma separated list of sbd devices", +- "required" : "1", ++ "required" : "0", + "shortdesc" : "SBD Device", + "order": 1 + } +@@ -382,10 +382,14 @@ def main(): + docs["vendorurl"] = "" + show_docs(options, docs) + +- # We need to check if --devices is given and not empty. ++ # If not specified then read SBD_DEVICE from environment + if "--devices" not in options: +- fail_usage("No SBD devices specified. \ +- At least one SBD device is required.") ++ dev_list = os.getenv("SBD_DEVICE") ++ if dev_list: ++ options["--devices"] = ",".join(dev_list.split(";")) ++ else: ++ fail_usage("No SBD devices specified. \ ++ At least one SBD device is required.") + + run_delay(options) + + +From 744d534225b51db26058660b753df2991b9356a0 Mon Sep 17 00:00:00 2001 +From: xin liang +Date: Fri, 26 Jul 2024 17:45:07 +0800 +Subject: [PATCH 2/3] fence_sbd: Update fence_sbd.xml + +--- + tests/data/metadata/fence_sbd.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/data/metadata/fence_sbd.xml b/tests/data/metadata/fence_sbd.xml +index 82ded25b9..c2daf0c54 100644 +--- a/tests/data/metadata/fence_sbd.xml ++++ b/tests/data/metadata/fence_sbd.xml +@@ -8,7 +8,7 @@ + + Fencing action + +- ++ + + + SBD Device + +From 06457f95a4d89d4b6a856ae14ccbcda4d357bef6 Mon Sep 17 00:00:00 2001 +From: xin liang +Date: Tue, 10 Dec 2024 10:00:00 +0800 +Subject: [PATCH 3/3] fence_sbd: Check if the sbd daemon is running before + using SBD_DEVICE enviroment variable + +And add @SBDPID_PATH@ for the sbd daemon pid file path +--- + agents/sbd/fence_sbd.py | 31 ++++++++++++++++++++++++++++++- + configure.ac | 2 ++ + make/fencebuild.mk | 1 + + 3 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/agents/sbd/fence_sbd.py b/agents/sbd/fence_sbd.py +index c36220295..bebc7fae1 100644 +--- a/agents/sbd/fence_sbd.py ++++ b/agents/sbd/fence_sbd.py +@@ -14,6 +14,7 @@ + DEVICE_NOT_INIT = -3 + PATH_NOT_EXISTS = -1 + PATH_NOT_BLOCK = -2 ++SBD_PID_FILE = "@SBDPID_PATH@" + + def is_block_device(filename): + """Checks if a given path is a valid block device +@@ -356,6 +357,34 @@ def define_new_opts(): + "order": 200 + } + ++ ++def sbd_daemon_is_running(): ++ """Check if the sbd daemon is running ++ """ ++ if not os.path.exists(SBD_PID_FILE): ++ logging.info("SBD PID file %s does not exist", SBD_PID_FILE) ++ return False ++ ++ try: ++ with open(SBD_PID_FILE, "r") as pid_file: ++ pid = int(pid_file.read().strip()) ++ except Exception as e: ++ logging.error("Failed to read PID file %s: %s", SBD_PID_FILE, e) ++ return False ++ ++ try: ++ # send signal 0 to check if the process is running ++ os.kill(pid, 0) ++ except ProcessLookupError: ++ logging.info("SBD daemon is not running") ++ return False ++ except Exception as e: ++ logging.error("Failed to send signal 0 to PID %d: %s", pid, e) ++ return False ++ ++ return True ++ ++ + def main(): + """Main function + """ +@@ -385,7 +414,7 @@ def main(): + # If not specified then read SBD_DEVICE from environment + if "--devices" not in options: + dev_list = os.getenv("SBD_DEVICE") +- if dev_list: ++ if dev_list and sbd_daemon_is_running(): + options["--devices"] = ",".join(dev_list.split(";")) + else: + fail_usage("No SBD devices specified. \ +diff --git a/configure.ac b/configure.ac +index 6b7322419..0425a9d21 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -145,6 +145,8 @@ eval FENCETMPDIR="`eval echo ${FENCETMPDIR}`" + AC_DEFINE_UNQUOTED(FENCETMPDIR,"$FENCETMPDIR", Where Fence agents keep state files) + AC_SUBST(FENCETMPDIR) + ++SBDPID_PATH=${localstatedir}/run/sbd.pid ++AC_SUBST(SBDPID_PATH) + + if test "x$AGENTS_LIST" = x; then + AC_ERROR([No agents selected]) +diff --git a/make/fencebuild.mk b/make/fencebuild.mk +index 9a3c6d6dd..bc9259190 100644 +--- a/make/fencebuild.mk ++++ b/make/fencebuild.mk +@@ -9,6 +9,7 @@ define gen_agent_from_py + -e 's#@''SBINDIR@#${sbindir}#g' \ + -e 's#@''LIBEXECDIR@#${libexecdir}#g' \ + -e 's#@''FENCETMPDIR@#${FENCETMPDIR}#g' \ ++ -e 's#@''SBDPID_PATH@#${SBDPID_PATH}#g' \ + -e 's#@''IPMITOOL_PATH@#${IPMITOOL_PATH}#g' \ + -e 's#@''OPENSTACK_PATH@#${OPENSTACK_PATH}#g' \ + -e 's#@''AMTTOOL_PATH@#${AMTTOOL_PATH}#g' \ diff --git a/RHEL-95903-pkg_resources-suppress-UserWarning.patch b/RHEL-95903-pkg_resources-suppress-UserWarning.patch new file mode 100644 index 0000000000000000000000000000000000000000..d1972fd1fed6921abee2e5f79fc2875c57c01d82 --- /dev/null +++ b/RHEL-95903-pkg_resources-suppress-UserWarning.patch @@ -0,0 +1,38 @@ +--- a/google/pkg_resources/__init__.py 2025-06-12 09:41:54.535219946 +0000 ++++ b/google/pkg_resources/__init__.py 2025-06-12 09:42:07.508276281 +0000 +@@ -95,16 +95,6 @@ + from _typeshed.importlib import LoaderProtocol + from typing_extensions import Self, TypeAlias + +-warnings.warn( +- "pkg_resources is deprecated as an API. " +- "See https://setuptools.pypa.io/en/latest/pkg_resources.html. " +- "The pkg_resources package is slated for removal as early as " +- "2025-11-30. Refrain from using this package or pin to " +- "Setuptools<81.", +- UserWarning, +- stacklevel=2, +-) +- + _T = TypeVar("_T") + _DistributionT = TypeVar("_DistributionT", bound="Distribution") + # Type aliases +--- a/kubevirt/pkg_resources/__init__.py 2025-06-12 09:41:54.535219946 +0000 ++++ b/kubevirt/pkg_resources/__init__.py 2025-06-12 09:42:07.508276281 +0000 +@@ -95,16 +95,6 @@ + from _typeshed.importlib import LoaderProtocol + from typing_extensions import Self, TypeAlias + +-warnings.warn( +- "pkg_resources is deprecated as an API. " +- "See https://setuptools.pypa.io/en/latest/pkg_resources.html. " +- "The pkg_resources package is slated for removal as early as " +- "2025-11-30. Refrain from using this package or pin to " +- "Setuptools<81.", +- UserWarning, +- stacklevel=2, +-) +- + _T = TypeVar("_T") + _DistributionT = TypeVar("_DistributionT", bound="Distribution") + # Type aliases diff --git a/RHEL-96183-fence_kubevirt-force-off.patch b/RHEL-96183-fence_kubevirt-force-off.patch new file mode 100644 index 0000000000000000000000000000000000000000..ac2e281693c46b35a0358ada864ecaeedfd4eb78 --- /dev/null +++ b/RHEL-96183-fence_kubevirt-force-off.patch @@ -0,0 +1,23 @@ +From b6e05c57a73e5d9bdde7d133ba7ec43737a7c6b7 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 25 Feb 2025 16:11:32 +0100 +Subject: [PATCH] fence_kubevirt: set grace_period_seconds=0 to immediately + power off the node + +--- + agents/kubevirt/fence_kubevirt.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/kubevirt/fence_kubevirt.py b/agents/kubevirt/fence_kubevirt.py +index e3817b0fb..8ba8ce8db 100755 +--- a/agents/kubevirt/fence_kubevirt.py ++++ b/agents/kubevirt/fence_kubevirt.py +@@ -108,7 +108,7 @@ def define_new_opts(): + def virtctl_vm_action(conn, action, namespace, name, apiversion): + path = '/apis/subresources.{api_version}/namespaces/{namespace}/virtualmachines/{name}/{action}' + path = path.format(api_version=apiversion, namespace=namespace, name=name, action=action) +- return conn.request('put', path, header_params={'accept': '*/*'}) ++ return conn.request('put', path, header_params={'accept': '*/*'}, body={'gracePeriod': 0} if action == 'stop' else None) + + # Main agent method + def main(): diff --git a/adal-1.2.7-py2.py3-none-any.whl b/adal-1.2.7-py2.py3-none-any.whl deleted file mode 100644 index b9ce893a78db5424409e7a0d39b81a362fb3d7a0..0000000000000000000000000000000000000000 Binary files a/adal-1.2.7-py2.py3-none-any.whl and /dev/null differ diff --git a/awscrt-0.11.13-cp36-cp36m-manylinux1_x86_64.whl b/awscrt-0.11.13-cp36-cp36m-manylinux1_x86_64.whl deleted file mode 100644 index 15c254520ed8f71ba86e8dcae2fd4f4d8655ae5a..0000000000000000000000000000000000000000 Binary files a/awscrt-0.11.13-cp36-cp36m-manylinux1_x86_64.whl and /dev/null differ diff --git a/awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl b/awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl deleted file mode 100644 index 1e75db4b6db074a5513e8c7d216d39a0aaa09582..0000000000000000000000000000000000000000 Binary files a/awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl and /dev/null differ diff --git a/azure-common-1.1.28.zip b/azure-common-1.1.28.zip new file mode 100644 index 0000000000000000000000000000000000000000..db2e2ea3bf1f1fb78237356cb72ecb5d3e705caa Binary files /dev/null and b/azure-common-1.1.28.zip differ diff --git a/azure-identity-1.10.0.zip b/azure-identity-1.10.0.zip deleted file mode 100644 index d30f2052aa1957d85915286d2abbe2f8cd300bdf..0000000000000000000000000000000000000000 Binary files a/azure-identity-1.10.0.zip and /dev/null differ diff --git a/azure_common-1.1.27-py2.py3-none-any.whl b/azure_common-1.1.27-py2.py3-none-any.whl deleted file mode 100644 index c6541d2d9420c651223cfaf0dbdd349d7e5ced02..0000000000000000000000000000000000000000 Binary files a/azure_common-1.1.27-py2.py3-none-any.whl and /dev/null differ diff --git a/azure_core-1.15.0-py2.py3-none-any.whl b/azure_core-1.15.0-py2.py3-none-any.whl deleted file mode 100644 index 4b5a6976c19908fd79c2823a2e9f97c354d82347..0000000000000000000000000000000000000000 Binary files a/azure_core-1.15.0-py2.py3-none-any.whl and /dev/null differ diff --git a/azure_mgmt_compute-21.0.0-py2.py3-none-any.whl b/azure_mgmt_compute-21.0.0-py2.py3-none-any.whl deleted file mode 100644 index 9d693e6b704f15e2f3491bd72b25cae3af2aa3f3..0000000000000000000000000000000000000000 Binary files a/azure_mgmt_compute-21.0.0-py2.py3-none-any.whl and /dev/null differ diff --git a/azure_mgmt_core-1.2.2-py2.py3-none-any.whl b/azure_mgmt_core-1.2.2-py2.py3-none-any.whl deleted file mode 100644 index 157429b290eb56faf62f0c68ef8cf7d465fd8b6c..0000000000000000000000000000000000000000 Binary files a/azure_mgmt_core-1.2.2-py2.py3-none-any.whl and /dev/null differ diff --git a/azure_mgmt_network-19.0.0-py2.py3-none-any.whl b/azure_mgmt_network-19.0.0-py2.py3-none-any.whl deleted file mode 100644 index bd9dab60fb0e40db2584a40c1cc0220c07345768..0000000000000000000000000000000000000000 Binary files a/azure_mgmt_network-19.0.0-py2.py3-none-any.whl and /dev/null differ diff --git a/botocore-2.0.0dev123.zip b/botocore-2.0.0dev123.zip deleted file mode 100644 index c9023980df4192ff85bb067aff706322e707d93f..0000000000000000000000000000000000000000 Binary files a/botocore-2.0.0dev123.zip and /dev/null differ diff --git a/bz2217902-1-kubevirt-fix-bundled-dateutil-CVE-2007-4559.patch b/bz2217902-1-kubevirt-fix-bundled-dateutil-CVE-2007-4559.patch index 56494f24ec55b66b9dab2c558bc8167da93d4efe..97707a57a8341007a4c3ea814fe25d54f6d33889 100644 --- a/bz2217902-1-kubevirt-fix-bundled-dateutil-CVE-2007-4559.patch +++ b/bz2217902-1-kubevirt-fix-bundled-dateutil-CVE-2007-4559.patch @@ -12,5 +12,6 @@ + # Fallback to a possibly dangerous extraction (before PEP 706) + tf.extract(name, tmpdir) filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) + + _run_zic(zonedir, filepaths) + diff --git a/bz2217902-2-aws-awscli-azure-fix-bundled-dateutil-CVE-2007-4559.patch b/bz2217902-2-aws-azure-fix-bundled-dateutil-CVE-2007-4559.patch similarity index 59% rename from bz2217902-2-aws-awscli-azure-fix-bundled-dateutil-CVE-2007-4559.patch rename to bz2217902-2-aws-azure-fix-bundled-dateutil-CVE-2007-4559.patch index 831ca45f7656c47650f4356e468507ff258b0cc5..c82999126b0b6e5ee9b89bd80d9381344d3371db 100644 --- a/bz2217902-2-aws-awscli-azure-fix-bundled-dateutil-CVE-2007-4559.patch +++ b/bz2217902-2-aws-azure-fix-bundled-dateutil-CVE-2007-4559.patch @@ -12,24 +12,9 @@ + # Fallback to a possibly dangerous extraction (before PEP 706) + tf.extract(name, tmpdir) filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) ---- a/awscli/dateutil/zoneinfo/rebuild.py 2023-01-26 16:29:30.000000000 +0100 -+++ b/awscli/dateutil/zoneinfo/rebuild.py 2023-07-19 10:12:42.277559948 +0200 -@@ -21,7 +21,12 @@ - try: - with TarFile.open(filename) as tf: - for name in zonegroups: -- tf.extract(name, tmpdir) -+ if hasattr(tarfile, 'data_filter'): -+ # Python with CVE-2007-4559 mitigation (PEP 706) -+ tf.extract(name, tmpdir, filter='data') -+ else: -+ # Fallback to a possibly dangerous extraction (before PEP 706) -+ tf.extract(name, tmpdir) - filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) + + _run_zic(zonedir, filepaths) + --- a/azure/dateutil/zoneinfo/rebuild.py 2023-01-26 16:29:30.000000000 +0100 +++ b/azure/dateutil/zoneinfo/rebuild.py 2023-07-19 10:12:42.277559948 +0200 @@ -21,7 +21,12 @@ @@ -44,5 +29,5 @@ + # Fallback to a possibly dangerous extraction (before PEP 706) + tf.extract(name, tmpdir) filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) + + _run_zic(zonedir, filepaths) diff --git a/cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl b/cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl deleted file mode 100644 index a6271bc46c1af307dc70a59e9308477b9db34926..0000000000000000000000000000000000000000 Binary files a/cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl and /dev/null differ diff --git a/colorama-0.4.3-py2.py3-none-any.whl b/colorama-0.4.3-py2.py3-none-any.whl deleted file mode 100644 index 59243efc8577335608dc95a5d782f5f91ee6dba3..0000000000000000000000000000000000000000 Binary files a/colorama-0.4.3-py2.py3-none-any.whl and /dev/null differ diff --git a/cryptography-3.3.2-cp36-abi3-manylinux1_x86_64.whl b/cryptography-3.3.2-cp36-abi3-manylinux1_x86_64.whl deleted file mode 100644 index 3893155d03aab66e1d58d99663105968817ca441..0000000000000000000000000000000000000000 Binary files a/cryptography-3.3.2-cp36-abi3-manylinux1_x86_64.whl and /dev/null differ diff --git a/dist b/dist index 635820538d487259e6dce4499a172e3066902da5..1f9f8c9bbdfdaf483d0bfdf0bf3c48d3cad6b1b9 100644 --- a/dist +++ b/dist @@ -1 +1 @@ -an9_5 +an9_6 diff --git a/distro-1.5.0-py2.py3-none-any.whl b/distro-1.5.0-py2.py3-none-any.whl deleted file mode 100644 index 508a4c81d77885214c70d674809fe6fed5a3e5b9..0000000000000000000000000000000000000000 Binary files a/distro-1.5.0-py2.py3-none-any.whl and /dev/null differ diff --git a/docutils-0.15.2-py3-none-any.whl b/docutils-0.15.2-py3-none-any.whl deleted file mode 100644 index 1125704732c12fb737af79709eeb7884ce66face..0000000000000000000000000000000000000000 Binary files a/docutils-0.15.2-py3-none-any.whl and /dev/null differ diff --git a/download b/download index 420fb52ce9714285610454512591f6e99481a46d..8752c666be20cb94f4fd04ef392bbead5d043910 100644 --- a/download +++ b/download @@ -1,8 +1,13 @@ +710b6969efbc3b6be9f71eebefa700ee adal-1.2.7.tar.gz fc38a2168ec9785693bb47e75dc67aaa aliyun-cli-3.0.198.tar.gz ab023f0f4f3de0aef5c7422beac9d48d aliyun-cli-go-vendor.tar.gz 9911cf982f939bccf5c4888198516c26 aliyun-openapi-meta-5cf98b660.tar.gz 832fbc4db8822fcb0099edb7158ddf81 aliyun-python-sdk-core-2.11.5.tar.gz -7c2d43fbfb0faeddec259a7f26adb8dc awscli-2.2.15.tar.gz +eac67c509ddce142eadef1e384e1f631 azure_core-1.32.0.tar.gz +5a9cf1977928beb57f85416adb204853 azure_identity-1.19.0.tar.gz +67182253ba53fc6a7d9bb69203b2841a azure_mgmt_compute-34.0.0.tar.gz +9d28b2cae9b711d06760a16cd4c43605 azure_mgmt_core-1.5.0.tar.gz +57502f745cd40e821c2f94dcb379b0ae azure_mgmt_network-28.1.0.tar.gz c64f38a505b122a2ecf2b7d93c0ec4b7 cachetools-4.2.4.tar.gz 10a72845d3fc2c38d212b4b7b1872c76 certifi-2023.7.22.tar.gz b28e4463613ff3911d5a2dc62b96233f charset-normalizer-2.0.7.tar.gz @@ -11,11 +16,13 @@ a56b8dc55158a41ab3c89c4c8feb8824 colorama-0.3.3.tar.gz 3bc52f1952b9a78361114147da63c35b flit_core-3.9.0.tar.gz a61b1015a213f1a9cf27252fbac579ee google-auth-2.3.0.tar.gz 5856306eac5f25db8249e37a4c6ee3e7 idna-3.3.tar.gz -a66396e3080a68928ff98276d6809138 Jinja2-3.1.3.tar.gz +1a310658b30a48641bafb5652ad91c40 isodate-0.6.1.tar.gz +66d4c25ff43d1deaf9637ccda523dec8 jinja2-3.1.6.tar.gz d44bf469fcc16312e12fe8548cb177ee kubernetes-12.0.1.tar.gz 892e0fefa3c488387e5cc0cad2daa523 MarkupSafe-2.0.1.tar.gz -e46e2af1ad29245ddbd93972770f528b msal-1.18.0.tar.gz -93f47277871a06956432af604c543cb2 msal-extensions-1.0.0.tar.gz +e49d312962cb195ca36761dd93ba1220 msal-1.31.1.tar.gz +804a213b61da2077f4baa908e6a98b31 msal_extensions-1.2.0.tar.gz +5310576f7b9a23fc9feff8ef9684ff24 msrestazure-0.6.4.post1.tar.gz 2f7b898cc1af8c1409cc329e8843ea8f oauthlib-3.2.2.tar.gz 6aef637aec8c21ae1c41f02aa731fa29 openshift-0.12.1.tar.gz 26909d08551f369fcde80f43529a1f92 poetry-core-1.0.7.tar.gz @@ -37,12 +44,12 @@ d0db73bc8015af946b3578330fb1e020 pyroute2.nftables-0.6.13.tar.gz 8c745949ad3e9ae83d9927fed213db8a requests-2.26.0.tar.gz 1ebcd55f1b1b9281940b4bc33010e2ba requests-oauthlib-1.3.0.tar.gz c21701cdd75c170f8d690f704a362c44 rsa-4.7.2.tar.gz -dd811a8f09dc0e622ad19a42508da7c1 ruamel.yaml-0.15.100.tar.gz ef2af87b5f265163700b12165a541406 ruamel.yaml-0.17.16.tar.gz e2397bedcd1f40b2f22b3696175082aa ruamel.yaml.clib-0.2.6.tar.gz -7a2c32ef46b0f91acc8c2756af56a711 setuptools-58.3.0.tar.gz -32918d8ac566360c21411e0b3556c695 setuptools_scm-6.3.2.tar.gz +82e1d67883b713f9493659b50d13b436 setuptools-80.9.0.tar.gz +d8046dce093a94dc382b68b45f6a6257 setuptools_scm-8.1.0.tar.gz a7c927740e4964dd29b72cebfc1429bb six-1.16.0.tar.gz -36fd182000c721cf495d4dc673a6f9e9 tomli-1.0.1.tar.gz +d4341621d423a7ca6822e23d6d52bb9a tomli-2.0.1.tar.gz +cf64c2313f5fa5eb04c1deb3fc93abe9 typing_extensions-4.12.2.tar.gz f986d8e9616d2a43389f678d5dad9893 urllib3-1.26.18.tar.gz a043b9a04dc10a7c9f333cf55f6222df websocket-client-1.2.1.tar.gz diff --git a/fence-agents.spec b/fence-agents.spec index 83562d0f35c9fe42a35304722a4e3be26915a372..bc3f9e48b9e95fbfeb66fdfe4ceaa2d11ff797c9 100644 --- a/fence-agents.spec +++ b/fence-agents.spec @@ -1,4 +1,3 @@ -%define anolis_release .0.1 # Copyright 2004-2011 Red Hat, Inc. # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions @@ -29,7 +28,7 @@ %global pyasn1 pyasn1 %global pyasn1_version 0.4.8 %global dateutil dateutil -%global dateutil_version 2.8.2 +%global dateutil_version 2.8.1 %global pyyaml PyYAML %global pyyaml_version 5.1 %global six six @@ -38,8 +37,8 @@ %global urllib3_version 1.26.18 %global websocketclient websocket-client %global websocketclient_version 1.2.1 -%global jinja2 Jinja2 -%global jinja2_version 3.1.3 +%global jinja2 jinja2 +%global jinja2_version 3.1.6 %global markupsafe MarkupSafe %global markupsafe_version 2.0.1 %global stringutils string-utils @@ -54,27 +53,22 @@ %global reqstsoauthlib_version 1.3.0 %global ruamelyaml ruamel.yaml %global ruamelyaml_version 0.17.16 -%global setuptools setuptools -%global setuptools_version 58.3.0 Name: fence-agents Summary: Set of unified programs capable of host isolation ("fencing") Version: 4.10.0 -Release: 76%{?alphatag:.%{alphatag}}%{anolis_release}%{?dist}.6 +Release: 86%{?alphatag:.%{alphatag}}%{?dist}.7 License: GPLv2+ and LGPLv2+ URL: https://github.com/ClusterLabs/fence-agents Source0: https://fedorahosted.org/releases/f/e/fence-agents/%{name}-%{version}.tar.gz ### HA support requirements-*.txt ### -Source100: requirements-aliyun.txt -Source101: requirements-aws.txt -Source102: requirements-azure.txt -Source103: requirements-google.txt -Source104: requirements-common.txt +Source100: requirements-common.txt +Source101: requirements-aliyun.txt +Source102: requirements-aws.txt +Source103: requirements-azure.txt +Source104: requirements-google.txt +Source105: requirements-ibm.txt ### HA support libs/utils ### -# awscli 2+ is only available from github (and needs to be renamed from aws-cli... to awscli) -Source900: awscli-2.2.15.tar.gz -# From awscli's requirements.txt: https://github.com/boto/botocore/zipball/v2#egg=botocore -Source901: botocore-2.0.0dev123.zip # update with ./update-ha-support.sh and replace lines below with output ### BEGIN ### # aliyun @@ -95,118 +89,96 @@ Source2000: aliyun-cli-3.0.198.tar.gz Source2001: aliyun-openapi-meta-5cf98b660.tar.gz ## go mod vendor Source2002: aliyun-cli-go-vendor.tar.gz -# awscli -Source1008: awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl -Source1009: colorama-0.4.3-py2.py3-none-any.whl -Source1010: cryptography-3.3.2-cp36-abi3-manylinux2010_x86_64.whl -Source1011: distro-1.5.0-py2.py3-none-any.whl -Source1012: docutils-0.15.2-py3-none-any.whl -Source1013: prompt_toolkit-2.0.10-py3-none-any.whl -Source1014: ruamel.yaml-0.15.100.tar.gz -Source1015: six-1.16.0-py2.py3-none-any.whl -Source1016: wcwidth-0.1.9-py2.py3-none-any.whl # aws -Source1017: boto3-1.17.102-py2.py3-none-any.whl -Source1018: botocore-1.20.102-py2.py3-none-any.whl -Source1019: python_dateutil-2.8.1-py2.py3-none-any.whl -Source1020: s3transfer-0.4.2-py2.py3-none-any.whl -Source1021: urllib3-1.26.18.tar.gz +Source1007: boto3-1.17.102-py2.py3-none-any.whl +Source1008: botocore-1.20.102-py2.py3-none-any.whl +Source1009: python_%{dateutil}-%{dateutil_version}-py2.py3-none-any.whl +Source1010: s3transfer-0.4.2-py2.py3-none-any.whl +Source1011: %{urllib3}-%{urllib3_version}.tar.gz # azure -Source1022: adal-1.2.7-py2.py3-none-any.whl -Source1023: azure_common-1.1.27-py2.py3-none-any.whl -Source1024: azure_core-1.15.0-py2.py3-none-any.whl -Source1025: azure_mgmt_compute-21.0.0-py2.py3-none-any.whl -Source1026: azure_mgmt_core-1.2.2-py2.py3-none-any.whl -Source1027: azure_mgmt_network-19.0.0-py2.py3-none-any.whl -Source1028: azure-identity-1.10.0.zip -Source1029: chardet-4.0.0-py2.py3-none-any.whl -Source1030: idna-2.10-py2.py3-none-any.whl -Source1031: isodate-0.6.0-py2.py3-none-any.whl -Source1032: msrest-0.6.21-py2.py3-none-any.whl -Source1033: msrestazure-0.6.4-py2.py3-none-any.whl -Source1034: %{oauthlib}-%{oauthlib_version}.tar.gz -Source1035: PyJWT-2.1.0-py3-none-any.whl -Source1036: requests-2.25.1-py2.py3-none-any.whl -Source1037: requests_oauthlib-1.3.0-py2.py3-none-any.whl -Source1038: msal-1.18.0.tar.gz -Source1039: msal-extensions-1.0.0.tar.gz -Source1040: portalocker-2.5.1.tar.gz +Source1012: adal-1.2.7.tar.gz +Source1013: azure-common-1.1.28.zip +Source1014: azure_core-1.32.0.tar.gz +Source1015: azure_mgmt_compute-34.0.0.tar.gz +Source1016: azure_mgmt_core-1.5.0.tar.gz +Source1017: azure_mgmt_network-28.1.0.tar.gz +Source1018: azure_identity-1.19.0.tar.gz +Source1019: chardet-4.0.0-py2.py3-none-any.whl +Source1020: isodate-0.6.1.tar.gz +Source1021: msrest-0.7.1.zip +Source1022: msrestazure-0.6.4.post1.tar.gz +Source1023: %{oauthlib}-%{oauthlib_version}.tar.gz +Source1024: PyJWT-2.1.0-py3-none-any.whl +Source1025: requests_oauthlib-1.3.0-py2.py3-none-any.whl +Source1026: msal-1.31.1.tar.gz +Source1027: msal_extensions-1.2.0.tar.gz +Source1028: portalocker-2.5.1.tar.gz +Source1029: cryptography-3.3.2-cp36-abi3-manylinux2010_x86_64.whl +Source1030: typing_extensions-4.12.2.tar.gz # google -Source1041: cachetools-4.2.2-py3-none-any.whl -Source1042: chardet-3.0.4-py2.py3-none-any.whl -Source1043: google_api_core-1.30.0-py2.py3-none-any.whl -Source1044: google_api_python_client-1.12.8-py2.py3-none-any.whl -Source1045: googleapis_common_protos-1.53.0-py2.py3-none-any.whl -Source1046: google_auth-1.32.0-py2.py3-none-any.whl -Source1047: google_auth_httplib2-0.1.0-py2.py3-none-any.whl -Source1048: httplib2-0.19.1-py3-none-any.whl -Source1049: packaging-20.9-py2.py3-none-any.whl -Source1050: protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl -Source1051: pyasn1-0.4.8-py2.py3-none-any.whl -Source1052: pyasn1_modules-0.2.8-py2.py3-none-any.whl -Source1053: pyparsing-2.4.7-py2.py3-none-any.whl -Source1054: pyroute2-0.7.12.tar.gz -Source1055: pyroute2.core-0.6.13.tar.gz -Source1056: pyroute2.ethtool-0.6.13.tar.gz -Source1057: pyroute2.ipdb-0.6.13.tar.gz -Source1058: pyroute2.ipset-0.6.13.tar.gz -Source1059: pyroute2.ndb-0.6.13.tar.gz -Source1060: pyroute2.nftables-0.6.13.tar.gz -Source1061: pyroute2.nslink-0.6.13.tar.gz -Source1062: pytz-2021.1-py2.py3-none-any.whl -Source1063: rsa-4.7.2-py3-none-any.whl -Source1064: setuptools-57.0.0-py3-none-any.whl -Source1065: uritemplate-3.0.1-py2.py3-none-any.whl +Source1031: cachetools-4.2.2-py3-none-any.whl +Source1032: chardet-3.0.4-py2.py3-none-any.whl +Source1033: google_api_core-1.30.0-py2.py3-none-any.whl +Source1034: google_api_python_client-1.12.8-py2.py3-none-any.whl +Source1035: googleapis_common_protos-1.53.0-py2.py3-none-any.whl +Source1036: google_auth-1.32.0-py2.py3-none-any.whl +Source1037: google_auth_httplib2-0.1.0-py2.py3-none-any.whl +Source1038: httplib2-0.19.1-py3-none-any.whl +Source1039: packaging-20.9-py2.py3-none-any.whl +Source1040: protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl +Source1041: pyasn1-0.4.8-py2.py3-none-any.whl +Source1042: pyasn1_modules-0.2.8-py2.py3-none-any.whl +Source1043: pyparsing-2.4.7-py2.py3-none-any.whl +Source1044: pyroute2-0.7.12.tar.gz +Source1045: pyroute2.core-0.6.13.tar.gz +Source1046: pyroute2.ethtool-0.6.13.tar.gz +Source1047: pyroute2.ipdb-0.6.13.tar.gz +Source1048: pyroute2.ipset-0.6.13.tar.gz +Source1049: pyroute2.ndb-0.6.13.tar.gz +Source1050: pyroute2.nftables-0.6.13.tar.gz +Source1051: pyroute2.nslink-0.6.13.tar.gz +Source1052: pytz-2021.1-py2.py3-none-any.whl +Source1053: rsa-4.7.2-py3-none-any.whl +Source1054: setuptools-80.9.0.tar.gz +Source1055: uritemplate-3.0.1-py2.py3-none-any.whl # common (pexpect / suds) -Source1066: pexpect-4.8.0-py2.py3-none-any.whl -Source1067: ptyprocess-0.7.0-py2.py3-none-any.whl -Source1068: suds_community-0.8.5-py3-none-any.whl +Source1056: pexpect-4.8.0-py2.py3-none-any.whl +Source1057: ptyprocess-0.7.0-py2.py3-none-any.whl +Source1058: suds_community-0.8.5-py3-none-any.whl ### END ### # kubevirt ## pip download --no-binary :all: openshift "ruamel.yaml.clib>=0.1.2" ### BEGIN -Source1069: %{openshift}-%{openshift_version}.tar.gz -Source1070: %{ruamelyamlclib}-%{ruamelyamlclib_version}.tar.gz -Source1071: %{kubernetes}-%{kubernetes_version}.tar.gz -Source1072: %{certifi}-%{certifi_version}.tar.gz -Source1073: %{googleauth}-%{googleauth_version}.tar.gz -Source1074: %{cachetools}-%{cachetools_version}.tar.gz -Source1075: %{pyasn1modules}-%{pyasn1modules_version}.tar.gz -Source1076: %{pyasn1}-%{pyasn1_version}.tar.gz -Source1078: %{pyyaml}-%{pyyaml_version}.tar.gz +Source1060: %{openshift}-%{openshift_version}.tar.gz +Source1061: %{ruamelyamlclib}-%{ruamelyamlclib_version}.tar.gz +Source1062: %{kubernetes}-%{kubernetes_version}.tar.gz +Source1063: %{certifi}-%{certifi_version}.tar.gz +Source1064: %{googleauth}-%{googleauth_version}.tar.gz +Source1065: %{cachetools}-%{cachetools_version}.tar.gz +Source1066: %{pyasn1modules}-%{pyasn1modules_version}.tar.gz +Source1067: %{pyasn1}-%{pyasn1_version}.tar.gz +Source1068: %{pyyaml}-%{pyyaml_version}.tar.gz ## rsa is dependency for "pip install", ## but gets removed to use cryptography lib instead -Source1079: rsa-4.7.2.tar.gz -Source1080: %{six}-%{six_version}.tar.gz -Source1081: %{websocketclient}-%{websocketclient_version}.tar.gz -Source1082: %{jinja2}-%{jinja2_version}.tar.gz -Source1083: %{markupsafe}-%{markupsafe_version}.tar.gz -Source1084: python-%{stringutils}-%{stringutils_version}.tar.gz -Source1085: %{requests}-%{requests_version}.tar.gz -Source1086: %{chrstnormalizer}-%{chrstnormalizer_version}.tar.gz -Source1087: %{idna}-%{idna_version}.tar.gz -Source1088: %{reqstsoauthlib}-%{reqstsoauthlib_version}.tar.gz -Source1089: %{ruamelyaml}-%{ruamelyaml_version}.tar.gz -Source1090: %{setuptools}-%{setuptools_version}.tar.gz +Source1069: rsa-4.7.2.tar.gz +Source1070: %{six}-%{six_version}.tar.gz +Source1071: %{websocketclient}-%{websocketclient_version}.tar.gz +Source1072: %{jinja2}-%{jinja2_version}.tar.gz +Source1073: %{markupsafe}-%{markupsafe_version}.tar.gz +Source1074: python-%{stringutils}-%{stringutils_version}.tar.gz +Source1075: %{requests}-%{requests_version}.tar.gz +Source1076: %{chrstnormalizer}-%{chrstnormalizer_version}.tar.gz +Source1077: %{idna}-%{idna_version}.tar.gz +Source1078: %{reqstsoauthlib}-%{reqstsoauthlib_version}.tar.gz +Source1079: %{ruamelyaml}-%{ruamelyaml_version}.tar.gz ## required for installation -Source1091: setuptools_scm-6.3.2.tar.gz -Source1092: packaging-21.2-py3-none-any.whl -Source1093: poetry-core-1.0.7.tar.gz -Source1094: pyparsing-3.0.1.tar.gz -Source1095: tomli-1.0.1.tar.gz -Source1096: flit_core-3.9.0.tar.gz -Source1097: wheel-0.37.0-py2.py3-none-any.whl -Source3000: pycryptodome-3.10.1.tar.gz -Source3001: cryptography-3.3.2-cp36-abi3-manylinux1_x86_64.whl -Source3002: awscrt-0.11.13-cp36-cp36m-manylinux1_x86_64.whl -Source3003: cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl -Source3004: urllib3-1.24.3-py2.py3-none-any.whl -Source3005: importlib_metadata-4.8.1-py3-none-any.whl -Source3006: protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl -Source3007: zipp-3.5.0-py3-none-any.whl -Source3008: typing_extensions-3.10.0.2-py3-none-any.whl -Source3009: importlib_resources-5.2.2-py3-none-any.whl -Source3010: MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl +Source1080: setuptools_scm-8.1.0.tar.gz +Source1081: packaging-21.2-py3-none-any.whl +Source1082: poetry-core-1.0.7.tar.gz +Source1083: pyparsing-3.0.1.tar.gz +Source1084: tomli-2.0.1.tar.gz +Source1085: flit_core-3.9.0.tar.gz +Source1086: wheel-0.37.0-py2.py3-none-any.whl ### END Patch0: ha-cloud-support-aliyun.patch @@ -267,25 +239,23 @@ Patch54: RHEL-35263-fence_eps-add-fence_epsr2-for-ePowerSwitch-R2-and-newer.patc Patch55: RHEL-25256-fence_vmware_rest-detect-user-sufficient-rights.patch Patch56: RHEL-43235-fence_aws-1-list-add-instance-name-status.patch Patch57: RHEL-43235-fence_aws-2-log-error-for-unknown-states.patch -Patch58: RHEL-59882-fence_scsi-only-preempt-once-for-mpath-devices.patch +Patch58: RHEL-59878-fence_scsi-only-preempt-once-for-mpath-devices.patch +Patch59: RHEL-56138-fence_mpath-1-support-hex-key-format.patch +Patch60: RHEL-56138-fence_mpath-2-fix-unfencing-issue-use-MULTILINE-avoid-duplicates.patch +Patch61: RHEL-62206-fence_ibm_powervs-add-private-endpoint-and-token-file-support.patch +Patch62: RHEL-76493-fence_azure_arm-use-azure-identity.patch +Patch63: RHEL-83488-fence_ibm_vpc-refresh-bearer-token.patch +Patch64: RHEL-92695-1-fence_sbd-improve-error-handling.patch +Patch65: RHEL-92695-2-fence_sbd-get-devices-from-SBD_DEVICE-if-devices-parameter-isnt-set.patch +Patch66: RHEL-96183-fence_kubevirt-force-off.patch ### HA support libs/utils ### # all archs Patch1000: bz2217902-1-kubevirt-fix-bundled-dateutil-CVE-2007-4559.patch -Patch1001: RHEL-35649-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch # cloud (x86_64 only) -Patch2000: bz2217902-2-aws-awscli-azure-fix-bundled-dateutil-CVE-2007-4559.patch +Patch2000: bz2217902-2-aws-azure-fix-bundled-dateutil-CVE-2007-4559.patch Patch2001: RHEL-43562-fix-bundled-urllib3-CVE-2024-37891.patch - -# https://github.com/pypa/setuptools/pull/4332 -Patch2002: setuptools-fix-CVE-2024-6345.patch - -# https://github.com/pallets/jinja/commit/767b23617628419ae3709ccfb02f9602ae9fe51f -Patch2003: 0001-fix-f-string-syntax-error-in-code-generation.patch -# https://github.com/pallets/jinja/commit/48b0687e05a5466a91cd5812d604fa37ad0943b4 -Patch2004: 0001-sandbox-indirect-calls-to-str.format.patch -# https://github.com/pallets/jinja/commit/065334d1ee5b7210e1a0a93c37238c86858f2af7 -Patch2005: 0001-attr-filter-uses-env.getattr.patch +Patch2002: RHEL-95903-pkg_resources-suppress-UserWarning.patch %global supportedagents amt_ws apc apc_snmp bladecenter brocade cisco_mds cisco_ucs compute drac5 eaton_snmp emerson eps evacuate hpblade ibmblade ibm_powervs ibm_vpc ifmib ilo ilo_moonshot ilo_mp ilo_ssh intelmodular ipdu ipmilan kdump kubevirt lpar mpath redfish rhevm rsa rsb sbd scsi vmware_rest vmware_soap wti %ifarch x86_64 @@ -363,7 +333,6 @@ BuildRequires: python3-pip python3-wheel BuildRequires: golang git %endif BuildRequires: python3-pycurl python3-requests -BuildRequires: python3-markupsafe %if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 BuildRequires: openwsman-python3 %endif @@ -459,24 +428,18 @@ BuildRequires: %{systemd_units} %patch -p1 -P 56 %patch -p1 -P 57 %patch -p1 -P 58 +%patch -p1 -P 59 +%patch -p1 -P 60 +%patch -p1 -P 61 +%patch -p1 -P 62 +%patch -p1 -P 63 +%patch -p1 -P 64 +%patch -p1 -P 65 +%patch -p1 -P 66 # prevent compilation of something that won't get used anyway sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac -pushd %{_sourcedir} -tar -xf %{setuptools}-%{setuptools_version}.tar.gz -%patch -p0 -P2002 -tar -zcvf %{setuptools}-%{setuptools_version}.tar.gz %{setuptools}-%{setuptools_version}/ -popd - -pushd %{_sourcedir} -tar -xf %{SOURCE1082} -%patch -p1 -P2003 -%patch -p1 -P2004 -%patch -p1 -P2005 -tar -czvf %{SOURCE1082} %{jinja2}-%{jinja2_version}/ -popd - %build %if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} export PYTHON="%{__python3}" @@ -503,24 +466,22 @@ popd # support libs %ifarch x86_64 LIBS="%{_sourcedir}/requirements-*.txt" -echo "awscli" >> %{_sourcedir}/requirements-awscli.txt %endif -%ifnarch x86_64 +%ifarch ppc64le +LIBS="%{_sourcedir}/requirements-common.txt %{_sourcedir}/requirements-ibm.txt" +%endif +%ifnarch x86_64 ppc64le LIBS="%{_sourcedir}/requirements-common.txt" %endif -# %{__python3} -m pip install --target support/$(echo $x | sed -E "s/.*requirements-(.*).txt/\1/") --no-index --find-links %{_sourcedir} setuptools_scm for x in $LIBS; do + [ "%{_arch}" = "x86_64" ] && [ "$x" = "%{_sourcedir}/requirements-ibm.txt" ] && continue %{__python3} -m pip install --target support/$(echo $x | sed -E "s/.*requirements-(.*).txt/\1/") --no-index --find-links %{_sourcedir} -r $x done # fix incorrect #! detected by CI -#%ifarch x86_64 -#sed -i -e "/^#\!\/Users/c#\!%{__python3}" support/aws/bin/jp support/awscli/bin/jp -#%endif - -# %ifarch x86_64 -# sed -i -e "/^import awscli.clidriver/isys.path.insert(0, '/usr/lib/%{name}/support/awscli')" support/awscli/bin/aws -# %endif +%ifarch x86_64 +sed -i -e "/^#\!\/Users/c#\!%{__python3}" support/aws/bin/jp +%endif # kubevirt %{__python3} -m pip install --user --no-index --find-links %{_sourcedir} setuptools-scm @@ -530,11 +491,11 @@ rm -rf kubevirt/rsa* # regular patch doesnt work in build-section pushd support /usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=2 < %{PATCH1000} -/usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=0 < %{PATCH1001} %ifarch x86_64 /usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=2 < %{PATCH2000} /usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=2 < %{PATCH2001} +/usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=0 < %{PATCH2002} %endif popd @@ -656,10 +617,12 @@ This package contains support files including the Python fencing library. %dir %{_usr}/lib/%{name} %{_usr}/lib/%{name}/support/common -%ifarch x86_64 +%ifarch x86_64 ppc64le %package -n ha-cloud-support License: GPL-2.0-or-later AND LGPL-2.0-or-later AND LGPL-2.1-or-later AND Apache-2.0 AND MIT AND BSD-2-Clause AND BSD-3-Clause AND MPL-2.0 AND Apache-2.0 AND PSF-2.0 AND Unlicense AND ISC Summary: Support libraries for HA Cloud agents +%ifarch x86_64 +Requires: awscli2 # aliyun Provides: bundled(python-aliyun-python-sdk-core) = 2.11.5 Provides: bundled(python-aliyun-python-sdk-ecs) = 4.24.7 @@ -670,40 +633,40 @@ Provides: bundled(python-pycryptodome) = 3.20.0 Provides: bundled(python-pycparser) = 2.20 Provides: bundled(aliyun-cli) = 3.0.198 Provides: bundled(aliyun-openapi-meta) = 5cf98b660 -# awscli -Provides: bundled(awscli) = 2.2.15 -Provides: bundled(python-awscrt) = 0.11.13 -Provides: bundled(python-colorama) = 0.4.3 -Provides: bundled(python-cryptography) = 3.3.2 -Provides: bundled(python-distro) = 1.5.0 -Provides: bundled(python-docutils) = 0.15.2 -Provides: bundled(python-prompt-toolkit) = 2.0.10 -Provides: bundled(python-ruamel-yaml) = 0.15.100 -Provides: bundled(python-six) = 1.16.0 -Provides: bundled(python-wcwidth) = 0.1.9 # aws Provides: bundled(python-boto3) = 1.17.102 Provides: bundled(python-botocore) = 1.20.102 -Provides: bundled(python-dateutil) = 2.8.1 +Provides: bundled(python-%{dateutil}) = %{dateutil_version} Provides: bundled(python-s3transfer) = 0.4.2 Provides: bundled(python-urllib3) = 1.26.18 # azure Provides: bundled(python-adal) = 1.2.7 -Provides: bundled(python-azure-common) = 1.1.27 -Provides: bundled(python-azure-core) = 1.15.0 -Provides: bundled(python-azure-mgmt-compute) = 21.0.0 -Provides: bundled(python-azure-mgmt-core) = 1.2.2 -Provides: bundled(python-azure-mgmt-network) = 19.0.0 -Provides: bundled(python-certifi) = %{certifi_version} +Provides: bundled(python-azure-common) = 1.1.28 +Provides: bundled(python-azure-core) = 1.32.0 +Provides: bundled(python-azure-identity) = 1.19.0 +Provides: bundled(python-azure-mgmt-compute) = 34.0.0 +Provides: bundled(python-azure-mgmt-core) = 1.5.0 +Provides: bundled(python-azure-mgmt-network) = 28.1.0 Provides: bundled(python-chardet) = 4.0.0 -Provides: bundled(python-idna) = 2.10 -Provides: bundled(python-isodate) = 0.6.0 -Provides: bundled(python-msrest) = 0.6.21 -Provides: bundled(python-msrestazure) = 0.6.4 -Provides: bundled(python-oauthlib) = 3.1.1 +Provides: bundled(python-cffi) = 1.14.5 +Provides: bundled(python-%{chrstnormalizer}) = %{chrstnormalizer_version} +Provides: bundled(python-cryptography) = 3.3.2 +Provides: bundled(python-%{dateutil}) = %{dateutil_version} +Provides: bundled(python-%{idna}) = %{idna_version} +Provides: bundled(python-isodate) = 0.6.1 +Provides: bundled(python-msal) = 1.31.1 +Provides: bundled(python-msal-extensions) = 1.2.0 +Provides: bundled(python-msrest) = 0.7.1 +Provides: bundled(python-msrestazure) = 0.6.4.post1 +Provides: bundled(python-%{oauthlib}) = %{oauthlib_version} +Provides: bundled(python-portalocker) = 2.5.1 +Provides: bundled(python-pycparser) = 2.20 Provides: bundled(python-PyJWT) = 2.1.0 -Provides: bundled(python-requests) = 2.25.1 +Provides: bundled(python-%{requests}) = %{requests_version} Provides: bundled(python-requests-oauthlib) = 1.3.0 +Provides: bundled(python-%{six}) = %{six_version} +Provides: bundled(python-typing-extensions) = 4.12.2 +Provides: bundled(python-%{urllib3}) = %{urllib3_version} # google Provides: bundled(python-cachetools) = 4.2.2 Provides: bundled(python-chardet) = 3.0.4 @@ -728,8 +691,17 @@ Provides: bundled(python-pyroute2-nftables) = 0.6.13 Provides: bundled(python-pyroute2-nslink) = 0.6.13 Provides: bundled(python-pytz) = 2021.1 Provides: bundled(python-rsa) = 4.7.2 -Provides: bundled(python3-setuptools) = 57.0.0 +Provides: bundled(python3-setuptools) = 80.9.0 Provides: bundled(python-uritemplate) = 3.0.1 +%endif +%ifarch ppc64le +# ibm +Provides: bundled(python3-%{certifi}) = %{certifi_version} +Provides: bundled(python3-%{chrstnormalizer}) = %{chrstnormalizer_version} +Provides: bundled(python3-%{idna}) = %{idna_version} +Provides: bundled(python3-%{requests}) = %{requests_version} +Provides: bundled(python3-%{urllib3}) = %{urllib3_version} +%endif %description -n ha-cloud-support Support libraries for Fence Agents. %files -n ha-cloud-support @@ -1265,7 +1237,7 @@ Provides: bundled(python3-%{idna}) = %{idna_version} Provides: bundled(python3-%{reqstsoauthlib}) = %{reqstsoauthlib_version} Provides: bundled(python3-%{oauthlib}) = %{oauthlib_version} Provides: bundled(python3-%{ruamelyaml}) = %{ruamelyaml_version} -Provides: bundled(python3-setuptools) = %{setuptools_version} +Provides: bundled(python3-setuptools) = 80.9.0 %description kubevirt Fence agent for KubeVirt platform. %files kubevirt @@ -1571,26 +1543,63 @@ are located on corosync cluster nodes. %endif %changelog -* Tue Mar 25 2025 Zhao Hang - 4.10.0-76.0.1.6 -- fix CVE-2025-27516 - -* Fri Jan 17 2025 Zhao Hang - 4.10.0-76.0.1.4 -- fix CVE-2024-56201 CVE-2024-56326 - -* Wed Dec 04 2024 Chang Gao - 4.10.0-76.0.1.1 -- Replace some packages with build env -- Update CVE-2007-4559 patches -- Change Jinja2 require python version -- fix CVE-2024-6345 (gc-taifu@linux.alibaba.com) - -* Wed Sep 25 2024 Oyvind Albrigtsen - 4.10.0-76.1 +* Thu Jun 26 2025 Oyvind Albrigtsen - 4.10.0-86.7 +- bundled setuptools: fix CVE-2025-47273 + Resolves: RHEL-95903 + +* Fri Jun 13 2025 Oyvind Albrigtsen - 4.10.0-86.6 +- fence_kubevirt: use hard poweroff + Resolves: RHEL-96183 + +* Wed May 21 2025 Oyvind Albrigtsen - 4.10.0-86.4 +- fence_sbd: improve error handling and get devices from SBD_DEVICE env + variable if devices parameter isnt set + Resolves: RHEL-92695 + +* Fri Mar 14 2025 Oyvind Albrigtsen - 4.10.0-86.3 +- fence_ibm_vpc: refresh bearer-token if token data is corrupt, and + avoid edge-case of writing empty token file + Resolves: RHEL-83488 + +* Tue Mar 11 2025 Oyvind Albrigtsen - 4.10.0-86 +- bundled jinja2: fix CVE-2025-27516 + Resolves: RHEL-82713 + +* Fri Jan 31 2025 Oyvind Albrigtsen - 4.10.0-85 +- fence_azure_arm: use azure-identity instead of msrestazure, which has + been deprecated + Resolves: RHEL-76493 + +* Wed Jan 8 2025 Oyvind Albrigtsen - 4.10.0-83 +- bundled jinja2: fix CVE-2024-56201 and CVE-2024-56326 + Resolves: RHEL-72074, RHEL-72067 + +* Tue Nov 26 2024 Oyvind Albrigtsen - 4.10.0-82 +- Move fence-agents to AppStream + Resolves: RHEL-68841 + +* Wed Oct 23 2024 Oyvind Albrigtsen - 4.10.0-81 +- fence_ibm_powervs: add private endpoint and token file support + Resolves: RHEL-62206 +- ha-cloud-support: bundle libs for the powervs-subnet resource agent + Resolves: RHEL-64023 + +* Thu Oct 10 2024 Oyvind Albrigtsen - 4.10.0-80 +- fence_mpath: add support for hex-key format (used in multipath.conf) + Resolves: RHEL-56138 +- fence_scsi/fence_mpath: add support for SPC-4 disks + Resolves: RHEL-7629 + +* Wed Sep 25 2024 Oyvind Albrigtsen - 4.10.0-77 - fence_scsi: preempt clears all devices on the mpath device, so only run it for the first device - Resolves: RHEL-59882 + Resolves: RHEL-59878 +- ha-cloud-support: remove bundled awscli and use awscli2 package + instead + Resolves: RHEL-60020 * Tue Jul 23 2024 Oyvind Albrigtsen - 4.10.0-76 - bundled setuptools: fix CVE-2024-6345 - Resolves: RHEL-49658 * Fri Jun 21 2024 Oyvind Albrigtsen - 4.10.0-75 diff --git a/idna-2.10-py2.py3-none-any.whl b/idna-2.10-py2.py3-none-any.whl deleted file mode 100644 index 41225cb056874de864c607426497cfa7bacb4676..0000000000000000000000000000000000000000 Binary files a/idna-2.10-py2.py3-none-any.whl and /dev/null differ diff --git a/importlib_metadata-4.8.1-py3-none-any.whl b/importlib_metadata-4.8.1-py3-none-any.whl deleted file mode 100644 index 0a226fb73c259dde1679607eafd87faabaf307fb..0000000000000000000000000000000000000000 Binary files a/importlib_metadata-4.8.1-py3-none-any.whl and /dev/null differ diff --git a/importlib_resources-5.2.2-py3-none-any.whl b/importlib_resources-5.2.2-py3-none-any.whl deleted file mode 100644 index 45047a5a848b39592607c46611a3cbb458eea331..0000000000000000000000000000000000000000 Binary files a/importlib_resources-5.2.2-py3-none-any.whl and /dev/null differ diff --git a/isodate-0.6.0-py2.py3-none-any.whl b/isodate-0.6.0-py2.py3-none-any.whl deleted file mode 100644 index 172a3325c72e68e85f90054fc752c14ce7be2af9..0000000000000000000000000000000000000000 Binary files a/isodate-0.6.0-py2.py3-none-any.whl and /dev/null differ diff --git a/msrest-0.6.21-py2.py3-none-any.whl b/msrest-0.6.21-py2.py3-none-any.whl deleted file mode 100644 index ebadaa5ff3b238c0a92929c23e170d9c71da51c6..0000000000000000000000000000000000000000 Binary files a/msrest-0.6.21-py2.py3-none-any.whl and /dev/null differ diff --git a/msrest-0.7.1.zip b/msrest-0.7.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..b55e818a06f08e5942c34e1f552389b7858a83ad Binary files /dev/null and b/msrest-0.7.1.zip differ diff --git a/msrestazure-0.6.4-py2.py3-none-any.whl b/msrestazure-0.6.4-py2.py3-none-any.whl deleted file mode 100644 index 73b22832ae6993ac2348d1a7030ace6e25c9a1c4..0000000000000000000000000000000000000000 Binary files a/msrestazure-0.6.4-py2.py3-none-any.whl and /dev/null differ diff --git a/prompt_toolkit-2.0.10-py3-none-any.whl b/prompt_toolkit-2.0.10-py3-none-any.whl deleted file mode 100644 index b13e271ea57954dd8b0a7ea1075ffca12394d7a2..0000000000000000000000000000000000000000 Binary files a/prompt_toolkit-2.0.10-py3-none-any.whl and /dev/null differ diff --git a/protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl b/protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl deleted file mode 100644 index 51f6ceadcf10bdaac6542d8eebd4904b234297d6..0000000000000000000000000000000000000000 Binary files a/protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl and /dev/null differ diff --git a/pycryptodome-3.10.1.tar.gz b/pycryptodome-3.10.1.tar.gz deleted file mode 100644 index ee913bf6f69f491e34d52758369cfeb8e9824378..0000000000000000000000000000000000000000 Binary files a/pycryptodome-3.10.1.tar.gz and /dev/null differ diff --git a/requests-2.25.1-py2.py3-none-any.whl b/requests-2.25.1-py2.py3-none-any.whl deleted file mode 100644 index 8d70e9716d747a79987ae3664ad82ced6349af78..0000000000000000000000000000000000000000 Binary files a/requests-2.25.1-py2.py3-none-any.whl and /dev/null differ diff --git a/requirements-ibm.txt b/requirements-ibm.txt new file mode 100644 index 0000000000000000000000000000000000000000..804abb1bfe60023de8ec8baa2d7cc48e9e1247a5 --- /dev/null +++ b/requirements-ibm.txt @@ -0,0 +1,2 @@ +requests +urllib3 diff --git a/setuptools-57.0.0-py3-none-any.whl b/setuptools-57.0.0-py3-none-any.whl deleted file mode 100644 index f704306d4566efdd0cc6a62d45659d15672989f9..0000000000000000000000000000000000000000 Binary files a/setuptools-57.0.0-py3-none-any.whl and /dev/null differ diff --git a/setuptools-fix-CVE-2024-6345.patch b/setuptools-fix-CVE-2024-6345.patch deleted file mode 100644 index 81c943dea78e801e966ec2c9c403b7a50f51abd2..0000000000000000000000000000000000000000 --- a/setuptools-fix-CVE-2024-6345.patch +++ /dev/null @@ -1,202 +0,0 @@ ---- setuptools-58.3.0/setuptools/package_index.py.orig 2024-09-20 10:49:27.031090108 +0800 -+++ setuptools-58.3.0/setuptools/package_index.py 2024-09-20 10:57:16.429147164 +0800 -@@ -1,5 +1,6 @@ - """PyPI and direct package downloading""" - import sys -+import subprocess - import os - import re - import io -@@ -558,7 +559,7 @@ - scheme = URL_SCHEME(spec) - if scheme: - # It's a url, download it to tmpdir -- found = self._download_url(scheme.group(1), spec, tmpdir) -+ found = self._download_url(spec, tmpdir) - base, fragment = egg_info_for_url(spec) - if base.endswith('.py'): - found = self.gen_setup(found, fragment, tmpdir) -@@ -777,7 +778,7 @@ - raise DistutilsError("Download error for %s: %s" - % (url, v)) from v - -- def _download_url(self, scheme, url, tmpdir): -+ def _download_url(self, url, tmpdir): - # Determine download filename - # - name, fragment = egg_info_for_url(url) -@@ -792,19 +793,59 @@ - - filename = os.path.join(tmpdir, name) - -- # Download the file -- # -- if scheme == 'svn' or scheme.startswith('svn+'): -- return self._download_svn(url, filename) -- elif scheme == 'git' or scheme.startswith('git+'): -- return self._download_git(url, filename) -- elif scheme.startswith('hg+'): -- return self._download_hg(url, filename) -- elif scheme == 'file': -- return urllib.request.url2pathname(urllib.parse.urlparse(url)[2]) -- else: -- self.url_ok(url, True) # raises error if not allowed -- return self._attempt_download(url, filename) -+ return self._download_vcs(url, filename) or self._download_other(url, filename) -+ -+ @staticmethod -+ def _resolve_vcs(url): -+ """ -+ >>> rvcs = PackageIndex._resolve_vcs -+ >>> rvcs('git+http://foo/bar') -+ 'git' -+ >>> rvcs('hg+https://foo/bar') -+ 'hg' -+ >>> rvcs('git:myhost') -+ 'git' -+ >>> rvcs('hg:myhost') -+ >>> rvcs('http://foo/bar') -+ """ -+ scheme = urllib.parse.urlsplit(url).scheme -+ pre, sep, post = scheme.partition('+') -+ # svn and git have their own protocol; hg does not -+ allowed = set(['svn', 'git'] + ['hg'] * bool(sep)) -+ return next(iter({pre} & allowed), None) -+ -+ def _download_vcs(self, url, spec_filename): -+ vcs = self._resolve_vcs(url) -+ if not vcs: -+ return -+ if vcs == 'svn': -+ raise DistutilsError( -+ f"Invalid config, SVN download is not supported: {url}" -+ ) -+ -+ filename, _, _ = spec_filename.partition('#') -+ url, rev = self._vcs_split_rev_from_url(url) -+ -+ self.info(f"Doing {vcs} clone from {url} to {filename}") -+ subprocess.check_call([vcs, 'clone', '--quiet', url, filename]) -+ -+ co_commands = dict( -+ git=[vcs, '-C', filename, 'checkout', '--quiet', rev], -+ hg=[vcs, '--cwd', filename, 'up', '-C', '-r', rev, '-q'], -+ ) -+ if rev is not None: -+ self.info(f"Checking out {rev}") -+ subprocess.check_call(co_commands[vcs]) -+ -+ return filename -+ -+ def _download_other(self, url, filename): -+ scheme = urllib.parse.urlsplit(url).scheme -+ if scheme == 'file': # pragma: no cover -+ return urllib.request.url2pathname(urllib.parse.urlparse(url).path) -+ # raise error if not allowed -+ self.url_ok(url, True) -+ return self._attempt_download(url, filename) - - def scan_url(self, url): - self.process_url(url, True) -@@ -831,77 +872,37 @@ - os.unlink(filename) - raise DistutilsError("Unexpected HTML page found at " + url) - -- def _download_svn(self, url, filename): -- warnings.warn("SVN download support is deprecated", UserWarning) -- url = url.split('#', 1)[0] # remove any fragment for svn's sake -- creds = '' -- if url.lower().startswith('svn:') and '@' in url: -- scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) -- if not netloc and path.startswith('//') and '/' in path[2:]: -- netloc, path = path[2:].split('/', 1) -- auth, host = _splituser(netloc) -- if auth: -- if ':' in auth: -- user, pw = auth.split(':', 1) -- creds = " --username=%s --password=%s" % (user, pw) -- else: -- creds = " --username=" + auth -- netloc = host -- parts = scheme, netloc, url, p, q, f -- url = urllib.parse.urlunparse(parts) -- self.info("Doing subversion checkout from %s to %s", url, filename) -- os.system("svn checkout%s -q %s %s" % (creds, url, filename)) -- return filename -- - @staticmethod -- def _vcs_split_rev_from_url(url, pop_prefix=False): -- scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) -- -- scheme = scheme.split('+', 1)[-1] -- -- # Some fragment identification fails -- path = path.split('#', 1)[0] -- -- rev = None -- if '@' in path: -- path, rev = path.rsplit('@', 1) -- -- # Also, discard fragment -- url = urllib.parse.urlunsplit((scheme, netloc, path, query, '')) -- -- return url, rev -- -- def _download_git(self, url, filename): -- filename = filename.split('#', 1)[0] -- url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) -- -- self.info("Doing git clone from %s to %s", url, filename) -- os.system("git clone --quiet %s %s" % (url, filename)) -+ def _vcs_split_rev_from_url(url): -+ """ -+ Given a possible VCS URL, return a clean URL and resolved revision if any. - -- if rev is not None: -- self.info("Checking out %s", rev) -- os.system("git -C %s checkout --quiet %s" % ( -- filename, -- rev, -- )) -+ >>> vsrfu = PackageIndex._vcs_split_rev_from_url -+ >>> vsrfu('git+https://github.com/pypa/setuptools@v69.0.0#egg-info=setuptools') -+ ('https://github.com/pypa/setuptools', 'v69.0.0') -+ >>> vsrfu('git+https://github.com/pypa/setuptools#egg-info=setuptools') -+ ('https://github.com/pypa/setuptools', None) -+ >>> vsrfu('http://foo/bar') -+ ('http://foo/bar', None) -+ """ -+ parts = urllib.parse.urlsplit(url) - -- return filename -+ clean_scheme = parts.scheme.split('+', 1)[-1] - -- def _download_hg(self, url, filename): -- filename = filename.split('#', 1)[0] -- url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) -+ # Some fragment identification fails -+ no_fragment_path, _, _ = parts.path.partition('#') - -- self.info("Doing hg clone from %s to %s", url, filename) -- os.system("hg clone --quiet %s %s" % (url, filename)) -+ pre, sep, post = no_fragment_path.rpartition('@') -+ clean_path, rev = (pre, post) if sep else (post, None) - -- if rev is not None: -- self.info("Updating to %s", rev) -- os.system("hg --cwd %s up -C -r %s -q" % ( -- filename, -- rev, -- )) -+ resolved = parts._replace( -+ scheme=clean_scheme, -+ path=clean_path, -+ # discard the fragment -+ fragment='', -+ ).geturl() - -- return filename -+ return resolved, rev - - def debug(self, msg, *args): - log.debug(msg, *args) diff --git a/six-1.16.0-py2.py3-none-any.whl b/six-1.16.0-py2.py3-none-any.whl deleted file mode 100644 index fd942658a2f748ba433dd8632abb910a416e184f..0000000000000000000000000000000000000000 Binary files a/six-1.16.0-py2.py3-none-any.whl and /dev/null differ diff --git a/typing_extensions-3.10.0.2-py3-none-any.whl b/typing_extensions-3.10.0.2-py3-none-any.whl deleted file mode 100644 index 7d994c5ef03d22e66d317e923f491ad812f997c2..0000000000000000000000000000000000000000 Binary files a/typing_extensions-3.10.0.2-py3-none-any.whl and /dev/null differ diff --git a/urllib3-1.24.3-py2.py3-none-any.whl b/urllib3-1.24.3-py2.py3-none-any.whl deleted file mode 100644 index 8da9f547675f6c4b7c0bfe0e9078d0b03af4b378..0000000000000000000000000000000000000000 Binary files a/urllib3-1.24.3-py2.py3-none-any.whl and /dev/null differ diff --git a/wcwidth-0.1.9-py2.py3-none-any.whl b/wcwidth-0.1.9-py2.py3-none-any.whl deleted file mode 100644 index dfb7d4d9cd33b19df50cd5c904e607ca3efe1b89..0000000000000000000000000000000000000000 Binary files a/wcwidth-0.1.9-py2.py3-none-any.whl and /dev/null differ diff --git a/zipp-3.5.0-py3-none-any.whl b/zipp-3.5.0-py3-none-any.whl deleted file mode 100644 index 9b606195459d3fa4808b0ad26caafe3a4a3d669d..0000000000000000000000000000000000000000 Binary files a/zipp-3.5.0-py3-none-any.whl and /dev/null differ