diff --git a/_lastrevision b/_lastrevision
index 310f131..65ffde6 100644
--- a/_lastrevision
+++ b/_lastrevision
@@ -1 +1 @@
-597049dd3d38cffb3d6e555ded591bc36ed09a58
\ No newline at end of file
+cc4e56e0465b20664e2f24bfe7034e5fee37232f
\ No newline at end of file
diff --git a/_service b/_service
index 86c2dbc..65371a9 100644
--- a/_service
+++ b/_service
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/openSUSE/salt-packaging.git</param>
     <param name="subdir">salt</param>
     <param name="filename">package</param>
-    <param name="revision">MU/5.0.1</param>
+    <param name="revision">MU/5.0.2</param>
     <param name="scm">git</param>
   </service>
   <service name="extract_file" mode="disabled">
diff --git a/allow-namedloadercontexts-to-be-returned-from-loader.patch b/allow-namedloadercontexts-to-be-returned-from-loader.patch
new file mode 100644
index 0000000..73e7487
--- /dev/null
+++ b/allow-namedloadercontexts-to-be-returned-from-loader.patch
@@ -0,0 +1,73 @@
+From 1be3f92ef3bf14e47340e2e075291204b3e75e98 Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Wed, 25 Sep 2024 14:07:42 +0300
+Subject: [PATCH] Allow NamedLoaderContexts to be returned from loader
+
+It is useful in some cases to return NamedLoaderContexts from loaded
+functions. Instead of choking or requireing implimenters to call the
+context's value() method before being de-scoped, detect when a
+NamedLoaderContext has been returned and return the value from the
+current context.
+
+Co-authored-by: Daniel A. Wozniak <daniel.wozniak@broadcom.com>
+---
+ salt/loader/lazy.py                              |  5 ++++-
+ tests/pytests/integration/modules/test_config.py |  8 ++++++++
+ tests/pytests/unit/loader/test_loader.py         | 13 +++++++++++++
+ 3 files changed, 25 insertions(+), 1 deletion(-)
+ create mode 100644 tests/pytests/integration/modules/test_config.py
+
+diff --git a/salt/loader/lazy.py b/salt/loader/lazy.py
+index 5de995d446..b7fd97f0e1 100644
+--- a/salt/loader/lazy.py
++++ b/salt/loader/lazy.py
+@@ -1246,7 +1246,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
+             self.parent_loader = current_loader
+         token = salt.loader.context.loader_ctxvar.set(self)
+         try:
+-            return _func_or_method(*args, **kwargs)
++            ret = _func_or_method(*args, **kwargs)
++            if isinstance(ret, salt.loader.context.NamedLoaderContext):
++                ret = ret.value()
++            return ret
+         finally:
+             self.parent_loader = None
+             salt.loader.context.loader_ctxvar.reset(token)
+diff --git a/tests/pytests/integration/modules/test_config.py b/tests/pytests/integration/modules/test_config.py
+new file mode 100644
+index 0000000000..afdf470605
+--- /dev/null
++++ b/tests/pytests/integration/modules/test_config.py
+@@ -0,0 +1,8 @@
++import pytest
++
++
++@pytest.mark.slow_test
++def test_config_items(salt_cli, salt_minion):
++    ret = salt_cli.run("config.items", minion_tgt=salt_minion.id)
++    assert ret.returncode == 0
++    assert isinstance(ret.data, dict)
+diff --git a/tests/pytests/unit/loader/test_loader.py b/tests/pytests/unit/loader/test_loader.py
+index 86348749db..aba605f42a 100644
+--- a/tests/pytests/unit/loader/test_loader.py
++++ b/tests/pytests/unit/loader/test_loader.py
+@@ -62,3 +62,16 @@ def test_raw_mod_functions():
+     ret = salt.loader.raw_mod(opts, "grains", "get")
+     for k, v in ret.items():
+         assert isinstance(v, salt.loader.lazy.LoadedFunc)
++
++
++def test_return_named_context_from_loaded_func(tmp_path):
++    opts = {
++        "optimization_order": [0],
++    }
++    contents = """
++    def foobar():
++        return __test__
++    """
++    with pytest.helpers.temp_file("mymod.py", contents, directory=tmp_path):
++        loader = salt.loader.LazyLoader([tmp_path], opts, pack={"__test__": "meh"})
++        assert loader["mymod.foobar"]() == "meh"
+-- 
+2.46.1
+
diff --git a/avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch b/avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch
new file mode 100644
index 0000000..7b7d716
--- /dev/null
+++ b/avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch
@@ -0,0 +1,153 @@
+From b2faa019f0f5aa03b03e6c54c9aa60b7f6aa4f91 Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Fri, 30 Aug 2024 14:35:33 +0200
+Subject: [PATCH] Avoid crash on wrong output of systemctl version
+ (bsc#1229539)
+
+* Better handling output of systemctl --version
+
+* Add more cases to test grains.core._systemd
+---
+ salt/grains/core.py                    | 27 +++++++-
+ tests/pytests/unit/grains/test_core.py | 89 ++++++++++++++++++++++++++
+ 2 files changed, 113 insertions(+), 3 deletions(-)
+
+diff --git a/salt/grains/core.py b/salt/grains/core.py
+index 4454c303fe..98bbd3868e 100644
+--- a/salt/grains/core.py
++++ b/salt/grains/core.py
+@@ -2432,10 +2432,31 @@ def _systemd():
+     """
+     Return the systemd grain
+     """
+-    systemd_info = __salt__["cmd.run"]("systemctl --version").splitlines()
++    systemd_version = "UNDEFINED"
++    systemd_features = ""
++    try:
++        systemd_output = __salt__["cmd.run_all"]("systemctl --version")
++    except Exception:  # pylint: disable=broad-except
++        log.error("Exception while executing `systemctl --version`", exc_info=True)
++        return {
++            "version": systemd_version,
++            "features": systemd_features,
++        }
++    if systemd_output.get("retcode") == 0:
++        systemd_info = systemd_output.get("stdout", "").splitlines()
++        try:
++            if systemd_info[0].startswith("systemd "):
++                systemd_version = systemd_info[0].split()[1]
++                systemd_features = systemd_info[1]
++        except IndexError:
++            pass
++    if systemd_version == "UNDEFINED" or systemd_features == "":
++        log.error(
++            "Unexpected output returned by `systemctl --version`: %s", systemd_output
++        )
+     return {
+-        "version": systemd_info[0].split()[1],
+-        "features": systemd_info[1],
++        "version": systemd_version,
++        "features": systemd_features,
+     }
+ 
+ 
+diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py
+index 36545287b9..b64b8c4bf8 100644
+--- a/tests/pytests/unit/grains/test_core.py
++++ b/tests/pytests/unit/grains/test_core.py
+@@ -3593,3 +3593,92 @@ def test_virtual_set_virtual_ec2():
+ 
+         assert virtual_grains["virtual"] == "Nitro"
+         assert virtual_grains["virtual_subtype"] == "Amazon EC2"
++
++
++@pytest.mark.parametrize(
++    "systemd_data,expected",
++    (
++        (
++            {
++                "pid": 1234,
++                "retcode": 0,
++                "stdout": "systemd 254 (254.3-1)\n+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK "
++                "+SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS "
++                "+FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 "
++                "-PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD "
++                "+BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified",
++                "stderr": "",
++            },
++            {
++                "version": "254",
++                "features": "+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL "
++                "+ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP "
++                "+LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ "
++                "+ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified",
++            },
++        ),
++        (
++            {
++                "pid": 2345,
++                "retcode": 1,
++                "stdout": "",
++                "stderr": "some garbage in the output",
++            },
++            {
++                "version": "UNDEFINED",
++                "features": "",
++            },
++        ),
++        (
++            {
++                "pid": 3456,
++                "retcode": 0,
++                "stdout": "unexpected stdout\none more line",
++                "stderr": "",
++            },
++            {
++                "version": "UNDEFINED",
++                "features": "",
++            },
++        ),
++        (
++            {
++                "pid": 4567,
++                "retcode": 0,
++                "stdout": "",
++                "stderr": "",
++            },
++            {
++                "version": "UNDEFINED",
++                "features": "",
++            },
++        ),
++        (
++            Exception("Some exception on calling `systemctl --version`"),
++            {
++                "version": "UNDEFINED",
++                "features": "",
++            },
++        ),
++    ),
++)
++def test__systemd(systemd_data, expected):
++    """
++    test _systemd
++    """
++
++    def mock_run_all_systemd(_):
++        if isinstance(systemd_data, Exception):
++            raise systemd_data
++        return systemd_data
++
++    with patch.dict(
++        core.__salt__,
++        {
++            "cmd.run_all": mock_run_all_systemd,
++        },
++    ):
++        ret = core._systemd()
++        assert "version" in ret
++        assert "features" in ret
++        assert ret == expected
+-- 
+2.46.0
+
diff --git a/avoid-explicit-reading-of-etc-salt-minion-bsc-122035.patch b/avoid-explicit-reading-of-etc-salt-minion-bsc-122035.patch
new file mode 100644
index 0000000..f0bc283
--- /dev/null
+++ b/avoid-explicit-reading-of-etc-salt-minion-bsc-122035.patch
@@ -0,0 +1,27 @@
+From bbdb56932845dceb47332a4c967c13a9a78b88bc Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Wed, 25 Sep 2024 14:08:20 +0300
+Subject: [PATCH] Avoid explicit reading of /etc/salt/minion
+ (bsc#1220357)
+
+Co-authored-by: Daniel A. Wozniak <dwozniak@vmware.com>
+---
+ salt/utils/azurearm.py | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/salt/utils/azurearm.py b/salt/utils/azurearm.py
+index 276cbb66b3..9ae128273c 100644
+--- a/salt/utils/azurearm.py
++++ b/salt/utils/azurearm.py
+@@ -47,8 +47,6 @@ try:
+ except ImportError:
+     HAS_AZURE = False
+ 
+-__opts__ = salt.config.minion_config("/etc/salt/minion")
+-__salt__ = salt.loader.minion_mods(__opts__)
+ 
+ log = logging.getLogger(__name__)
+ 
+-- 
+2.46.1
+
diff --git a/fix-deprecated-code-677.patch b/fix-deprecated-code-677.patch
new file mode 100644
index 0000000..fee2ca0
--- /dev/null
+++ b/fix-deprecated-code-677.patch
@@ -0,0 +1,166 @@
+From d5f3df07783d8aaf3a897ca2f209e662973b930c Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Wed, 4 Sep 2024 13:11:33 +0200
+Subject: [PATCH] Fix deprecated code (#677)
+
+Due to SUSE's extended support policy, we won't remove
+code from Salt until next major release.
+---
+ salt/_logging/handlers.py          | 6 +++---
+ salt/log/__init__.py               | 2 +-
+ salt/log/handlers/__init__.py      | 2 +-
+ salt/log/mixins.py                 | 2 +-
+ salt/log/setup.py                  | 4 ++--
+ salt/modules/aptpkg.py             | 2 +-
+ salt/modules/cassandra_mod.py      | 2 +-
+ salt/returners/cassandra_return.py | 2 +-
+ salt/returners/django_return.py    | 2 +-
+ 9 files changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/salt/_logging/handlers.py b/salt/_logging/handlers.py
+index f4b0b6fec3d..5a1a1613137 100644
+--- a/salt/_logging/handlers.py
++++ b/salt/_logging/handlers.py
+@@ -36,7 +36,7 @@ class TemporaryLoggingHandler(logging.NullHandler):
+ 
+     def __init__(self, level=logging.NOTSET, max_queue_size=10000):
+         warn_until_date(
+-            "20240101",
++            "20260101",
+             "Please stop using '{name}.TemporaryLoggingHandler'. "
+             "'{name}.TemporaryLoggingHandler' will go away after "
+             "{{date}}.".format(name=__name__),
+@@ -225,7 +225,7 @@ if sys.version_info < (3, 7):
+         def __init__(self, queue):  # pylint: disable=useless-super-delegation
+             super().__init__(queue)
+             warn_until_date(
+-                "20240101",
++                "20260101",
+                 "Please stop using '{name}.QueueHandler' and instead "
+                 "use 'logging.handlers.QueueHandler'. "
+                 "'{name}.QueueHandler' will go away after "
+@@ -283,7 +283,7 @@ else:
+         def __init__(self, queue):  # pylint: disable=useless-super-delegation
+             super().__init__(queue)
+             warn_until_date(
+-                "20240101",
++                "20260101",
+                 "Please stop using '{name}.QueueHandler' and instead "
+                 "use 'logging.handlers.QueueHandler'. "
+                 "'{name}.QueueHandler' will go away after "
+diff --git a/salt/log/__init__.py b/salt/log/__init__.py
+index 3458474f2ca..69bfa8ed15b 100644
+--- a/salt/log/__init__.py
++++ b/salt/log/__init__.py
+@@ -24,7 +24,7 @@ from salt.log.setup import (
+ from salt.utils.versions import warn_until_date
+ 
+ warn_until_date(
+-    "20240101",
++    "20260101",
+     "Please stop using '{name}' and instead use 'salt._logging'. "
+     "'{name}' will go away after {{date}}.".format(name=__name__),
+     stacklevel=3,
+diff --git a/salt/log/handlers/__init__.py b/salt/log/handlers/__init__.py
+index 8bc740e20f1..55cf10cdb78 100644
+--- a/salt/log/handlers/__init__.py
++++ b/salt/log/handlers/__init__.py
+@@ -12,7 +12,7 @@ from salt._logging.handlers import (
+ from salt.utils.versions import warn_until_date
+ 
+ warn_until_date(
+-    "20240101",
++    "20260101",
+     "Please stop using '{name}' and instead use 'salt._logging.handlers'. "
+     "'{name}' will go away after {{date}}.".format(name=__name__),
+ )
+diff --git a/salt/log/mixins.py b/salt/log/mixins.py
+index 6619b564198..65f5ed7f78a 100644
+--- a/salt/log/mixins.py
++++ b/salt/log/mixins.py
+@@ -11,7 +11,7 @@ from salt.utils.versions import warn_until_date
+ # pylint: enable=unused-import
+ 
+ warn_until_date(
+-    "20240101",
++    "20260101",
+     "Please stop using '{name}' and instead use 'salt._logging.mixins'. "
+     "'{name}' will go away after {{date}}.".format(name=__name__),
+ )
+diff --git a/salt/log/setup.py b/salt/log/setup.py
+index 74bd7bbd3e1..f4c80b0f280 100644
+--- a/salt/log/setup.py
++++ b/salt/log/setup.py
+@@ -21,7 +21,7 @@ from salt._logging.impl import set_log_record_factory as setLogRecordFactory
+ from salt.utils.versions import warn_until_date
+ 
+ warn_until_date(
+-    "20240101",
++    "20260101",
+     "Please stop using '{name}' and instead use 'salt._logging'. "
+     "'{name}' will go away after {{date}}. Do note however that "
+     "'salt._logging' is now considered a non public implementation "
+@@ -34,7 +34,7 @@ def _deprecated_warning(func):
+     @wraps(func)
+     def wrapper(*args, **kwargs):
+         warn_until_date(
+-            "20240101",
++            "20260101",
+             "Please stop using 'salt.log.setup.{name}()' as it no longer does anything and "
+             "will go away after {{date}}.".format(name=func.__qualname__),
+             stacklevel=4,
+diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
+index ad5450c4151..cd40aea54f1 100644
+--- a/salt/modules/aptpkg.py
++++ b/salt/modules/aptpkg.py
+@@ -3128,7 +3128,7 @@ def expand_repo_def(**kwargs):
+         NOT USABLE IN THE CLI
+     """
+     warn_until_date(
+-        "20250101",
++        "20260101",
+         "The pkg.expand_repo_def function is deprecated and set for removal "
+         "after {date}. This is only unsed internally by the apt pkg state "
+         "module. If that's not the case, please file an new issue requesting "
+diff --git a/salt/modules/cassandra_mod.py b/salt/modules/cassandra_mod.py
+index 029fd08fb9b..db9c8821920 100644
+--- a/salt/modules/cassandra_mod.py
++++ b/salt/modules/cassandra_mod.py
+@@ -45,7 +45,7 @@ def __virtual__():
+         )
+ 
+     warn_until_date(
+-        "20240101",
++        "20260101",
+         "The cassandra returner is broken and deprecated, and will be removed"
+         " after {date}. Use the cassandra_cql returner instead",
+     )
+diff --git a/salt/returners/cassandra_return.py b/salt/returners/cassandra_return.py
+index ac01a4e46cb..5fcc00ee8ce 100644
+--- a/salt/returners/cassandra_return.py
++++ b/salt/returners/cassandra_return.py
+@@ -53,7 +53,7 @@ def __virtual__():
+     if not HAS_PYCASSA:
+         return False, "Could not import cassandra returner; pycassa is not installed."
+     warn_until_date(
+-        "20240101",
++        "20260101",
+         "The cassandra returner is broken and deprecated, and will be removed"
+         " after {date}. Use the cassandra_cql returner instead",
+     )
+diff --git a/salt/returners/django_return.py b/salt/returners/django_return.py
+index 36386875552..474653f3831 100644
+--- a/salt/returners/django_return.py
++++ b/salt/returners/django_return.py
+@@ -57,7 +57,7 @@ __virtualname__ = "django"
+ 
+ def __virtual__():
+     warn_until_date(
+-        "20240101",
++        "20260101",
+         "The django returner is broken and deprecated, and will be removed"
+         " after {date}.",
+     )
+-- 
+2.46.0
+
diff --git a/fix-test_debian-to-work-in-our-infrastructure-676.patch b/fix-test_debian-to-work-in-our-infrastructure-676.patch
new file mode 100644
index 0000000..5fd1714
--- /dev/null
+++ b/fix-test_debian-to-work-in-our-infrastructure-676.patch
@@ -0,0 +1,25 @@
+From a6d27a6f50bbbea539ec64bf96a5b9755e32bf69 Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Wed, 4 Sep 2024 13:11:05 +0200
+Subject: [PATCH] Fix test_debian to work in our infrastructure (#676)
+
+---
+ tests/pytests/functional/states/pkgrepo/test_debian.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/pytests/functional/states/pkgrepo/test_debian.py b/tests/pytests/functional/states/pkgrepo/test_debian.py
+index 87716706d5e..7bda100b634 100644
+--- a/tests/pytests/functional/states/pkgrepo/test_debian.py
++++ b/tests/pytests/functional/states/pkgrepo/test_debian.py
+@@ -205,7 +205,7 @@ def ubuntu_state_tree(system_aptsources, state_tree, grains):
+         - dist: {{ codename }}
+         - file: /etc/apt/sources.list.d/firefox-beta.list
+         - keyid: CE49EC21
+-        - keyserver: keyserver.ubuntu.com
++        - keyserver: hkp://keyserver.ubuntu.com:80
+     {%- endif %}
+ 
+     {%- if backports %}{%- do ubuntu_repos.append('kubuntu-ppa') %}
+-- 
+2.46.0
+
diff --git a/fix-test_system-flaky-setup_teardown-fn.patch b/fix-test_system-flaky-setup_teardown-fn.patch
new file mode 100644
index 0000000..f461f1e
--- /dev/null
+++ b/fix-test_system-flaky-setup_teardown-fn.patch
@@ -0,0 +1,44 @@
+From 5567f2bd51d66b7797c986cf64f79f71ca57eb63 Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Wed, 4 Sep 2024 13:10:44 +0200
+Subject: [PATCH] Fix test_system flaky setup_teardown fn
+
+---
+ tests/pytests/functional/modules/test_system.py | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/tests/pytests/functional/modules/test_system.py b/tests/pytests/functional/modules/test_system.py
+index 2cd03a3a3e4..270aafbe2cd 100644
+--- a/tests/pytests/functional/modules/test_system.py
++++ b/tests/pytests/functional/modules/test_system.py
+@@ -4,10 +4,12 @@ import os
+ import signal
+ import subprocess
+ import textwrap
++import time
+ 
+ import pytest
+ 
+ import salt.utils.files
++from salt.exceptions import CommandExecutionError
+ 
+ INSIDE_CONTAINER = os.getenv("HOSTNAME", "") == "salt-test-container"
+ 
+@@ -80,7 +82,13 @@ def setup_teardown_vars(file, service, system):
+             file.remove("/etc/machine-info")
+ 
+         if _systemd_timesyncd_available_:
+-            res = service.start("systemd-timesyncd")
++            try:
++                res = service.start("systemd-timesyncd")
++            except CommandExecutionError:
++                # We possibly did too many restarts in too short time
++                # Wait 10s (default systemd timeout) and try again
++                time.sleep(10)
++                res = service.start("systemd-timesyncd")
+             assert res
+ 
+ 
+-- 
+2.46.0
+
diff --git a/fix-the-selinux-context-for-salt-minion-service-bsc-.patch b/fix-the-selinux-context-for-salt-minion-service-bsc-.patch
new file mode 100644
index 0000000..280a9c6
--- /dev/null
+++ b/fix-the-selinux-context-for-salt-minion-service-bsc-.patch
@@ -0,0 +1,83 @@
+From d933c8f0795fdada84a01a2cc754586fa720993d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
+ <psuarezhernandez@suse.com>
+Date: Tue, 10 Sep 2024 13:46:09 +0100
+Subject: [PATCH] Fix the SELinux context for Salt Minion service
+ (bsc#1219041) (#670)
+
+Currently there are no SELinux policies for Salt.
+
+By default, the Salt Minion service runs as 'unconfined_service_t' when
+SELinux is enabled. This works fine in most cases but generates a problem
+then trying to transition to an 'unconfined_t', i.a. when running
+"cmd.run .... runas=nobody". Then we see this denied in audit logs:
+
+type=AVC msg=audit(1722870119.142:718): avc:  denied  { transition } for  pid=3421 comm="su" path="/usr/bin/bash" dev="vda3" ino=28565 scontext=system_u:system_r:unconfined_service_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0 tclass=process permissive=0
+
+(This happens for cmd.run at the time of trying to invoke a shell as a
+different user to gather the environment variables from this particular
+user)
+
+Fixing the SELinuxContext for the Salt Minion systemd service to a
+general 'unconfined_t' workarounds this situation.
+
+SELinuxContext attribute was added on systemd version 209.
+---
+ pkg/common/salt-minion.service         | 1 +
+ pkg/old/deb/salt-minion.service        | 1 +
+ pkg/old/suse/salt-minion.service       | 1 +
+ pkg/old/suse/salt-minion.service.rhel7 | 1 +
+ 4 files changed, 4 insertions(+)
+
+diff --git a/pkg/common/salt-minion.service b/pkg/common/salt-minion.service
+index 69aff18c583..696d0263c39 100644
+--- a/pkg/common/salt-minion.service
++++ b/pkg/common/salt-minion.service
+@@ -9,6 +9,7 @@ Type=notify
+ NotifyAccess=all
+ LimitNOFILE=8192
+ ExecStart=/usr/bin/salt-minion
++SELinuxContext=system_u:system_r:unconfined_t:s0
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff --git a/pkg/old/deb/salt-minion.service b/pkg/old/deb/salt-minion.service
+index 7e6cf146549..b0ad82c1334 100644
+--- a/pkg/old/deb/salt-minion.service
++++ b/pkg/old/deb/salt-minion.service
+@@ -8,6 +8,7 @@ KillMode=process
+ NotifyAccess=all
+ LimitNOFILE=8192
+ ExecStart=/usr/bin/salt-minion
++SELinuxContext=system_u:system_r:unconfined_t:s0
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff --git a/pkg/old/suse/salt-minion.service b/pkg/old/suse/salt-minion.service
+index 12f28314cb1..b99ef063522 100644
+--- a/pkg/old/suse/salt-minion.service
++++ b/pkg/old/suse/salt-minion.service
+@@ -10,6 +10,7 @@ ExecStart=/usr/bin/salt-minion
+ KillMode=process
+ Restart=on-failure
+ RestartSec=15
++SELinuxContext=system_u:system_r:unconfined_t:s0
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff --git a/pkg/old/suse/salt-minion.service.rhel7 b/pkg/old/suse/salt-minion.service.rhel7
+index 69172677140..92cc66d32f4 100644
+--- a/pkg/old/suse/salt-minion.service.rhel7
++++ b/pkg/old/suse/salt-minion.service.rhel7
+@@ -9,6 +9,7 @@ ExecStart=/usr/bin/salt-minion
+ KillMode=process
+ Restart=on-failure
+ RestartSec=15
++SELinuxContext=system_u:system_r:unconfined_t:s0
+ 
+ [Install]
+ WantedBy=multi-user.target
+-- 
+2.46.0
+
+
diff --git a/fix-x509-test-fails-on-old-openssl-systems-682.patch b/fix-x509-test-fails-on-old-openssl-systems-682.patch
new file mode 100644
index 0000000..bc650d5
--- /dev/null
+++ b/fix-x509-test-fails-on-old-openssl-systems-682.patch
@@ -0,0 +1,261 @@
+From 7daf461528c90776b8f865cd58d20e23bd5b6f3f Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Wed, 2 Oct 2024 09:09:34 +0200
+Subject: [PATCH] Fix x509 test fails on old openssl systems (#682)
+
+---
+ .../functional/modules/test_x509_v2.py        | 41 +++++++++++++----
+ .../pytests/functional/states/test_x509_v2.py | 44 +++++++++++++++----
+ .../scenarios/performance/test_performance.py |  8 +++-
+ 3 files changed, 75 insertions(+), 18 deletions(-)
+
+diff --git a/tests/pytests/functional/modules/test_x509_v2.py b/tests/pytests/functional/modules/test_x509_v2.py
+index 2e8152d04a..7de8f3b01f 100644
+--- a/tests/pytests/functional/modules/test_x509_v2.py
++++ b/tests/pytests/functional/modules/test_x509_v2.py
+@@ -681,8 +681,13 @@ def test_create_certificate_self_signed(x509, algo, request):
+     privkey = request.getfixturevalue(f"{algo}_privkey")
+     try:
+         res = x509.create_certificate(signing_private_key=privkey, CN="success")
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++    except salt.exceptions.CommandExecutionError as e:
++        if "Could not load PEM-encoded" in e.error:
++            pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++        else:
++            raise e
+     assert res.startswith("-----BEGIN CERTIFICATE-----")
+     cert = _get_cert(res)
+     assert cert.subject.rfc4514_string() == "CN=success"
+@@ -754,8 +759,13 @@ def test_create_certificate_from_privkey(x509, ca_key, ca_cert, algo, request):
+             private_key=privkey,
+             CN="success",
+         )
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++    except salt.exceptions.CommandExecutionError as e:
++        if "Could not load PEM-encoded" in e.error:
++            pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++        else:
++            raise e
+     assert res.startswith("-----BEGIN CERTIFICATE-----")
+     cert = _get_cert(res)
+     assert cert.subject.rfc4514_string() == "CN=success"
+@@ -802,8 +812,13 @@ def test_create_certificate_from_pubkey(x509, ca_key, ca_cert, algo, request):
+             public_key=pubkey,
+             CN="success",
+         )
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++    except salt.exceptions.CommandExecutionError as e:
++        if "Could not load PEM-encoded" in e.error:
++            pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++        else:
++            raise e
+     assert res.startswith("-----BEGIN CERTIFICATE-----")
+     cert = _get_cert(res)
+     assert cert.subject.rfc4514_string() == "CN=success"
+@@ -1341,8 +1356,13 @@ def test_create_csr(x509, algo, request):
+     privkey = request.getfixturevalue(f"{algo}_privkey")
+     try:
+         res = x509.create_csr(private_key=privkey)
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++    except salt.exceptions.CommandExecutionError as e:
++        if "Could not load PEM-encoded" in e.error:
++            pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++        else:
++            raise e
+     assert res.startswith("-----BEGIN CERTIFICATE REQUEST-----")
+ 
+ 
+@@ -1402,7 +1422,7 @@ def test_create_csr_raw(x509, rsa_privkey):
+ def test_create_private_key(x509, algo):
+     try:
+         res = x509.create_private_key(algo=algo)
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     assert res.startswith("-----BEGIN PRIVATE KEY-----")
+ 
+@@ -1413,7 +1433,7 @@ def test_create_private_key_with_passphrase(x509, algo):
+     passphrase = "hunter2"
+     try:
+         res = x509.create_private_key(algo=algo, passphrase=passphrase)
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     assert res.startswith("-----BEGIN ENCRYPTED PRIVATE KEY-----")
+     # ensure it can be loaded
+@@ -1465,8 +1485,13 @@ def test_get_private_key_size(x509, algo, expected, request):
+     privkey = request.getfixturevalue(f"{algo}_privkey")
+     try:
+         res = x509.get_private_key_size(privkey)
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++    except salt.exceptions.CommandExecutionError as e:
++        if "Could not load PEM-encoded" in e.error:
++            pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
++        else:
++            raise e
+     assert res == expected
+ 
+ 
+@@ -1612,7 +1637,7 @@ def test_verify_signature(x509, algo, request):
+     wrong_privkey = request.getfixturevalue(f"{algo}_privkey")
+     try:
+         privkey = x509.create_private_key(algo=algo)
+-    except UnsupportedAlgorithm:
++    except (UnsupportedAlgorithm, NotImplementedError):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     cert = x509.create_certificate(signing_private_key=privkey)
+     assert x509.verify_signature(cert, privkey)
+diff --git a/tests/pytests/functional/states/test_x509_v2.py b/tests/pytests/functional/states/test_x509_v2.py
+index 47a1c555f8..139f7b1906 100644
+--- a/tests/pytests/functional/states/test_x509_v2.py
++++ b/tests/pytests/functional/states/test_x509_v2.py
+@@ -574,9 +574,9 @@ def existing_cert(x509, cert_args, ca_key, rsa_privkey, request):
+         ca_key,
+         encoding=cert_args.get("encoding", "pem"),
+         passphrase=cert_args.get("pkcs12_passphrase"),
+-        subject=subject
+-        if "signing_policy" not in cert_args
+-        else "CN=from_signing_policy",
++        subject=(
++            subject if "signing_policy" not in cert_args else "CN=from_signing_policy"
++        ),
+     )
+     yield cert_args["name"]
+ 
+@@ -694,8 +694,12 @@ def existing_csr_exts(x509, csr_args, csr_args_exts, ca_key, rsa_privkey, reques
+ def existing_pk(x509, pk_args, request):
+     pk_args.update(request.param)
+     ret = x509.private_key_managed(**pk_args)
+-    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
+-        pytest.skip(f"Algorithm '{pk_args['algo']}' is not supported on this OpenSSL version")
++    if ret.result == False and (
++        "UnsupportedAlgorithm" in ret.comment or "NotImplementedError" in ret.comment
++    ):
++        pytest.skip(
++            f"Algorithm '{pk_args['algo']}' is not supported on this OpenSSL version"
++        )
+     _assert_pk_basic(
+         ret,
+         pk_args.get("algo", "rsa"),
+@@ -1054,6 +1058,8 @@ def test_certificate_managed_days_valid_does_not_override_days_remaining(
+ def test_certificate_managed_privkey_change(x509, cert_args, ec_privkey, ca_key):
+     cert_args["private_key"] = ec_privkey
+     ret = x509.certificate_managed(**cert_args)
++    if ret.result == False and "NotImplementedError" in ret.comment:
++        pytest.skip("Current OpenSSL does not support 'ec' algorithm")
+     _assert_cert_basic(ret, cert_args["name"], ec_privkey, ca_key)
+     assert ret.changes["private_key"]
+ 
+@@ -1237,6 +1243,8 @@ def test_certificate_managed_wrong_ca_key(
+     cert_args["private_key"] = ec_privkey
+     cert_args["signing_private_key"] = rsa_privkey
+     ret = x509.certificate_managed(**cert_args)
++    if ret.result == False and "NotImplementedError" in ret.comment:
++        pytest.skip("Current OpenSSL does not support 'ec' algorithm")
+     assert ret.result is False
+     assert not ret.changes
+     assert "Signing private key does not match the certificate" in ret.comment
+@@ -1917,6 +1925,8 @@ def test_csr_managed_existing_invalid_version(x509, csr_args, rsa_privkey):
+ def test_csr_managed_privkey_change(x509, csr_args, ec_privkey):
+     csr_args["private_key"] = ec_privkey
+     ret = x509.csr_managed(**csr_args)
++    if ret.result == False and "NotImplementedError" in ret.comment:
++        pytest.skip("Current OpenSSL does not support 'ec' algorithm")
+     _assert_csr_basic(ret, ec_privkey)
+     assert ret.changes["private_key"]
+ 
+@@ -2141,11 +2151,14 @@ def test_private_key_managed(x509, pk_args, algo, encoding, passphrase):
+         pytest.skip(
+             "PKCS12 serialization of Edwards-curve keys requires cryptography v37"
+         )
++
+     pk_args["algo"] = algo
+     pk_args["encoding"] = encoding
+     pk_args["passphrase"] = passphrase
+     ret = x509.private_key_managed(**pk_args)
+-    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
++    if ret.result == False and (
++        "UnsupportedAlgorithm" in ret.comment or "NotImplementedError" in ret.comment
++    ):
+         pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     _assert_pk_basic(ret, algo, encoding, passphrase)
+ 
+@@ -2155,6 +2168,8 @@ def test_private_key_managed_keysize(x509, pk_args, algo, keysize):
+     pk_args["algo"] = algo
+     pk_args["keysize"] = keysize
+     ret = x509.private_key_managed(**pk_args)
++    if ret.result == False and "NotImplementedError" in ret.comment:
++        pytest.skip("Current OpenSSL does not support 'ec' algorithm")
+     pk = _assert_pk_basic(ret, algo)
+     assert pk.key_size == keysize
+ 
+@@ -2174,8 +2189,12 @@ def test_private_key_managed_keysize(x509, pk_args, algo, keysize):
+ )
+ def test_private_key_managed_existing(x509, pk_args):
+     ret = x509.private_key_managed(**pk_args)
+-    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
+-        pytest.skip(f"Algorithm '{pk_args['algo']}' is not supported on this OpenSSL version")
++    if ret.result == False and (
++        "UnsupportedAlgorithm" in ret.comment or "NotImplementedError" in ret.comment
++    ):
++        pytest.skip(
++            f"Algorithm '{pk_args['algo']}' is not supported on this OpenSSL version"
++        )
+     _assert_not_changed(ret)
+ 
+ 
+@@ -2382,6 +2401,8 @@ def test_private_key_managed_follow_symlinks_changes(
+     pk_args["encoding"] = encoding
+     pk_args["algo"] = "ec"
+     ret = x509.private_key_managed(**pk_args)
++    if ret.result == False and "NotImplementedError" in ret.comment:
++        pytest.skip("Current OpenSSL does not support 'ec' algorithm")
+     assert ret.changes
+     assert Path(ret.name).is_symlink() == follow
+ 
+@@ -2722,7 +2743,12 @@ def _get_cert(cert, encoding="pem", passphrase=None):
+ def _belongs_to(cert_or_pubkey, privkey):
+     if isinstance(cert_or_pubkey, cx509.Certificate):
+         cert_or_pubkey = cert_or_pubkey.public_key()
+-    return x509util.is_pair(cert_or_pubkey, x509util.load_privkey(privkey))
++    try:
++        return x509util.is_pair(cert_or_pubkey, x509util.load_privkey(privkey))
++    except NotImplementedError:
++        pytest.skip(
++            "This OpenSSL version does not support current cryptographic algorithm"
++        )
+ 
+ 
+ def _signed_by(cert, privkey):
+diff --git a/tests/pytests/scenarios/performance/test_performance.py b/tests/pytests/scenarios/performance/test_performance.py
+index 85b92ed986..6319e26ce1 100644
+--- a/tests/pytests/scenarios/performance/test_performance.py
++++ b/tests/pytests/scenarios/performance/test_performance.py
+@@ -10,7 +10,13 @@ from saltfactories.utils import random_string
+ 
+ from salt.version import SaltVersionsInfo, __version__
+ 
+-pytestmark = [pytest.mark.skip_if_binaries_missing("docker")]
++pytestmark = [
++    pytest.mark.skip_if_binaries_missing("docker"),
++    pytest.mark.skipif(
++        os.environ.get("GITHUB_ACTIONS", "") == "true",
++        reason="Cannot spawn containers in GH actions run",
++    ),
++]
+ 
+ 
+ class ContainerMaster(SaltDaemon, master.SaltMaster):
+-- 
+2.46.1
+
diff --git a/improve-error-handling-with-different-openssl-versio.patch b/improve-error-handling-with-different-openssl-versio.patch
new file mode 100644
index 0000000..aaa103e
--- /dev/null
+++ b/improve-error-handling-with-different-openssl-versio.patch
@@ -0,0 +1,98 @@
+From 4e226426d0897f2d9dc64891ced78487b181d40e Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Fri, 30 Aug 2024 14:33:51 +0200
+Subject: [PATCH] Improve error handling with different OpenSSL
+ versions
+
+* Make error checking of x509 more flexible
+
+for most recent cryptography and openSSL versions
+
+* Add test for different exception value on loading private key
+
+* Add fix for test_privkey_new_with_prereq on old OpenSSL
+---
+ salt/utils/x509.py                            |  3 +-
+ .../pytests/functional/states/test_x509_v2.py | 29 +++++++++++++++++++
+ .../integration/states/test_x509_v2.py        |  7 +++++
+ 3 files changed, 38 insertions(+), 1 deletion(-)
+
+diff --git a/salt/utils/x509.py b/salt/utils/x509.py
+index 5b2ae15882..f9fdca64d9 100644
+--- a/salt/utils/x509.py
++++ b/salt/utils/x509.py
+@@ -695,7 +695,8 @@ def load_privkey(pk, passphrase=None, get_encoding=False):
+                 return pk, "pem", None
+             return pk
+         except ValueError as err:
+-            if "Bad decrypt" in str(err):
++            str_err = str(err)
++            if "Bad decrypt" in str_err or "Could not deserialize key data" in str_err:
+                 raise SaltInvocationError(
+                     "Bad decrypt - is the password correct?"
+                 ) from err
+diff --git a/tests/pytests/functional/states/test_x509_v2.py b/tests/pytests/functional/states/test_x509_v2.py
+index 929be014cd..47a1c555f8 100644
+--- a/tests/pytests/functional/states/test_x509_v2.py
++++ b/tests/pytests/functional/states/test_x509_v2.py
+@@ -3,6 +3,8 @@ from pathlib import Path
+ 
+ import pytest
+ 
++from tests.support.mock import patch
++
+ try:
+     import cryptography
+     import cryptography.x509 as cx509
+@@ -2826,3 +2828,30 @@ def _get_privkey(pk, encoding="pem", passphrase=None):
+             pk = base64.b64decode(pk)
+         return pkcs12.load_pkcs12(pk, passphrase).key
+     raise ValueError("Need correct encoding")
++
++
++@pytest.mark.usefixtures("existing_pk")
++@pytest.mark.parametrize("existing_pk", [{"passphrase": "password"}], indirect=True)
++def test_exceptions_on_calling_load_pem_private_key(x509, pk_args):
++    pk_args["passphrase"] = "hunter1"
++    pk_args["overwrite"] = True
++
++    with patch(
++        "cryptography.hazmat.primitives.serialization.load_pem_private_key",
++        side_effect=ValueError("Bad decrypt. Incorrect password?"),
++    ):
++        ret = x509.private_key_managed(**pk_args)
++    _assert_pk_basic(ret, "rsa", passphrase="hunter1")
++
++    with patch(
++        "cryptography.hazmat.primitives.serialization.load_pem_private_key",
++        side_effect=ValueError(
++            "Could not deserialize key data. The data may be in an incorrect format, "
++            "the provided password may be incorrect, "
++            "it may be encrypted with an unsupported algorithm, "
++            "or it may be an unsupported key type "
++            "(e.g. EC curves with explicit parameters)."
++        ),
++    ):
++        ret = x509.private_key_managed(**pk_args)
++    _assert_pk_basic(ret, "rsa", passphrase="hunter1")
+diff --git a/tests/pytests/integration/states/test_x509_v2.py b/tests/pytests/integration/states/test_x509_v2.py
+index 4f94341295..ad8d904c92 100644
+--- a/tests/pytests/integration/states/test_x509_v2.py
++++ b/tests/pytests/integration/states/test_x509_v2.py
+@@ -195,6 +195,13 @@ Certificate:
+     """
+     with x509_salt_master.state_tree.base.temp_file("manage_cert.sls", state):
+         ret = x509_salt_call_cli.run("state.apply", "manage_cert")
++        if (
++            ret.returncode == 1
++            and "NotImplementedError: ECDSA keys with unnamed curves" in ret.stdout
++        ):
++            pytest.skip(
++                "The version of OpenSSL doesn't support ECDSA keys with unnamed curves"
++            )
+         assert ret.returncode == 0
+         assert ret.data[next(iter(ret.data))]["changes"]
+         assert (tmp_path / "priv.key").exists()
+-- 
+2.46.0
+
diff --git a/join-masters-if-it-is-a-list-671.patch b/join-masters-if-it-is-a-list-671.patch
new file mode 100644
index 0000000..01a8dac
--- /dev/null
+++ b/join-masters-if-it-is-a-list-671.patch
@@ -0,0 +1,105 @@
+From 94973ee85d766d7e98d02d89f4c81e59b36cb716 Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Thu, 29 Aug 2024 10:01:12 +0200
+Subject: [PATCH] Join masters if it is a list (#671)
+
+Co-authored-by: Twangboy <shane.d.lee@gmail.com>
+---
+ changelog/64170.fixed.md               |  2 +
+ salt/utils/cloud.py                    | 10 +++++
+ tests/pytests/unit/utils/test_cloud.py | 52 ++++++++++++++++++++++++++
+ 3 files changed, 64 insertions(+)
+ create mode 100644 changelog/64170.fixed.md
+
+diff --git a/changelog/64170.fixed.md b/changelog/64170.fixed.md
+new file mode 100644
+index 0000000000..1d20355bf1
+--- /dev/null
++++ b/changelog/64170.fixed.md
+@@ -0,0 +1,2 @@
++Fixed issue in salt-cloud so that multiple masters specified in the cloud
++are written to the minion config properly
+diff --git a/salt/utils/cloud.py b/salt/utils/cloud.py
+index b7208dc4a6..a084313059 100644
+--- a/salt/utils/cloud.py
++++ b/salt/utils/cloud.py
+@@ -1202,6 +1202,16 @@ def wait_for_passwd(
+             time.sleep(trysleep)
+ 
+ 
++def _format_master_param(master):
++    """
++    If the master is a list, we need to convert it to a comma delimited string
++    Otherwise, we just return master
++    """
++    if isinstance(master, list):
++        return ",".join(master)
++    return master
++
++
+ def deploy_windows(
+     host,
+     port=445,
+diff --git a/tests/pytests/unit/utils/test_cloud.py b/tests/pytests/unit/utils/test_cloud.py
+index 550b63c974..db9d258d39 100644
+--- a/tests/pytests/unit/utils/test_cloud.py
++++ b/tests/pytests/unit/utils/test_cloud.py
+@@ -605,3 +605,55 @@ def test_deploy_script_ssh_timeout():
+         ssh_kwargs = root_cmd.call_args.kwargs
+         assert "ssh_timeout" in ssh_kwargs
+         assert ssh_kwargs["ssh_timeout"] == 34
++
++
++@pytest.mark.parametrize(
++    "master,expected",
++    [
++        (None, None),
++        ("single_master", "single_master"),
++        (["master1", "master2", "master3"], "master1,master2,master3"),
++    ],
++)
++def test__format_master_param(master, expected):
++    result = cloud._format_master_param(master)
++    assert result == expected
++
++
++@pytest.mark.skip_unless_on_windows(reason="Only applicable for Windows.")
++@pytest.mark.parametrize(
++    "master,expected",
++    [
++        (None, None),
++        ("single_master", "single_master"),
++        (["master1", "master2", "master3"], "master1,master2,master3"),
++    ],
++)
++def test_deploy_windows_master(master, expected):
++    """
++    Test deploy_windows with master parameter
++    """
++    mock_true = MagicMock(return_value=True)
++    mock_tuple = MagicMock(return_value=(0, 0, 0))
++    with patch("salt.utils.smb.get_conn", MagicMock()), patch(
++        "salt.utils.smb.mkdirs", MagicMock()
++    ), patch("salt.utils.smb.put_file", MagicMock()), patch(
++        "salt.utils.smb.delete_file", MagicMock()
++    ), patch(
++        "salt.utils.smb.delete_directory", MagicMock()
++    ), patch(
++        "time.sleep", MagicMock()
++    ), patch.object(
++        cloud, "wait_for_port", mock_true
++    ), patch.object(
++        cloud, "fire_event", MagicMock()
++    ), patch.object(
++        cloud, "wait_for_psexecsvc", mock_true
++    ), patch.object(
++        cloud, "run_psexec_command", mock_tuple
++    ) as mock:
++        cloud.deploy_windows(host="test", win_installer="install.exe", master=master)
++        expected_cmd = "c:\\salttemp\\install.exe"
++        expected_args = "/S /master={} /minion-name=None".format(expected)
++        assert mock.call_args_list[0].args[0] == expected_cmd
++        assert mock.call_args_list[0].args[1] == expected_args
+-- 
+2.44.0
+
diff --git a/make-tests-compatible-with-venv-bundle.patch b/make-tests-compatible-with-venv-bundle.patch
new file mode 100644
index 0000000..9d72973
--- /dev/null
+++ b/make-tests-compatible-with-venv-bundle.patch
@@ -0,0 +1,883 @@
+From 25c3df7713bd2a19a0980358fa72c1c48a08a1f4 Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Wed, 7 Aug 2024 10:28:07 +0200
+Subject: [PATCH] Make tests compatible with venv bundle
+
+Co-authored-by: cmcmarrow <charles.mcmarrow.4@gmail.com>
+---
+ tests/pytests/functional/modules/test_sdb.py  |  1 +
+ tests/pytests/functional/modules/test_yaml.py |  2 +-
+ .../rthooks/test_salt_utils_vt_terminal.py    | 22 +++++--
+ .../pyinstaller/rthooks/test_subprocess.py    | 22 +++++--
+ .../utils/yamllint/test_yamllint.py           |  2 +-
+ tests/pytests/unit/modules/test_pip.py        | 63 +++++++++++++------
+ .../unit/modules/test_transactional_update.py | 13 ++--
+ tests/pytests/unit/states/test_pkgrepo.py     |  3 +-
+ tests/pytests/unit/test_fileserver.py         |  8 +--
+ tests/pytests/unit/utils/test_gitfs.py        | 18 ++++++
+ tests/pytests/unit/utils/test_msgpack.py      |  2 +-
+ tests/pytests/unit/utils/test_pycrypto.py     | 25 ++++----
+ tests/unit/test_config.py                     | 20 +++++-
+ tests/unit/utils/test_sdb.py                  |  2 +-
+ tests/unit/utils/test_templates.py            | 34 ++++++++++
+ 15 files changed, 177 insertions(+), 60 deletions(-)
+
+diff --git a/tests/pytests/functional/modules/test_sdb.py b/tests/pytests/functional/modules/test_sdb.py
+index 5519bf8ab57..837e7515d30 100644
+--- a/tests/pytests/functional/modules/test_sdb.py
++++ b/tests/pytests/functional/modules/test_sdb.py
+@@ -16,6 +16,7 @@ def minion_config_overrides():
+         }
+ 
+ 
++@pytest.mark.skip("Great module migration")
+ @pytest.mark.parametrize(
+     "expected_value",
+     (
+diff --git a/tests/pytests/functional/modules/test_yaml.py b/tests/pytests/functional/modules/test_yaml.py
+index 2a8fbc113ff..9aad0dfdc8c 100644
+--- a/tests/pytests/functional/modules/test_yaml.py
++++ b/tests/pytests/functional/modules/test_yaml.py
+@@ -13,7 +13,7 @@ try:
+     import salt.modules.yaml
+     import salt.utils.yamllint
+ 
+-    YAMLLINT_AVAILABLE = True
++    YAMLLINT_AVAILABLE = salt.utils.yamllint.has_yamllint()
+ except ImportError:
+     YAMLLINT_AVAILABLE = False
+ 
+diff --git a/tests/pytests/functional/utils/pyinstaller/rthooks/test_salt_utils_vt_terminal.py b/tests/pytests/functional/utils/pyinstaller/rthooks/test_salt_utils_vt_terminal.py
+index c45b5730a8e..ea687c0776d 100644
+--- a/tests/pytests/functional/utils/pyinstaller/rthooks/test_salt_utils_vt_terminal.py
++++ b/tests/pytests/functional/utils/pyinstaller/rthooks/test_salt_utils_vt_terminal.py
+@@ -8,6 +8,9 @@ import salt.utils.pyinstaller.rthooks._overrides as overrides
+ from tests.support import mock
+ from tests.support.helpers import PatchedEnviron
+ 
++LD_LIBRARY_PATH = ""
++if os.environ.get('VIRTUAL_ENV'):
++    LD_LIBRARY_PATH = f"{os.environ.get('VIRTUAL_ENV')}/lib"
+ 
+ @pytest.fixture(params=("LD_LIBRARY_PATH", "LIBPATH"))
+ def envvar(request):
+@@ -17,9 +20,14 @@ def envvar(request):
+ @pytest.fixture
+ def meipass(envvar):
+     with mock.patch("salt.utils.pyinstaller.rthooks._overrides.sys") as patched_sys:
+-        patched_sys._MEIPASS = "{}_VALUE".format(envvar)
+-        assert overrides.sys._MEIPASS == "{}_VALUE".format(envvar)
+-        yield "{}_VALUE".format(envvar)
++        ld_path_mock_val = f"{envvar}_VALUE"
++        if envvar == "LD_LIBRARY_PATH" and LD_LIBRARY_PATH:
++            # venv-minion python wrapper hardcodes LD_LIB_PATH that
++            # we cannot overwrite from the testsuite
++            ld_path_mock_val = LD_LIBRARY_PATH
++        patched_sys._MEIPASS = ld_path_mock_val
++        assert overrides.sys._MEIPASS == ld_path_mock_val
++        yield ld_path_mock_val
+     assert not hasattr(sys, "_MEIPASS")
+     assert not hasattr(overrides.sys, "_MEIPASS")
+ 
+@@ -111,7 +119,8 @@ def test_vt_terminal_environ_cleanup(envvar, meipass):
+         returned_env = json.loads(buffer_o)
+         assert returned_env != original_env
+         assert envvar in returned_env
+-        assert returned_env[envvar] == ""
++        envvar_value = LD_LIBRARY_PATH if envvar == "LD_LIBRARY_PATH" else ""
++        assert returned_env[envvar] == envvar_value
+ 
+ 
+ def test_vt_terminal_environ_cleanup_passed_directly_not_removed(envvar, meipass):
+@@ -139,4 +148,7 @@ def test_vt_terminal_environ_cleanup_passed_directly_not_removed(envvar, meipass
+     returned_env = json.loads(buffer_o)
+     assert returned_env != original_env
+     assert envvar in returned_env
+-    assert returned_env[envvar] == envvar
++    envvar_val = envvar
++    if LD_LIBRARY_PATH and envvar == "LD_LIBRARY_PATH":
++        envvar_val = LD_LIBRARY_PATH
++    assert returned_env[envvar] == envvar_val
+diff --git a/tests/pytests/functional/utils/pyinstaller/rthooks/test_subprocess.py b/tests/pytests/functional/utils/pyinstaller/rthooks/test_subprocess.py
+index 836e392d016..e4b5420d5e3 100644
+--- a/tests/pytests/functional/utils/pyinstaller/rthooks/test_subprocess.py
++++ b/tests/pytests/functional/utils/pyinstaller/rthooks/test_subprocess.py
+@@ -9,6 +9,9 @@ import salt.utils.pyinstaller.rthooks._overrides as overrides
+ from tests.support import mock
+ from tests.support.helpers import PatchedEnviron
+ 
++LD_LIBRARY_PATH = ""
++if os.environ.get('VIRTUAL_ENV'):
++    LD_LIBRARY_PATH = f"{os.environ.get('VIRTUAL_ENV')}/lib"
+ 
+ @pytest.fixture(params=("LD_LIBRARY_PATH", "LIBPATH"))
+ def envvar(request):
+@@ -18,9 +21,14 @@ def envvar(request):
+ @pytest.fixture
+ def meipass(envvar):
+     with mock.patch("salt.utils.pyinstaller.rthooks._overrides.sys") as patched_sys:
+-        patched_sys._MEIPASS = "{}_VALUE".format(envvar)
+-        assert overrides.sys._MEIPASS == "{}_VALUE".format(envvar)
+-        yield "{}_VALUE".format(envvar)
++        ld_path_mock_val = f"{envvar}_VALUE"
++        if envvar == "LD_LIBRARY_PATH" and LD_LIBRARY_PATH:
++            # venv-minion python wrapper hardcodes LD_LIB_PATH that
++            # we cannot overwrite from the testsuite
++            ld_path_mock_val = LD_LIBRARY_PATH
++        patched_sys._MEIPASS = ld_path_mock_val
++        assert overrides.sys._MEIPASS == ld_path_mock_val
++        yield ld_path_mock_val
+     assert not hasattr(sys, "_MEIPASS")
+     assert not hasattr(overrides.sys, "_MEIPASS")
+ 
+@@ -88,7 +96,8 @@ def test_subprocess_popen_environ_cleanup(envvar, meipass):
+         returned_env = json.loads(stdout)
+         assert returned_env != original_env
+         assert envvar in returned_env
+-        assert returned_env[envvar] == ""
++        envvar_value = LD_LIBRARY_PATH if envvar == "LD_LIBRARY_PATH" else ""
++        assert returned_env[envvar] == envvar_value
+ 
+ 
+ def test_subprocess_popen_environ_cleanup_passed_directly_not_removed(envvar, meipass):
+@@ -108,4 +117,7 @@ def test_subprocess_popen_environ_cleanup_passed_directly_not_removed(envvar, me
+     returned_env = json.loads(stdout)
+     assert returned_env != original_env
+     assert envvar in returned_env
+-    assert returned_env[envvar] == envvar
++    envvar_val = envvar
++    if LD_LIBRARY_PATH and envvar == "LD_LIBRARY_PATH":
++        envvar_val = LD_LIBRARY_PATH
++    assert returned_env[envvar] == envvar_val
+diff --git a/tests/pytests/functional/utils/yamllint/test_yamllint.py b/tests/pytests/functional/utils/yamllint/test_yamllint.py
+index 403c6fc610e..3c730523c4d 100644
+--- a/tests/pytests/functional/utils/yamllint/test_yamllint.py
++++ b/tests/pytests/functional/utils/yamllint/test_yamllint.py
+@@ -7,7 +7,7 @@ import salt.utils.versions as versions
+ try:
+     import salt.utils.yamllint as yamllint
+ 
+-    YAMLLINT_AVAILABLE = True
++    YAMLLINT_AVAILABLE = yamllint.has_yamllint()
+ except ImportError:
+     YAMLLINT_AVAILABLE = False
+ 
+diff --git a/tests/pytests/unit/modules/test_pip.py b/tests/pytests/unit/modules/test_pip.py
+index 4b2da77786b..fbe0dc5f1cf 100644
+--- a/tests/pytests/unit/modules/test_pip.py
++++ b/tests/pytests/unit/modules/test_pip.py
+@@ -15,6 +15,10 @@ MISSING_SETUP_PY_FILE = not os.path.exists(
+     os.path.join(RUNTIME_VARS.CODE_DIR, "setup.py")
+ )
+ 
++TARGET = []
++if os.environ.get('VENV_PIP_TARGET'):
++    TARGET = ["--target", os.environ.get('VENV_PIP_TARGET')]
++
+ 
+ class FakeFopen:
+     def __init__(self, filename):
+@@ -102,6 +106,7 @@ def test_install_frozen_app(python_binary):
+                 expected = [
+                     *python_binary,
+                     "install",
++                    *TARGET,
+                     pkg,
+                 ]
+                 mock.assert_called_with(
+@@ -123,6 +128,7 @@ def test_install_source_app(python_binary):
+                 expected = [
+                     *python_binary,
+                     "install",
++                    *TARGET,
+                     pkg,
+                 ]
+                 mock.assert_called_with(
+@@ -143,6 +149,7 @@ def test_fix4361(python_binary):
+             "install",
+             "--requirement",
+             "requirements.txt",
++            *TARGET,
+         ]
+         mock.assert_called_with(
+             expected_cmd,
+@@ -169,7 +176,7 @@ def test_install_multiple_editable(python_binary):
+         "git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting",
+     ]
+ 
+-    expected = [*python_binary, "install"]
++    expected = [*python_binary, "install", *TARGET]
+     for item in editables:
+         expected.extend(["--editable", item])
+ 
+@@ -205,7 +212,7 @@ def test_install_multiple_pkgs_and_editables(python_binary):
+         "git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting",
+     ]
+ 
+-    expected = [*python_binary, "install"]
++    expected = [*python_binary, "install", *TARGET]
+     expected.extend(pkgs)
+     for item in editables:
+         expected.extend(["--editable", item])
+@@ -241,6 +248,7 @@ def test_install_multiple_pkgs_and_editables(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             pkgs[0],
+             "--editable",
+             editables[0],
+@@ -268,7 +276,7 @@ def test_issue5940_install_multiple_pip_mirrors(python_binary):
+         expected = [*python_binary, "install", "--use-mirrors"]
+         for item in mirrors:
+             expected.extend(["--mirrors", item])
+-        expected.append("pep8")
++        expected = [*expected, *TARGET, "pep8"]
+ 
+         # Passing mirrors as a list
+         mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+@@ -300,6 +308,7 @@ def test_issue5940_install_multiple_pip_mirrors(python_binary):
+             "--use-mirrors",
+             "--mirrors",
+             mirrors[0],
++            *TARGET,
+             "pep8",
+         ]
+ 
+@@ -327,7 +336,7 @@ def test_install_with_multiple_find_links(python_binary):
+     expected = [*python_binary, "install"]
+     for item in find_links:
+         expected.extend(["--find-links", item])
+-    expected.append(pkg)
++    expected = [*expected, *TARGET, pkg]
+ 
+     # Passing mirrors as a list
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+@@ -370,6 +379,7 @@ def test_install_with_multiple_find_links(python_binary):
+         "install",
+         "--find-links",
+         find_links[0],
++        *TARGET,
+         pkg,
+     ]
+ 
+@@ -435,6 +445,7 @@ def test_install_cached_requirements_used(python_binary):
+                 "install",
+                 "--requirement",
+                 "my_cached_reqs",
++                *TARGET,
+             ]
+             mock.assert_called_with(
+                 expected,
+@@ -491,6 +502,7 @@ def test_install_log_argument_in_resulting_command(python_binary):
+                 "install",
+                 "--log",
+                 log_path,
++                *TARGET,
+                 pkg,
+             ]
+             mock.assert_called_with(
+@@ -521,7 +533,7 @@ def test_install_timeout_argument_in_resulting_command(python_binary):
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, timeout=10)
+         mock.assert_called_with(
+-            expected + [10, pkg],
++            expected + [10, *TARGET, pkg],
+             saltenv="base",
+             runas=None,
+             use_vt=False,
+@@ -533,7 +545,7 @@ def test_install_timeout_argument_in_resulting_command(python_binary):
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, timeout="10")
+         mock.assert_called_with(
+-            expected + ["10", pkg],
++            expected + ["10", *TARGET, pkg],
+             saltenv="base",
+             runas=None,
+             use_vt=False,
+@@ -557,6 +569,7 @@ def test_install_index_url_argument_in_resulting_command(python_binary):
+             "install",
+             "--index-url",
+             index_url,
++            *TARGET,
+             pkg,
+         ]
+         mock.assert_called_with(
+@@ -579,6 +592,7 @@ def test_install_extra_index_url_argument_in_resulting_command(python_binary):
+             "install",
+             "--extra-index-url",
+             extra_index_url,
++            *TARGET,
+             pkg,
+         ]
+         mock.assert_called_with(
+@@ -595,7 +609,7 @@ def test_install_no_index_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, no_index=True)
+-        expected = [*python_binary, "install", "--no-index", pkg]
++        expected = [*python_binary, "install", "--no-index", *TARGET, pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -611,7 +625,7 @@ def test_install_build_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, build=build)
+-        expected = [*python_binary, "install", "--build", build, pkg]
++        expected = [*python_binary, "install", "--build", build, *TARGET, pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -646,6 +660,7 @@ def test_install_download_argument_in_resulting_command(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             "--download",
+             download,
+             pkg,
+@@ -664,7 +679,7 @@ def test_install_no_download_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, no_download=True)
+-        expected = [*python_binary, "install", "--no-download", pkg]
++        expected = [*python_binary, "install", *TARGET, "--no-download", pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -691,6 +706,7 @@ def test_install_download_cache_dir_arguments_in_resulting_command(python_binary
+                 expected = [
+                     *python_binary,
+                     "install",
++                    *TARGET,
+                     cmd_arg,
+                     download_cache,
+                     pkg,
+@@ -720,7 +736,7 @@ def test_install_source_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, source=source)
+-        expected = [*python_binary, "install", "--source", source, pkg]
++        expected = [*python_binary, "install", *TARGET, "--source", source, pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -739,6 +755,7 @@ def test_install_exists_action_argument_in_resulting_command(python_binary):
+             expected = [
+                 *python_binary,
+                 "install",
++                *TARGET,
+                 "--exists-action",
+                 action,
+                 pkg,
+@@ -761,7 +778,7 @@ def test_install_install_options_argument_in_resulting_command(python_binary):
+     install_options = ["--exec-prefix=/foo/bar", "--install-scripts=/foo/bar/bin"]
+     pkg = "pep8"
+ 
+-    expected = [*python_binary, "install"]
++    expected = [*python_binary, "install", *TARGET]
+     for item in install_options:
+         expected.extend(["--install-option", item])
+     expected.append(pkg)
+@@ -797,6 +814,7 @@ def test_install_install_options_argument_in_resulting_command(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             "--install-option",
+             install_options[0],
+             pkg,
+@@ -814,7 +832,7 @@ def test_install_global_options_argument_in_resulting_command(python_binary):
+     global_options = ["--quiet", "--no-user-cfg"]
+     pkg = "pep8"
+ 
+-    expected = [*python_binary, "install"]
++    expected = [*python_binary, "install", *TARGET]
+     for item in global_options:
+         expected.extend(["--global-option", item])
+     expected.append(pkg)
+@@ -850,6 +868,7 @@ def test_install_global_options_argument_in_resulting_command(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             "--global-option",
+             global_options[0],
+             pkg,
+@@ -868,7 +887,7 @@ def test_install_upgrade_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, upgrade=True)
+-        expected = [*python_binary, "install", "--upgrade", pkg]
++        expected = [*python_binary, "install", *TARGET, "--upgrade", pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -886,6 +905,7 @@ def test_install_force_reinstall_argument_in_resulting_command(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             "--force-reinstall",
+             pkg,
+         ]
+@@ -906,6 +926,7 @@ def test_install_ignore_installed_argument_in_resulting_command(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             "--ignore-installed",
+             pkg,
+         ]
+@@ -923,7 +944,7 @@ def test_install_no_deps_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, no_deps=True)
+-        expected = [*python_binary, "install", "--no-deps", pkg]
++        expected = [*python_binary, "install", *TARGET, "--no-deps", pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -938,7 +959,7 @@ def test_install_no_install_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, no_install=True)
+-        expected = [*python_binary, "install", "--no-install", pkg]
++        expected = [*python_binary, "install", *TARGET, "--no-install", pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -954,7 +975,7 @@ def test_install_proxy_argument_in_resulting_command(python_binary):
+     mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         pip.install(pkg, proxy=proxy)
+-        expected = [*python_binary, "install", "--proxy", proxy, pkg]
++        expected = [*python_binary, "install", "--proxy", proxy, *TARGET, pkg]
+         mock.assert_called_with(
+             expected,
+             saltenv="base",
+@@ -981,7 +1002,7 @@ def test_install_proxy_false_argument_in_resulting_command(python_binary):
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         with patch.dict(pip.__opts__, config_mock):
+             pip.install(pkg, proxy=proxy)
+-            expected = [*python_binary, "install", pkg]
++            expected = [*python_binary, "install", *TARGET, pkg]
+             mock.assert_called_with(
+                 expected,
+                 saltenv="base",
+@@ -1012,6 +1033,7 @@ def test_install_global_proxy_in_resulting_command(python_binary):
+                 "install",
+                 "--proxy",
+                 proxy,
++                *TARGET,
+                 pkg,
+             ]
+             mock.assert_called_with(
+@@ -1032,6 +1054,7 @@ def test_install_multiple_requirements_arguments_in_resulting_command(python_bin
+         expected = [*python_binary, "install"]
+         for item in cached_reqs:
+             expected.extend(["--requirement", item])
++        expected.extend(TARGET)
+ 
+         # Passing option as a list
+         mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
+@@ -1068,6 +1091,7 @@ def test_install_multiple_requirements_arguments_in_resulting_command(python_bin
+                 "install",
+                 "--requirement",
+                 cached_reqs[0],
++                *TARGET,
+             ]
+             mock.assert_called_with(
+                 expected,
+@@ -1088,6 +1112,7 @@ def test_install_extra_args_arguments_in_resulting_command(python_binary):
+         expected = [
+             *python_binary,
+             "install",
++            *TARGET,
+             pkg,
+             "--latest-pip-kwarg",
+             "param",
+@@ -1604,7 +1629,7 @@ def test_install_pre_argument_in_resulting_command(python_binary):
+     with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
+         with patch("salt.modules.pip.version", MagicMock(return_value="1.3")):
+             pip.install(pkg, pre_releases=True)
+-            expected = [*python_binary, "install", pkg]
++            expected = [*python_binary, "install", *TARGET, pkg]
+             mock.assert_called_with(
+                 expected,
+                 saltenv="base",
+@@ -1620,7 +1645,7 @@ def test_install_pre_argument_in_resulting_command(python_binary):
+     ):
+         with patch("salt.modules.pip._get_pip_bin", MagicMock(return_value=["pip"])):
+             pip.install(pkg, pre_releases=True)
+-            expected = ["pip", "install", "--pre", pkg]
++            expected = ["pip", "install", *TARGET, "--pre", pkg]
+             mock_run_all.assert_called_with(
+                 expected,
+                 saltenv="base",
+diff --git a/tests/pytests/unit/modules/test_transactional_update.py b/tests/pytests/unit/modules/test_transactional_update.py
+index dbd72fd74bf..e0ef2abd0f3 100644
+--- a/tests/pytests/unit/modules/test_transactional_update.py
++++ b/tests/pytests/unit/modules/test_transactional_update.py
+@@ -1,3 +1,4 @@
++import os
+ import pytest
+ 
+ import salt.loader.context
+@@ -10,6 +11,10 @@ pytestmark = [
+     pytest.mark.skip_on_windows(reason="Not supported on Windows"),
+ ]
+ 
++SALT_CALL_BINARY = "salt-call"
++if os.environ.get('VIRTUAL_ENV'):
++    SALT_CALL_BINARY = f"{os.environ.get('VIRTUAL_ENV')}/bin/salt-call"
++
+ 
+ @pytest.fixture
+ def configure_loader_modules():
+@@ -379,7 +384,7 @@ def test_call_fails_function():
+                 "--continue",
+                 "--quiet",
+                 "run",
+-                "salt-call",
++                SALT_CALL_BINARY,
+                 "--out",
+                 "json",
+                 "-l",
+@@ -411,7 +416,7 @@ def test_call_success_no_reboot():
+                 "--continue",
+                 "--quiet",
+                 "run",
+-                "salt-call",
++                SALT_CALL_BINARY,
+                 "--out",
+                 "json",
+                 "-l",
+@@ -454,7 +459,7 @@ def test_call_success_reboot():
+                 "--continue",
+                 "--quiet",
+                 "run",
+-                "salt-call",
++                SALT_CALL_BINARY,
+                 "--out",
+                 "json",
+                 "-l",
+@@ -488,7 +493,7 @@ def test_call_success_parameters():
+                 "--continue",
+                 "--quiet",
+                 "run",
+-                "salt-call",
++                SALT_CALL_BINARY,
+                 "--out",
+                 "json",
+                 "-l",
+diff --git a/tests/pytests/unit/states/test_pkgrepo.py b/tests/pytests/unit/states/test_pkgrepo.py
+index 5f540bd2454..14d17ad3f9f 100644
+--- a/tests/pytests/unit/states/test_pkgrepo.py
++++ b/tests/pytests/unit/states/test_pkgrepo.py
+@@ -1,7 +1,6 @@
+ """
+     :codeauthor: Tyler Johnson <tjohnson@saltstack.com>
+ """
+-
+ import pytest
+ 
+ import salt.states.pkgrepo as pkgrepo
+@@ -390,7 +389,7 @@ def test_migrated_wrong_method():
+     with patch.dict(pkgrepo.__grains__, grains), patch.dict(
+         pkgrepo.__salt__, salt_mock
+     ):
+-        assert pkgrepo.migrated("/mnt", method_="magic") == {
++        assert pkgrepo.migrated("/mnt", method="magic") == {
+             "name": "/mnt",
+             "result": False,
+             "changes": {},
+diff --git a/tests/pytests/unit/test_fileserver.py b/tests/pytests/unit/test_fileserver.py
+index 8dd3ea0a27d..49be3967dc4 100644
+--- a/tests/pytests/unit/test_fileserver.py
++++ b/tests/pytests/unit/test_fileserver.py
+@@ -75,9 +75,7 @@ def test_file_server_url_escape(tmp_path):
+     opts = {
+         "fileserver_backend": ["roots"],
+         "extension_modules": "",
+-        "optimization_order": [
+-            0,
+-        ],
++        "optimization_order": [0, 1],
+         "file_roots": {
+             "base": [fileroot],
+         },
+@@ -102,9 +100,7 @@ def test_file_server_serve_url_escape(tmp_path):
+     opts = {
+         "fileserver_backend": ["roots"],
+         "extension_modules": "",
+-        "optimization_order": [
+-            0,
+-        ],
++        "optimization_order": [0, 1],
+         "file_roots": {
+             "base": [fileroot],
+         },
+diff --git a/tests/pytests/unit/utils/test_gitfs.py b/tests/pytests/unit/utils/test_gitfs.py
+index 2bf627049f9..bd7d74cb2b2 100644
+--- a/tests/pytests/unit/utils/test_gitfs.py
++++ b/tests/pytests/unit/utils/test_gitfs.py
+@@ -3,6 +3,7 @@ import time
+ 
+ import pytest
+ 
++import salt.config
+ import salt.fileserver.gitfs
+ import salt.utils.gitfs
+ from salt.exceptions import FileserverConfigError
+@@ -24,6 +25,23 @@ if HAS_PYGIT2:
+     import pygit2
+ 
+ 
++@pytest.fixture
++def minion_opts(tmp_path):
++    """
++    Default minion configuration with relative temporary paths to not require root permissions.
++    """
++    root_dir = tmp_path / "minion"
++    opts = salt.config.DEFAULT_MINION_OPTS.copy()
++    opts["__role"] = "minion"
++    opts["root_dir"] = str(root_dir)
++    for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"):
++        dirpath = root_dir / name
++        dirpath.mkdir(parents=True)
++        opts[name] = str(dirpath)
++    opts["log_file"] = "logs/minion.log"
++    return opts
++
++
+ @pytest.mark.parametrize(
+     "role_name,role_class",
+     (
+diff --git a/tests/pytests/unit/utils/test_msgpack.py b/tests/pytests/unit/utils/test_msgpack.py
+index a09b6e5b8b1..3d0b9d7fc8c 100644
+--- a/tests/pytests/unit/utils/test_msgpack.py
++++ b/tests/pytests/unit/utils/test_msgpack.py
+@@ -3,7 +3,7 @@ import pytest
+ import salt.utils.msgpack
+ from tests.support.mock import MagicMock, patch
+ 
+-
++@pytest.mark.skipif(salt.utils.msgpack.version < (1, 0, 0), reason="Test requires msgpack version >= 1.0.0")
+ def test_load_encoding(tmp_path):
+     """
+     test when using msgpack version >= 1.0.0 we
+diff --git a/tests/pytests/unit/utils/test_pycrypto.py b/tests/pytests/unit/utils/test_pycrypto.py
+index 693ad10e240..9e0b58d1b35 100644
+--- a/tests/pytests/unit/utils/test_pycrypto.py
++++ b/tests/pytests/unit/utils/test_pycrypto.py
+@@ -57,21 +57,20 @@ def test_gen_hash_crypt(algorithm, expected):
+     """
+     Test gen_hash with crypt library
+     """
+-    with patch("salt.utils.pycrypto.methods", {}):
+-        ret = salt.utils.pycrypto.gen_hash(
+-            crypt_salt=expected["salt"], password=passwd, algorithm=algorithm
+-        )
+-        assert ret == expected["hashed"]
++    ret = salt.utils.pycrypto.gen_hash(
++        crypt_salt=expected["salt"], password=passwd, algorithm=algorithm
++    )
++    assert ret == expected["hashed"]
+ 
+-        ret = salt.utils.pycrypto.gen_hash(
+-            crypt_salt=expected["badsalt"], password=passwd, algorithm=algorithm
+-        )
+-        assert ret != expected["hashed"]
++    ret = salt.utils.pycrypto.gen_hash(
++        crypt_salt=expected["badsalt"], password=passwd, algorithm=algorithm
++    )
++    assert ret != expected["hashed"]
+ 
+-        ret = salt.utils.pycrypto.gen_hash(
+-            crypt_salt=None, password=passwd, algorithm=algorithm
+-        )
+-        assert ret != expected["hashed"]
++    ret = salt.utils.pycrypto.gen_hash(
++        crypt_salt=None, password=passwd, algorithm=algorithm
++    )
++    assert ret != expected["hashed"]
+ 
+ 
+ @pytest.mark.skipif(not salt.utils.pycrypto.HAS_CRYPT, reason="crypt not available")
+diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py
+index 5cc58c273d0..6995b01c892 100644
+--- a/tests/unit/test_config.py
++++ b/tests/unit/test_config.py
+@@ -83,9 +83,12 @@ class SampleConfTest(DefaultConfigsBase, TestCase):
+         """
+         master_config = SAMPLE_CONF_DIR + "master"
+         ret = salt.config._read_conf_file(master_config)
++        # openSUSE modified the default config in
++        # https://github.com/opensuse/salt/commit/6ffbf7fcc178f32c670b177b25ed64658c59f1bf
++        expected_config = {"user": "salt", "syndic_user": "salt"}
+         self.assertEqual(
+             ret,
+-            {},
++            expected_config,
+             "Sample config file '{}' must be commented out.".format(master_config),
+         )
+ 
+@@ -347,7 +350,10 @@ class ConfigTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
+ 
+         with patched_environ(SALT_MINION_CONFIG=env_fpath):
+             # Should load from env variable, not the default configuration file
+-            config = salt.config.minion_config("{}/minion".format(CONFIG_DIR))
++            # Override defaults from venv-minion conf
++            defaults = salt.config.DEFAULT_MINION_OPTS.copy()
++            defaults["default_include"] = ""
++            config = salt.config.minion_config("{}/minion".format(CONFIG_DIR), defaults=defaults)
+             self.assertEqual(config["log_file"], env_fpath)
+ 
+         root_dir = os.path.join(tempdir, "foo", "bar")
+@@ -1946,6 +1952,11 @@ class APIConfigTestCase(DefaultConfigsBase, TestCase):
+             if salt.utils.platform.is_windows():
+                 expected = "{}\\var\\log\\salt\\api".format(RUNTIME_VARS.TMP_ROOT_DIR)
+ 
++            if os.environ.get("VIRTUAL_ENV"):
++                # venv bundle configures --salt-logs-dir=%{_localstatedir}/log
++                # in the RPM spec file
++                expected = expected.replace("/salt/api", "/api")
++
+             ret = salt.config.api_config("/some/fake/path")
+             self.assertEqual(ret["log_file"], expected)
+ 
+@@ -2017,6 +2028,11 @@ class APIConfigTestCase(DefaultConfigsBase, TestCase):
+             mock_pid = "c:\\mock\\root\\var\\run\\salt-api.pid"
+             mock_master_config["root_dir"] = "c:\\mock\\root"
+ 
++        if os.environ.get("VIRTUAL_ENV"):
++            # venv bundle configures --salt-logs-dir=%{_localstatedir}/log
++            # in the RPM spec file
++            mock_log = mock_log.replace("/salt", "")
++
+         with patch(
+             "salt.config.client_config", MagicMock(return_value=mock_master_config)
+         ):
+diff --git a/tests/unit/utils/test_sdb.py b/tests/unit/utils/test_sdb.py
+index 87886cbc521..69cbda07beb 100644
+--- a/tests/unit/utils/test_sdb.py
++++ b/tests/unit/utils/test_sdb.py
+@@ -49,7 +49,7 @@ class SdbTestCase(TestCase, LoaderModuleMockMixin):
+     # test with SQLite database write and read
+ 
+     def test_sqlite_get_found(self):
+-        expected = {b"name": b"testone", b"number": 46}
++        expected = {"name": "testone", "number": 46}
+         sdb.sdb_set("sdb://test_sdb_data/test1", expected, self.sdb_opts)
+         resp = sdb.sdb_get("sdb://test_sdb_data/test1", self.sdb_opts)
+         self.assertEqual(resp, expected)
+diff --git a/tests/unit/utils/test_templates.py b/tests/unit/utils/test_templates.py
+index 264b4ae801d..604395f5e08 100644
+--- a/tests/unit/utils/test_templates.py
++++ b/tests/unit/utils/test_templates.py
+@@ -1,6 +1,7 @@
+ """
+ Unit tests for salt.utils.templates.py
+ """
++
+ import logging
+ import os
+ import sys
+@@ -22,6 +23,20 @@ try:
+ except ImportError:
+     HAS_CHEETAH = False
+ 
++try:
++    import genshi as _
++
++    HAS_GENSHI = True
++except ImportError:
++    HAS_GENSHI = False
++
++try:
++    import mako as _
++
++    HAS_MAKO = True
++except ImportError:
++    HAS_MAKO = False
++
+ log = logging.getLogger(__name__)
+ 
+ 
+@@ -83,16 +98,19 @@ class RenderTestCase(TestCase):
+         assert res == expected
+ 
+     ### Tests for mako template
++    @pytest.mark.skipif(not HAS_MAKO, reason="Mako module not available for testing")
+     def test_render_mako_sanity(self):
+         tmpl = """OK"""
+         res = salt.utils.templates.render_mako_tmpl(tmpl, dict(self.context))
+         self.assertEqual(res, "OK")
+ 
++    @pytest.mark.skipif(not HAS_MAKO, reason="Mako module not available for testing")
+     def test_render_mako_evaluate(self):
+         tmpl = """${ "OK" }"""
+         res = salt.utils.templates.render_mako_tmpl(tmpl, dict(self.context))
+         self.assertEqual(res, "OK")
+ 
++    @pytest.mark.skipif(not HAS_MAKO, reason="Mako module not available for testing")
+     def test_render_mako_evaluate_multi(self):
+         tmpl = """
+         % if 1:
+@@ -103,6 +121,7 @@ class RenderTestCase(TestCase):
+         stripped = res.strip()
+         self.assertEqual(stripped, "OK")
+ 
++    @pytest.mark.skipif(not HAS_MAKO, reason="Mako module not available for testing")
+     def test_render_mako_variable(self):
+         tmpl = """${ var }"""
+ 
+@@ -152,21 +171,33 @@ class RenderTestCase(TestCase):
+         self.assertEqual(res, "OK")
+ 
+     ### Tests for genshi template (xml-based)
++    @pytest.mark.skipif(
++        not HAS_GENSHI, reason="Genshi module not available for testing"
++    )
+     def test_render_genshi_sanity(self):
+         tmpl = """<RU>OK</RU>"""
+         res = salt.utils.templates.render_genshi_tmpl(tmpl, dict(self.context))
+         self.assertEqual(res, "<RU>OK</RU>")
+ 
++    @pytest.mark.skipif(
++        not HAS_GENSHI, reason="Genshi module not available for testing"
++    )
+     def test_render_genshi_evaluate(self):
+         tmpl = """<RU>${ "OK" }</RU>"""
+         res = salt.utils.templates.render_genshi_tmpl(tmpl, dict(self.context))
+         self.assertEqual(res, "<RU>OK</RU>")
+ 
++    @pytest.mark.skipif(
++        not HAS_GENSHI, reason="Genshi module not available for testing"
++    )
+     def test_render_genshi_evaluate_condition(self):
+         tmpl = """<RU xmlns:py="http://genshi.edgewall.org/" py:if="1">OK</RU>"""
+         res = salt.utils.templates.render_genshi_tmpl(tmpl, dict(self.context))
+         self.assertEqual(res, "<RU>OK</RU>")
+ 
++    @pytest.mark.skipif(
++        not HAS_GENSHI, reason="Genshi module not available for testing"
++    )
+     def test_render_genshi_variable(self):
+         tmpl = """<RU>$var</RU>"""
+ 
+@@ -175,6 +206,9 @@ class RenderTestCase(TestCase):
+         res = salt.utils.templates.render_genshi_tmpl(tmpl, ctx)
+         self.assertEqual(res, "<RU>OK</RU>")
+ 
++    @pytest.mark.skipif(
++        not HAS_GENSHI, reason="Genshi module not available for testing"
++    )
+     def test_render_genshi_variable_replace(self):
+         tmpl = """<RU xmlns:py="http://genshi.edgewall.org/" py:content="var">not ok</RU>"""
+ 
+-- 
+2.46.0
+
diff --git a/prevent-using-syncwrapper-with-no-reason.patch b/prevent-using-syncwrapper-with-no-reason.patch
new file mode 100644
index 0000000..c4f956a
--- /dev/null
+++ b/prevent-using-syncwrapper-with-no-reason.patch
@@ -0,0 +1,25 @@
+From 936c298c177a50783b080c445745bedf77050cb0 Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Wed, 25 Sep 2024 14:04:40 +0300
+Subject: [PATCH] Prevent using SyncWrapper with no reason
+
+---
+ salt/channel/server.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/salt/channel/server.py b/salt/channel/server.py
+index b6d51fef08..f1b6f701a9 100644
+--- a/salt/channel/server.py
++++ b/salt/channel/server.py
+@@ -86,7 +86,7 @@ class ReqServerChannel:
+         # other things needed for _auth
+         # Create the event manager
+         self.event = salt.utils.event.get_master_event(
+-            self.opts, self.opts["sock_dir"], listen=False
++            self.opts, self.opts["sock_dir"], listen=False, io_loop=io_loop
+         )
+         self.auto_key = salt.daemons.masterapi.AutoKey(self.opts)
+         # only create a con_cache-client if the con_cache is active
+-- 
+2.46.1
+
diff --git a/remove-redundant-run_func-from-salt.master.mworker._.patch b/remove-redundant-run_func-from-salt.master.mworker._.patch
new file mode 100644
index 0000000..cc403a7
--- /dev/null
+++ b/remove-redundant-run_func-from-salt.master.mworker._.patch
@@ -0,0 +1,224 @@
+From ff789d88541954e4fc1678dff728bc6a3ea7472e Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Fri, 30 Aug 2024 14:30:27 +0200
+Subject: [PATCH] Remove redundant run_func from
+ salt.master.MWorker._handle_aes
+
+* New request context
+
+* Fix docs
+
+* Remove redundant run_func from salt.master.MWorker._handle_aes
+
+* Get rid of run_func in salt.Minion._target
+
+---------
+
+Co-authored-by: Daniel A. Wozniak <dwozniak@vmware.com>
+---
+ doc/topics/releases/3007.0.rst |  0
+ salt/_logging/impl.py          | 15 ++++++---
+ salt/master.py                 | 12 ++-----
+ salt/minion.py                 | 10 ++----
+ salt/utils/ctx.py              | 60 +++++++++++-----------------------
+ 5 files changed, 34 insertions(+), 63 deletions(-)
+ create mode 100644 doc/topics/releases/3007.0.rst
+
+diff --git a/doc/topics/releases/3007.0.rst b/doc/topics/releases/3007.0.rst
+new file mode 100644
+index 0000000000..e69de29bb2
+diff --git a/salt/_logging/impl.py b/salt/_logging/impl.py
+index 1d71cb8be8..4d1ebd2495 100644
+--- a/salt/_logging/impl.py
++++ b/salt/_logging/impl.py
+@@ -26,6 +26,8 @@ GARBAGE = logging.GARBAGE = 1
+ QUIET = logging.QUIET = 1000
+ 
+ import salt.defaults.exitcodes  # isort:skip  pylint: disable=unused-import
++import salt.utils.ctx
++
+ from salt._logging.handlers import DeferredStreamHandler  # isort:skip
+ from salt._logging.handlers import RotatingFileHandler  # isort:skip
+ from salt._logging.handlers import StreamHandler  # isort:skip
+@@ -33,7 +35,6 @@ from salt._logging.handlers import SysLogHandler  # isort:skip
+ from salt._logging.handlers import WatchedFileHandler  # isort:skip
+ from salt._logging.mixins import LoggingMixinMeta  # isort:skip
+ from salt.exceptions import LoggingRuntimeError  # isort:skip
+-from salt.utils.ctx import RequestContext  # isort:skip
+ from salt.utils.immutabletypes import freeze, ImmutableDict  # isort:skip
+ from salt.utils.textformat import TextFormat  # isort:skip
+ 
+@@ -242,10 +243,14 @@ class SaltLoggingClass(LOGGING_LOGGER_CLASS, metaclass=LoggingMixinMeta):
+         if extra is None:
+             extra = {}
+ 
+-        # pylint: disable=no-member
+-        current_jid = RequestContext.current.get("data", {}).get("jid", None)
+-        log_fmt_jid = RequestContext.current.get("opts", {}).get("log_fmt_jid", None)
+-        # pylint: enable=no-member
++        current_jid = (
++            salt.utils.ctx.get_request_context().get("data", {}).get("jid", None)
++        )
++        log_fmt_jid = (
++            salt.utils.ctx.get_request_context()
++            .get("opts", {})
++            .get("log_fmt_jid", None)
++        )
+ 
+         if current_jid is not None:
+             extra["jid"] = current_jid
+diff --git a/salt/master.py b/salt/master.py
+index d7182d10b5..49cfb68860 100644
+--- a/salt/master.py
++++ b/salt/master.py
+@@ -38,6 +38,7 @@ import salt.state
+ import salt.utils.args
+ import salt.utils.atomicfile
+ import salt.utils.crypt
++import salt.utils.ctx
+ import salt.utils.event
+ import salt.utils.files
+ import salt.utils.gitfs
+@@ -58,10 +59,8 @@ import salt.wheel
+ from salt.cli.batch_async import BatchAsync, batch_async_required
+ from salt.config import DEFAULT_INTERVAL
+ from salt.defaults import DEFAULT_TARGET_DELIM
+-from salt.ext.tornado.stack_context import StackContext
+ from salt.transport import TRANSPORTS
+ from salt.utils.channel import iter_transport_opts
+-from salt.utils.ctx import RequestContext
+ from salt.utils.debug import (
+     enable_sigusr1_handler,
+     enable_sigusr2_handler,
+@@ -1108,13 +1107,8 @@ class MWorker(salt.utils.process.SignalHandlingProcess):
+             start = time.time()
+             self.stats[cmd]["runs"] += 1
+ 
+-        def run_func(data):
+-            return self.aes_funcs.run_func(data["cmd"], data)
+-
+-        with StackContext(
+-            functools.partial(RequestContext, {"data": data, "opts": self.opts})
+-        ):
+-            ret = run_func(data)
++        with salt.utils.ctx.request_context({"data": data, "opts": self.opts}):
++            ret = self.aes_funcs.run_func(data["cmd"], data)
+ 
+         if self.opts["master_stats"]:
+             self._post_stats(start, cmd)
+diff --git a/salt/minion.py b/salt/minion.py
+index 2ccd0cd5a9..e21a017cfd 100644
+--- a/salt/minion.py
++++ b/salt/minion.py
+@@ -39,6 +39,7 @@ import salt.transport
+ import salt.utils.args
+ import salt.utils.context
+ import salt.utils.crypt
++import salt.utils.ctx
+ import salt.utils.data
+ import salt.utils.dictdiffer
+ import salt.utils.dictupdate
+@@ -70,7 +71,6 @@ from salt.exceptions import (
+     SaltSystemExit,
+ )
+ from salt.template import SLS_ENCODING
+-from salt.utils.ctx import RequestContext
+ from salt.utils.debug import enable_sigusr1_handler
+ from salt.utils.event import tagify
+ from salt.utils.network import parse_host_port
+@@ -1805,18 +1805,12 @@ class Minion(MinionBase):
+                 uid = salt.utils.user.get_uid(user=opts.get("user", None))
+                 minion_instance.proc_dir = get_proc_dir(opts["cachedir"], uid=uid)
+ 
+-        def run_func(minion_instance, opts, data):
++        with salt.utils.ctx.request_context({"data": data, "opts": opts}):
+             if isinstance(data["fun"], tuple) or isinstance(data["fun"], list):
+                 return Minion._thread_multi_return(minion_instance, opts, data)
+             else:
+                 return Minion._thread_return(minion_instance, opts, data)
+ 
+-        with salt.ext.tornado.stack_context.StackContext(
+-            functools.partial(RequestContext, {"data": data, "opts": opts})
+-        ):
+-            with salt.ext.tornado.stack_context.StackContext(minion_instance.ctx):
+-                run_func(minion_instance, opts, data)
+-
+     def _execute_job_function(
+         self, function_name, function_args, executors, opts, data
+     ):
+diff --git a/salt/utils/ctx.py b/salt/utils/ctx.py
+index a9c0931bd8..2f4b5b4c9b 100644
+--- a/salt/utils/ctx.py
++++ b/salt/utils/ctx.py
+@@ -1,49 +1,27 @@
+-import threading
++import contextlib
+ 
++try:
++    # Try the stdlib C extension first
++    import _contextvars as contextvars
++except ImportError:
++    # Py<3.7
++    import contextvars
+ 
+-class ClassProperty(property):
+-    """
+-    Use a classmethod as a property
+-    http://stackoverflow.com/a/1383402/1258307
+-    """
++DEFAULT_CTX_VAR = "request_ctxvar"
++request_ctxvar = contextvars.ContextVar(DEFAULT_CTX_VAR)
+ 
+-    def __get__(self, cls, owner):
+-        return self.fget.__get__(None, owner)()  # pylint: disable=no-member
+ 
+-
+-class RequestContext:
++@contextlib.contextmanager
++def request_context(data):
+     """
+-    A context manager that saves some per-thread state globally.
+-    Intended for use with Tornado's StackContext.
+-    https://gist.github.com/simon-weber/7755289
+-    Simply import this class into any module and access the current request handler by this
+-    class's class method property 'current'. If it returns None, there's no active request.
+-    .. code:: python
+-        from raas.utils.ctx import RequestContext
+-        current_request_handler = RequestContext.current
++    A context manager that sets and un-sets the loader context
+     """
++    tok = request_ctxvar.set(data)
++    try:
++        yield
++    finally:
++        request_ctxvar.reset(tok)
+ 
+-    _state = threading.local()
+-    _state.current_request = {}
+-
+-    def __init__(self, current_request):
+-        self._current_request = current_request
+-
+-    @ClassProperty
+-    @classmethod
+-    def current(cls):
+-        if not hasattr(cls._state, "current_request"):
+-            return {}
+-        return cls._state.current_request
+-
+-    def __enter__(self):
+-        self._prev_request = self.__class__.current
+-        self.__class__._state.current_request = self._current_request
+-
+-    def __exit__(self, *exc):
+-        self.__class__._state.current_request = self._prev_request
+-        del self._prev_request
+-        return False
+ 
+-    def __call__(self):
+-        return self
++def get_request_context():
++    return request_ctxvar.get({})
+-- 
+2.46.0
+
diff --git a/replace-use-of-pygit2-deprecated-and-removed-1.15.0-.patch b/replace-use-of-pygit2-deprecated-and-removed-1.15.0-.patch
new file mode 100644
index 0000000..58f9475
--- /dev/null
+++ b/replace-use-of-pygit2-deprecated-and-removed-1.15.0-.patch
@@ -0,0 +1,122 @@
+From 3f3c8d80427c9d90bea5fbca785b210260d33a0f Mon Sep 17 00:00:00 2001
+From: Marek Czernek <marek.czernek@suse.com>
+Date: Wed, 21 Aug 2024 16:15:02 +0200
+Subject: [PATCH] Replace use of pygit2 deprecated and removed (1.15.0)
+ oid with id (#673)
+
+Co-authored-by: David Murphy <damurphy@vmware.com>
+---
+ salt/utils/gitfs.py | 31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/salt/utils/gitfs.py b/salt/utils/gitfs.py
+index 061647edaca..f3902c1f19a 100644
+--- a/salt/utils/gitfs.py
++++ b/salt/utils/gitfs.py
+@@ -1683,7 +1683,7 @@ class Pygit2(GitProvider):
+                     # remote ref.
+                     self.repo.checkout(checkout_ref)
+                     if branch:
+-                        self.repo.reset(oid, pygit2.GIT_RESET_HARD)
++                        self.repo.reset(pygit2_id, pygit2.GIT_RESET_HARD)
+                 return True
+             except GitLockError as exc:
+                 if exc.errno == errno.EEXIST:
+@@ -1714,11 +1714,11 @@ class Pygit2(GitProvider):
+                 tag_ref = "refs/tags/" + tgt_ref
+             if remote_ref in refs:
+                 # Get commit id for the remote ref
+-                oid = self.peel(self.repo.lookup_reference(remote_ref)).id
++                pygit2_id = self.peel(self.repo.lookup_reference(remote_ref)).id
+                 if local_ref not in refs:
+                     # No local branch for this remote, so create one and point
+                     # it at the commit id of the remote ref
+-                    self.repo.create_reference(local_ref, oid)
++                    self.repo.create_reference(local_ref, pygit2_id)
+ 
+                 try:
+                     target_sha = self.peel(self.repo.lookup_reference(remote_ref)).hex
+@@ -1749,7 +1749,8 @@ class Pygit2(GitProvider):
+                     # cachedir).
+                     head_ref = local_head.target
+                     # If head_ref is not a string, it will point to a
+-                    # pygit2.Oid object and we are in detached HEAD mode.
++                    # pygit2.id object (oid is deprecated and removed) and
++                    # we are in detached HEAD mode.
+                     # Therefore, there is no need to add a local reference. If
+                     # head_ref == local_ref, then the local reference for HEAD
+                     # in refs/heads/ already exists and again, no need to add.
+@@ -1918,10 +1919,10 @@ class Pygit2(GitProvider):
+             the empty directories within it in the "blobs" list
+             """
+             for entry in iter(tree):
+-                if entry.oid not in self.repo:
++                if entry.id not in self.repo:
+                     # Entry is a submodule, skip it
+                     continue
+-                blob = self.repo[entry.oid]
++                blob = self.repo[entry.id]
+                 if not isinstance(blob, pygit2.Tree):
+                     continue
+                 blobs.append(
+@@ -1940,8 +1941,8 @@ class Pygit2(GitProvider):
+             return ret
+         if self.root(tgt_env):
+             try:
+-                oid = tree[self.root(tgt_env)].oid
+-                tree = self.repo[oid]
++                pygit2_id = tree[self.root(tgt_env)].id
++                tree = self.repo[pygit2_id]
+             except KeyError:
+                 return ret
+             if not isinstance(tree, pygit2.Tree):
+@@ -2056,17 +2057,17 @@ class Pygit2(GitProvider):
+             the file paths and symlink info in the "blobs" dict
+             """
+             for entry in iter(tree):
+-                if entry.oid not in self.repo:
++                if entry.id not in self.repo:
+                     # Entry is a submodule, skip it
+                     continue
+-                obj = self.repo[entry.oid]
++                obj = self.repo[entry.id]
+                 if isinstance(obj, pygit2.Blob):
+                     repo_path = salt.utils.path.join(
+                         prefix, entry.name, use_posixpath=True
+                     )
+                     blobs.setdefault("files", []).append(repo_path)
+                     if stat.S_ISLNK(tree[entry.name].filemode):
+-                        link_tgt = self.repo[tree[entry.name].oid].data
++                        link_tgt = self.repo[tree[entry.name].id].data
+                         blobs.setdefault("symlinks", {})[repo_path] = link_tgt
+                 elif isinstance(obj, pygit2.Tree):
+                     _traverse(
+@@ -2085,8 +2086,8 @@ class Pygit2(GitProvider):
+             try:
+                 # This might need to be changed to account for a root that
+                 # spans more than one directory
+-                oid = tree[self.root(tgt_env)].oid
+-                tree = self.repo[oid]
++                pygit2_id = tree[self.root(tgt_env)].id
++                tree = self.repo[pygit2_id]
+             except KeyError:
+                 return files, symlinks
+             if not isinstance(tree, pygit2.Tree):
+@@ -2130,12 +2131,12 @@ class Pygit2(GitProvider):
+                     # path's object ID will be the target of the symlink. Follow
+                     # the symlink and set path to the location indicated
+                     # in the blob data.
+-                    link_tgt = self.repo[entry.oid].data
++                    link_tgt = self.repo[entry.id].data
+                     path = salt.utils.path.join(
+                         os.path.dirname(path), link_tgt, use_posixpath=True
+                     )
+                 else:
+-                    blob = self.repo[entry.oid]
++                    blob = self.repo[entry.id]
+                     if isinstance(blob, pygit2.Tree):
+                         # Path is a directory, not a file.
+                         blob = None
+-- 
+2.46.0
+
diff --git a/revert-the-change-making-reactor-less-blocking-bsc-1.patch b/revert-the-change-making-reactor-less-blocking-bsc-1.patch
new file mode 100644
index 0000000..5755632
--- /dev/null
+++ b/revert-the-change-making-reactor-less-blocking-bsc-1.patch
@@ -0,0 +1,106 @@
+From c00801d2f9807e49769d0e0d848ec12be555dbc1 Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Wed, 25 Sep 2024 14:07:05 +0300
+Subject: [PATCH] Revert the change making reactor less blocking
+ (bsc#1230322)
+
+This reverts commit 0d35f09288700f5c961567442c3fcc25838b8de4.
+---
+ salt/utils/reactor.py | 45 ++++++++++++++++---------------------------
+ 1 file changed, 17 insertions(+), 28 deletions(-)
+
+diff --git a/salt/utils/reactor.py b/salt/utils/reactor.py
+index 78adad34da..19420a51cf 100644
+--- a/salt/utils/reactor.py
++++ b/salt/utils/reactor.py
+@@ -1,12 +1,10 @@
+ """
+ Functions which implement running reactor jobs
+ """
+-
+ import fnmatch
+ import glob
+ import logging
+ import os
+-from threading import Lock
+ 
+ import salt.client
+ import salt.defaults.exitcodes
+@@ -196,6 +194,13 @@ class Reactor(salt.utils.process.SignalHandlingProcess, salt.state.Compiler):
+         self.resolve_aliases(chunks)
+         return chunks
+ 
++    def call_reactions(self, chunks):
++        """
++        Execute the reaction state
++        """
++        for chunk in chunks:
++            self.wrap.run(chunk)
++
+     def run(self):
+         """
+         Enter into the server loop
+@@ -213,7 +218,7 @@ class Reactor(salt.utils.process.SignalHandlingProcess, salt.state.Compiler):
+         ) as event:
+             self.wrap = ReactWrap(self.opts)
+ 
+-            for data in event.iter_events(full=True, auto_reconnect=True):
++            for data in event.iter_events(full=True):
+                 # skip all events fired by ourselves
+                 if data["data"].get("user") == self.wrap.event_user:
+                     continue
+@@ -263,9 +268,15 @@ class Reactor(salt.utils.process.SignalHandlingProcess, salt.state.Compiler):
+                     if not self.is_leader:
+                         continue
+                     else:
+-                        self.wrap.call_reactions(
+-                            data, self.list_reactors, self.reactions
+-                        )
++                        reactors = self.list_reactors(data["tag"])
++                        if not reactors:
++                            continue
++                        chunks = self.reactions(data["tag"], data["data"], reactors)
++                        if chunks:
++                            try:
++                                self.call_reactions(chunks)
++                            except SystemExit:
++                                log.warning("Exit ignored by reactor")
+ 
+ 
+ class ReactWrap:
+@@ -286,7 +297,6 @@ class ReactWrap:
+ 
+     def __init__(self, opts):
+         self.opts = opts
+-        self._run_lock = Lock()
+         if ReactWrap.client_cache is None:
+             ReactWrap.client_cache = salt.utils.cache.CacheDict(
+                 opts["reactor_refresh_interval"]
+@@ -470,24 +480,3 @@ class ReactWrap:
+         Wrap LocalCaller to execute remote exec functions locally on the Minion
+         """
+         self.client_cache["caller"].cmd(fun, *kwargs["arg"], **kwargs["kwarg"])
+-
+-    def _call_reactions(self, data, list_reactors, get_reactions):
+-        reactors = list_reactors(data["tag"])
+-        if not reactors:
+-            return
+-        chunks = get_reactions(data["tag"], data["data"], reactors)
+-        if not chunks:
+-            return
+-        with self._run_lock:
+-            try:
+-                for chunk in chunks:
+-                    self.run(chunk)
+-            except Exception as exc:  # pylint: disable=broad-except
+-                log.error(
+-                    "Exception while calling the reactions: %s", exc, exc_info=True
+-                )
+-
+-    def call_reactions(self, data, list_reactors, get_reactions):
+-        return self.pool.fire_async(
+-            self._call_reactions, args=(data, list_reactors, get_reactions)
+-        )
+-- 
+2.46.1
+
diff --git a/salt.changes b/salt.changes
index 26ff331..8ef776d 100644
--- a/salt.changes
+++ b/salt.changes
@@ -1,3 +1,44 @@
+-------------------------------------------------------------------
+Wed Oct  2 11:48:49 UTC 2024 - Yeray Gutiérrez Cedrés <yeray.gutierrez@suse.com>
+
+- Fix failing x509 tests with OpenSSL < 1.1
+- Avoid explicit reading of /etc/salt/minion (bsc#1220357)
+- Allow NamedLoaderContexts to be returned from loader
+- Revert the change making reactor less blocking (bsc#1230322)
+- Use --cachedir for extension_modules in salt-call (bsc#1226141)
+- Prevent using SyncWrapper with no reason
+- Fix the SELinux context for Salt Minion service (bsc#1219041)
+- Set contextvars as a build requirement for package
+- Increase warn_until_date date for code we still support
+- The test_debian test now uses port 80 for ubuntu keyserver
+- Fix too frequent systemd service restart in test_system test
+- Avoid crash on wrong output of systemctl version (bsc#1229539)
+- Improve error handling with different OpenSSL versions
+- Remove redundant run_func from salt.master.MWorker._handle_aes
+- Fix cloud minion configuration for multiple masters (bsc#1229109)
+- Use Pygit2 id instead of deprecated oid in gitfs
+- Fix few failing tests to work with both Salt and Salt bundle
+- Skip testing unsupported OpenSSL crypto algorithms
+
+- Added:
+  * fix-x509-test-fails-on-old-openssl-systems-682.patch
+  * make-tests-compatible-with-venv-bundle.patch
+  * use-cachedir-for-extension_modules-in-salt-call-bsc-.patch
+  * fix-test_system-flaky-setup_teardown-fn.patch
+  * fix-deprecated-code-677.patch
+  * join-masters-if-it-is-a-list-671.patch
+  * fix-test_debian-to-work-in-our-infrastructure-676.patch
+  * skip-more-tests-related-to-old-openssl-algorithms.patch
+  * remove-redundant-run_func-from-salt.master.mworker._.patch
+  * avoid-explicit-reading-of-etc-salt-minion-bsc-122035.patch
+  * avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch
+  * allow-namedloadercontexts-to-be-returned-from-loader.patch
+  * fix-the-selinux-context-for-salt-minion-service-bsc-.patch
+  * improve-error-handling-with-different-openssl-versio.patch
+  * prevent-using-syncwrapper-with-no-reason.patch
+  * revert-the-change-making-reactor-less-blocking-bsc-1.patch
+  * replace-use-of-pygit2-deprecated-and-removed-1.15.0-.patch
+
 -------------------------------------------------------------------
 Thu Aug  1 15:34:21 UTC 2024 - Yeray Gutiérrez Cedrés <yeray.gutierrez@suse.com>
 
diff --git a/salt.spec b/salt.spec
index 56069bc..8fc19eb 100644
--- a/salt.spec
+++ b/salt.spec
@@ -410,6 +410,44 @@ Patch124:       some-more-small-tests-fixes-enhancements-661.patch
 Patch125:       test_vultrpy-adjust-test-expectation-to-prevent-fail.patch
 # PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/66698
 Patch126:       firewalld-normalize-new-rich-rules-before-comparing-.patch
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/669
+Patch127:       skip-more-tests-related-to-old-openssl-algorithms.patch
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/662
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66730
+Patch128:       make-tests-compatible-with-venv-bundle.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66743
+Patch129:       replace-use-of-pygit2-deprecated-and-removed-1.15.0-.patch
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/671
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64173
+Patch130:       join-masters-if-it-is-a-list-671.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66509
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/commit/0c3ebc0795f9c2adec90118281343cae3070e0f6
+Patch131:       remove-redundant-run_func-from-salt.master.mworker._.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66818
+Patch132:       improve-error-handling-with-different-openssl-versio.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66856
+Patch133:       avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66861
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/675
+Patch134:       fix-test_system-flaky-setup_teardown-fn.patch
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/676
+Patch135:       fix-test_debian-to-work-in-our-infrastructure-676.patch
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/677
+Patch136:       fix-deprecated-code-677.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66780
+Patch137:       fix-the-selinux-context-for-salt-minion-service-bsc-.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66510
+Patch138:       prevent-using-syncwrapper-with-no-reason.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66742
+Patch139:       use-cachedir-for-extension_modules-in-salt-call-bsc-.patch
+# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/680
+Patch140:       revert-the-change-making-reactor-less-blocking-bsc-1.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66649
+Patch141:       allow-namedloadercontexts-to-be-returned-from-loader.patch
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/commit/d54407ba6dc664e5e5f3f613e27ae24f828c9648
+Patch142:       avoid-explicit-reading-of-etc-salt-minion-bsc-122035.patch
+# PATCH-FIX_UPSTREAM: https://github.com/openSUSE/salt/pull/682
+Patch143:       fix-x509-test-fails-on-old-openssl-systems-682.patch
 
 ### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
 ### SALT PATCHES LIST END
@@ -528,6 +566,7 @@ BuildRequires:  python3-requests >= 1.0.0
 BuildRequires:  python3-distro
 BuildRequires:  python3-looseversion
 BuildRequires:  python3-packaging
+BuildRequires:  python3-contextvars
 
 # requirements/zeromq.txt
 %if %{with test}
@@ -602,9 +641,9 @@ Recommends:     python3-pyinotify
 %endif
 
 # Required by Salt modules
-Recommends:     iputils
-Recommends:     sudo
-Recommends:     file
+Requires:       iputils
+Requires:       sudo
+Requires:       file
 Recommends:     man
 
 Provides:       bundled(python3-tornado) = 4.5.3
diff --git a/skip-more-tests-related-to-old-openssl-algorithms.patch b/skip-more-tests-related-to-old-openssl-algorithms.patch
new file mode 100644
index 0000000..a600ded
--- /dev/null
+++ b/skip-more-tests-related-to-old-openssl-algorithms.patch
@@ -0,0 +1,97 @@
+From 63ff8ce775eec43b2f768b72fba4154c7832b1f7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Yeray=20Guti=C3=A9rrez=20Cedr=C3=A9s?=
+ <yeray.gutierrez@suse.com>
+Date: Wed, 7 Aug 2024 08:54:24 +0100
+Subject: [PATCH] Skip more tests related to old OpenSSL algorithms
+
+* Skip more tests related to old OpenSSL algorithms
+
+* Check the comment from state apply ret instead of exception
+
+---------
+
+Co-authored-by: vzhestkov <vzhestkov@suse.com>
+---
+ tests/pytests/functional/modules/test_x509_v2.py | 10 ++++++++--
+ tests/pytests/functional/states/test_x509_v2.py  |  9 +++++++++
+ 2 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/tests/pytests/functional/modules/test_x509_v2.py b/tests/pytests/functional/modules/test_x509_v2.py
+index c060ad2971c..2e8152d04a3 100644
+--- a/tests/pytests/functional/modules/test_x509_v2.py
++++ b/tests/pytests/functional/modules/test_x509_v2.py
+@@ -1400,7 +1400,10 @@ def test_create_csr_raw(x509, rsa_privkey):
+ @pytest.mark.slow_test
+ @pytest.mark.parametrize("algo", ["rsa", "ec", "ed25519", "ed448"])
+ def test_create_private_key(x509, algo):
+-    res = x509.create_private_key(algo=algo)
++    try:
++        res = x509.create_private_key(algo=algo)
++    except UnsupportedAlgorithm:
++        pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     assert res.startswith("-----BEGIN PRIVATE KEY-----")
+ 
+ 
+@@ -1408,7 +1411,10 @@ def test_create_private_key(x509, algo):
+ @pytest.mark.parametrize("algo", ["rsa", "ec", "ed25519", "ed448"])
+ def test_create_private_key_with_passphrase(x509, algo):
+     passphrase = "hunter2"
+-    res = x509.create_private_key(algo=algo, passphrase=passphrase)
++    try:
++        res = x509.create_private_key(algo=algo, passphrase=passphrase)
++    except UnsupportedAlgorithm:
++        pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     assert res.startswith("-----BEGIN ENCRYPTED PRIVATE KEY-----")
+     # ensure it can be loaded
+     x509.get_private_key_size(res, passphrase=passphrase)
+diff --git a/tests/pytests/functional/states/test_x509_v2.py b/tests/pytests/functional/states/test_x509_v2.py
+index e74bdd73f37..929be014cdb 100644
+--- a/tests/pytests/functional/states/test_x509_v2.py
++++ b/tests/pytests/functional/states/test_x509_v2.py
+@@ -6,6 +6,7 @@ import pytest
+ try:
+     import cryptography
+     import cryptography.x509 as cx509
++    from cryptography.exceptions import UnsupportedAlgorithm
+     from cryptography.hazmat.primitives import hashes
+     from cryptography.hazmat.primitives.asymmetric import ec, ed448, ed25519, rsa
+     from cryptography.hazmat.primitives.serialization import (
+@@ -691,6 +692,8 @@ def existing_csr_exts(x509, csr_args, csr_args_exts, ca_key, rsa_privkey, reques
+ def existing_pk(x509, pk_args, request):
+     pk_args.update(request.param)
+     ret = x509.private_key_managed(**pk_args)
++    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
++        pytest.skip(f"Algorithm '{pk_args['algo']}' is not supported on this OpenSSL version")
+     _assert_pk_basic(
+         ret,
+         pk_args.get("algo", "rsa"),
+@@ -2140,6 +2143,8 @@ def test_private_key_managed(x509, pk_args, algo, encoding, passphrase):
+     pk_args["encoding"] = encoding
+     pk_args["passphrase"] = passphrase
+     ret = x509.private_key_managed(**pk_args)
++    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
++        pytest.skip(f"Algorithm '{algo}' is not supported on this OpenSSL version")
+     _assert_pk_basic(ret, algo, encoding, passphrase)
+ 
+ 
+@@ -2167,6 +2172,8 @@ def test_private_key_managed_keysize(x509, pk_args, algo, keysize):
+ )
+ def test_private_key_managed_existing(x509, pk_args):
+     ret = x509.private_key_managed(**pk_args)
++    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
++        pytest.skip(f"Algorithm '{pk_args['algo']}' is not supported on this OpenSSL version")
+     _assert_not_changed(ret)
+ 
+ 
+@@ -2194,6 +2201,8 @@ def test_private_key_managed_existing_new_with_passphrase_change(x509, pk_args):
+ def test_private_key_managed_algo_change(x509, pk_args):
+     pk_args["algo"] = "ed25519"
+     ret = x509.private_key_managed(**pk_args)
++    if ret.result == False and "UnsupportedAlgorithm" in ret.comment:
++        pytest.skip("Algorithm 'ed25519' is not supported on this OpenSSL version")
+     _assert_pk_basic(ret, "ed25519")
+ 
+ 
+-- 
+2.46.0
+
diff --git a/use-cachedir-for-extension_modules-in-salt-call-bsc-.patch b/use-cachedir-for-extension_modules-in-salt-call-bsc-.patch
new file mode 100644
index 0000000..383503c
--- /dev/null
+++ b/use-cachedir-for-extension_modules-in-salt-call-bsc-.patch
@@ -0,0 +1,110 @@
+From 2fb453d04b8abe765a964174ae77d57398f2877a Mon Sep 17 00:00:00 2001
+From: Victor Zhestkov <vzhestkov@suse.com>
+Date: Wed, 25 Sep 2024 14:06:19 +0300
+Subject: [PATCH] Use --cachedir for extension_modules in salt-call
+ (bsc#1226141)
+
+* Use --cachedir parameter for extension_modules with salt-call
+
+* Add test to check extension_modules value alignment
+---
+ salt/cli/call.py                         | 11 +++++++-
+ salt/config/__init__.py                  |  6 +++++
+ tests/pytests/unit/cli/test_salt_call.py | 32 ++++++++++++++++++++++++
+ 3 files changed, 48 insertions(+), 1 deletion(-)
+ create mode 100644 tests/pytests/unit/cli/test_salt_call.py
+
+diff --git a/salt/cli/call.py b/salt/cli/call.py
+index 932dc61681..be3ded77e6 100644
+--- a/salt/cli/call.py
++++ b/salt/cli/call.py
+@@ -3,7 +3,7 @@ import os
+ import salt.cli.caller
+ import salt.defaults.exitcodes
+ import salt.utils.parsers
+-from salt.config import _expand_glob_path
++from salt.config import _expand_glob_path, prepend_root_dir
+ 
+ 
+ class SaltCall(salt.utils.parsers.SaltCallOptionParser):
+@@ -37,6 +37,15 @@ class SaltCall(salt.utils.parsers.SaltCallOptionParser):
+         if self.options.master:
+             self.config["master"] = self.options.master
+ 
++        if self.options.cachedir and self.config.get(
++            "extension_modules"
++        ) == os.path.join(self.config.get("__cachedir"), "extmods"):
++            # Override `extension_modules`, but only in case if it was autogenerated
++            cache_dir = os.path.abspath(self.options.cachedir)
++            self.config["cachedir"] = cache_dir
++            self.config["extension_modules"] = os.path.join(cache_dir, "extmods")
++            prepend_root_dir(self.config, ["cachedir", "extension_modules"])
++
+         caller = salt.cli.caller.Caller.factory(self.config)
+ 
+         if self.options.doc:
+diff --git a/salt/config/__init__.py b/salt/config/__init__.py
+index 68f2b0f674..b3cd5d85ae 100644
+--- a/salt/config/__init__.py
++++ b/salt/config/__init__.py
+@@ -1,6 +1,7 @@
+ """
+ All salt configuration loading and defaults should be in this module
+ """
++
+ import codecs
+ import glob
+ import logging
+@@ -3841,6 +3842,11 @@ def apply_minion_config(
+     _update_ssl_config(opts)
+     _update_discovery_config(opts)
+ 
++    # Store original `cachedir` value, before overriding,
++    # to make overriding more accurate.
++    if "__cachedir" not in opts:
++        opts["__cachedir"] = opts["cachedir"]
++
+     return opts
+ 
+ 
+diff --git a/tests/pytests/unit/cli/test_salt_call.py b/tests/pytests/unit/cli/test_salt_call.py
+new file mode 100644
+index 0000000000..078f2af70d
+--- /dev/null
++++ b/tests/pytests/unit/cli/test_salt_call.py
+@@ -0,0 +1,32 @@
++import os
++
++from salt.cli.call import SaltCall
++from tests.support.mock import MagicMock, patch
++
++
++def test_passing_cachedir_to_extension_modules(temp_salt_minion):
++    """
++    Test passing `cachedir` CLI parameter to `extension_modules` opts
++    """
++    test_cache_dir = os.path.join(temp_salt_minion.config["root_dir"], "new_cache_tmp")
++    with patch(
++        "sys.argv",
++        [
++            "salt-call",
++            "--local",
++            "--config-dir",
++            temp_salt_minion.config["root_dir"],
++            "--cachedir",
++            test_cache_dir,
++            "test.true",
++        ],
++    ), patch("salt.utils.verify.verify_files", MagicMock()), patch(
++        "salt._logging.impl.setup_logfile_handler", MagicMock()
++    ):
++        salt_call = SaltCall()
++        with patch("salt.cli.caller.Caller.factory", MagicMock()) as caller_mock:
++            salt_call.run()
++            assert salt_call.config["cachedir"] == test_cache_dir
++            assert salt_call.config["extension_modules"] == os.path.join(
++                test_cache_dir, "extmods"
++            )
+-- 
+2.46.1
+