diff --git a/SOURCES/ci-Add-_netdev-option-to-mount-Azure-ephemeral-disk-121.patch b/SOURCES/ci-Add-_netdev-option-to-mount-Azure-ephemeral-disk-121.patch
new file mode 100644
index 0000000..2b9367d
--- /dev/null
+++ b/SOURCES/ci-Add-_netdev-option-to-mount-Azure-ephemeral-disk-121.patch
@@ -0,0 +1,43 @@
+From 244a3f9059fc95a5e644bd7868aed8060d9edc61 Mon Sep 17 00:00:00 2001
+From: Eduardo Otubo <otubo@redhat.com>
+Date: Fri, 4 Feb 2022 16:04:31 +0100
+Subject: [PATCH] Add _netdev option to mount Azure ephemeral disk (#1213)
+
+RH-Author: Eduardo Otubo <otubo@redhat.com>
+RH-MergeRequest: 19: Add _netdev option to mount Azure ephemeral disk (#1213)
+RH-Commit: [1/1] e44291a50634594b8a0505cab3415d5c58cc34c4 (otubo/cloud-init-src)
+RH-Bugzilla: 1998445
+RH-Acked-by: Mohamed Gamal Morsy <mmorsy@redhat.com>
+RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+
+The ephemeral disk depends on a functional network to be mounted. Even
+though it depends on cloud-init.service, sometimes an ordering cycle is
+noticed on the instance. If the option "_netdev" is added the problem is
+gone.
+
+rhbz: #1998445
+
+Signed-off-by: Eduardo Otubo otubo@redhat.com
+---
+ cloudinit/config/cc_mounts.py | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
+index c22d1698..5125f17c 100644
+--- a/cloudinit/config/cc_mounts.py
++++ b/cloudinit/config/cc_mounts.py
+@@ -362,7 +362,9 @@ def handle(_name, cfg, cloud, log, _args):
+     def_mnt_opts = "defaults,nobootwait"
+     uses_systemd = cloud.distro.uses_systemd()
+     if uses_systemd:
+-        def_mnt_opts = "defaults,nofail,x-systemd.requires=cloud-init.service"
++        def_mnt_opts = (
++            "defaults,nofail, x-systemd.requires=cloud-init.service, _netdev"
++        )
+ 
+     defvals = [None, None, "auto", def_mnt_opts, "0", "2"]
+     defvals = cfg.get("mount_default_fields", defvals)
+-- 
+2.27.0
+
diff --git a/SOURCES/ci-Adding-_netdev-to-the-default-mount-configuration.patch b/SOURCES/ci-Adding-_netdev-to-the-default-mount-configuration.patch
new file mode 100644
index 0000000..d558635
--- /dev/null
+++ b/SOURCES/ci-Adding-_netdev-to-the-default-mount-configuration.patch
@@ -0,0 +1,38 @@
+From b9c6c6c88d16685475bb9c8f0de3c765bd5303fa Mon Sep 17 00:00:00 2001
+From: Eduardo Otubo <otubo@redhat.com>
+Date: Thu, 17 Feb 2022 15:01:41 +0100
+Subject: [PATCH 2/3] Adding _netdev to the default mount configuration
+
+RH-Author: Eduardo Otubo <otubo@redhat.com>
+RH-MergeRequest: 21: Adding _netdev to the default mount configuration
+RH-Commit: [1/1] 250860a24db396a5088d207d6526a0028ac73eb3 (otubo/cloud-init-src)
+RH-Bugzilla: 1998445
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+
+Adding _netdev option also to the default configuration for RHEL.
+
+rhbz: 1998445
+x-downstream-only: yes
+
+Signed-off-by: Eduardo Otubo <otubo@redhat.com>
+---
+ rhel/cloud.cfg | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg
+index cbee197a..75d5c84b 100644
+--- a/rhel/cloud.cfg
++++ b/rhel/cloud.cfg
+@@ -4,7 +4,7 @@ users:
+ disable_root: 1
+ ssh_pwauth:   0
+ 
+-mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2']
++mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2']
+ resize_rootfs_tmp: /dev
+ ssh_deletekeys:   1
+ ssh_genkeytypes:  ['rsa', 'ecdsa', 'ed25519']
+-- 
+2.27.0
+
diff --git a/SOURCES/ci-Fix-IPv6-netmask-format-for-sysconfig-1215.patch b/SOURCES/ci-Fix-IPv6-netmask-format-for-sysconfig-1215.patch
new file mode 100644
index 0000000..ee1aa02
--- /dev/null
+++ b/SOURCES/ci-Fix-IPv6-netmask-format-for-sysconfig-1215.patch
@@ -0,0 +1,474 @@
+From 290353d6df0b3bbbbcfa4f949f943388939ebc12 Mon Sep 17 00:00:00 2001
+From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+Date: Fri, 11 Feb 2022 14:57:40 +0100
+Subject: [PATCH 1/3] Fix IPv6 netmask format for sysconfig (#1215)
+
+RH-Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+RH-MergeRequest: 20: Fix IPv6 netmask format for sysconfig (#1215)
+RH-Commit: [1/1] 2eb7ac7c85e82c14f9a95b9baf1482ac987b1084 (eesposit/cloud-init-centos-)
+RH-Bugzilla: 2053546
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+commit b97a30f0a05c1dea918c46ca9c05c869d15fe2d5
+Author: Harald <hjensas@redhat.com>
+Date:   Tue Feb 8 15:49:00 2022 +0100
+
+    Fix IPv6 netmask format for sysconfig (#1215)
+
+    This change converts the IPv6 netmask from the network_data.json[1]
+    format to the CIDR style, <IPv6_addr>/<prefix>.
+
+    Using an IPv6 address like ffff:ffff:ffff:ffff:: does not work with
+    NetworkManager, nor networkscripts.
+
+    NetworkManager will ignore the route, logging:
+      ifcfg-rh: ignoring invalid route at \
+        "::/:: via fd00:fd00:fd00:2::fffe dev $DEV" \
+        (/etc/sysconfig/network-scripts/route6-$DEV:3): \
+        Argument for "::/::" is not ADDR/PREFIX format
+
+    Similarly if using networkscripts, ip route fail with error:
+      Error: inet6 prefix is expected rather than \
+        "fd00:fd00:fd00::/ffff:ffff:ffff:ffff::".
+
+    Also a bit of refactoring ...
+
+    cloudinit.net.sysconfig.Route.to_string:
+    * Move a couple of lines around to reduce repeated code.
+    * if "ADDRESS" not in key -> continute, so that the
+      code block following it can be de-indented.
+    cloudinit.net.network_state:
+    * Refactors the ipv4_mask_to_net_prefix, ipv6_mask_to_net_prefix
+      removes mask_to_net_prefix methods. Utilize ipaddress library to
+      do some of the heavy lifting.
+
+    LP: #1959148
+
+Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+---
+ cloudinit/net/__init__.py                     |   7 +-
+ cloudinit/net/network_state.py                | 103 +++++++-----------
+ cloudinit/net/sysconfig.py                    |  91 ++++++++++------
+ cloudinit/sources/DataSourceOpenNebula.py     |   2 +-
+ .../sources/helpers/vmware/imc/config_nic.py  |   4 +-
+ tests/unittests/test_net.py                   |  78 ++++++++++++-
+ 6 files changed, 176 insertions(+), 109 deletions(-)
+
+diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
+index 4bdc1bda..91cb0627 100644
+--- a/cloudinit/net/__init__.py
++++ b/cloudinit/net/__init__.py
+@@ -13,7 +13,7 @@ import re
+ 
+ from cloudinit import subp
+ from cloudinit import util
+-from cloudinit.net.network_state import mask_to_net_prefix
++from cloudinit.net.network_state import ipv4_mask_to_net_prefix
+ from cloudinit.url_helper import UrlError, readurl
+ 
+ LOG = logging.getLogger(__name__)
+@@ -986,10 +986,11 @@ class EphemeralIPv4Network(object):
+                 'Cannot init network on {0} with {1}/{2} and bcast {3}'.format(
+                     interface, ip, prefix_or_mask, broadcast))
+         try:
+-            self.prefix = mask_to_net_prefix(prefix_or_mask)
++            self.prefix = ipv4_mask_to_net_prefix(prefix_or_mask)
+         except ValueError as e:
+             raise ValueError(
+-                'Cannot setup network: {0}'.format(e)
++                "Cannot setup network, invalid prefix or "
++                "netmask: {0}".format(e)
+             ) from e
+ 
+         self.connectivity_url = connectivity_url
+diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
+index e8bf9e39..2768ef94 100644
+--- a/cloudinit/net/network_state.py
++++ b/cloudinit/net/network_state.py
+@@ -6,6 +6,7 @@
+ 
+ import copy
+ import functools
++import ipaddress
+ import logging
+ import socket
+ import struct
+@@ -872,12 +873,18 @@ def _normalize_net_keys(network, address_keys=()):
+         try:
+             prefix = int(maybe_prefix)
+         except ValueError:
+-            # this supports input of <address>/255.255.255.0
+-            prefix = mask_to_net_prefix(maybe_prefix)
+-    elif netmask:
+-        prefix = mask_to_net_prefix(netmask)
+-    elif 'prefix' in net:
+-        prefix = int(net['prefix'])
++            if ipv6:
++                # this supports input of ffff:ffff:ffff::
++                prefix = ipv6_mask_to_net_prefix(maybe_prefix)
++            else:
++                # this supports input of 255.255.255.0
++                prefix = ipv4_mask_to_net_prefix(maybe_prefix)
++    elif netmask and not ipv6:
++        prefix = ipv4_mask_to_net_prefix(netmask)
++    elif netmask and ipv6:
++        prefix = ipv6_mask_to_net_prefix(netmask)
++    elif "prefix" in net:
++        prefix = int(net["prefix"])
+     else:
+         prefix = 64 if ipv6 else 24
+ 
+@@ -972,72 +979,42 @@ def ipv4_mask_to_net_prefix(mask):
+        str(24)         => 24
+        "24"            => 24
+     """
+-    if isinstance(mask, int):
+-        return mask
+-    if isinstance(mask, str):
+-        try:
+-            return int(mask)
+-        except ValueError:
+-            pass
+-    else:
+-        raise TypeError("mask '%s' is not a string or int")
+-
+-    if '.' not in mask:
+-        raise ValueError("netmask '%s' does not contain a '.'" % mask)
+-
+-    toks = mask.split(".")
+-    if len(toks) != 4:
+-        raise ValueError("netmask '%s' had only %d parts" % (mask, len(toks)))
+-
+-    return sum([bin(int(x)).count('1') for x in toks])
++    return ipaddress.ip_network(f"0.0.0.0/{mask}").prefixlen
+ 
+ 
+ def ipv6_mask_to_net_prefix(mask):
+     """Convert an ipv6 netmask (very uncommon) or prefix (64) to prefix.
+ 
+-    If 'mask' is an integer or string representation of one then
+-    int(mask) will be returned.
++    If the input is already an integer or a string representation of
++    an integer, then int(mask) will be returned.
++       "ffff:ffff:ffff::"  => 48
++       "48"                => 48
+     """
+-
+-    if isinstance(mask, int):
+-        return mask
+-    if isinstance(mask, str):
+-        try:
+-            return int(mask)
+-        except ValueError:
+-            pass
+-    else:
+-        raise TypeError("mask '%s' is not a string or int")
+-
+-    if ':' not in mask:
+-        raise ValueError("mask '%s' does not have a ':'")
+-
+-    bitCount = [0, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00,
+-                0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc,
+-                0xfffe, 0xffff]
+-    prefix = 0
+-    for word in mask.split(':'):
+-        if not word or int(word, 16) == 0:
+-            break
+-        prefix += bitCount.index(int(word, 16))
+-
+-    return prefix
+-
+-
+-def mask_to_net_prefix(mask):
+-    """Return the network prefix for the netmask provided.
+-
+-    Supports ipv4 or ipv6 netmasks."""
+     try:
+-        # if 'mask' is a prefix that is an integer.
+-        # then just return it.
+-        return int(mask)
++        # In the case the mask is already a prefix
++        prefixlen = ipaddress.ip_network(f"::/{mask}").prefixlen
++        return prefixlen
+     except ValueError:
++        # ValueError means mask is an IPv6 address representation and need
++        # conversion.
+         pass
+-    if is_ipv6_addr(mask):
+-        return ipv6_mask_to_net_prefix(mask)
+-    else:
+-        return ipv4_mask_to_net_prefix(mask)
++
++    netmask = ipaddress.ip_address(mask)
++    mask_int = int(netmask)
++    # If the mask is all zeroes, just return it
++    if mask_int == 0:
++        return mask_int
++
++    trailing_zeroes = min(
++        ipaddress.IPV6LENGTH, (~mask_int & (mask_int - 1)).bit_length()
++    )
++    leading_ones = mask_int >> trailing_zeroes
++    prefixlen = ipaddress.IPV6LENGTH - trailing_zeroes
++    all_ones = (1 << prefixlen) - 1
++    if leading_ones != all_ones:
++        raise ValueError("Invalid network mask '%s'" % mask)
++
++    return prefixlen
+ 
+ 
+ def mask_and_ipv4_to_bcast_addr(mask, ip):
+diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
+index d5440998..7ecbe1c3 100644
+--- a/cloudinit/net/sysconfig.py
++++ b/cloudinit/net/sysconfig.py
+@@ -12,6 +12,7 @@ from cloudinit import util
+ from cloudinit import subp
+ from cloudinit.distros.parsers import networkmanager_conf
+ from cloudinit.distros.parsers import resolv_conf
++from cloudinit.net import network_state
+ 
+ from . import renderer
+ from .network_state import (
+@@ -171,43 +172,61 @@ class Route(ConfigMap):
+         # (because Route can contain a mix of IPv4 and IPv6)
+         reindex = -1
+         for key in sorted(self._conf.keys()):
+-            if 'ADDRESS' in key:
+-                index = key.replace('ADDRESS', '')
+-                address_value = str(self._conf[key])
+-                # only accept combinations:
+-                # if proto ipv6 only display ipv6 routes
+-                # if proto ipv4 only display ipv4 routes
+-                # do not add ipv6 routes if proto is ipv4
+-                # do not add ipv4 routes if proto is ipv6
+-                # (this array will contain a mix of ipv4 and ipv6)
+-                if proto == "ipv4" and not self.is_ipv6_route(address_value):
+-                    netmask_value = str(self._conf['NETMASK' + index])
+-                    gateway_value = str(self._conf['GATEWAY' + index])
+-                    # increase IPv4 index
+-                    reindex = reindex + 1
+-                    buf.write("%s=%s\n" % ('ADDRESS' + str(reindex),
+-                                           _quote_value(address_value)))
+-                    buf.write("%s=%s\n" % ('GATEWAY' + str(reindex),
+-                                           _quote_value(gateway_value)))
+-                    buf.write("%s=%s\n" % ('NETMASK' + str(reindex),
+-                                           _quote_value(netmask_value)))
+-                    metric_key = 'METRIC' + index
+-                    if metric_key in self._conf:
+-                        metric_value = str(self._conf['METRIC' + index])
+-                        buf.write("%s=%s\n" % ('METRIC' + str(reindex),
+-                                               _quote_value(metric_value)))
+-                elif proto == "ipv6" and self.is_ipv6_route(address_value):
+-                    netmask_value = str(self._conf['NETMASK' + index])
+-                    gateway_value = str(self._conf['GATEWAY' + index])
+-                    metric_value = (
+-                        'metric ' + str(self._conf['METRIC' + index])
+-                        if 'METRIC' + index in self._conf else '')
++            if "ADDRESS" not in key:
++                continue
++
++            index = key.replace("ADDRESS", "")
++            address_value = str(self._conf[key])
++            netmask_value = str(self._conf["NETMASK" + index])
++            gateway_value = str(self._conf["GATEWAY" + index])
++
++            # only accept combinations:
++            # if proto ipv6 only display ipv6 routes
++            # if proto ipv4 only display ipv4 routes
++            # do not add ipv6 routes if proto is ipv4
++            # do not add ipv4 routes if proto is ipv6
++            # (this array will contain a mix of ipv4 and ipv6)
++            if proto == "ipv4" and not self.is_ipv6_route(address_value):
++                # increase IPv4 index
++                reindex = reindex + 1
++                buf.write(
++                    "%s=%s\n"
++                    % ("ADDRESS" + str(reindex), _quote_value(address_value))
++                )
++                buf.write(
++                    "%s=%s\n"
++                    % ("GATEWAY" + str(reindex), _quote_value(gateway_value))
++                )
++                buf.write(
++                    "%s=%s\n"
++                    % ("NETMASK" + str(reindex), _quote_value(netmask_value))
++                )
++                metric_key = "METRIC" + index
++                if metric_key in self._conf:
++                    metric_value = str(self._conf["METRIC" + index])
+                     buf.write(
+-                        "%s/%s via %s %s dev %s\n" % (address_value,
+-                                                      netmask_value,
+-                                                      gateway_value,
+-                                                      metric_value,
+-                                                      self._route_name))
++                        "%s=%s\n"
++                        % ("METRIC" + str(reindex), _quote_value(metric_value))
++                    )
++            elif proto == "ipv6" and self.is_ipv6_route(address_value):
++                prefix_value = network_state.ipv6_mask_to_net_prefix(
++                    netmask_value
++                )
++                metric_value = (
++                    "metric " + str(self._conf["METRIC" + index])
++                    if "METRIC" + index in self._conf
++                    else ""
++                )
++                buf.write(
++                    "%s/%s via %s %s dev %s\n"
++                    % (
++                        address_value,
++                        prefix_value,
++                        gateway_value,
++                        metric_value,
++                        self._route_name,
++                    )
++                )
+ 
+         return buf.getvalue()
+ 
+diff --git a/cloudinit/sources/DataSourceOpenNebula.py b/cloudinit/sources/DataSourceOpenNebula.py
+index 730ec586..e7980ab1 100644
+--- a/cloudinit/sources/DataSourceOpenNebula.py
++++ b/cloudinit/sources/DataSourceOpenNebula.py
+@@ -233,7 +233,7 @@ class OpenNebulaNetwork(object):
+             # Set IPv4 address
+             devconf['addresses'] = []
+             mask = self.get_mask(c_dev)
+-            prefix = str(net.mask_to_net_prefix(mask))
++            prefix = str(net.ipv4_mask_to_net_prefix(mask))
+             devconf['addresses'].append(
+                 self.get_ip(c_dev, mac) + '/' + prefix)
+ 
+diff --git a/cloudinit/sources/helpers/vmware/imc/config_nic.py b/cloudinit/sources/helpers/vmware/imc/config_nic.py
+index 9cd2c0c0..3a45c67e 100644
+--- a/cloudinit/sources/helpers/vmware/imc/config_nic.py
++++ b/cloudinit/sources/helpers/vmware/imc/config_nic.py
+@@ -9,7 +9,7 @@ import logging
+ import os
+ import re
+ 
+-from cloudinit.net.network_state import mask_to_net_prefix
++from cloudinit.net.network_state import ipv4_mask_to_net_prefix
+ from cloudinit import subp
+ from cloudinit import util
+ 
+@@ -180,7 +180,7 @@ class NicConfigurator(object):
+         """
+         route_list = []
+ 
+-        cidr = mask_to_net_prefix(netmask)
++        cidr = ipv4_mask_to_net_prefix(netmask)
+ 
+         for gateway in gateways:
+             destination = "%s/%d" % (gen_subnet(gateway, netmask), cidr)
+diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
+index c67b5fcc..0bc547af 100644
+--- a/tests/unittests/test_net.py
++++ b/tests/unittests/test_net.py
+@@ -2025,10 +2025,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
+                     routes:
+                         - gateway: 2001:67c:1562:1
+                           network: 2001:67c:1
+-                          netmask: ffff:ffff:0
++                          netmask: "ffff:ffff::"
+                         - gateway: 3001:67c:1562:1
+                           network: 3001:67c:1
+-                          netmask: ffff:ffff:0
++                          netmask: "ffff:ffff::"
+                           metric: 10000
+             """),
+         'expected_netplan': textwrap.dedent("""
+@@ -2295,8 +2295,8 @@ iface bond0 inet6 static
+             'route6-bond0': textwrap.dedent("""\
+         # Created by cloud-init on instance boot automatically, do not edit.
+         #
+-        2001:67c:1/ffff:ffff:0 via 2001:67c:1562:1  dev bond0
+-        3001:67c:1/ffff:ffff:0 via 3001:67c:1562:1 metric 10000 dev bond0
++        2001:67c:1/32 via 2001:67c:1562:1  dev bond0
++        3001:67c:1/32 via 3001:67c:1562:1 metric 10000 dev bond0
+             """),
+             'route-bond0': textwrap.dedent("""\
+         ADDRESS0=10.1.3.0
+@@ -3084,6 +3084,76 @@ USERCTL=no
+             renderer.render_network_state(ns, target=render_dir)
+         self.assertEqual([], os.listdir(render_dir))
+ 
++    def test_invalid_network_mask_ipv6(self):
++        net_json = {
++            "services": [{"type": "dns", "address": "172.19.0.12"}],
++            "networks": [
++                {
++                    "network_id": "public-ipv6",
++                    "type": "ipv6",
++                    "netmask": "",
++                    "link": "tap1a81968a-79",
++                    "routes": [
++                        {
++                            "gateway": "2001:DB8::1",
++                            "netmask": "ff:ff:ff:ff::",
++                            "network": "2001:DB8:1::1",
++                        },
++                    ],
++                    "ip_address": "2001:DB8::10",
++                    "id": "network1",
++                }
++            ],
++            "links": [
++                {
++                    "ethernet_mac_address": "fa:16:3e:ed:9a:59",
++                    "mtu": None,
++                    "type": "bridge",
++                    "id": "tap1a81968a-79",
++                    "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f",
++                },
++            ],
++        }
++        macs = {"fa:16:3e:ed:9a:59": "eth0"}
++        network_cfg = openstack.convert_net_json(net_json, known_macs=macs)
++        with self.assertRaises(ValueError):
++            network_state.parse_net_config_data(network_cfg, skip_broken=False)
++
++    def test_invalid_network_mask_ipv4(self):
++        net_json = {
++            "services": [{"type": "dns", "address": "172.19.0.12"}],
++            "networks": [
++                {
++                    "network_id": "public-ipv4",
++                    "type": "ipv4",
++                    "netmask": "",
++                    "link": "tap1a81968a-79",
++                    "routes": [
++                        {
++                            "gateway": "172.20.0.1",
++                            "netmask": "255.234.255.0",
++                            "network": "172.19.0.0",
++                        },
++                    ],
++                    "ip_address": "172.20.0.10",
++                    "id": "network1",
++                }
++            ],
++            "links": [
++                {
++                    "ethernet_mac_address": "fa:16:3e:ed:9a:59",
++                    "mtu": None,
++                    "type": "bridge",
++                    "id": "tap1a81968a-79",
++                    "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f",
++                },
++            ],
++        }
++        macs = {"fa:16:3e:ed:9a:59": "eth0"}
++        network_cfg = openstack.convert_net_json(net_json, known_macs=macs)
++        with self.assertRaises(ValueError):
++            network_state.parse_net_config_data(network_cfg, skip_broken=False)
++
+     def test_openstack_rendering_samples(self):
+         for os_sample in OS_SAMPLES:
+             render_dir = self.tmp_dir()
+-- 
+2.27.0
+
diff --git a/SOURCES/ci-Setting-highest-autoconnect-priority-for-network-scr.patch b/SOURCES/ci-Setting-highest-autoconnect-priority-for-network-scr.patch
new file mode 100644
index 0000000..a1aae51
--- /dev/null
+++ b/SOURCES/ci-Setting-highest-autoconnect-priority-for-network-scr.patch
@@ -0,0 +1,46 @@
+From cf7b45eaa070061615ad26f6754f7d2b39e7de76 Mon Sep 17 00:00:00 2001
+From: Eduardo Otubo <otubo@redhat.com>
+Date: Thu, 17 Feb 2022 15:32:35 +0100
+Subject: [PATCH 3/3] Setting highest autoconnect priority for network-scripts
+
+RH-Author: Eduardo Otubo <otubo@redhat.com>
+RH-MergeRequest: 22: Setting highest autoconnect priority for network-scripts
+RH-Commit: [1/1] 34f1d62f8934a983a124df95b861a1e448681d3b (otubo/cloud-init-src)
+RH-Bugzilla: 2036060
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+
+Set the highest autoconnect priority for network-scripts which is
+loaded by NetworkManager ifcfg-rh plugin.  Note that keyfile is the only
+and default existing plugin on RHEL9, by setting the highest autoconnect
+priority for network-scripts, NetworkManager will activate
+network-scripts but keyfile.  Network-scripts path:
+
+Since this is a blocking issue, we decided to have this one-liner
+downstream-only patch so we can move forward and have a better
+NetworkManager support later on the release.
+
+rhbz: 2036060
+x-downstream-only: yes
+
+Signed-off-by: Eduardo Otubo <otubo@redhat.com>
+---
+ cloudinit/net/sysconfig.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
+index 7ecbe1c3..c7ca7c56 100644
+--- a/cloudinit/net/sysconfig.py
++++ b/cloudinit/net/sysconfig.py
+@@ -309,7 +309,7 @@ class Renderer(renderer.Renderer):
+ 
+     iface_defaults = {
+         'rhel': {'ONBOOT': True, 'USERCTL': False,
+-                 'BOOTPROTO': 'none'},
++                 'BOOTPROTO': 'none', "AUTOCONNECT_PRIORITY": 999},
+         'suse': {'BOOTPROTO': 'static', 'STARTMODE': 'auto'},
+     }
+ 
+-- 
+2.27.0
+
diff --git a/SPECS/cloud-init.spec b/SPECS/cloud-init.spec
index c16a07c..cd2c478 100644
--- a/SPECS/cloud-init.spec
+++ b/SPECS/cloud-init.spec
@@ -1,6 +1,6 @@
 Name:           cloud-init
 Version:        21.1
-Release:        17%{?dist}
+Release:        19%{?dist}
 Summary:        Cloud instance init scripts
 License:        ASL 2.0 or GPLv3
 URL:            http://launchpad.net/cloud-init
@@ -56,6 +56,14 @@ Patch24: ci-Azure-Retrieve-username-and-hostname-from-IMDS-865.patch
 Patch25: ci-Azure-Retry-net-metadata-during-nic-attach-for-non-t.patch
 # For bz#2042351 - [RHEL-9] Support for provisioning Azure VM with userdata
 Patch26: ci-Azure-adding-support-for-consuming-userdata-from-IMD.patch
+# For bz#1998445 - [Azure][RHEL-9] ordering cycle exists after reboot
+Patch27: ci-Add-_netdev-option-to-mount-Azure-ephemeral-disk-121.patch
+# For bz#2053546 - cloud-init writes route6-$DEVICE config with a HEX netmask. ip route does not like : Error: inet6 prefix is expected rather than "fd00:fd00:fd00::/ffff:ffff:ffff:ffff::".
+Patch28: ci-Fix-IPv6-netmask-format-for-sysconfig-1215.patch
+# For bz#1998445 - [Azure][RHEL-9] ordering cycle exists after reboot
+Patch29: ci-Adding-_netdev-to-the-default-mount-configuration.patch
+# For bz#2036060 - [cloud-init][ESXi][RHEL-9] Failed to config static IP according to VMware Customization Config File
+Patch30: ci-Setting-highest-autoconnect-priority-for-network-scr.patch
 
 # Source-git patches
 
@@ -257,6 +265,22 @@ fi
 %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
 
 %changelog
+* Fri Feb 25 2022 Miroslav Rezanina <mrezanin@redhat.com> - 21.1-19
+- ci-Fix-IPv6-netmask-format-for-sysconfig-1215.patch [bz#2053546]
+- ci-Adding-_netdev-to-the-default-mount-configuration.patch [bz#1998445]
+- ci-Setting-highest-autoconnect-priority-for-network-scr.patch [bz#2036060]
+- Resolves: bz#2053546
+  (cloud-init writes route6-$DEVICE config with a HEX netmask. ip route does not like : Error: inet6 prefix is expected rather than "fd00:fd00:fd00::/ffff:ffff:ffff:ffff::".)
+- Resolves: bz#1998445
+  ([Azure][RHEL-9] ordering cycle exists after reboot)
+- Resolves: bz#2036060
+  ([cloud-init][ESXi][RHEL-9] Failed to config static IP according to VMware Customization Config File)
+
+* Fri Feb 11 2022 Miroslav Rezanina <mrezanin@redhat.com> - 21.1-18
+- ci-Add-_netdev-option-to-mount-Azure-ephemeral-disk-121.patch [bz#1998445]
+- Resolves: bz#1998445
+  ([Azure][RHEL-9] ordering cycle exists after reboot)
+
 * Mon Feb 07 2022 Miroslav Rezanina <mrezanin@redhat.com> - 21.1-17
 - ci-Add-flexibility-to-IMDS-api-version-793.patch [bz#2042351]
 - ci-Azure-helper-Ensure-Azure-http-handler-sleeps-betwee.patch [bz#2042351]