Import from CS git
This commit is contained in:
parent
10e5bc48cf
commit
43d54958cc
@ -0,0 +1,350 @@
|
|||||||
|
From 773501c6d2b52a5623b5fed3c5534d41aa6488fa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ani Sinha <anisinha@redhat.com>
|
||||||
|
Date: Thu, 20 Jun 2024 22:27:03 +0530
|
||||||
|
Subject: [PATCH] feat(sysconfig): Add DNS from interface config to resolv.conf
|
||||||
|
(#5401)
|
||||||
|
|
||||||
|
RH-Author: xiachen <xiachen@redhat.com>
|
||||||
|
RH-MergeRequest: 140: feat(sysconfig): Add DNS from interface config to resolv.conf (#5401)
|
||||||
|
RH-Jira: RHEL-46013
|
||||||
|
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||||
|
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
|
||||||
|
RH-Commit: [1/1] b9f492627cdae3bf356f388eb0870241793a7f99
|
||||||
|
|
||||||
|
sysconfig renderer currently only uses global dns and search domain
|
||||||
|
configuration in order to populate /etc/resolv.conf. This means it ignores
|
||||||
|
interface specific dns configuration completely. This means, when global dns
|
||||||
|
information is absent and only interface specific dns configuration is present,
|
||||||
|
/etc/resolv.conf will not have complete dns information. Fix this so that
|
||||||
|
per interface dns information is also taken into account along with global dns
|
||||||
|
configuration in order to populate /etc/resolv.conf.
|
||||||
|
|
||||||
|
Fixes: GH-5400
|
||||||
|
|
||||||
|
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||||
|
(cherry picked from commit 1b8030e0c7fd6fbff7e38ad1e3e6266ae50c83a5)
|
||||||
|
---
|
||||||
|
cloudinit/net/sysconfig.py | 52 +++++++++-
|
||||||
|
tests/unittests/test_net.py | 183 +++++++++++++++++++++++++++++++++++-
|
||||||
|
2 files changed, 229 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
|
||||||
|
index f01c4236..42eb2be3 100644
|
||||||
|
--- a/cloudinit/net/sysconfig.py
|
||||||
|
+++ b/cloudinit/net/sysconfig.py
|
||||||
|
@@ -824,20 +824,62 @@ class Renderer(renderer.Renderer):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _render_dns(network_state, existing_dns_path=None):
|
||||||
|
- # skip writing resolv.conf if network_state doesn't include any input.
|
||||||
|
+
|
||||||
|
+ found_nameservers = []
|
||||||
|
+ found_dns_search = []
|
||||||
|
+
|
||||||
|
+ for iface in network_state.iter_interfaces():
|
||||||
|
+ for subnet in iface["subnets"]:
|
||||||
|
+ # Add subnet-level DNS
|
||||||
|
+ if "dns_nameservers" in subnet:
|
||||||
|
+ found_nameservers.extend(subnet["dns_nameservers"])
|
||||||
|
+ if "dns_search" in subnet:
|
||||||
|
+ found_dns_search.extend(subnet["dns_search"])
|
||||||
|
+
|
||||||
|
+ # Add interface-level DNS
|
||||||
|
+ if "dns" in iface:
|
||||||
|
+ found_nameservers += [
|
||||||
|
+ dns
|
||||||
|
+ for dns in iface["dns"]["nameservers"]
|
||||||
|
+ if dns not in found_nameservers
|
||||||
|
+ ]
|
||||||
|
+ found_dns_search += [
|
||||||
|
+ search
|
||||||
|
+ for search in iface["dns"]["search"]
|
||||||
|
+ if search not in found_dns_search
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ # When both global and interface specific entries are present,
|
||||||
|
+ # use them both to generate /etc/resolv.conf eliminating duplicate
|
||||||
|
+ # entries. Otherwise use global or interface specific entries whichever
|
||||||
|
+ # is provided.
|
||||||
|
+ if network_state.dns_nameservers:
|
||||||
|
+ found_nameservers += [
|
||||||
|
+ nameserver
|
||||||
|
+ for nameserver in network_state.dns_nameservers
|
||||||
|
+ if nameserver not in found_nameservers
|
||||||
|
+ ]
|
||||||
|
+ if network_state.dns_searchdomains:
|
||||||
|
+ found_dns_search += [
|
||||||
|
+ search
|
||||||
|
+ for search in network_state.dns_searchdomains
|
||||||
|
+ if search not in found_dns_search
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ # skip writing resolv.conf if no dns information is provided in conf.
|
||||||
|
if not any(
|
||||||
|
[
|
||||||
|
- len(network_state.dns_nameservers),
|
||||||
|
- len(network_state.dns_searchdomains),
|
||||||
|
+ len(found_nameservers),
|
||||||
|
+ len(found_dns_search),
|
||||||
|
]
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
content = resolv_conf.ResolvConf("")
|
||||||
|
if existing_dns_path and os.path.isfile(existing_dns_path):
|
||||||
|
content = resolv_conf.ResolvConf(util.load_file(existing_dns_path))
|
||||||
|
- for nameserver in network_state.dns_nameservers:
|
||||||
|
+ for nameserver in found_nameservers:
|
||||||
|
content.add_nameserver(nameserver)
|
||||||
|
- for searchdomain in network_state.dns_searchdomains:
|
||||||
|
+ for searchdomain in found_dns_search:
|
||||||
|
content.add_search_domain(searchdomain)
|
||||||
|
header = _make_header(";")
|
||||||
|
content_str = str(content)
|
||||||
|
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
|
||||||
|
index e010eb6b..86ba398d 100644
|
||||||
|
--- a/tests/unittests/test_net.py
|
||||||
|
+++ b/tests/unittests/test_net.py
|
||||||
|
@@ -516,6 +516,8 @@ OS_SAMPLES = [
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ip_address": "172.19.1.34",
|
||||||
|
+ "dns_search": ["testweb.com"],
|
||||||
|
+ "dns_nameservers": ["172.19.0.13"],
|
||||||
|
"id": "network0",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
@@ -550,7 +552,9 @@ STARTMODE=auto
|
||||||
|
"""
|
||||||
|
; Created by cloud-init automatically, do not edit.
|
||||||
|
;
|
||||||
|
+nameserver 172.19.0.13
|
||||||
|
nameserver 172.19.0.12
|
||||||
|
+search testweb.com
|
||||||
|
""".lstrip(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
@@ -581,6 +585,8 @@ dns = none
|
||||||
|
BOOTPROTO=none
|
||||||
|
DEFROUTE=yes
|
||||||
|
DEVICE=eth0
|
||||||
|
+DNS1=172.19.0.13
|
||||||
|
+DOMAIN=testweb.com
|
||||||
|
GATEWAY=172.19.3.254
|
||||||
|
HWADDR=fa:16:3e:ed:9a:59
|
||||||
|
IPADDR=172.19.1.34
|
||||||
|
@@ -595,7 +601,173 @@ USERCTL=no
|
||||||
|
"""
|
||||||
|
; Created by cloud-init automatically, do not edit.
|
||||||
|
;
|
||||||
|
+nameserver 172.19.0.13
|
||||||
|
nameserver 172.19.0.12
|
||||||
|
+search testweb.com
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "etc/NetworkManager/conf.d/99-cloud-init.conf",
|
||||||
|
+ """
|
||||||
|
+# Created by cloud-init automatically, do not edit.
|
||||||
|
+#
|
||||||
|
+[main]
|
||||||
|
+dns = none
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "etc/udev/rules.d/70-persistent-net.rules",
|
||||||
|
+ "".join(
|
||||||
|
+ [
|
||||||
|
+ 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
|
||||||
|
+ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n',
|
||||||
|
+ ]
|
||||||
|
+ ),
|
||||||
|
+ ),
|
||||||
|
+ ],
|
||||||
|
+ "expected_network_manager": [
|
||||||
|
+ (
|
||||||
|
+ "".join(
|
||||||
|
+ [
|
||||||
|
+ "etc/NetworkManager/system-connections",
|
||||||
|
+ "/cloud-init-eth0.nmconnection",
|
||||||
|
+ ]
|
||||||
|
+ ),
|
||||||
|
+ """
|
||||||
|
+# Generated by cloud-init. Changes will be lost.
|
||||||
|
+
|
||||||
|
+[connection]
|
||||||
|
+id=cloud-init eth0
|
||||||
|
+uuid=1dd9a779-d327-56e1-8454-c65e2556c12c
|
||||||
|
+autoconnect-priority=120
|
||||||
|
+type=ethernet
|
||||||
|
+
|
||||||
|
+[user]
|
||||||
|
+org.freedesktop.NetworkManager.origin=cloud-init
|
||||||
|
+
|
||||||
|
+[ethernet]
|
||||||
|
+mac-address=FA:16:3E:ED:9A:59
|
||||||
|
+
|
||||||
|
+[ipv4]
|
||||||
|
+method=manual
|
||||||
|
+may-fail=false
|
||||||
|
+address1=172.19.1.34/22
|
||||||
|
+route1=0.0.0.0/0,172.19.3.254
|
||||||
|
+dns=172.19.0.13;
|
||||||
|
+dns-search=testweb.com;
|
||||||
|
+
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ ],
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ "in_data": {
|
||||||
|
+ "services": [
|
||||||
|
+ {
|
||||||
|
+ "type": "dns",
|
||||||
|
+ "address": "172.19.0.12",
|
||||||
|
+ "search": ["example1.com", "example2.com"],
|
||||||
|
+ }
|
||||||
|
+ ],
|
||||||
|
+ "networks": [
|
||||||
|
+ {
|
||||||
|
+ "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
|
||||||
|
+ "type": "ipv4",
|
||||||
|
+ "netmask": "255.255.252.0",
|
||||||
|
+ "link": "eth0",
|
||||||
|
+ "routes": [
|
||||||
|
+ {
|
||||||
|
+ "netmask": "0.0.0.0",
|
||||||
|
+ "network": "0.0.0.0",
|
||||||
|
+ "gateway": "172.19.3.254",
|
||||||
|
+ }
|
||||||
|
+ ],
|
||||||
|
+ "ip_address": "172.19.1.34",
|
||||||
|
+ "dns_search": ["example3.com"],
|
||||||
|
+ "dns_nameservers": ["172.19.0.12"],
|
||||||
|
+ "id": "network0",
|
||||||
|
+ }
|
||||||
|
+ ],
|
||||||
|
+ "links": [
|
||||||
|
+ {
|
||||||
|
+ "ethernet_mac_address": "fa:16:3e:ed:9a:59",
|
||||||
|
+ "mtu": None,
|
||||||
|
+ "type": "physical",
|
||||||
|
+ "id": "eth0",
|
||||||
|
+ },
|
||||||
|
+ ],
|
||||||
|
+ },
|
||||||
|
+ "in_macs": {
|
||||||
|
+ "fa:16:3e:ed:9a:59": "eth0",
|
||||||
|
+ },
|
||||||
|
+ "out_sysconfig_opensuse": [
|
||||||
|
+ (
|
||||||
|
+ "etc/sysconfig/network/ifcfg-eth0",
|
||||||
|
+ """
|
||||||
|
+# Created by cloud-init automatically, do not edit.
|
||||||
|
+#
|
||||||
|
+BOOTPROTO=static
|
||||||
|
+IPADDR=172.19.1.34
|
||||||
|
+LLADDR=fa:16:3e:ed:9a:59
|
||||||
|
+NETMASK=255.255.252.0
|
||||||
|
+STARTMODE=auto
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "etc/resolv.conf",
|
||||||
|
+ """
|
||||||
|
+; Created by cloud-init automatically, do not edit.
|
||||||
|
+;
|
||||||
|
+nameserver 172.19.0.12
|
||||||
|
+search example3.com example1.com example2.com
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "etc/NetworkManager/conf.d/99-cloud-init.conf",
|
||||||
|
+ """
|
||||||
|
+# Created by cloud-init automatically, do not edit.
|
||||||
|
+#
|
||||||
|
+[main]
|
||||||
|
+dns = none
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "etc/udev/rules.d/85-persistent-net-cloud-init.rules",
|
||||||
|
+ "".join(
|
||||||
|
+ [
|
||||||
|
+ 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
|
||||||
|
+ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n',
|
||||||
|
+ ]
|
||||||
|
+ ),
|
||||||
|
+ ),
|
||||||
|
+ ],
|
||||||
|
+ "out_sysconfig_rhel": [
|
||||||
|
+ (
|
||||||
|
+ "etc/sysconfig/network-scripts/ifcfg-eth0",
|
||||||
|
+ """
|
||||||
|
+# Created by cloud-init automatically, do not edit.
|
||||||
|
+#
|
||||||
|
+BOOTPROTO=none
|
||||||
|
+DEFROUTE=yes
|
||||||
|
+DEVICE=eth0
|
||||||
|
+DNS1=172.19.0.12
|
||||||
|
+DOMAIN=example3.com
|
||||||
|
+GATEWAY=172.19.3.254
|
||||||
|
+HWADDR=fa:16:3e:ed:9a:59
|
||||||
|
+IPADDR=172.19.1.34
|
||||||
|
+NETMASK=255.255.252.0
|
||||||
|
+ONBOOT=yes
|
||||||
|
+TYPE=Ethernet
|
||||||
|
+USERCTL=no
|
||||||
|
+""".lstrip(),
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "etc/resolv.conf",
|
||||||
|
+ """
|
||||||
|
+; Created by cloud-init automatically, do not edit.
|
||||||
|
+;
|
||||||
|
+nameserver 172.19.0.12
|
||||||
|
+search example3.com example1.com example2.com
|
||||||
|
""".lstrip(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
@@ -646,6 +818,7 @@ may-fail=false
|
||||||
|
address1=172.19.1.34/22
|
||||||
|
route1=0.0.0.0/0,172.19.3.254
|
||||||
|
dns=172.19.0.12;
|
||||||
|
+dns-search=example3.com;
|
||||||
|
|
||||||
|
""".lstrip(),
|
||||||
|
),
|
||||||
|
@@ -653,7 +826,13 @@ dns=172.19.0.12;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in_data": {
|
||||||
|
- "services": [{"type": "dns", "address": "172.19.0.12"}],
|
||||||
|
+ "services": [
|
||||||
|
+ {
|
||||||
|
+ "type": "dns",
|
||||||
|
+ "address": "172.19.0.12",
|
||||||
|
+ "search": "example.com",
|
||||||
|
+ }
|
||||||
|
+ ],
|
||||||
|
"networks": [
|
||||||
|
{
|
||||||
|
"network_id": "public-ipv4",
|
||||||
|
@@ -714,6 +893,7 @@ STARTMODE=auto
|
||||||
|
; Created by cloud-init automatically, do not edit.
|
||||||
|
;
|
||||||
|
nameserver 172.19.0.12
|
||||||
|
+search example.com
|
||||||
|
""".lstrip(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
@@ -761,6 +941,7 @@ USERCTL=no
|
||||||
|
; Created by cloud-init automatically, do not edit.
|
||||||
|
;
|
||||||
|
nameserver 172.19.0.12
|
||||||
|
+search example.com
|
||||||
|
""".lstrip(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
--
|
||||||
|
2.45.1
|
||||||
|
|
247
SOURCES/ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch
Normal file
247
SOURCES/ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
From cfbe83d4a869ab20d385b5058031df0364483bda Mon Sep 17 00:00:00 2001
|
||||||
|
From: James Falcon <james.falcon@canonical.com>
|
||||||
|
Date: Thu, 18 Jul 2024 09:04:54 -0400
|
||||||
|
Subject: [PATCH] fix: Clean cache if no datasource fallback (#5499)
|
||||||
|
|
||||||
|
RH-Author: Ani Sinha <anisinha@redhat.com>
|
||||||
|
RH-MergeRequest: 141: fix: Clean cache if no datasource fallback (#5499)
|
||||||
|
RH-Jira: RHEL-49742
|
||||||
|
RH-Acked-by: xiachen <xiachen@redhat.com>
|
||||||
|
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
|
||||||
|
RH-Commit: [1/1] 64a79c1a6bd06c280aed85032bb55cc60ec1fc2e
|
||||||
|
|
||||||
|
9929a00 added the ability to used a cached datasource when none is
|
||||||
|
found. This was supposed to be per-datasource, but the lack of cache
|
||||||
|
cleaning got applied universally. This commit makes it so cache will be
|
||||||
|
cleaned as it was before if fallback isn't implemented in datasource.
|
||||||
|
|
||||||
|
Fixes GH-5486
|
||||||
|
|
||||||
|
(cherry picked from commit 550c685c98551f65c30832b186fe091721b48477)
|
||||||
|
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||||
|
---
|
||||||
|
cloudinit/stages.py | 1 +
|
||||||
|
.../assets/DataSourceNoCacheNetworkOnly.py | 23 ++++
|
||||||
|
.../assets/DataSourceNoCacheWithFallback.py | 29 +++++
|
||||||
|
.../datasources/test_caching.py | 115 ++++++++++++++++++
|
||||||
|
tests/integration_tests/instances.py | 4 +-
|
||||||
|
5 files changed, 171 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py
|
||||||
|
create mode 100644 tests/integration_tests/assets/DataSourceNoCacheWithFallback.py
|
||||||
|
create mode 100644 tests/integration_tests/datasources/test_caching.py
|
||||||
|
|
||||||
|
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
|
||||||
|
index 0b795624..ace94c9a 100644
|
||||||
|
--- a/cloudinit/stages.py
|
||||||
|
+++ b/cloudinit/stages.py
|
||||||
|
@@ -378,6 +378,7 @@ class Init:
|
||||||
|
ds,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
+ util.del_file(self.paths.instance_link)
|
||||||
|
raise e
|
||||||
|
self.datasource = ds
|
||||||
|
# Ensure we adjust our path members datasource
|
||||||
|
diff --git a/tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py b/tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..54a7bab3
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py
|
||||||
|
@@ -0,0 +1,23 @@
|
||||||
|
+import logging
|
||||||
|
+
|
||||||
|
+from cloudinit import sources
|
||||||
|
+
|
||||||
|
+LOG = logging.getLogger(__name__)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class DataSourceNoCacheNetworkOnly(sources.DataSource):
|
||||||
|
+ def _get_data(self):
|
||||||
|
+ LOG.debug("TEST _get_data called")
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+datasources = [
|
||||||
|
+ (
|
||||||
|
+ DataSourceNoCacheNetworkOnly,
|
||||||
|
+ (sources.DEP_FILESYSTEM, sources.DEP_NETWORK),
|
||||||
|
+ ),
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def get_datasource_list(depends):
|
||||||
|
+ return sources.list_from_depends(depends, datasources)
|
||||||
|
diff --git a/tests/integration_tests/assets/DataSourceNoCacheWithFallback.py b/tests/integration_tests/assets/DataSourceNoCacheWithFallback.py
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..fdfc473f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/integration_tests/assets/DataSourceNoCacheWithFallback.py
|
||||||
|
@@ -0,0 +1,29 @@
|
||||||
|
+import logging
|
||||||
|
+import os
|
||||||
|
+
|
||||||
|
+from cloudinit import sources
|
||||||
|
+
|
||||||
|
+LOG = logging.getLogger(__name__)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class DataSourceNoCacheWithFallback(sources.DataSource):
|
||||||
|
+ def _get_data(self):
|
||||||
|
+ if os.path.exists("/ci-test-firstboot"):
|
||||||
|
+ LOG.debug("TEST _get_data called")
|
||||||
|
+ return True
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+ def check_if_fallback_is_allowed(self):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+datasources = [
|
||||||
|
+ (
|
||||||
|
+ DataSourceNoCacheWithFallback,
|
||||||
|
+ (sources.DEP_FILESYSTEM,),
|
||||||
|
+ ),
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def get_datasource_list(depends):
|
||||||
|
+ return sources.list_from_depends(depends, datasources)
|
||||||
|
diff --git a/tests/integration_tests/datasources/test_caching.py b/tests/integration_tests/datasources/test_caching.py
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..33e4b671
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/integration_tests/datasources/test_caching.py
|
||||||
|
@@ -0,0 +1,115 @@
|
||||||
|
+import pytest
|
||||||
|
+
|
||||||
|
+from tests.integration_tests import releases, util
|
||||||
|
+from tests.integration_tests.instances import IntegrationInstance
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def setup_custom_datasource(client: IntegrationInstance, datasource_name: str):
|
||||||
|
+ client.write_to_file(
|
||||||
|
+ "/etc/cloud/cloud.cfg.d/99-imds.cfg",
|
||||||
|
+ f"datasource_list: [ {datasource_name}, None ]\n"
|
||||||
|
+ "datasource_pkg_list: [ cisources ]",
|
||||||
|
+ )
|
||||||
|
+ assert client.execute(
|
||||||
|
+ "mkdir -p /usr/lib/python3/dist-packages/cisources"
|
||||||
|
+ )
|
||||||
|
+ client.push_file(
|
||||||
|
+ util.ASSETS_DIR / f"DataSource{datasource_name}.py",
|
||||||
|
+ "/usr/lib/python3/dist-packages/cisources/"
|
||||||
|
+ f"DataSource{datasource_name}.py",
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def verify_no_cache_boot(client: IntegrationInstance):
|
||||||
|
+ log = client.read_from_file("/var/log/cloud-init.log")
|
||||||
|
+ util.verify_ordered_items_in_text(
|
||||||
|
+ [
|
||||||
|
+ "No local datasource found",
|
||||||
|
+ "running 'init'",
|
||||||
|
+ "no cache found",
|
||||||
|
+ "Detected platform",
|
||||||
|
+ "TEST _get_data called",
|
||||||
|
+ ],
|
||||||
|
+ text=log,
|
||||||
|
+ )
|
||||||
|
+ util.verify_clean_boot(client)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.skipif(
|
||||||
|
+ not releases.IS_UBUNTU,
|
||||||
|
+ reason="hardcoded dist-packages directory",
|
||||||
|
+)
|
||||||
|
+def test_no_cache_network_only(client: IntegrationInstance):
|
||||||
|
+ """Test cache removal per boot. GH-5486
|
||||||
|
+
|
||||||
|
+ This tests the CloudStack password reset use case. The expectation is:
|
||||||
|
+ - Metadata is fetched in network timeframe only
|
||||||
|
+ - Because `check_instance_id` is not defined, no cached datasource
|
||||||
|
+ is found in the init-local phase, but the cache is used in the
|
||||||
|
+ remaining phases due to existance of /run/cloud-init/.instance-id
|
||||||
|
+ - Because `check_if_fallback_is_allowed` is not defined, cloud-init
|
||||||
|
+ does NOT fall back to the pickled datasource, and will
|
||||||
|
+ instead delete the cache during the init-local phase
|
||||||
|
+ - Metadata is therefore fetched every boot in the network phase
|
||||||
|
+ """
|
||||||
|
+ setup_custom_datasource(client, "NoCacheNetworkOnly")
|
||||||
|
+
|
||||||
|
+ # Run cloud-init as if first boot
|
||||||
|
+ assert client.execute("cloud-init clean --logs")
|
||||||
|
+ client.restart()
|
||||||
|
+
|
||||||
|
+ verify_no_cache_boot(client)
|
||||||
|
+
|
||||||
|
+ # Clear the log without clean and run cloud-init for subsequent boot
|
||||||
|
+ assert client.execute("echo '' > /var/log/cloud-init.log")
|
||||||
|
+ client.restart()
|
||||||
|
+
|
||||||
|
+ verify_no_cache_boot(client)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.skipif(
|
||||||
|
+ not releases.IS_UBUNTU,
|
||||||
|
+ reason="hardcoded dist-packages directory",
|
||||||
|
+)
|
||||||
|
+def test_no_cache_with_fallback(client: IntegrationInstance):
|
||||||
|
+ """Test we use fallback when defined and no cache available."""
|
||||||
|
+ setup_custom_datasource(client, "NoCacheWithFallback")
|
||||||
|
+
|
||||||
|
+ # Run cloud-init as if first boot
|
||||||
|
+ assert client.execute("cloud-init clean --logs")
|
||||||
|
+ # Used by custom datasource
|
||||||
|
+ client.execute("touch /ci-test-firstboot")
|
||||||
|
+ client.restart()
|
||||||
|
+
|
||||||
|
+ log = client.read_from_file("/var/log/cloud-init.log")
|
||||||
|
+ util.verify_ordered_items_in_text(
|
||||||
|
+ [
|
||||||
|
+ "no cache found",
|
||||||
|
+ "Detected platform",
|
||||||
|
+ "TEST _get_data called",
|
||||||
|
+ "running 'init'",
|
||||||
|
+ "restored from cache with run check",
|
||||||
|
+ "running 'modules:config'",
|
||||||
|
+ ],
|
||||||
|
+ text=log,
|
||||||
|
+ )
|
||||||
|
+ util.verify_clean_boot(client)
|
||||||
|
+
|
||||||
|
+ # Clear the log without clean and run cloud-init for subsequent boot
|
||||||
|
+ assert client.execute("echo '' > /var/log/cloud-init.log")
|
||||||
|
+ client.execute("rm /ci-test-firstboot")
|
||||||
|
+ client.restart()
|
||||||
|
+
|
||||||
|
+ log = client.read_from_file("/var/log/cloud-init.log")
|
||||||
|
+ util.verify_ordered_items_in_text(
|
||||||
|
+ [
|
||||||
|
+ "cache invalid in datasource",
|
||||||
|
+ "Detected platform",
|
||||||
|
+ "Restored fallback datasource from checked cache",
|
||||||
|
+ "running 'init'",
|
||||||
|
+ "restored from cache with run check",
|
||||||
|
+ "running 'modules:config'",
|
||||||
|
+ ],
|
||||||
|
+ text=log,
|
||||||
|
+ )
|
||||||
|
+ util.verify_clean_boot(client)
|
||||||
|
diff --git a/tests/integration_tests/instances.py b/tests/integration_tests/instances.py
|
||||||
|
index 3fc6558a..23c0dc98 100644
|
||||||
|
--- a/tests/integration_tests/instances.py
|
||||||
|
+++ b/tests/integration_tests/instances.py
|
||||||
|
@@ -88,7 +88,9 @@ class IntegrationInstance:
|
||||||
|
# First push to a temporary directory because of permissions issues
|
||||||
|
tmp_path = _get_tmp_path()
|
||||||
|
self.instance.push_file(str(local_path), tmp_path)
|
||||||
|
- assert self.execute("mv {} {}".format(tmp_path, str(remote_path))).ok
|
||||||
|
+ assert self.execute(
|
||||||
|
+ "mv {} {}".format(tmp_path, str(remote_path))
|
||||||
|
+ ), f"Failed to push {tmp_path} to {remote_path}"
|
||||||
|
|
||||||
|
def read_from_file(self, remote_path) -> str:
|
||||||
|
result = self.execute("cat {}".format(remote_path))
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
From 6e3c351b013dc2ac01035853229ffdfdafa3afa8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brett Holman <brett.holman@canonical.com>
|
||||||
|
Date: Wed, 3 Jan 2024 09:11:40 -0700
|
||||||
|
Subject: [PATCH] fix(cloudstack): Use parsed lease file for virtual router in
|
||||||
|
cloudstack
|
||||||
|
|
||||||
|
RH-Author: Ani Sinha <anisinha@redhat.com>
|
||||||
|
RH-MergeRequest: 137: fix(cloudstack): Use parsed lease file for virtual router in cloudstack
|
||||||
|
RH-Jira: RHEL-40418
|
||||||
|
RH-Acked-by: Cathy Avery <cavery@redhat.com>
|
||||||
|
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||||
|
RH-Commit: [1/1] 77f97c04432fffff125dc1725d66b33ae0ab4af8
|
||||||
|
|
||||||
|
Fixes 5942f4023e2581a
|
||||||
|
|
||||||
|
(cherry picked from commit cb36bf38b823f811a3e938ccffc03d7d13190095)
|
||||||
|
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||||
|
---
|
||||||
|
cloudinit/sources/DataSourceCloudStack.py | 22 +++++++++++-----------
|
||||||
|
1 file changed, 11 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py
|
||||||
|
index fd2482a3..f752765d 100644
|
||||||
|
--- a/cloudinit/sources/DataSourceCloudStack.py
|
||||||
|
+++ b/cloudinit/sources/DataSourceCloudStack.py
|
||||||
|
@@ -229,18 +229,18 @@ def get_vr_address():
|
||||||
|
)
|
||||||
|
return latest_address
|
||||||
|
|
||||||
|
- # Try dhcp lease files next...
|
||||||
|
+ # Try dhcp lease files next
|
||||||
|
lease_file = dhcp.IscDhclient.get_latest_lease()
|
||||||
|
- if not lease_file:
|
||||||
|
- LOG.debug("No lease file found, using default gateway")
|
||||||
|
- return get_default_gateway()
|
||||||
|
-
|
||||||
|
- lease_file = dhcp.IscDhclient.parse_dhcp_server_from_lease_file(lease_file)
|
||||||
|
- if not latest_address:
|
||||||
|
- # No virtual router found, fallback on default gateway
|
||||||
|
- LOG.debug("No DHCP found, using default gateway")
|
||||||
|
- return get_default_gateway()
|
||||||
|
- return latest_address
|
||||||
|
+ if lease_file:
|
||||||
|
+ latest_address = dhcp.IscDhclient.parse_dhcp_server_from_lease_file(
|
||||||
|
+ lease_file
|
||||||
|
+ )
|
||||||
|
+ if latest_address:
|
||||||
|
+ return latest_address
|
||||||
|
+
|
||||||
|
+ # No virtual router found, fallback to default gateway
|
||||||
|
+ LOG.debug("No DHCP found, using default gateway")
|
||||||
|
+ return get_default_gateway()
|
||||||
|
|
||||||
|
|
||||||
|
# Used to match classes to dependencies
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Name: cloud-init
|
Name: cloud-init
|
||||||
Version: 23.4
|
Version: 23.4
|
||||||
Release: 7%{?dist}.3
|
Release: 7%{?dist}.7
|
||||||
Summary: Cloud instance init scripts
|
Summary: Cloud instance init scripts
|
||||||
|
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
@ -49,6 +49,12 @@ Patch26: ci-fix-Undeprecate-network-in-schema-route-definition-5.patch
|
|||||||
Patch27: ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch
|
Patch27: ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch
|
||||||
# For RHEL-36701 - DataSourceNoCloudNet not configurable via config files [rhel-8.10.z]
|
# For RHEL-36701 - DataSourceNoCloudNet not configurable via config files [rhel-8.10.z]
|
||||||
Patch28: ci-fix-Always-use-single-datasource-if-specified-5098.patch
|
Patch28: ci-fix-Always-use-single-datasource-if-specified-5098.patch
|
||||||
|
# For RHEL-40418 - [Cloud-init] CloudstackDataSource cannot work with NetworkManager [rhel-8.10.z]
|
||||||
|
Patch29: ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch
|
||||||
|
# For RHEL-46013 - [RHEL-8] cloud-init fails to configure DNS search domains [rhel-8.10.z]
|
||||||
|
Patch30: ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch
|
||||||
|
# For RHEL-49742 - [Cloud-init] [RHEL-8.10] Password reset feature broken with CloudstackDataSource
|
||||||
|
Patch31: ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch
|
||||||
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
@ -264,6 +270,21 @@ fi
|
|||||||
%config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
|
%config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jul 25 2024 Miroslav Rezanina <mrezanin@redhat.com> - 23.4-7.el8_10.7
|
||||||
|
- ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch [RHEL-49742]
|
||||||
|
- Resolves: RHEL-49742
|
||||||
|
([Cloud-init] [RHEL-8.10] Password reset feature broken with CloudstackDataSource)
|
||||||
|
|
||||||
|
* Tue Jul 09 2024 Jon Maloy <jmaloy@redhat.com> - 23.4-7.el8_10.6
|
||||||
|
- ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch [RHEL-46013]
|
||||||
|
- Resolves: RHEL-46013
|
||||||
|
([RHEL-8] cloud-init fails to configure DNS search domains [rhel-8.10.z])
|
||||||
|
|
||||||
|
* Tue Jul 09 2024 Miroslav Rezanina <mrezanin@redhat.com> - 23.4-7.el8_10.5
|
||||||
|
- ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch [RHEL-40418]
|
||||||
|
- Resolves: RHEL-40418
|
||||||
|
([Cloud-init] CloudstackDataSource cannot work with NetworkManager [rhel-8.10.z])
|
||||||
|
|
||||||
* Wed May 29 2024 Jon Maloy <jmaloy@redhat.com> - 23.4-7.el8.3
|
* Wed May 29 2024 Jon Maloy <jmaloy@redhat.com> - 23.4-7.el8.3
|
||||||
- ci-fix-Always-use-single-datasource-if-specified-5098.patch [RHEL-36701]
|
- ci-fix-Always-use-single-datasource-if-specified-5098.patch [RHEL-36701]
|
||||||
- Resolves: RHEL-36701
|
- Resolves: RHEL-36701
|
||||||
|
Loading…
Reference in New Issue
Block a user