diff --git a/SOURCES/sos-bz2058279-ocp-backports.patch b/SOURCES/sos-bz2058279-ocp-backports.patch
new file mode 100644
index 0000000..7cfaa91
--- /dev/null
+++ b/SOURCES/sos-bz2058279-ocp-backports.patch
@@ -0,0 +1,1113 @@
+From d0f9d507b0ec63c9e8f3e5d7b6507d9d0f97c038 Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Tue, 15 Feb 2022 16:24:47 -0500
+Subject: [PATCH] [runtimes] Allow container IDs to be used with
+ `container_exists()`
+
+As container runtimes can interchange container names and container IDs,
+sos should also allow the use of container IDs when checking for the
+presence of a given container.
+
+In particular, this change unblocks the use of `Plugin.exec_cmd()` when
+used in conjunction with `Plugin.get_container_by_name()` to pick a
+container based on a provided regex that the container name may match.
+
+Related: #2856
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/policies/runtimes/__init__.py | 17 +++++++++++++++++
+ sos/report/plugins/__init__.py    |  6 +++---
+ 2 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/sos/policies/runtimes/__init__.py b/sos/policies/runtimes/__init__.py
+index 5ac67354..d2837349 100644
+--- a/sos/policies/runtimes/__init__.py
++++ b/sos/policies/runtimes/__init__.py
+@@ -147,6 +147,23 @@ class ContainerRuntime():
+                     vols.append(ent[-1])
+         return vols
+ 
++    def container_exists(self, container):
++        """Check if a given container ID or name exists on the system from the
++        perspective of the container runtime.
++
++        Note that this will only check _running_ containers
++
++        :param container:       The name or ID of the container
++        :type container:        ``str``
++
++        :returns:               True if the container exists, else False
++        :rtype:                 ``bool``
++        """
++        for _contup in self.containers:
++            if container in _contup:
++                return True
++        return False
++
+     def fmt_container_cmd(self, container, cmd, quotecmd):
+         """Format a command to run inside a container using the runtime
+ 
+diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py
+index 2988be08..cc5cb65b 100644
+--- a/sos/report/plugins/__init__.py
++++ b/sos/report/plugins/__init__.py
+@@ -2593,7 +2593,7 @@ class Plugin():
+         """If a container runtime is present, check to see if a container with
+         a given name is currently running
+ 
+-        :param name:    The name of the container to check presence of
++        :param name:    The name or ID of the container to check presence of
+         :type name: ``str``
+ 
+         :returns: ``True`` if `name` exists, else ``False``
+@@ -2601,8 +2601,8 @@ class Plugin():
+         """
+         _runtime = self._get_container_runtime()
+         if _runtime is not None:
+-            con = _runtime.get_container_by_name(name)
+-            return con is not None
++            return (_runtime.container_exists(name) or
++                    _runtime.get_container_by_name(name) is not None)
+         return False
+ 
+     def get_all_containers_by_regex(self, regex, get_all=False):
+-- 
+2.34.3
+
+From 2ae16e0245e1b01b8547e507abb69c11871a8467 Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Mon, 21 Feb 2022 14:37:09 -0500
+Subject: [PATCH] [sosnode] Handle downstream versioning for runtime option
+ check
+
+First, adds parsing and formatting for an sos installation's release
+version according to the loaded package manager for that node.
+
+Adds a fallback version check for 4.2-13 for RHEL downstreams that
+backport the `container-runtime` option into sos-4.2.
+
+Carry this in upstream to account for use cases where a workstation used
+to run `collect` from may be from a different stream than those used by
+cluster nodes.
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/collector/sosnode.py | 60 ++++++++++++++++++++++++++++++++++------
+ 1 file changed, 51 insertions(+), 9 deletions(-)
+
+diff --git a/sos/collector/sosnode.py b/sos/collector/sosnode.py
+index 7bbe0cd1..d9b998b0 100644
+--- a/sos/collector/sosnode.py
++++ b/sos/collector/sosnode.py
+@@ -275,21 +275,34 @@ class SosNode():
+     def _load_sos_info(self):
+         """Queries the node for information about the installed version of sos
+         """
++        ver = None
++        rel = None
+         if self.host.container_version_command is None:
+             pkg = self.host.package_manager.pkg_version(self.host.sos_pkg_name)
+             if pkg is not None:
+                 ver = '.'.join(pkg['version'])
+-                self.sos_info['version'] = ver
++                if pkg['release']:
++                    rel = pkg['release']
++
+         else:
+             # use the containerized policy's command
+             pkgs = self.run_command(self.host.container_version_command,
+                                     use_container=True, need_root=True)
+             if pkgs['status'] == 0:
+-                ver = pkgs['output'].strip().split('-')[1]
+-                if ver:
+-                    self.sos_info['version'] = ver
+-            else:
+-                self.sos_info['version'] = None
++                _, ver, rel = pkgs['output'].strip().split('-')
++
++        if ver:
++            if len(ver.split('.')) == 2:
++                # safeguard against maintenance releases throwing off the
++                # comparison by LooseVersion
++                ver += '.0'
++            try:
++                ver += '-%s' % rel.split('.')[0]
++            except Exception as err:
++                self.log_debug("Unable to fully parse sos release: %s" % err)
++
++        self.sos_info['version'] = ver
++
+         if self.sos_info['version']:
+             self.log_info('sos version is %s' % self.sos_info['version'])
+         else:
+@@ -381,9 +394,37 @@ class SosNode():
+         """Checks to see if the sos installation on the node is AT LEAST the
+         given ver. This means that if the installed version is greater than
+         ver, this will still return True
++
++        :param ver: Version number we are trying to verify is installed
++        :type ver:  ``str``
++
++        :returns:   True if installed version is at least ``ver``, else False
++        :rtype:     ``bool``
+         """
+-        return self.sos_info['version'] is not None and \
+-            LooseVersion(self.sos_info['version']) >= ver
++        def _format_version(ver):
++            # format the version we're checking to a standard form of X.Y.Z-R
++            try:
++                _fver = ver.split('-')[0]
++                _rel = ''
++                if '-' in ver:
++                    _rel = '-' + ver.split('-')[-1].split('.')[0]
++                if len(_fver.split('.')) == 2:
++                    _fver += '.0'
++
++                return _fver + _rel
++            except Exception as err:
++                self.log_debug("Unable to format '%s': %s" % (ver, err))
++                return ver
++
++        _ver = _format_version(ver)
++
++        try:
++            _node_ver = LooseVersion(self.sos_info['version'])
++            _test_ver = LooseVersion(_ver)
++            return _node_ver >= _test_ver
++        except Exception as err:
++            self.log_error("Error checking sos version: %s" % err)
++            return False
+ 
+     def is_installed(self, pkg):
+         """Checks if a given package is installed on the node"""
+@@ -587,7 +628,8 @@ class SosNode():
+                 sos_opts.append('--cmd-timeout=%s'
+                                 % quote(str(self.opts.cmd_timeout)))
+ 
+-        if self.check_sos_version('4.3'):
++        # handle downstream versions that backported this option
++        if self.check_sos_version('4.3') or self.check_sos_version('4.2-13'):
+             if self.opts.container_runtime != 'auto':
+                 sos_opts.append(
+                     "--container-runtime=%s" % self.opts.container_runtime
+-- 
+2.34.3
+
+From cc60fa5ee25bffed9203a4f786256185b7fe0115 Mon Sep 17 00:00:00 2001
+From: Nadia Pinaeva <npinaeva@redhat.com>
+Date: Tue, 15 Mar 2022 11:49:57 +0100
+Subject: [PATCH] Add ovs datapath and groups collection commands Add
+ ct-zone-list command for openshift-ovn
+
+Signed-off-by: Nadia Pinaeva <npinaeva@redhat.com>
+---
+ sos/report/plugins/openshift_ovn.py | 4 ++++
+ sos/report/plugins/openvswitch.py   | 3 +++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/sos/report/plugins/openshift_ovn.py b/sos/report/plugins/openshift_ovn.py
+index 168f1dd3..b4787b8e 100644
+--- a/sos/report/plugins/openshift_ovn.py
++++ b/sos/report/plugins/openshift_ovn.py
+@@ -34,6 +34,10 @@ class OpenshiftOVN(Plugin, RedHatPlugin):
+             'ovn-appctl -t /var/run/ovn/ovnsb_db.ctl ' +
+             'cluster/status OVN_Southbound'],
+             container='ovnkube-master')
++        self.add_cmd_output([
++            'ovs-appctl -t /var/run/ovn/ovn-controller.*.ctl ' +
++            'ct-zone-list'],
++            container='ovnkube-node')
+         self.add_cmd_output([
+             'ovs-appctl -t ovs-monitor-ipsec tunnels/show',
+             'ipsec status',
+diff --git a/sos/report/plugins/openvswitch.py b/sos/report/plugins/openvswitch.py
+index 179d1532..159b0bd2 100644
+--- a/sos/report/plugins/openvswitch.py
++++ b/sos/report/plugins/openvswitch.py
+@@ -124,6 +124,8 @@ class OpenVSwitch(Plugin):
+             "ovs-vsctl -t 5 list interface",
+             # Capture OVS detailed information from all the bridges
+             "ovs-vsctl -t 5 list bridge",
++            # Capture OVS datapath list
++            "ovs-vsctl -t 5 list datapath",
+             # Capture DPDK queue to pmd mapping
+             "ovs-appctl dpif-netdev/pmd-rxq-show",
+             # Capture DPDK pmd stats
+@@ -229,6 +231,7 @@ class OpenVSwitch(Plugin):
+                     "ovs-ofctl queue-get-config %s" % br,
+                     "ovs-ofctl queue-stats %s" % br,
+                     "ovs-ofctl show %s" % br,
++                    "ovs-ofctl dump-groups %s" % br,
+                 ])
+ 
+                 # Flow protocols currently supported
+-- 
+2.34.3
+
+From af40be92f502b35fa9d39ce4d4fea7d80c367830 Mon Sep 17 00:00:00 2001
+From: Nadia Pinaeva <npinaeva@redhat.com>
+Date: Tue, 15 Mar 2022 13:09:55 +0100
+Subject: [PATCH] Improve sos collect for OCP: 1. wait for sos tmp project to
+ be deleted (just calling delete changes project state to Terminating, and
+ running a new sos collect is not possible before this project is fully
+ deleted) 2. use --retries flag to copy sos reports from the nodes more
+ reliably. The flag has been recently added to kubectl, and the most reliable
+ way to check if it's available or not is to check command error output for
+ "unknown flag" substring
+
+Signed-off-by: Nadia Pinaeva <npinaeva@redhat.com>
+---
+ sos/collector/clusters/ocp.py  | 5 +++++
+ sos/collector/transports/oc.py | 6 +++++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/sos/collector/clusters/ocp.py b/sos/collector/clusters/ocp.py
+index f1714239..9beb2f9b 100644
+--- a/sos/collector/clusters/ocp.py
++++ b/sos/collector/clusters/ocp.py
+@@ -123,6 +123,11 @@ class ocp(Cluster):
+             if not ret['status'] == 0:
+                 self.log_error("Error deleting temporary project: %s"
+                                % ret['output'])
++            ret = self.exec_primary_cmd("oc wait namespace/%s --for=delete "
++                                        "--timeout=30s" % self.project)
++            if not ret['status'] == 0:
++                self.log_error("Error waiting for temporary project to be "
++                               "deleted: %s" % ret['output'])
+             # don't leave the config on a non-existing project
+             self.exec_primary_cmd("oc project default")
+             self.project = None
+diff --git a/sos/collector/transports/oc.py b/sos/collector/transports/oc.py
+index 0fc9eee8..90a802b2 100644
+--- a/sos/collector/transports/oc.py
++++ b/sos/collector/transports/oc.py
+@@ -231,5 +231,9 @@ class OCTransport(RemoteTransport):
+                 % (self.project, self.pod_name))
+ 
+     def _retrieve_file(self, fname, dest):
+-        cmd = self.run_oc("cp %s:%s %s" % (self.pod_name, fname, dest))
++        # check if --retries flag is available for given version of oc
++        result = self.run_oc("cp --retries", stderr=True)
++        flags = '' if "unknown flag" in result["output"] else '--retries=5'
++        cmd = self.run_oc("cp %s %s:%s %s"
++                          % (flags, self.pod_name, fname, dest))
+         return cmd['status'] == 0
+-- 
+2.34.3
+
+From 3b0676b90ff65f20eaba3062775ff72b89386ffc Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Tue, 22 Mar 2022 14:25:24 -0400
+Subject: [PATCH] [Plugin] Allow plugins to define default command environment
+ vars
+
+Adds the ability for plugins to define a default set of environment vars
+to pass to all commands executed by the plugin. This may be done either
+via the new `set_default_cmd_environment()` or
+`add_default_cmd_environment()` methods. The former will override any
+previously set values, whereas the latter will add/update/modify any
+existing values.
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/report/plugins/__init__.py                | 55 ++++++++++++++++++-
+ .../plugin_tests/plugin_environment.py        | 44 +++++++++++++++
+ .../fake_plugins/default_env_test.py          | 28 ++++++++++
+ tests/unittests/plugin_tests.py               | 15 +++++
+ 4 files changed, 140 insertions(+), 2 deletions(-)
+ create mode 100644 tests/report_tests/plugin_tests/plugin_environment.py
+ create mode 100644 tests/test_data/fake_plugins/default_env_test.py
+
+diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py
+index 336b4d22..74b4f4be 100644
+--- a/sos/report/plugins/__init__.py
++++ b/sos/report/plugins/__init__.py
+@@ -571,6 +571,7 @@ class Plugin():
+         self.manifest = None
+         self.skip_files = commons['cmdlineopts'].skip_files
+         self.skip_commands = commons['cmdlineopts'].skip_commands
++        self.default_environment = {}
+ 
+         self.soslog = self.commons['soslog'] if 'soslog' in self.commons \
+             else logging.getLogger('sos')
+@@ -624,6 +625,52 @@ class Plugin():
+         self.manifest.add_field('strings', {})
+         self.manifest.add_field('containers', {})
+ 
++    def set_default_cmd_environment(self, env_vars):
++        """
++        Specify a collection of environment variables that should always be
++        passed to commands being executed by this plugin.
++
++        :param env_vars:    The environment variables and their values to set
++        :type env_vars:     ``dict{ENV_VAR_NAME: ENV_VAR_VALUE}``
++        """
++        if not isinstance(env_vars, dict):
++            raise TypeError(
++                "Environment variables for Plugin must be specified by dict"
++            )
++        self.default_environment = env_vars
++        self._log_debug("Default environment for all commands now set to %s"
++                        % self.default_environment)
++
++    def add_default_cmd_environment(self, env_vars):
++        """
++        Add or modify a specific environment variable in the set of default
++        environment variables used by this Plugin.
++
++        :param env_vars:    The environment variables to add to the current
++                            set of env vars in use
++        :type env_vars:     ``dict``
++        """
++        if not isinstance(env_vars, dict):
++            raise TypeError("Environment variables must be added via dict")
++        self._log_debug("Adding %s to default environment" % env_vars)
++        self.default_environment.update(env_vars)
++
++    def _get_cmd_environment(self, env=None):
++        """
++        Get the merged set of environment variables for a command about to be
++        executed by this plugin.
++
++        :returns: The set of env vars to use for a command
++        :rtype: ``dict``
++        """
++        if env is None:
++            return self.default_environment
++        if not isinstance(env, dict):
++            raise TypeError("Command env vars must be passed as dict")
++        _env = self.default_environment.copy()
++        _env.update(env)
++        return _env
++
+     def timeout_from_options(self, optname, plugoptname, default_timeout):
+         """Returns either the default [plugin|cmd] timeout value, the value as
+         provided on the commandline via -k plugin.[|cmd-]timeout=value, or the
+@@ -2258,6 +2305,8 @@ class Plugin():
+ 
+         _tags = list(set(_tags))
+ 
++        _env = self._get_cmd_environment(env)
++
+         if chroot or self.commons['cmdlineopts'].chroot == 'always':
+             root = self.sysroot
+         else:
+@@ -2282,7 +2331,7 @@ class Plugin():
+ 
+         result = sos_get_command_output(
+             cmd, timeout=timeout, stderr=stderr, chroot=root,
+-            chdir=runat, env=env, binary=binary, sizelimit=sizelimit,
++            chdir=runat, env=_env, binary=binary, sizelimit=sizelimit,
+             poller=self.check_timeout, foreground=foreground,
+             to_file=out_file
+         )
+@@ -2510,6 +2559,8 @@ class Plugin():
+         else:
+             root = None
+ 
++        _env = self._get_cmd_environment(env)
++
+         if container:
+             if self._get_container_runtime() is None:
+                 self._log_info("Cannot run cmd '%s' in container %s: no "
+@@ -2522,7 +2573,7 @@ class Plugin():
+                                "container is running." % (cmd, container))
+ 
+         return sos_get_command_output(cmd, timeout=timeout, chroot=root,
+-                                      chdir=runat, binary=binary, env=env,
++                                      chdir=runat, binary=binary, env=_env,
+                                       foreground=foreground, stderr=stderr)
+ 
+     def _add_container_file_to_manifest(self, container, path, arcpath, tags):
+diff --git a/tests/report_tests/plugin_tests/plugin_environment.py b/tests/report_tests/plugin_tests/plugin_environment.py
+new file mode 100644
+index 00000000..3158437a
+--- /dev/null
++++ b/tests/report_tests/plugin_tests/plugin_environment.py
+@@ -0,0 +1,44 @@
++# This file is part of the sos project: https://github.com/sosreport/sos
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions of
++# version 2 of the GNU General Public License.
++#
++# See the LICENSE file in the source distribution for further information.
++
++import os
++
++from sos_tests import StageTwoReportTest
++
++
++class PluginDefaultEnvironmentTest(StageTwoReportTest):
++    """
++    Ensure that being able to set a default set of environment variables is
++    working correctly and does not leave a lingering env var on the system
++
++    :avocado: tags=stageone
++    """
++
++    install_plugins = ['default_env_test']
++    sos_cmd = '-o default_env_test'
++
++    def test_environment_used_in_cmd(self):
++        self.assertFileHasContent(
++            'sos_commands/default_env_test/env_var_test',
++            'Does Linus play hockey?'
++        )
++
++    def test_environment_setting_logged(self):
++        self.assertSosLogContains(
++            'Default environment for all commands now set to'
++        )
++
++    def test_environment_not_set_on_host(self):
++        self.assertTrue('TORVALDS' not in os.environ)
++        self.assertTrue('GREATESTSPORT' not in os.environ)
++
++    def test_environment_not_captured(self):
++        # we should still have an empty environment file
++        self.assertFileCollected('environment')
++        self.assertFileNotHasContent('environment', 'TORVALDS')
++        self.assertFileNotHasContent('environment', 'GREATESTSPORT')
+diff --git a/tests/test_data/fake_plugins/default_env_test.py b/tests/test_data/fake_plugins/default_env_test.py
+new file mode 100644
+index 00000000..d1d1fb78
+--- /dev/null
++++ b/tests/test_data/fake_plugins/default_env_test.py
+@@ -0,0 +1,28 @@
++# This file is part of the sos project: https://github.com/sosreport/sos
++#
++# This copyrighted material is made available to anyone wishing to use,
++# modify, copy, or redistribute it subject to the terms and conditions of
++# version 2 of the GNU General Public License.
++#
++# See the LICENSE file in the source distribution for further information.
++
++from sos.report.plugins import Plugin, IndependentPlugin
++
++
++class DefaultEnv(Plugin, IndependentPlugin):
++
++    plugin_name = 'default_env_test'
++    short_desc = 'Fake plugin to test default env var handling'
++
++    def setup(self):
++        self.set_default_cmd_environment({
++            'TORVALDS': 'Linus',
++            'GREATESTSPORT': 'hockey'
++        })
++
++        self.add_cmd_output(
++            "sh -c 'echo Does '$TORVALDS' play '$GREATESTSPORT'?'",
++            suggest_filename='env_var_test'
++        )
++
++        self.add_env_var(['TORVALDS', 'GREATESTSPORT'])
+diff --git a/tests/unittests/plugin_tests.py b/tests/unittests/plugin_tests.py
+index 0dfa243d..e469b78e 100644
+--- a/tests/unittests/plugin_tests.py
++++ b/tests/unittests/plugin_tests.py
+@@ -305,6 +305,21 @@ class PluginTests(unittest.TestCase):
+         p.postproc()
+         self.assertTrue(p.did_postproc)
+ 
++    def test_set_default_cmd_env(self):
++        p = MockPlugin({
++            'sysroot': self.sysroot,
++            'policy': LinuxPolicy(init=InitSystem(), probe_runtime=False),
++            'cmdlineopts': MockOptions(),
++            'devices': {}
++        })
++        e = {'TORVALDS': 'Linus'}
++        p.set_default_cmd_environment(e)
++        self.assertEquals(p.default_environment, e)
++        add_e = {'GREATESTSPORT': 'hockey'}
++        p.add_default_cmd_environment(add_e)
++        self.assertEquals(p.default_environment['GREATESTSPORT'], 'hockey')
++        self.assertEquals(p.default_environment['TORVALDS'], 'Linus')
++
+ 
+ class AddCopySpecTests(unittest.TestCase):
+ 
+-- 
+2.34.3
+
+From 1e12325efaa500d304dcbfbeeb50e72ed0f938f5 Mon Sep 17 00:00:00 2001
+From: Vladislav Walek <22072258+vwalek@users.noreply.github.com>
+Date: Thu, 17 Mar 2022 14:10:26 -0700
+Subject: [PATCH] [openshift] Adding ability to use the localhost.kubeconfig
+ and KUBECONFIG env to use system:admin
+
+Signed-off-by: Vladislav Walek <22072258+vwalek@users.noreply.github.com>
+---
+ sos/report/plugins/openshift.py | 45 +++++++++++++++++++++++++++++++--
+ 1 file changed, 43 insertions(+), 2 deletions(-)
+
+diff --git a/sos/report/plugins/openshift.py b/sos/report/plugins/openshift.py
+index 5ae38178..d643f04c 100644
+--- a/sos/report/plugins/openshift.py
++++ b/sos/report/plugins/openshift.py
+@@ -53,12 +53,19 @@ class Openshift(Plugin, RedHatPlugin):
+     profiles = ('openshift',)
+     packages = ('openshift-hyperkube',)
+ 
++    master_localhost_kubeconfig = (
++        '/etc/kubernetes/static-pod-resources/'
++        'kube-apiserver-certs/secrets/node-kubeconfigs/localhost.kubeconfig'
++        )
++
+     option_list = [
+         PluginOpt('token', default=None, val_type=str,
+                   desc='admin token to allow API queries'),
++        PluginOpt('kubeconfig', default=None, val_type=str,
++                  desc='Path to a locally available kubeconfig file'),
+         PluginOpt('host', default='https://localhost:6443',
+                   desc='host address to use for oc login, including port'),
+-        PluginOpt('no-oc', default=False, desc='do not collect `oc` output'),
++        PluginOpt('no-oc', default=True, desc='do not collect `oc` output'),
+         PluginOpt('podlogs', default=True, desc='collect logs from each pod'),
+         PluginOpt('podlogs-filter', default='', val_type=str,
+                   desc='only collect logs from pods matching this pattern'),
+@@ -73,6 +80,10 @@ class Openshift(Plugin, RedHatPlugin):
+         """Check to see if we can run `oc` commands"""
+         return self.exec_cmd('oc whoami')['status'] == 0
+ 
++    def _check_localhost_kubeconfig(self):
++        """Check if the localhost.kubeconfig exists with system:admin user"""
++        return self.path_exists(self.get_option('kubeconfig'))
++
+     def _check_oc_logged_in(self):
+         """See if we're logged in to the API service, and if not attempt to do
+         so using provided plugin options
+@@ -80,8 +91,38 @@ class Openshift(Plugin, RedHatPlugin):
+         if self._check_oc_function():
+             return True
+ 
+-        # Not logged in currently, attempt to do so
++        if self.get_option('kubeconfig') is None:
++            # If admin doesn't add the kubeconfig
++            # use default localhost.kubeconfig
++            self.set_option(
++                'kubeconfig',
++                self.master_localhost_kubeconfig
++            )
++
++        # Check first if we can use the localhost.kubeconfig before
++        # using token. We don't want to use 'host' option due we use
++        # cluster url from kubeconfig. Default is localhost.
++        if self._check_localhost_kubeconfig():
++            self.set_default_cmd_environment({
++                'KUBECONFIG': self.get_option('kubeconfig')
++            })
++
++            oc_res = self.exec_cmd(
++                "oc login -u system:admin "
++                "--insecure-skip-tls-verify=True"
++            )
++            if oc_res['status'] == 0 and self._check_oc_function():
++                return True
++
++            self._log_warn(
++                "The login command failed with status: %s and error: %s"
++                % (oc_res['status'], oc_res['output'])
++            )
++            return False
++
++        # If kubeconfig is not defined, check if token is provided.
+         token = self.get_option('token') or os.getenv('SOSOCPTOKEN', None)
++
+         if token:
+             oc_res = self.exec_cmd("oc login %s --token=%s "
+                                    "--insecure-skip-tls-verify=True"
+-- 
+2.34.3
+
+From 61765992812afb785e9552e01e3b5579118a6963 Mon Sep 17 00:00:00 2001
+From: Nadia Pinaeva <npinaeva@redhat.com>
+Date: Fri, 1 Apr 2022 12:05:36 +0200
+Subject: [PATCH] Add one more container for plugin enablement
+
+Signed-off-by: Nadia Pinaeva <npinaeva@redhat.com>
+---
+ sos/report/plugins/openshift_ovn.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sos/report/plugins/openshift_ovn.py b/sos/report/plugins/openshift_ovn.py
+index b4787b8e..98522b1e 100644
+--- a/sos/report/plugins/openshift_ovn.py
++++ b/sos/report/plugins/openshift_ovn.py
+@@ -16,7 +16,7 @@ class OpenshiftOVN(Plugin, RedHatPlugin):
+     """
+     short_desc = 'Openshift OVN'
+     plugin_name = "openshift_ovn"
+-    containers = ('ovnkube-master', 'ovn-ipsec')
++    containers = ('ovnkube-master', 'ovnkube-node', 'ovn-ipsec')
+     profiles = ('openshift',)
+ 
+     def setup(self):
+-- 
+2.34.3
+
+From d3aa071efc85507341cf65dd61414a734654f50a Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Mon, 28 Mar 2022 14:47:09 -0400
+Subject: [PATCH] [presets] Adjust OCP preset options
+
+Adjust the options used by the 'ocp' preset to better reflect the
+current collection needs and approach.
+
+This includes disabling the `cgroups` plugin due to the large amount of
+mostly irrelevant data captured due to the high number of containers
+present on OCP nodes, ensuring the `--container-runtime` option is set
+to `crio` to align container-based collections, disabling HTML report
+generation and increasing the base log size rather than blindly enabling
+all-logs.
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/presets/redhat/__init__.py | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sos/presets/redhat/__init__.py b/sos/presets/redhat/__init__.py
+index 865c9b6b..0b9f6f11 100644
+--- a/sos/presets/redhat/__init__.py
++++ b/sos/presets/redhat/__init__.py
+@@ -36,10 +36,15 @@ RHOSP_OPTS = SoSOptions(plugopts=[
+ 
+ RHOCP = "ocp"
+ RHOCP_DESC = "OpenShift Container Platform by Red Hat"
+-RHOCP_OPTS = SoSOptions(all_logs=True, verify=True, plugopts=[
+-                             'networking.timeout=600',
+-                             'networking.ethtool_namespaces=False',
+-                             'networking.namespaces=200'])
++RHOCP_OPTS = SoSOptions(
++    verify=True, skip_plugins=['cgroups'], container_runtime='crio',
++    no_report=True, log_size=100,
++    plugopts=[
++        'crio.timeout=600',
++        'networking.timeout=600',
++        'networking.ethtool_namespaces=False',
++        'networking.namespaces=200'
++    ])
+ 
+ RH_CFME = "cfme"
+ RH_CFME_DESC = "Red Hat CloudForms"
+-- 
+2.34.3
+
+From f2b67ab820070063995689fed03492cdaa012d01 Mon Sep 17 00:00:00 2001
+From: Nadia Pinaeva <npinaeva@redhat.com>
+Date: Fri, 1 Apr 2022 17:01:35 +0200
+Subject: [PATCH] Use /etc/os-release instead of /etc/redhat-release as the
+ most compatible way to find host release
+
+Signed-off-by: Nadia Pinaeva <npinaeva@redhat.com>
+---
+ sos/policies/distros/redhat.py | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/sos/policies/distros/redhat.py b/sos/policies/distros/redhat.py
+index 0c72a5e4..2e117f37 100644
+--- a/sos/policies/distros/redhat.py
++++ b/sos/policies/distros/redhat.py
+@@ -40,7 +40,6 @@ class RedHatPolicy(LinuxPolicy):
+         ('Distribution Website', 'https://www.redhat.com/'),
+         ('Commercial Support', 'https://www.access.redhat.com/')
+     ]
+-    _redhat_release = '/etc/redhat-release'
+     _tmp_dir = "/var/tmp"
+     _in_container = False
+     default_scl_prefix = '/opt/rh'
+@@ -471,7 +470,7 @@ support representative.
+         atomic = False
+         if ENV_HOST_SYSROOT not in os.environ:
+             return atomic
+-        host_release = os.environ[ENV_HOST_SYSROOT] + cls._redhat_release
++        host_release = os.environ[ENV_HOST_SYSROOT] + OS_RELEASE
+         if not os.path.exists(host_release):
+             return False
+         try:
+@@ -558,7 +557,7 @@ support representative.
+         coreos = False
+         if ENV_HOST_SYSROOT not in os.environ:
+             return coreos
+-        host_release = os.environ[ENV_HOST_SYSROOT] + cls._redhat_release
++        host_release = os.environ[ENV_HOST_SYSROOT] + OS_RELEASE
+         try:
+             for line in open(host_release, 'r').read().splitlines():
+                 coreos |= 'Red Hat Enterprise Linux CoreOS' in line
+-- 
+2.34.3
+
+From ee0dd68199a2c9296eafe64ead5b2263c8270e4a Mon Sep 17 00:00:00 2001
+From: Nadia Pinaeva <npinaeva@redhat.com>
+Date: Wed, 6 Apr 2022 11:56:41 +0200
+Subject: [PATCH] Use --force-pull-image option for pods created with oc. Set
+ --force-pull-image=True by default, can be turned off with
+ --force-pull-image=False
+
+Signed-off-by: Nadia Pinaeva <npinaeva@redhat.com>
+---
+ man/en/sos-collect.1           | 16 +++++++++++-----
+ sos/collector/__init__.py      |  9 +++++----
+ sos/collector/transports/oc.py |  2 ++
+ sos/options.py                 | 20 ++++++++++++++------
+ 4 files changed, 32 insertions(+), 15 deletions(-)
+
+diff --git a/man/en/sos-collect.1 b/man/en/sos-collect.1
+index 9b0a5d7b..2f60332b 100644
+--- a/man/en/sos-collect.1
++++ b/man/en/sos-collect.1
+@@ -28,7 +28,7 @@ sos collect \- Collect sosreports from multiple (cluster) nodes
+     [\-\-no\-local]
+     [\-\-primary PRIMARY]
+     [\-\-image IMAGE]
+-    [\-\-force-pull-image]
++    [\-\-force-pull-image TOGGLE, --pull TOGGLE]
+     [\-\-registry-user USER]
+     [\-\-registry-password PASSWORD]
+     [\-\-registry-authfile FILE]
+@@ -262,10 +262,16 @@ Specify an image to use for the temporary container created for collections on
+ containerized host, if you do not want to use the default image specifed by the
+ host's policy. Note that this should include the registry.
+ .TP
+-\fB\-\-force-pull-image\fR
+-Use this option to force the container runtime to pull the specified image (even
+-if it is the policy default image) even if the image already exists on the host.
+-This may be useful to update an older container image on containerized hosts.
++\fB\-\-force-pull-image TOGGLE, \-\-pull TOGGLE\fR
++When collecting an sos report from a containerized host, force the host to always
++pull the specified image, even if that image already exists on the host.
++This is useful to ensure that the latest version of that image is always in use.
++Disabling this option will use whatever version of the image is present on the node,
++and only attempt a pull if there is no copy of the image present at all.
++
++Enable with true/on/yes or disable with false/off/no
++
++Default: true
+ .TP
+ \fB\-\-registry-user USER\fR
+ Specify the username to authenticate to the registry with in order to pull the container
+diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py
+index d898ca34..66c3d932 100644
+--- a/sos/collector/__init__.py
++++ b/sos/collector/__init__.py
+@@ -27,7 +27,7 @@ from pipes import quote
+ from textwrap import fill
+ from sos.cleaner import SoSCleaner
+ from sos.collector.sosnode import SosNode
+-from sos.options import ClusterOption
++from sos.options import ClusterOption, str_to_bool
+ from sos.component import SoSComponent
+ from sos.utilities import bold
+ from sos import __version__
+@@ -85,7 +85,7 @@ class SoSCollector(SoSComponent):
+         'encrypt_pass': '',
+         'group': None,
+         'image': '',
+-        'force_pull_image': False,
++        'force_pull_image': True,
+         'jobs': 4,
+         'keywords': [],
+         'keyword_file': None,
+@@ -357,8 +357,9 @@ class SoSCollector(SoSComponent):
+         collect_grp.add_argument('--image',
+                                  help=('Specify the container image to use for'
+                                        ' containerized hosts.'))
+-        collect_grp.add_argument('--force-pull-image', '--pull', default=False,
+-                                 action='store_true',
++        collect_grp.add_argument('--force-pull-image', '--pull',
++                                 default=True, choices=(True, False),
++                                 type=str_to_bool,
+                                  help='Force pull the container image even if '
+                                       'it already exists on the host')
+         collect_grp.add_argument('--registry-user', default=None,
+diff --git a/sos/collector/transports/oc.py b/sos/collector/transports/oc.py
+index 90a802b2..8f6aa9b4 100644
+--- a/sos/collector/transports/oc.py
++++ b/sos/collector/transports/oc.py
+@@ -147,6 +147,8 @@ class OCTransport(RemoteTransport):
+                         "tty": True
+                     }
+                 ],
++                "imagePullPolicy":
++                    "Always" if self.opts.force_pull_image else "IfNotPresent",
+                 "restartPolicy": "Never",
+                 "nodeName": self.address,
+                 "hostNetwork": True,
+diff --git a/sos/options.py b/sos/options.py
+index 4846a509..2d5a5135 100644
+--- a/sos/options.py
++++ b/sos/options.py
+@@ -18,6 +18,16 @@ def _is_seq(val):
+     return val_type is list or val_type is tuple
+ 
+ 
++def str_to_bool(val):
++    _val = val.lower()
++    if _val in ['true', 'on', 'yes']:
++        return True
++    elif _val in ['false', 'off', 'no']:
++        return False
++    else:
++        return None
++
++
+ class SoSOptions():
+ 
+     def _merge_opt(self, opt, src, is_default):
+@@ -153,15 +163,13 @@ class SoSOptions():
+         if isinstance(self.arg_defaults[key], list):
+             return [v for v in val.split(',')]
+         if isinstance(self.arg_defaults[key], bool):
+-            _val = val.lower()
+-            if _val in ['true', 'on', 'yes']:
+-                return True
+-            elif _val in ['false', 'off', 'no']:
+-                return False
+-            else:
++            val = str_to_bool(val)
++            if val is None:
+                 raise Exception(
+                     "Value of '%s' in %s must be True or False or analagous"
+                     % (key, conf))
++            else:
++                return val
+         if isinstance(self.arg_defaults[key], int):
+             try:
+                 return int(val)
+-- 
+2.34.3
+
+From ce289a3ae7101a898efdb84ddfd575576ba5819b Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Tue, 5 Apr 2022 11:32:11 -0400
+Subject: [PATCH] [ocp, openshift] Re-align API collection options and rename
+ option
+
+Previously, in #2888, the `openshift` plugin was extended to allow API
+collections by using a default-available kubeconfig file rather than
+relying on user-provided tokens. This also included flipping the default
+value of the `no-oc` plugin option to `True` (meaning do not collect API
+output by default).
+
+This worked for the plugin, but it introduced a gap in `sos collect`
+whereby the cluster profile could no longer reliably enable API
+collections when trying to leverage the new functionality of not
+requiring a user token.
+
+Fix this by updating the cluster profile to align with the new
+default-off approach of API collections.
+
+Along with this, add a toggle to the cluster profile directly to allow
+users to toggle API collections on or off (default off) directly. This
+is done via a new `with-api` cluster option (e.g. `-c ocp.with-api`).
+Further, rename the `openshift` plugin option from `no-oc` to
+`with-api`. This change not only makes the option use case far more
+obvious, it will also align the use of the option to both `collect` and
+`report` so that users need only be aware of a single option for either
+method.
+
+The cluster profile also has logic to detect which plugin option,
+`no-oc` or `with-api` to use based on the (RHEL) sos version installed
+on the nodes being inspected by the `ocp` cluster profile.
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/collector/clusters/ocp.py   | 72 +++++++++++++++++++++++++++------
+ sos/report/plugins/openshift.py | 26 +++++++-----
+ 2 files changed, 77 insertions(+), 21 deletions(-)
+
+diff --git a/sos/collector/clusters/ocp.py b/sos/collector/clusters/ocp.py
+index 9beb2f9b..e31d1903 100644
+--- a/sos/collector/clusters/ocp.py
++++ b/sos/collector/clusters/ocp.py
+@@ -30,7 +30,11 @@ class ocp(Cluster):
+     clusterAdmin privileges.
+ 
+     If this requires the use of a secondary configuration file, specify that
+-    path with the 'kubeconfig' cluster option.
++    path with the 'kubeconfig' cluster option. This config file will also be
++    used on a single master node to perform API collections if the `with-api`
++    option is enabled (default disabled). If no `kubeconfig` option is given,
++    but `with-api` is enabled, the cluster profile will attempt to use a
++    well-known default kubeconfig file if it is available on the host.
+ 
+     Alternatively, provide a clusterAdmin access token either via the 'token'
+     cluster option or, preferably, the SOSOCPTOKEN environment variable.
+@@ -45,7 +49,7 @@ class ocp(Cluster):
+     option mentioned above.
+ 
+     To avoid redundant collections of OCP API information (e.g. 'oc get'
+-    commands), this profile will attempt to enable the openshift plugin on only
++    commands), this profile will attempt to enable the API collections on only
+     a single master node. If the none of the master nodes have a functional
+     'oc' binary available, *and* the --no-local option is used, that means that
+     no API data will be collected.
+@@ -63,7 +67,8 @@ class ocp(Cluster):
+         ('label', '', 'Colon delimited list of labels to select nodes with'),
+         ('role', 'master', 'Colon delimited list of roles to filter on'),
+         ('kubeconfig', '', 'Path to the kubeconfig file'),
+-        ('token', '', 'Service account token to use for oc authorization')
++        ('token', '', 'Service account token to use for oc authorization'),
++        ('with-api', False, 'Collect OCP API data from a master node')
+     ]
+ 
+     def fmt_oc_cmd(self, cmd):
+@@ -219,13 +224,52 @@ class ocp(Cluster):
+             return False
+         return 'master' in self.node_dict[sosnode.address]['roles']
+ 
++    def _toggle_api_opt(self, node, use_api):
++        """In earlier versions of sos, the openshift plugin option that is
++        used to toggle the API collections was called `no-oc` rather than
++        `with-api`. This older plugin option had the inverse logic of the
++        current `with-api` option.
++
++        Use this to toggle the correct plugin option given the node's sos
++        version. Note that the use of version 4.2 here is tied to the RHEL
++        release (the only usecase for this cluster profile) rather than
++        the upstream version given the backports for that downstream.
++
++        :param node:    The node being inspected for API collections
++        :type node:     ``SoSNode``
++
++        :param use_api: Should this node enable API collections?
++        :type use_api:  ``bool``
++        """
++        if node.check_sos_version('4.2-16'):
++            _opt = 'with-api'
++            _val = 'on' if use_api else 'off'
++        else:
++            _opt = 'no-oc'
++            _val = 'off' if use_api else 'on'
++        node.plugopts.append("openshift.%s=%s" % (_opt, _val))
++
+     def set_primary_options(self, node):
++
+         node.enable_plugins.append('openshift')
++        if not self.get_option('with-api'):
++            self._toggle_api_opt(node, False)
++            return
+         if self.api_collect_enabled:
+             # a primary has already been enabled for API collection, disable
+             # it among others
+-            node.plugopts.append('openshift.no-oc=on')
++            self._toggle_api_opt(node, False)
+         else:
++            # running in a container, so reference the /host mount point
++            master_kube = (
++                '/host/etc/kubernetes/static-pod-resources/'
++                'kube-apiserver-certs/secrets/node-kubeconfigs/'
++                'localhost.kubeconfig'
++            )
++            _optconfig = self.get_option('kubeconfig')
++            if _optconfig and not _optconfig.startswith('/host'):
++                _optconfig = '/host/' + _optconfig
++            _kubeconfig = _optconfig or master_kube
+             _oc_cmd = 'oc'
+             if node.host.containerized:
+                 _oc_cmd = '/host/bin/oc'
+@@ -244,17 +288,21 @@ class ocp(Cluster):
+                                       need_root=True)
+             if can_oc['status'] == 0:
+                 # the primary node can already access the API
++                self._toggle_api_opt(node, True)
+                 self.api_collect_enabled = True
+             elif self.token:
+                 node.sos_env_vars['SOSOCPTOKEN'] = self.token
++                self._toggle_api_opt(node, True)
++                self.api_collect_enabled = True
++            elif node.file_exists(_kubeconfig):
++                # if the file exists, then the openshift sos plugin will use it
++                # if the with-api option is turned on
++                if not _kubeconfig == master_kube:
++                    node.plugopts.append(
++                        "openshift.kubeconfig=%s" % _kubeconfig
++                    )
++                self._toggle_api_opt(node, True)
+                 self.api_collect_enabled = True
+-            elif self.get_option('kubeconfig'):
+-                kc = self.get_option('kubeconfig')
+-                if node.file_exists(kc):
+-                    if node.host.containerized:
+-                        kc = "/host/%s" % kc
+-                    node.sos_env_vars['KUBECONFIG'] = kc
+-                    self.api_collect_enabled = True
+             if self.api_collect_enabled:
+                 msg = ("API collections will be performed on %s\nNote: API "
+                        "collections may extend runtime by 10s of minutes\n"
+@@ -264,6 +312,6 @@ class ocp(Cluster):
+ 
+     def set_node_options(self, node):
+         # don't attempt OC API collections on non-primary nodes
+-        node.plugopts.append('openshift.no-oc=on')
++        self._toggle_api_opt(node, False)
+ 
+ # vim: set et ts=4 sw=4 :
+diff --git a/sos/report/plugins/openshift.py b/sos/report/plugins/openshift.py
+index d643f04c..a41ab62b 100644
+--- a/sos/report/plugins/openshift.py
++++ b/sos/report/plugins/openshift.py
+@@ -19,7 +19,10 @@ class Openshift(Plugin, RedHatPlugin):
+     further extending the kubernetes plugin (or the OCP 3.x extensions included
+     in the Red Hat version of the kube plugin).
+ 
+-    By default, this plugin will collect cluster information and inspect the
++    This plugin may collect OCP API information when the `with-api` option is
++    enabled. This option is disabled by default.
++
++    When enabled, this plugin will collect cluster information and inspect the
+     default namespaces/projects that are created during deployment - i.e. the
+     namespaces of the cluster projects matching openshift.* and kube.*. At the
+     time of this plugin's creation that number of default projects is already
+@@ -34,16 +37,20 @@ class Openshift(Plugin, RedHatPlugin):
+ 
+     Users will need to either:
+ 
+-        1) Provide the bearer token via the `-k openshift.token` option
+-        2) Provide the bearer token via the `SOSOCPTOKEN` environment variable
+-        3) Otherwise ensure that the root user can successfully run `oc` and
++        1) Accept the use of a well-known stock kubeconfig file provided via a
++           static pod resource for the kube-apiserver
++        2) Provide the bearer token via the `-k openshift.token` option
++        3) Provide the bearer token via the `SOSOCPTOKEN` environment variable
++        4) Otherwise ensure that the root user can successfully run `oc` and
+            get proper output prior to running this plugin
+ 
+ 
+-    It is highly suggested that option #2 be used first, as this will prevent
+-    the token from being recorded in output saved to the archive. Option #1 may
++    It is highly suggested that option #1 be used first, as this uses well
++    known configurations and requires the least information from the user. If
++    using a token, it is recommended to use option #3 as this will prevent
++    the token from being recorded in output saved to the archive. Option #2 may
+     be used if this is considered an acceptable risk. It is not recommended to
+-    rely on option #3, though it will provide the functionality needed.
++    rely on option #4, though it will provide the functionality needed.
+     """
+ 
+     short_desc = 'Openshift Container Platform 4.x'
+@@ -65,7 +72,8 @@ class Openshift(Plugin, RedHatPlugin):
+                   desc='Path to a locally available kubeconfig file'),
+         PluginOpt('host', default='https://localhost:6443',
+                   desc='host address to use for oc login, including port'),
+-        PluginOpt('no-oc', default=True, desc='do not collect `oc` output'),
++        PluginOpt('with-api', default=False,
++                  desc='collect output from the OCP API'),
+         PluginOpt('podlogs', default=True, desc='collect logs from each pod'),
+         PluginOpt('podlogs-filter', default='', val_type=str,
+                   desc='only collect logs from pods matching this pattern'),
+@@ -212,7 +220,7 @@ class Openshift(Plugin, RedHatPlugin):
+         self.add_copy_spec('/etc/kubernetes/*')
+ 
+         # see if we run `oc` commands
+-        if not self.get_option('no-oc'):
++        if self.get_option('with-api'):
+             can_run_oc = self._check_oc_logged_in()
+         else:
+             can_run_oc = False
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2062908-tigervnc-update-collections.patch b/SOURCES/sos-bz2062908-tigervnc-update-collections.patch
new file mode 100644
index 0000000..f2767c9
--- /dev/null
+++ b/SOURCES/sos-bz2062908-tigervnc-update-collections.patch
@@ -0,0 +1,67 @@
+From 4c92968ce461cdfc6a5d913748b2ce4f148ff4a9 Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Thu, 10 Mar 2022 12:31:49 -0500
+Subject: [PATCH] [tigervnc] Update collections for newer versions of TigerVNC
+
+First, relaxes the file specifications for collection by capturing the
+entire `/etc/tigervnc/` directory.
+
+Second, adds collection of service status and journal output for each
+configured vnc server. Collection of `vncserver -list` is kept for
+backwards compatibility.
+
+Finally, add a short docstring for the plugin for --help output.
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/report/plugins/tigervnc.py | 28 +++++++++++++++++++++++-----
+ 1 file changed, 23 insertions(+), 5 deletions(-)
+
+diff --git a/sos/report/plugins/tigervnc.py b/sos/report/plugins/tigervnc.py
+index 1302f6d4..e31aee25 100644
+--- a/sos/report/plugins/tigervnc.py
++++ b/sos/report/plugins/tigervnc.py
+@@ -12,17 +12,35 @@ from sos.report.plugins import Plugin, RedHatPlugin
+ 
+ 
+ class TigerVNC(Plugin, RedHatPlugin):
++    """
++    This plugin gathers information for VNC servers provided by the tigervnc
++    package. This is explicitly for server-side collections, not clients.
++
++    By default, this plugin will capture the contents of /etc/tigervnc, which
++    may include usernames. If usernames are sensitive information for end
++    users of sos, consider using the `--clean` option to obfuscate these
++    names.
++    """
+ 
+     short_desc = 'TigerVNC server configuration'
+     plugin_name = 'tigervnc'
+     packages = ('tigervnc-server',)
+ 
+     def setup(self):
+-        self.add_copy_spec([
+-            '/etc/tigervnc/vncserver-config-defaults',
+-            '/etc/tigervnc/vncserver-config-mandatory',
+-            '/etc/tigervnc/vncserver.users'
+-        ])
++        self.add_copy_spec('/etc/tigervnc/')
++
++        # service names are 'vncserver@$port' where $port is :1,, :2, etc...
++        # however they are not reported via list-unit-files, only list-units
++        vncs = self.exec_cmd(
++            'systemctl list-units --type=service --no-legend vncserver*'
++        )
++        if vncs['status'] == 0:
++            for serv in vncs['output'].splitlines():
++                vnc = serv.split()
++                if not vnc:
++                    continue
++                self.add_service_status(vnc[0])
++                self.add_journal(vnc[0])
+ 
+         self.add_cmd_output('vncserver -list')
+ 
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2065805-collect-pacemaker-cluster.patch b/SOURCES/sos-bz2065805-collect-pacemaker-cluster.patch
new file mode 100644
index 0000000..d573ea2
--- /dev/null
+++ b/SOURCES/sos-bz2065805-collect-pacemaker-cluster.patch
@@ -0,0 +1,230 @@
+From 3b84b4ccfa9e4924a5a3829d3810568dfb69bf63 Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Fri, 18 Mar 2022 16:25:35 -0400
+Subject: [PATCH 1/2] [pacemaker] Redesign node enumeration logic
+
+It has been found that `pcs status` output is liable to change, which
+ends up breaking our parsing of node lists when using it on newer
+versions.
+
+Instead, first try to parse through `crm_mon` output, which is what `pcs
+status` uses under the hood, but as a stable and reliable xml format.
+
+Failing that, for example if the `--primary` node is not functioning as
+part of the cluster, source `/etc/corosync/corosync.conf` instead.
+
+Related: RHBZ2065805
+Related: RHBZ2065811
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/collector/clusters/pacemaker.py | 110 +++++++++++++++++++---------
+ 1 file changed, 76 insertions(+), 34 deletions(-)
+
+diff --git a/sos/collector/clusters/pacemaker.py b/sos/collector/clusters/pacemaker.py
+index 55024314..49d0ce51 100644
+--- a/sos/collector/clusters/pacemaker.py
++++ b/sos/collector/clusters/pacemaker.py
+@@ -8,7 +8,11 @@
+ #
+ # See the LICENSE file in the source distribution for further information.
+ 
++import re
++
+ from sos.collector.clusters import Cluster
++from setuptools._vendor.packaging import version
++from xml.etree import ElementTree
+ 
+ 
+ class pacemaker(Cluster):
+@@ -18,42 +22,80 @@ class pacemaker(Cluster):
+     packages = ('pacemaker',)
+     option_list = [
+         ('online', True, 'Collect nodes listed as online'),
+-        ('offline', True, 'Collect nodes listed as offline')
++        ('offline', True, 'Collect nodes listed as offline'),
++        ('only-corosync', False, 'Only use corosync.conf to enumerate nodes')
+     ]
+ 
+     def get_nodes(self):
+-        self.res = self.exec_primary_cmd('pcs status')
+-        if self.res['status'] != 0:
+-            self.log_error('Cluster status could not be determined. Is the '
+-                           'cluster running on this node?')
+-            return []
+-        if 'node names do not match' in self.res['output']:
+-            self.log_warn('Warning: node name mismatch reported. Attempts to '
+-                          'connect to some nodes may fail.\n')
+-        return self.parse_pcs_output()
+-
+-    def parse_pcs_output(self):
+-        nodes = []
+-        if self.get_option('online'):
+-            nodes += self.get_online_nodes()
+-        if self.get_option('offline'):
+-            nodes += self.get_offline_nodes()
+-        return nodes
+-
+-    def get_online_nodes(self):
+-        for line in self.res['output'].splitlines():
+-            if line.startswith('Online:'):
+-                nodes = line.split('[')[1].split(']')[0]
+-                return [n for n in nodes.split(' ') if n]
+-
+-    def get_offline_nodes(self):
+-        offline = []
+-        for line in self.res['output'].splitlines():
+-            if line.startswith('Node') and line.endswith('(offline)'):
+-                offline.append(line.split()[1].replace(':', ''))
+-            if line.startswith('OFFLINE:'):
+-                nodes = line.split('[')[1].split(']')[0]
+-                offline.extend([n for n in nodes.split(' ') if n])
+-        return offline
++        self.nodes = []
++        # try crm_mon first
++        try:
++            if not self.get_option('only-corosync'):
++                try:
++                    self.get_nodes_from_crm()
++                except Exception as err:
++                    self.log_warn("Falling back to sourcing corosync.conf. "
++                                  "Could not parse crm_mon output: %s" % err)
++            if not self.nodes:
++                # fallback to corosync.conf, in case the node we're inspecting
++                # is offline from the cluster
++                self.get_nodes_from_corosync()
++        except Exception as err:
++            self.log_error("Could not determine nodes from cluster: %s" % err)
++
++        _shorts = [n for n in self.nodes if '.' not in n]
++        if _shorts:
++            self.log_warn(
++                "WARNING: Node addresses '%s' may not resolve locally if you "
++                "are not running on a node in the cluster. Try using option "
++                "'-c pacemaker.only-corosync' if these connections fail."
++                % ','.join(_shorts)
++            )
++        return self.nodes
++
++    def get_nodes_from_crm(self):
++        """
++        Try to parse crm_mon output for node list and status.
++        """
++        xmlopt = '--output-as=xml'
++        # older pacemaker had a different option for xml output
++        _ver = self.exec_primary_cmd('crm_mon --version')
++        if _ver['status'] == 0:
++            cver = _ver['output'].split()[1].split('-')[0]
++            if not version.parse(cver) > version.parse('2.0.3'):
++                xmlopt = '--as-xml'
++        else:
++            return
++        _out = self.exec_primary_cmd(
++            "crm_mon --one-shot --inactive %s" % xmlopt,
++            need_root=True
++        )
++        if _out['status'] == 0:
++            self.parse_crm_xml(_out['output'])
++
++    def parse_crm_xml(self, xmlstring):
++        """
++        Parse the xml output string provided by crm_mon
++        """
++        _xml = ElementTree.fromstring(xmlstring)
++        nodes = _xml.find('nodes')
++        for node in nodes:
++            _node = node.attrib
++            if self.get_option('online') and _node['online'] == 'true':
++                self.nodes.append(_node['name'])
++            elif self.get_option('offline') and _node['online'] == 'false':
++                self.nodes.append(_node['name'])
++
++    def get_nodes_from_corosync(self):
++        """
++        As a fallback measure, read corosync.conf to get the node list. Note
++        that this prevents us from separating online nodes from offline nodes.
++        """
++        self.log_warn("WARNING: unable to distinguish online nodes from "
++                      "offline nodes when sourcing from corosync.conf")
++        cc = self.primary.read_file('/etc/corosync/corosync.conf')
++        nodes = re.findall(r'((\sring0_addr:)(.*))', cc)
++        for node in nodes:
++            self.nodes.append(node[-1].strip())
+ 
+ # vim: set et ts=4 sw=4 :
+-- 
+2.34.3
+
+
+From 6701a7d77ecc998b018b54ecc00f9fd102ae9518 Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Mon, 21 Mar 2022 12:05:59 -0400
+Subject: [PATCH 2/2] [clusters] Allow clusters to not add localhost to node
+ list
+
+For most of our supported clusters, we end up needing to add the
+local host executing `sos collect` to the node list (unless `--no-local`
+is used) as that accounts for the primary node that may otherwise be
+left off. However, this is not helpful for clusters that may reports
+node names as something other than resolveable names. In those cases,
+such as with pacemaker, adding the local hostname may result in
+duplicate collections.
+
+Add a toggle to cluster profiles via a new `strict_node_list` class attr
+that, if True, will skip this addition. This toggle is default `False`
+to preserve existing behavior, and is now enabled for `pacemaker`
+specifically.
+
+Related: RHBZ#2065821
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/collector/__init__.py           | 3 ++-
+ sos/collector/clusters/__init__.py  | 4 ++++
+ sos/collector/clusters/pacemaker.py | 1 +
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py
+index a8bb0064..d898ca34 100644
+--- a/sos/collector/__init__.py
++++ b/sos/collector/__init__.py
+@@ -1073,7 +1073,8 @@ class SoSCollector(SoSComponent):
+             for node in self.node_list:
+                 if host == node.split('.')[0]:
+                     self.node_list.remove(node)
+-            self.node_list.append(self.hostname)
++            if not self.cluster.strict_node_list:
++                self.node_list.append(self.hostname)
+         self.reduce_node_list()
+         try:
+             _node_max = len(max(self.node_list, key=len))
+diff --git a/sos/collector/clusters/__init__.py b/sos/collector/clusters/__init__.py
+index f3f550ad..f00677b8 100644
+--- a/sos/collector/clusters/__init__.py
++++ b/sos/collector/clusters/__init__.py
+@@ -57,6 +57,10 @@ class Cluster():
+     sos_plugin_options = {}
+     sos_preset = ''
+     cluster_name = None
++    # set this to True if the local host running collect should *not* be
++    # forcibly added to the node list. This can be helpful in situations where
++    # the host's fqdn and the name the cluster uses are different
++    strict_node_list = False
+ 
+     def __init__(self, commons):
+         self.primary = None
+diff --git a/sos/collector/clusters/pacemaker.py b/sos/collector/clusters/pacemaker.py
+index 49d0ce51..bebcb265 100644
+--- a/sos/collector/clusters/pacemaker.py
++++ b/sos/collector/clusters/pacemaker.py
+@@ -20,6 +20,7 @@ class pacemaker(Cluster):
+     cluster_name = 'Pacemaker High Availability Cluster Manager'
+     sos_plugins = ['pacemaker']
+     packages = ('pacemaker',)
++    strict_node_list = True
+     option_list = [
+         ('online', True, 'Collect nodes listed as online'),
+         ('offline', True, 'Collect nodes listed as offline'),
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2079187-honor-default-plugin-timeout.patch b/SOURCES/sos-bz2079187-honor-default-plugin-timeout.patch
new file mode 100644
index 0000000..822565d
--- /dev/null
+++ b/SOURCES/sos-bz2079187-honor-default-plugin-timeout.patch
@@ -0,0 +1,39 @@
+From 7069e99d1c5c443f96a98a7ed6db67fa14683e67 Mon Sep 17 00:00:00 2001
+From: Pavel Moravec <pmoravec@redhat.com>
+Date: Thu, 17 Feb 2022 09:14:15 +0100
+Subject: [PATCH] [report] Honor plugins' hardcoded plugin_timeout
+
+Currently, plugin's plugin_timeout hardcoded default is superseded by
+whatever --plugin-timeout value, even when this option is not used and
+we eval it to TIMEOUT_DEFAULT.
+
+In this case of not setting --plugin-timeout either -k plugin.timeout,
+honour plugin's plugin_timeout instead.
+
+Resolves: #2863
+Closes: #2864
+
+Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
+---
+ sos/report/plugins/__init__.py | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py
+index cc5cb65b..336b4d22 100644
+--- a/sos/report/plugins/__init__.py
++++ b/sos/report/plugins/__init__.py
+@@ -636,7 +636,10 @@ class Plugin():
+             if opt_timeout is None:
+                 _timeout = own_timeout
+             elif opt_timeout is not None and own_timeout == -1:
+-                _timeout = int(opt_timeout)
++                if opt_timeout == TIMEOUT_DEFAULT:
++                    _timeout = default_timeout
++                else:
++                    _timeout = int(opt_timeout)
+             elif opt_timeout is not None and own_timeout > -1:
+                 _timeout = own_timeout
+             else:
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2079484-list-plugins-ignore-options.patch b/SOURCES/sos-bz2079484-list-plugins-ignore-options.patch
new file mode 100644
index 0000000..f0bda41
--- /dev/null
+++ b/SOURCES/sos-bz2079484-list-plugins-ignore-options.patch
@@ -0,0 +1,68 @@
+From f3dc8cd574614572d441f76c02453fd85d0c57e2 Mon Sep 17 00:00:00 2001
+From: Jake Hunsaker <jhunsake@redhat.com>
+Date: Wed, 27 Apr 2022 10:40:55 -0400
+Subject: [PATCH] [report] --list-plugins should report used, not default,
+ option values
+
+When using `--list-plugins`, sos should report the values that will be
+used in a given command, or with a given config file, not what the
+default values are.
+
+By reporting the set value, users can be sure their configuration or
+commandline settings are being honored correctly before executing a
+report collection.
+
+Closes: #2921
+
+Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
+---
+ sos/report/__init__.py | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/sos/report/__init__.py b/sos/report/__init__.py
+index 74c7973a..8735c903 100644
+--- a/sos/report/__init__.py
++++ b/sos/report/__init__.py
+@@ -868,24 +868,32 @@ class SoSReport(SoSComponent):
+             _defaults = self.loaded_plugins[0][1].get_default_plugin_opts()
+             for _opt in _defaults:
+                 opt = _defaults[_opt]
+-                val = opt.default
+-                if opt.default == -1:
+-                    val = TIMEOUT_DEFAULT
++                val = opt.value
++                if opt.value == -1:
++                    if _opt == 'timeout':
++                        val = self.opts.plugin_timeout or TIMEOUT_DEFAULT
++                    elif _opt == 'cmd-timeout':
++                        val = self.opts.cmd_timeout or TIMEOUT_DEFAULT
++                    else:
++                        val = TIMEOUT_DEFAULT
++                if opt.name == 'postproc':
++                    val = not self.opts.no_postproc
+                 self.ui_log.info(" %-25s %-15s %s" % (opt.name, val, opt.desc))
+             self.ui_log.info("")
+ 
+             self.ui_log.info(_("The following plugin options are available:"))
+             for opt in self.all_options:
+                 if opt.name in ('timeout', 'postproc', 'cmd-timeout'):
+-                    continue
++                    if opt.value == opt.default:
++                        continue
+                 # format option value based on its type (int or bool)
+-                if isinstance(opt.default, bool):
+-                    if opt.default is True:
++                if isinstance(opt.value, bool):
++                    if opt.value is True:
+                         tmpopt = "on"
+                     else:
+                         tmpopt = "off"
+                 else:
+-                    tmpopt = opt.default
++                    tmpopt = opt.value
+ 
+                 if tmpopt is None:
+                     tmpopt = 0
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2079485-plugopts-valtype-str.patch b/SOURCES/sos-bz2079485-plugopts-valtype-str.patch
new file mode 100644
index 0000000..eaf42ab
--- /dev/null
+++ b/SOURCES/sos-bz2079485-plugopts-valtype-str.patch
@@ -0,0 +1,34 @@
+From 9b10abcdd4aaa41e2549438d5bc52ece86dcb21f Mon Sep 17 00:00:00 2001
+From: Pavel Moravec <pmoravec@redhat.com>
+Date: Sat, 7 May 2022 14:23:04 +0200
+Subject: [PATCH] [plugins] Allow 'str' PlugOpt type to accept any value
+
+For PlugOpt type 'str', we should allow any content including e.g.
+numbers, and interpret it as a string.
+
+Resolves: #2922
+Closes: #2935
+
+Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
+---
+ sos/report/plugins/__init__.py | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py
+index d6be42b9..2a42e6b0 100644
+--- a/sos/report/plugins/__init__.py
++++ b/sos/report/plugins/__init__.py
+@@ -452,6 +452,10 @@ class PluginOpt():
+         return self.__str__()
+ 
+     def set_value(self, val):
++        # 'str' type accepts any value, incl. numbers
++        if type('') in self.val_type:
++            self.value = str(val)
++            return
+         if not any([type(val) == _t for _t in self.val_type]):
+             valid = []
+             for t in self.val_type:
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2079486-timeouted-exec-cmd-exception.patch b/SOURCES/sos-bz2079486-timeouted-exec-cmd-exception.patch
new file mode 100644
index 0000000..dc58a67
--- /dev/null
+++ b/SOURCES/sos-bz2079486-timeouted-exec-cmd-exception.patch
@@ -0,0 +1,31 @@
+From 5e27b92a8a9f066af4c41ddd0bedc7c69187ff52 Mon Sep 17 00:00:00 2001
+From: Pavel Moravec <pmoravec@redhat.com>
+Date: Mon, 2 May 2022 22:13:34 +0200
+Subject: [PATCH] [utilities] Close file only when storing to file
+
+Call _output.close() only when to_file=true.
+
+Closes: #2925
+
+Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
+---
+ sos/utilities.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sos/utilities.py b/sos/utilities.py
+index d2f73d86..1075d1d4 100644
+--- a/sos/utilities.py
++++ b/sos/utilities.py
+@@ -212,7 +212,8 @@ def sos_get_command_output(command, timeout=TIMEOUT_DEFAULT, stderr=False,
+                 p.wait(timeout if timeout else None)
+             except Exception:
+                 p.terminate()
+-                _output.close()
++                if to_file:
++                    _output.close()
+                 # until we separate timeouts from the `timeout` command
+                 # handle per-cmd timeouts via Plugin status checks
+                 return {'status': 124, 'output': reader.get_contents(),
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2092969-openshift-ovn-disabled.patch b/SOURCES/sos-bz2092969-openshift-ovn-disabled.patch
new file mode 100644
index 0000000..29241ba
--- /dev/null
+++ b/SOURCES/sos-bz2092969-openshift-ovn-disabled.patch
@@ -0,0 +1,73 @@
+From c2e66fa4dae51f03c7310ba5278897ddecac1aad Mon Sep 17 00:00:00 2001
+From: Nadia Pinaeva <npinaeva@redhat.com>
+Date: Thu, 2 Jun 2022 15:43:09 +0200
+Subject: [PATCH] crio: switch from parsing output in table format to json
+
+Signed-off-by: Nadia Pinaeva <npinaeva@redhat.com>
+---
+ sos/policies/runtimes/crio.py | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+diff --git a/sos/policies/runtimes/crio.py b/sos/policies/runtimes/crio.py
+index 55082d07..4cae1ecc 100644
+--- a/sos/policies/runtimes/crio.py
++++ b/sos/policies/runtimes/crio.py
+@@ -7,6 +7,7 @@
+ # version 2 of the GNU General Public License.
+ #
+ # See the LICENSE file in the source distribution for further information.
++import json
+ 
+ from sos.policies.runtimes import ContainerRuntime
+ from sos.utilities import sos_get_command_output
+@@ -29,14 +30,15 @@ class CrioContainerRuntime(ContainerRuntime):
+         :type get_all: ``bool``
+         """
+         containers = []
+-        _cmd = "%s ps %s" % (self.binary, '-a' if get_all else '')
++        _cmd = "%s ps %s -o json" % (self.binary, '-a' if get_all else '')
+         if self.active:
+             out = sos_get_command_output(_cmd, chroot=self.policy.sysroot)
+-            if out['status'] == 0:
+-                for ent in out['output'].splitlines()[1:]:
+-                    ent = ent.split()
++            if out["status"] == 0:
++                out_json = json.loads(out["output"])
++                for container in out_json["containers"]:
+                     # takes the form (container_id, container_name)
+-                    containers.append((ent[0], ent[-3]))
++                    containers.append(
++                        (container["id"], container["metadata"]["name"]))
+         return containers
+ 
+     def get_images(self):
+@@ -47,13 +49,21 @@ class CrioContainerRuntime(ContainerRuntime):
+         """
+         images = []
+         if self.active:
+-            out = sos_get_command_output("%s images" % self.binary,
++            out = sos_get_command_output("%s images -o json" % self.binary,
+                                          chroot=self.policy.sysroot)
+             if out['status'] == 0:
+-                for ent in out['output'].splitlines():
+-                    ent = ent.split()
+-                    # takes the form (image_name, image_id)
+-                    images.append((ent[0] + ':' + ent[1], ent[2]))
++                out_json = json.loads(out["output"])
++                for image in out_json["images"]:
++                    # takes the form (repository:tag, image_id)
++                    if len(image["repoTags"]) > 0:
++                        for repo_tag in image["repoTags"]:
++                            images.append((repo_tag, image["id"]))
++                    else:
++                        if len(image["repoDigests"]) == 0:
++                            image_name = "<none>"
++                        else:
++                            image_name = image["repoDigests"][0].split("@")[0]
++                        images.append((image_name + ":<none>", image["id"]))
+         return images
+ 
+     def fmt_container_cmd(self, container, cmd, quotecmd):
+-- 
+2.34.3
+
diff --git a/SOURCES/sos-bz2095263-ovirt-answer-files-passwords.patch b/SOURCES/sos-bz2095263-ovirt-answer-files-passwords.patch
new file mode 100644
index 0000000..67eb6a0
--- /dev/null
+++ b/SOURCES/sos-bz2095263-ovirt-answer-files-passwords.patch
@@ -0,0 +1,66 @@
+From 5fd872c64c53af37015f366295e0c2418c969757 Mon Sep 17 00:00:00 2001
+From: Yedidyah Bar David <didi@redhat.com>
+Date: Thu, 26 May 2022 16:43:21 +0300
+Subject: [PATCH] [ovirt] answer files: Filter out all password keys
+
+Instead of hard-coding specific keys and having to maintain them over
+time, replace the values of all keys that have 'password' in their name.
+I think this covers all our current and hopefully future keys. It might
+add "false positives" - keys that are not passwords but have 'password'
+in their name - and I think that's a risk worth taking.
+
+Sadly, the engine admin password prompt's name is
+'OVESETUP_CONFIG_ADMIN_SETUP', which does not include 'password', so has
+to be listed specifically.
+
+A partial list of keys added since the replaced code was written:
+- grafana-related stuff
+- keycloak-related stuff
+- otopi-style answer files
+
+Signed-off-by: Yedidyah Bar David <didi@redhat.com>
+Change-Id: I416c6e4078e7c3638493eb271d08d73a0c22b5ba
+---
+ sos/report/plugins/ovirt.py | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+diff --git a/sos/report/plugins/ovirt.py b/sos/report/plugins/ovirt.py
+index 09647bf1..3b1bb29b 100644
+--- a/sos/report/plugins/ovirt.py
++++ b/sos/report/plugins/ovirt.py
+@@ -241,19 +241,22 @@ class Ovirt(Plugin, RedHatPlugin):
+                 r'{key}=********'.format(key=key)
+             )
+ 
+-        # Answer files contain passwords
+-        for key in (
+-            'OVESETUP_CONFIG/adminPassword',
+-            'OVESETUP_CONFIG/remoteEngineHostRootPassword',
+-            'OVESETUP_DWH_DB/password',
+-            'OVESETUP_DB/password',
+-            'OVESETUP_REPORTS_CONFIG/adminPassword',
+-            'OVESETUP_REPORTS_DB/password',
++        # Answer files contain passwords.
++        # Replace all keys that have 'password' in them, instead of hard-coding
++        # here the list of keys, which changes between versions.
++        # Sadly, the engine admin password prompt name does not contain
++        # 'password'... so neither does the env key.
++        for item in (
++            'password',
++            'OVESETUP_CONFIG_ADMIN_SETUP',
+         ):
+             self.do_path_regex_sub(
+                 r'/var/lib/ovirt-engine/setup/answers/.*',
+-                r'{key}=(.*)'.format(key=key),
+-                r'{key}=********'.format(key=key)
++                re.compile(
++                    r'(?P<key>[^=]*{item}[^=]*)=.*'.format(item=item),
++                    flags=re.IGNORECASE
++                ),
++                r'\g<key>=********'
+             )
+ 
+         # aaa profiles contain passwords
+-- 
+2.34.3
+
diff --git a/SPECS/sos.spec b/SPECS/sos.spec
index 2d2535a..ad1a715 100644
--- a/SPECS/sos.spec
+++ b/SPECS/sos.spec
@@ -5,7 +5,7 @@
 Summary: A set of tools to gather troubleshooting information from a system
 Name: sos
 Version: 4.3
-Release: 1%{?dist}
+Release: 2%{?dist}
 Group: Applications/System
 Source0: https://github.com/sosreport/sos/archive/%{version}/sos-%{version}.tar.gz
 Source1: sos-audit-%{auditversion}.tgz
@@ -22,6 +22,16 @@ Obsoletes: sos-collector
 Recommends: python3-pexpect
 Recommends: python3-requests
 Patch1: sos-bz2055002-rebase-sos-add-sos-help.patch
+Patch2: sos-bz2095263-ovirt-answer-files-passwords.patch
+Patch3: sos-bz2079485-plugopts-valtype-str.patch
+Patch4: sos-bz2062908-tigervnc-update-collections.patch
+Patch5: sos-bz2065805-collect-pacemaker-cluster.patch
+Patch6: sos-bz2079187-honor-default-plugin-timeout.patch
+Patch7: sos-bz2079484-list-plugins-ignore-options.patch
+Patch8: sos-bz2079486-timeouted-exec-cmd-exception.patch
+Patch9: sos-bz2058279-ocp-backports.patch
+Patch10: sos-bz2092969-openshift-ovn-disabled.patch
+
 
 %description
 Sos is a set of tools that gathers information about system
@@ -33,6 +43,16 @@ support technicians and developers.
 %setup -qn %{name}-%{version}
 %setup -T -D -a1 -q
 %patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+
 
 %build
 %py3_build
@@ -100,6 +120,26 @@ of the system. Currently storage and filesystem commands are audited.
 %ghost /etc/audit/rules.d/40-sos-storage.rules
 
 %changelog
+* Thu Jun 16 2022 Pavel Moravec <pmoravec@redhat.com> = 4.3-2
+- [ovirt] answer files: Filter out all password keys
+  Resolves: bz2095263
+- [plugins] Allow 'str' PlugOpt type to accept any value
+  Resolves: bz2079485
+- [tigervnc] Update collections for newer versions of TigerVNC
+  Resolves: bz2062908
+- [pacemaker] Redesign node enumeration logic
+  Resolves: bz2065805
+- crio: switch from parsing output in table format to json
+  Resolves: bz2092969
+- [report] Honor plugins' hardcoded plugin_timeout
+  Resolves: bz2079187
+- [report] --list-plugins should report used, not default,
+  Resolves: bz2079484
+- [utilities] Close file only when storing to file
+  Resolves: bz2079486
+- [presets] Adjust OCP preset options, more OCP backports
+  Resolves: bz2058279
+
 * Mon Apr 04 2022 Pavel Moravec <pmoravec@redhat.com> = 4.3-1
 - Rebase on upstream 4.3
   Resolves: bz2055002