← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~raharper/cloud-init:fix/sysconfig-skip-resolvconf-no-dns-config into cloud-init:master

 

Ryan Harper has proposed merging ~raharper/cloud-init:fix/sysconfig-skip-resolvconf-no-dns-config into cloud-init:master.

Commit message:
sysconfig: only write resolv.conf if network_state has DNS values
    
If an OS image provided an /etc/resolv.conf file that was not empty
cloud-init would read and re-write it with a cloud-init header even
if no DNS network configuration was provided (e.g. DHCP only).
    
This can cause problems for some network services which don't
ignore cloud-init's header.
    
LP: #1843634

Requested reviews:
  cloud-init Commiters (cloud-init-dev)
Related bugs:
  Bug #1843634 in cloud-init: "cloud-init misconfigure the network on SLES"
  https://bugs.launchpad.net/cloud-init/+bug/1843634

For more details, see:
https://code.launchpad.net/~raharper/cloud-init/+git/cloud-init/+merge/372727
-- 
Your team cloud-init Commiters is requested to review the proposed merge of ~raharper/cloud-init:fix/sysconfig-skip-resolvconf-no-dns-config into cloud-init:master.
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index be5dede..ccc7b85 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -585,7 +585,10 @@ class Renderer(renderer.Renderer):
             content.add_nameserver(nameserver)
         for searchdomain in network_state.dns_searchdomains:
             content.add_search_domain(searchdomain)
-        if not str(content):
+        # content may included existing values, skip writing resolv.conf
+        # if network_state doesn't include any input.
+        if not any([len(network_state.dns_nameservers),
+                    len(network_state.dns_searchdomains)]):
             return None
         header = _make_header(';')
         content_str = str(content)
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index e578992..82eb18f 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -2701,6 +2701,10 @@ USERCTL=no
         ns = network_state.parse_net_config_data(CONFIG_V1_EXPLICIT_LOOPBACK)
         render_dir = self.tmp_path("render")
         os.makedirs(render_dir)
+        # write an etc/resolv.conf and expect it to not be modified
+        resolvconf = os.path.join(render_dir, 'etc/resolv.conf')
+        content = "# Original Content"
+        util.write_file(resolvconf, content)
         renderer = self._get_renderer()
         renderer.render_network_state(ns, target=render_dir)
         found = dir2dict(render_dir)
@@ -2718,6 +2722,8 @@ TYPE=Ethernet
 USERCTL=no
 """
         self.assertEqual(expected, found[nspath + 'ifcfg-eth0'])
+        # a dhcp only config should not modify resolv.conf
+        self.assertEqual(content, found['/etc/resolv.conf'])
 
     def test_bond_config(self):
         expected_name = 'expected_sysconfig_rhel'
@@ -3202,6 +3208,10 @@ USERCTL=no
         ns = network_state.parse_net_config_data(CONFIG_V1_EXPLICIT_LOOPBACK)
         render_dir = self.tmp_path("render")
         os.makedirs(render_dir)
+        # write an etc/resolv.conf and expect it to not be modified
+        resolvconf = os.path.join(render_dir, 'etc/resolv.conf')
+        content = "# Original Content"
+        util.write_file(resolvconf, content)
         renderer = self._get_renderer()
         renderer.render_network_state(ns, target=render_dir)
         found = dir2dict(render_dir)
@@ -3219,6 +3229,8 @@ TYPE=Ethernet
 USERCTL=no
 """
         self.assertEqual(expected, found[nspath + 'ifcfg-eth0'])
+        # a dhcp only config should not modify resolv.conf
+        self.assertEqual(content, found['/etc/resolv.conf'])
 
     def test_bond_config(self):
         expected_name = 'expected_sysconfig_opensuse'

Follow ups