diff --git a/SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch b/SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch
new file mode 100644
index 0000000..93d922f
--- /dev/null
+++ b/SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch
@@ -0,0 +1,516 @@
+From 1176a788c23697099093b4d8a9a21f10f71ebb12 Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 1 Feb 2023 10:47:07 +0100
+Subject: [PATCH] Allow growpart to resize encrypted partitions (#1316)
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2166245
+
+commit d95a331d1035d52443c470e0c00765a2c2b271cc
+Author: James Falcon <james.falcon@canonical.com>
+Date:   Tue Apr 26 19:03:13 2022 -0500
+
+    Allow growpart to resize encrypted partitions (#1316)
+
+    Adds the ability for growpart to resize a LUKS formatted partition.
+    This involves resizing the underlying partition as well as the
+    filesystem. 'cryptsetup' is used for resizing.
+
+    This relies on a file present at /cc_growpart_keydata containing
+    json formatted 'key' and 'slot' keys, with the key being
+    base64 encoded. After resize, cloud-init will destroy
+    the luks slot used for resizing and remove the key file.
+
+Conflicts:
+	cloudinit/config/cc_growpart.py (includes only)
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+---
+ cloudinit/config/cc_growpart.py            | 171 +++++++++++++++-
+ test-requirements.txt                      |   1 +
+ tests/unittests/config/test_cc_growpart.py | 228 +++++++++++++++++++++
+ tox.ini                                    |   1 +
+ 4 files changed, 400 insertions(+), 1 deletion(-)
+
+diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py
+index 43334caa..bdf17aba 100644
+--- a/cloudinit/config/cc_growpart.py
++++ b/cloudinit/config/cc_growpart.py
+@@ -64,10 +64,16 @@ growpart is::
+         ignore_growroot_disabled: <true/false>
+ """
+ 
++import base64
++import copy
++import json
+ import os
+ import os.path
+ import re
+ import stat
++from contextlib import suppress
++from pathlib import Path
++from typing import Tuple
+ 
+ from cloudinit import log as logging
+ from cloudinit import subp, temp_utils, util
+@@ -81,6 +87,8 @@ DEFAULT_CONFIG = {
+     "ignore_growroot_disabled": False,
+ }
+ 
++KEYDATA_PATH = Path("/cc_growpart_keydata")
++
+ 
+ class RESIZE(object):
+     SKIPPED = "SKIPPED"
+@@ -289,10 +297,128 @@ def devent2dev(devent):
+     return dev
+ 
+ 
++def get_mapped_device(blockdev):
++    """Returns underlying block device for a mapped device.
++
++    If it is mapped, blockdev will usually take the form of
++    /dev/mapper/some_name
++
++    If blockdev is a symlink pointing to a /dev/dm-* device, return
++    the device pointed to. Otherwise, return None.
++    """
++    realpath = os.path.realpath(blockdev)
++    if realpath.startswith("/dev/dm-"):
++        LOG.debug("%s is a mapped device pointing to %s", blockdev, realpath)
++        return realpath
++    return None
++
++
++def is_encrypted(blockdev, partition) -> bool:
++    """
++    Check if a device is an encrypted device. blockdev should have
++    a /dev/dm-* path whereas partition is something like /dev/sda1.
++    """
++    if not subp.which("cryptsetup"):
++        LOG.debug("cryptsetup not found. Assuming no encrypted partitions")
++        return False
++    try:
++        subp.subp(["cryptsetup", "status", blockdev])
++    except subp.ProcessExecutionError as e:
++        if e.exit_code == 4:
++            LOG.debug("Determined that %s is not encrypted", blockdev)
++        else:
++            LOG.warning(
++                "Received unexpected exit code %s from "
++                "cryptsetup status. Assuming no encrypted partitions.",
++                e.exit_code,
++            )
++        return False
++    with suppress(subp.ProcessExecutionError):
++        subp.subp(["cryptsetup", "isLuks", partition])
++        LOG.debug("Determined that %s is encrypted", blockdev)
++        return True
++    return False
++
++
++def get_underlying_partition(blockdev):
++    command = ["dmsetup", "deps", "--options=devname", blockdev]
++    dep: str = subp.subp(command)[0]  # type: ignore
++    # Returned result should look something like:
++    # 1 dependencies : (vdb1)
++    if not dep.startswith("1 depend"):
++        raise RuntimeError(
++            f"Expecting '1 dependencies' from 'dmsetup'. Received: {dep}"
++        )
++    try:
++        return f'/dev/{dep.split(": (")[1].split(")")[0]}'
++    except IndexError as e:
++        raise RuntimeError(
++            f"Ran `{command}`, but received unexpected stdout: `{dep}`"
++        ) from e
++
++
++def resize_encrypted(blockdev, partition) -> Tuple[str, str]:
++    """Use 'cryptsetup resize' to resize LUKS volume.
++
++    The loaded keyfile is json formatted with 'key' and 'slot' keys.
++    key is base64 encoded. Example:
++    {"key":"XFmCwX2FHIQp0LBWaLEMiHIyfxt1SGm16VvUAVledlY=","slot":5}
++    """
++    if not KEYDATA_PATH.exists():
++        return (RESIZE.SKIPPED, "No encryption keyfile found")
++    try:
++        with KEYDATA_PATH.open() as f:
++            keydata = json.load(f)
++        key = keydata["key"]
++        decoded_key = base64.b64decode(key)
++        slot = keydata["slot"]
++    except Exception as e:
++        raise RuntimeError(
++            "Could not load encryption key. This is expected if "
++            "the volume has been previously resized."
++        ) from e
++
++    try:
++        subp.subp(
++            ["cryptsetup", "--key-file", "-", "resize", blockdev],
++            data=decoded_key,
++        )
++    finally:
++        try:
++            subp.subp(
++                [
++                    "cryptsetup",
++                    "luksKillSlot",
++                    "--batch-mode",
++                    partition,
++                    str(slot),
++                ]
++            )
++        except subp.ProcessExecutionError as e:
++            LOG.warning(
++                "Failed to kill luks slot after resizing encrypted volume: %s",
++                e,
++            )
++        try:
++            KEYDATA_PATH.unlink()
++        except Exception:
++            util.logexc(
++                LOG, "Failed to remove keyfile after resizing encrypted volume"
++            )
++
++    return (
++        RESIZE.CHANGED,
++        f"Successfully resized encrypted volume '{blockdev}'",
++    )
++
++
+ def resize_devices(resizer, devices):
+     # returns a tuple of tuples containing (entry-in-devices, action, message)
++    devices = copy.copy(devices)
+     info = []
+-    for devent in devices:
++
++    while devices:
++        devent = devices.pop(0)
+         try:
+             blockdev = devent2dev(devent)
+         except ValueError as e:
+@@ -329,6 +455,49 @@ def resize_devices(resizer, devices):
+             )
+             continue
+ 
++        underlying_blockdev = get_mapped_device(blockdev)
++        if underlying_blockdev:
++            try:
++                # We need to resize the underlying partition first
++                partition = get_underlying_partition(blockdev)
++                if is_encrypted(underlying_blockdev, partition):
++                    if partition not in [x[0] for x in info]:
++                        # We shouldn't attempt to resize this mapped partition
++                        # until the underlying partition is resized, so re-add
++                        # our device to the beginning of the list we're
++                        # iterating over, then add our underlying partition
++                        # so it can get processed first
++                        devices.insert(0, devent)
++                        devices.insert(0, partition)
++                        continue
++                    status, message = resize_encrypted(blockdev, partition)
++                    info.append(
++                        (
++                            devent,
++                            status,
++                            message,
++                        )
++                    )
++                else:
++                    info.append(
++                        (
++                            devent,
++                            RESIZE.SKIPPED,
++                            f"Resizing mapped device ({blockdev}) skipped "
++                            "as it is not encrypted.",
++                        )
++                    )
++            except Exception as e:
++                info.append(
++                    (
++                        devent,
++                        RESIZE.FAILED,
++                        f"Resizing encrypted device ({blockdev}) failed: {e}",
++                    )
++                )
++            # At this point, we WON'T resize a non-encrypted mapped device
++            # though we should probably grow the ability to
++            continue
+         try:
+             (disk, ptnum) = device_part_info(blockdev)
+         except (TypeError, ValueError) as e:
+diff --git a/test-requirements.txt b/test-requirements.txt
+index 06dfbbec..7160416a 100644
+--- a/test-requirements.txt
++++ b/test-requirements.txt
+@@ -2,6 +2,7 @@
+ httpretty>=0.7.1
+ pytest
+ pytest-cov
++pytest-mock
+ 
+ # Only really needed on older versions of python
+ setuptools
+diff --git a/tests/unittests/config/test_cc_growpart.py b/tests/unittests/config/test_cc_growpart.py
+index ba66f136..7d4e2629 100644
+--- a/tests/unittests/config/test_cc_growpart.py
++++ b/tests/unittests/config/test_cc_growpart.py
+@@ -8,6 +8,7 @@ import shutil
+ import stat
+ import unittest
+ from contextlib import ExitStack
++from itertools import chain
+ from unittest import mock
+ 
+ from cloudinit import cloud, subp, temp_utils
+@@ -342,6 +343,233 @@ class TestResize(unittest.TestCase):
+             os.stat = real_stat
+ 
+ 
++class TestEncrypted:
++    """Attempt end-to-end scenarios using encrypted devices.
++
++    Things are mocked such that:
++     - "/fake_encrypted" is mounted onto "/dev/mapper/fake"
++     - "/dev/mapper/fake" is a LUKS device and symlinked to /dev/dm-1
++     - The partition backing "/dev/mapper/fake" is "/dev/vdx1"
++     - "/" is not encrypted and mounted onto "/dev/vdz1"
++
++    Note that we don't (yet) support non-encrypted mapped drives, such
++    as LVM volumes. If our mount point is /dev/mapper/*, then we will
++    not resize it if it is not encrypted.
++    """
++
++    def _subp_side_effect(self, value, good=True, **kwargs):
++        if value[0] == "dmsetup":
++            return ("1 dependencies : (vdx1)",)
++        return mock.Mock()
++
++    def _device_part_info_side_effect(self, value):
++        if value.startswith("/dev/mapper/"):
++            raise TypeError(f"{value} not a partition")
++        return (1024, 1024)
++
++    def _devent2dev_side_effect(self, value):
++        if value == "/fake_encrypted":
++            return "/dev/mapper/fake"
++        elif value == "/":
++            return "/dev/vdz"
++        elif value.startswith("/dev"):
++            return value
++        raise Exception(f"unexpected value {value}")
++
++    def _realpath_side_effect(self, value):
++        return "/dev/dm-1" if value.startswith("/dev/mapper") else value
++
++    def assert_resize_and_cleanup(self):
++        all_subp_args = list(
++            chain(*[args[0][0] for args in self.m_subp.call_args_list])
++        )
++        assert "resize" in all_subp_args
++        assert "luksKillSlot" in all_subp_args
++        self.m_unlink.assert_called_once()
++
++    def assert_no_resize_or_cleanup(self):
++        all_subp_args = list(
++            chain(*[args[0][0] for args in self.m_subp.call_args_list])
++        )
++        assert "resize" not in all_subp_args
++        assert "luksKillSlot" not in all_subp_args
++        self.m_unlink.assert_not_called()
++
++    @pytest.fixture
++    def common_mocks(self, mocker):
++        # These are all "happy path" mocks which will get overridden
++        # when needed
++        mocker.patch(
++            "cloudinit.config.cc_growpart.device_part_info",
++            side_effect=self._device_part_info_side_effect,
++        )
++        mocker.patch("os.stat")
++        mocker.patch("stat.S_ISBLK")
++        mocker.patch("stat.S_ISCHR")
++        mocker.patch(
++            "cloudinit.config.cc_growpart.devent2dev",
++            side_effect=self._devent2dev_side_effect,
++        )
++        mocker.patch(
++            "os.path.realpath", side_effect=self._realpath_side_effect
++        )
++        # Only place subp.which is used in cc_growpart is for cryptsetup
++        mocker.patch(
++            "cloudinit.config.cc_growpart.subp.which",
++            return_value="/usr/sbin/cryptsetup",
++        )
++        self.m_subp = mocker.patch(
++            "cloudinit.config.cc_growpart.subp.subp",
++            side_effect=self._subp_side_effect,
++        )
++        mocker.patch(
++            "pathlib.Path.open",
++            new_callable=mock.mock_open,
++            read_data=(
++                '{"key":"XFmCwX2FHIQp0LBWaLEMiHIyfxt1SGm16VvUAVledlY=",'
++                '"slot":5}'
++            ),
++        )
++        mocker.patch("pathlib.Path.exists", return_value=True)
++        self.m_unlink = mocker.patch("pathlib.Path.unlink", autospec=True)
++
++        self.resizer = mock.Mock()
++        self.resizer.resize = mock.Mock(return_value=(1024, 1024))
++
++    def test_resize_when_encrypted(self, common_mocks, caplog):
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++        assert len(info) == 2
++        assert info[0][0] == "/dev/vdx1"
++        assert info[0][2].startswith("no change necessary")
++        assert info[1][0] == "/fake_encrypted"
++        assert (
++            info[1][2]
++            == "Successfully resized encrypted volume '/dev/mapper/fake'"
++        )
++        assert (
++            "/dev/mapper/fake is a mapped device pointing to /dev/dm-1"
++            in caplog.text
++        )
++        assert "Determined that /dev/dm-1 is encrypted" in caplog.text
++
++        self.assert_resize_and_cleanup()
++
++    def test_resize_when_unencrypted(self, common_mocks):
++        info = cc_growpart.resize_devices(self.resizer, ["/"])
++        assert len(info) == 1
++        assert info[0][0] == "/"
++        assert "encrypted" not in info[0][2]
++        self.assert_no_resize_or_cleanup()
++
++    def test_encrypted_but_cryptsetup_not_found(
++        self, common_mocks, mocker, caplog
++    ):
++        mocker.patch(
++            "cloudinit.config.cc_growpart.subp.which",
++            return_value=None,
++        )
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++
++        assert len(info) == 1
++        assert "skipped as it is not encrypted" in info[0][2]
++        assert "cryptsetup not found" in caplog.text
++        self.assert_no_resize_or_cleanup()
++
++    def test_dmsetup_not_found(self, common_mocks, mocker, caplog):
++        def _subp_side_effect(value, **kwargs):
++            if value[0] == "dmsetup":
++                raise subp.ProcessExecutionError()
++
++        mocker.patch(
++            "cloudinit.config.cc_growpart.subp.subp",
++            side_effect=_subp_side_effect,
++        )
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++        assert len(info) == 1
++        assert info[0][0] == "/fake_encrypted"
++        assert info[0][1] == "FAILED"
++        assert (
++            "Resizing encrypted device (/dev/mapper/fake) failed" in info[0][2]
++        )
++        self.assert_no_resize_or_cleanup()
++
++    def test_unparsable_dmsetup(self, common_mocks, mocker, caplog):
++        def _subp_side_effect(value, **kwargs):
++            if value[0] == "dmsetup":
++                return ("2 dependencies",)
++            return mock.Mock()
++
++        mocker.patch(
++            "cloudinit.config.cc_growpart.subp.subp",
++            side_effect=_subp_side_effect,
++        )
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++        assert len(info) == 1
++        assert info[0][0] == "/fake_encrypted"
++        assert info[0][1] == "FAILED"
++        assert (
++            "Resizing encrypted device (/dev/mapper/fake) failed" in info[0][2]
++        )
++        self.assert_no_resize_or_cleanup()
++
++    def test_missing_keydata(self, common_mocks, mocker, caplog):
++        # Note that this will be standard behavior after first boot
++        # on a system with an encrypted root partition
++        mocker.patch("pathlib.Path.open", side_effect=FileNotFoundError())
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++        assert len(info) == 2
++        assert info[0][0] == "/dev/vdx1"
++        assert info[0][2].startswith("no change necessary")
++        assert info[1][0] == "/fake_encrypted"
++        assert info[1][1] == "FAILED"
++        assert (
++            info[1][2]
++            == "Resizing encrypted device (/dev/mapper/fake) failed: Could "
++            "not load encryption key. This is expected if the volume has "
++            "been previously resized."
++        )
++        self.assert_no_resize_or_cleanup()
++
++    def test_resize_failed(self, common_mocks, mocker, caplog):
++        def _subp_side_effect(value, **kwargs):
++            if value[0] == "dmsetup":
++                return ("1 dependencies : (vdx1)",)
++            elif value[0] == "cryptsetup" and "resize" in value:
++                raise subp.ProcessExecutionError()
++            return mock.Mock()
++
++        self.m_subp = mocker.patch(
++            "cloudinit.config.cc_growpart.subp.subp",
++            side_effect=_subp_side_effect,
++        )
++
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++        assert len(info) == 2
++        assert info[0][0] == "/dev/vdx1"
++        assert info[0][2].startswith("no change necessary")
++        assert info[1][0] == "/fake_encrypted"
++        assert info[1][1] == "FAILED"
++        assert (
++            "Resizing encrypted device (/dev/mapper/fake) failed" in info[1][2]
++        )
++        # Assert we still cleanup
++        all_subp_args = list(
++            chain(*[args[0][0] for args in self.m_subp.call_args_list])
++        )
++        assert "luksKillSlot" in all_subp_args
++        self.m_unlink.assert_called_once()
++
++    def test_resize_skipped(self, common_mocks, mocker, caplog):
++        mocker.patch("pathlib.Path.exists", return_value=False)
++        info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"])
++        assert len(info) == 2
++        assert info[1] == (
++            "/fake_encrypted",
++            "SKIPPED",
++            "No encryption keyfile found",
++        )
++
++
+ def simple_device_part_info(devpath):
+     # simple stupid return (/dev/vda, 1) for /dev/vda
+     ret = re.search("([^0-9]*)([0-9]*)$", devpath)
+diff --git a/tox.ini b/tox.ini
+index c494cb94..04a206f2 100644
+--- a/tox.ini
++++ b/tox.ini
+@@ -108,6 +108,7 @@ deps =
+     # test-requirements
+     pytest==3.3.2
+     pytest-cov==2.5.1
++    pytest-mock==1.7.1
+     # Needed by pytest and default causes failures
+     attrs==17.4.0
+ 
+-- 
+2.39.1
+
diff --git a/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch b/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch
index 43a9ae4..cd93ee6 100644
--- a/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch
+++ b/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch
@@ -1,17 +1,10 @@
-From 799ef819e75bdddbf4e983e6990a6a6a51c61bdb Mon Sep 17 00:00:00 2001
+From 14d1952c17637b80923d1bfaf3b6b5f8cf032147 Mon Sep 17 00:00:00 2001
 From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
-Date: Wed, 14 Dec 2022 09:21:32 +0100
+Date: Wed, 14 Dec 2022 09:31:51 +0100
 Subject: [PATCH] Ensure network ready before cloud-init service runs on RHEL
  (#1893)
 
-RH-Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
-RH-MergeRequest: 85: Ensure network ready before cloud-init service runs on RHEL (#1893)
-RH-Bugzilla: 2153183
-RH-Acked-by: Mohamed Gamal Morsy <mmorsy@redhat.com>
-RH-Acked-by: Camilla Conte <cconte@redhat.com>
-RH-Commit: [1/1] d1abf2692aeddea9eac69f6ff8b173e188c3e013
-
-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2153183
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2152100
 
 commit 6e725f36647407d201af0603d7db11fc96a93d4d
 Author: James Falcon <james.falcon@canonical.com>
diff --git a/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch b/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch
index 4ea2d35..c26c847 100644
--- a/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch
+++ b/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch
@@ -1,17 +1,10 @@
-From c7ad2c8d1ddddcb9acaa1ffebb8e3b9752201f91 Mon Sep 17 00:00:00 2001
+From d51546dee17c9abbb9d44fb33cf81be085a46dae Mon Sep 17 00:00:00 2001
 From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
-Date: Tue, 31 Jan 2023 15:28:33 +0100
-Subject: [PATCH] cc_set_hostname: ignore /var/lib/cloud/data/set-hostname if
- it's empty (#1967)
+Date: Thu, 19 Jan 2023 09:40:10 +0100
+Subject: [PATCH 22/22] cc_set_hostname: ignore
+ /var/lib/cloud/data/set-hostname if it's empty (#1967)
 
-RH-Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
-RH-MergeRequest: 89: cc_set_hostname: ignore /var/lib/cloud/data/set-hostname if it's empty (#1967)
-RH-Bugzilla: 2165942
-RH-Acked-by: Mohamed Gamal Morsy <mmorsy@redhat.com>
-RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
-RH-Commit: [1/1] 53809c47b4d7f5b30cbeb2903a48f1ee42f68c53
-
-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165942
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2140893
 
 commit 9c7502a801763520639c66125eb373123d1e4f44
 Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
diff --git a/SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch b/SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch
new file mode 100644
index 0000000..df94668
--- /dev/null
+++ b/SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch
@@ -0,0 +1,139 @@
+From dd5ae3081491a2a98bd74e1655b22c9354707630 Mon Sep 17 00:00:00 2001
+From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+Date: Thu, 8 Sep 2022 17:46:45 +0200
+Subject: [PATCH] cloud.cfg.tmpl: make sure "centos" settings are identical to
+ "rhel" (#1639)
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2115576
+
+commit 7593243a1abe2ccaf4698579720999380a4da73b
+Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+Date:   Wed Sep 7 14:53:26 2022 +0200
+
+    cloud.cfg.tmpl: make sure "centos" settings are identical to "rhel" (#1639)
+
+    We have a couple of bugs where centos does not have the default user as rhel.
+    This PR makes sure the configuration is exactly the same.
+
+    Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+
+    RHBZ: 2115565
+    RHBZ: 2115576
+    Conflicts:
+            config/cloud.cfg.tmpl: "openmandriva" distro added in the options
+
+Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+---
+ config/cloud.cfg.tmpl                   | 27 +++++++++++++------------
+ tests/unittests/test_render_cloudcfg.py |  1 +
+ 2 files changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl
+index 80ab4f96..08b6efbc 100644
+--- a/config/cloud.cfg.tmpl
++++ b/config/cloud.cfg.tmpl
+@@ -2,6 +2,7 @@
+ # The top level settings are used as module
+ # and system configuration.
+ {% set is_bsd = variant in ["dragonfly", "freebsd", "netbsd", "openbsd"] %}
++{% set is_rhel = variant in ["rhel", "centos"] %}
+ {% if is_bsd %}
+ syslog_fix_perms: root:wheel
+ {% elif variant in ["suse"] %}
+@@ -32,9 +33,9 @@ disable_root: false
+ disable_root: true
+ {% endif %}
+ 
+-{% if variant in ["almalinux", "alpine", "amazon", "centos", "cloudlinux", "eurolinux",
+-                  "fedora", "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %}
+-{% if variant == "rhel" %}
++{% if variant in ["almalinux", "alpine", "amazon", "cloudlinux", "eurolinux",
++                  "fedora", "miraclelinux", "openEuler", "openmandriva", "rocky", "virtuozzo"] or is_rhel %}
++{% if is_rhel %}
+ mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2']
+ {% else %}
+ mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
+@@ -70,7 +71,7 @@ network:
+   config: disabled
+ {% endif %}
+ 
+-{% if variant == "rhel" %}
++{% if is_rhel %}
+ # Default redhat settings:
+ ssh_deletekeys:   true
+ ssh_genkeytypes:  ['rsa', 'ecdsa', 'ed25519']
+@@ -119,16 +120,16 @@ cloud_config_modules:
+ {% endif %}
+ {% if variant not in ["photon"] %}
+  - ssh-import-id
+-{% if variant not in ["rhel"] %}
++{% if not is_rhel %}
+  - keyboard
+ {% endif %}
+  - locale
+ {% endif %}
+  - set-passwords
+-{% if variant in ["rhel"] %}
++{% if is_rhel %}
+  - rh_subscription
+ {% endif %}
+-{% if variant in ["rhel", "fedora", "photon"] %}
++{% if variant in ["fedora", "openmandriva", "photon"] or is_rhel %}
+ {% if variant not in ["photon"] %}
+  - spacewalk
+ {% endif %}
+@@ -193,9 +194,9 @@ cloud_final_modules:
+ # (not accessible to handlers/transforms)
+ system_info:
+    # This will affect which distro class gets used
+-{% if variant in ["almalinux", "alpine", "amazon", "arch", "centos", "cloudlinux", "debian",
++{% if variant in ["almalinux", "alpine", "amazon", "arch", "cloudlinux", "debian",
+                   "eurolinux", "fedora", "freebsd", "gentoo", "netbsd", "miraclelinux", "openbsd", "openEuler",
+-                  "photon", "rhel", "rocky", "suse", "ubuntu", "virtuozzo"] %}
++                  "openmandriva", "photon", "rocky", "suse", "ubuntu", "virtuozzo"] or is_rhel %}
+    distro: {{ variant }}
+ {% elif variant in ["dragonfly"] %}
+    distro: dragonflybsd
+@@ -248,15 +249,15 @@ system_info:
+          primary: http://ports.ubuntu.com/ubuntu-ports
+          security: http://ports.ubuntu.com/ubuntu-ports
+    ssh_svcname: ssh
+-{% elif variant in ["almalinux", "alpine", "amazon", "arch", "centos", "cloudlinux", "eurolinux",
+-                    "fedora", "gentoo", "miraclelinux", "openEuler", "rhel", "rocky", "suse", "virtuozzo"] %}
++{% elif variant in ["almalinux", "alpine", "amazon", "arch", "cloudlinux", "eurolinux",
++                    "fedora", "gentoo", "miraclelinux", "openEuler", "openmandriva", "rocky", "suse", "virtuozzo"] or is_rhel %}
+    # Default user name + that default users groups (if added/used)
+    default_user:
+ {% if variant == "amazon" %}
+      name: ec2-user
+      lock_passwd: True
+      gecos: EC2 Default User
+-{% elif variant == "rhel" %}
++{% elif is_rhel %}
+      name: cloud-user
+      lock_passwd: true
+      gecos: Cloud User
+@@ -275,7 +276,7 @@ system_info:
+      groups: [adm, sudo]
+ {% elif variant == "arch" %}
+      groups: [wheel, users]
+-{% elif variant == "rhel" %}
++{% elif is_rhel %}
+      groups: [adm, systemd-journal]
+ {% else %}
+      groups: [wheel, adm, systemd-journal]
+diff --git a/tests/unittests/test_render_cloudcfg.py b/tests/unittests/test_render_cloudcfg.py
+index 9f95d448..1a6e2715 100644
+--- a/tests/unittests/test_render_cloudcfg.py
++++ b/tests/unittests/test_render_cloudcfg.py
+@@ -69,6 +69,7 @@ class TestRenderCloudCfg:
+             "amazon": "ec2-user",
+             "debian": "ubuntu",
+             "rhel": "cloud-user",
++            "centos": "cloud-user",
+             "unknown": "ubuntu",
+         }
+         default_user = system_cfg["system_info"]["default_user"]["name"]
+-- 
+2.37.3
+
diff --git a/SPECS/cloud-init.spec b/SPECS/cloud-init.spec
index 7e3e108..3078090 100644
--- a/SPECS/cloud-init.spec
+++ b/SPECS/cloud-init.spec
@@ -1,6 +1,6 @@
 Name:           cloud-init
 Version:        22.1
-Release:        7%{?dist}
+Release:        9%{?dist}
 Summary:        Cloud instance init scripts
 License:        ASL 2.0 or GPLv3
 URL:            http://launchpad.net/cloud-init
@@ -46,10 +46,14 @@ Patch17: ci-Revert-Use-Network-Manager-and-Netplan-as-default-re.patch
 # For bz#2117532 - [RHEL9.1] Revert patch of configuring networking by NM keyfiles
 # For bz#2098501 - [RHEL-9.1] IPv6 not workable when cloud-init configure network using NM keyfiles
 Patch18: ci-Revert-Revert-Setting-highest-autoconnect-priority-f.patch
-# For bz#2153183 - [RHEL-9] Ensure network ready before cloud-init service runs on RHEL [rhel-9.1.0.z]
-Patch19: ci-Ensure-network-ready-before-cloud-init-service-runs-.patch
-# For bz#2165942 - systemd[1]: Failed to start Initial cloud-init job after reboot system via sysrq 'b' [RHEL-9] [rhel-9.1.0.z]
-Patch20: ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch
+# For bz#2115565 - cloud-init configures user "centos" or "rhel" instead of "cloud-user" with cloud-init-22.1
+Patch19: ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch
+# For bz#2152100 - [RHEL-9] Ensure network ready before cloud-init service runs on RHEL
+Patch20: ci-Ensure-network-ready-before-cloud-init-service-runs-.patch
+# For bz#2140893 - systemd[1]: Failed to start Initial cloud-init job after reboot system via sysrq 'b'
+Patch21: ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch
+# For bz#2166245 - Add support for resizing encrypted root volume
+Patch22: ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch
 
 # Source-git patches
 
@@ -240,15 +244,25 @@ fi
 %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
 
 %changelog
-* Wed Feb 08 2023 Camilla Conte <cconte@redhat.com> - 22.1-7.el9_1
-- ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch [bz#2165942]
-- Resolves: bz#2165942
-  (systemd[1]: Failed to start Initial cloud-init job after reboot system via sysrq 'b' [RHEL-9] [rhel-9.1.0.z])
-
-* Thu Dec 22 2022 Camilla Conte <cconte@redhat.com> - 22.1-6
-- ci-Ensure-network-ready-before-cloud-init-service-runs-.patch [bz#2153183]
-- Resolves: bz#2153183
-  ([RHEL-9] Ensure network ready before cloud-init service runs on RHEL [rhel-9.1.0.z])
+* Wed Feb 08 2023 Camilla Conte <cconte@redhat.com> - 22.1-9
+- ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch [bz#2166245]
+- Resolves: bz#2166245
+  (Add support for resizing encrypted root volume)
+
+* Fri Jan 27 2023 Camilla Conte <cconte@redhat.com> - 22.1-8
+- ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch [bz#2140893]
+- Resolves: bz#2140893
+(systemd[1]: Failed to start Initial cloud-init job after reboot system via sysrq 'b')
+
+* Wed Dec 21 2022 Camilla Conte <cconte@redhat.com> - 22.1-7
+- ci-Ensure-network-ready-before-cloud-init-service-runs-.patch [bz#2152100]
+- Resolves: bz#2152100
+  ([RHEL-9] Ensure network ready before cloud-init service runs on RHEL)
+
+* Tue Sep 27 2022 Camilla Conte <cconte@redhat.com> - 22.1-6
+- ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch [bz#2115565]
+- Resolves: bz#2115565
+  (cloud-init configures user "centos" or "rhel" instead of "cloud-user" with cloud-init-22.1)
 
 * Wed Aug 17 2022 Miroslav Rezanina <mrezanin@redhat.com> - 22.1-5
 - ci-Revert-Add-native-NetworkManager-support-1224.patch [bz#2107463 bz#2104389 bz#2117532 bz#2098501]