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

Proposed by Ryan Harper
Status: Merged
Approved by: Ryan Harper
Approved revision: 6ac5b74e1a91cfad0edb999bfbbad9715ccd68a2
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~raharper/cloud-init:fix/sysconfig-skip-resolvconf-no-dns-config
Merge into: cloud-init:master
Diff against target: 68 lines (+16/-2)
2 files modified
cloudinit/net/sysconfig.py (+4/-2)
tests/unittests/test_net.py (+12/-0)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Dan Watkins Approve
Review via email: mp+372727@code.launchpad.net

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

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:cc70b43e9becd6a469ed17430c5907b85b5f2b2d
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1139/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1139//rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

It can be argued that cloud-init *was* doing the right thing.
It was told that there were no dns servers and no dns 'search' (by lack of that in network config).

dhcp muddies that argument for sure.

That said, based on the content in the description of the bug (the
previously-existing /etc/resolv.conf), cloud-init should *never* be
writing that file when 'netconfig' is involved. It seems rather that
resolv.conf is generated based on contents of
/etc/sysconfig/network/config .

Would writing /etc/sysconfig/network/config with valid content for NETCONFIG_DNS_STATIC_SEARCHLIST and friends fix this?

Revision history for this message
Ryan Harper (raharper) wrote :

Maybe, but I don't think we really wanted to always append a header to the file, and we certainly wanted to avoid writing the file if we didn't have a config. Lastly the side-effect of modifying resolvconf without dns settings disabled system auto-generation.

We do need to be careful w.r.t detecting whether netconfig is present or not. I think that we could replace updating resolvconf directly if netconfig is present. This renderer is shared by a range of SuSE and RHEL releases which may or maynot have netconfig (or something equivalent).

I'd like Robert to comment on whether we want to move to netconfig or not. That can be done incrementally (land this fix of not touching resolv.conf at all if we don't have settings) and then separately replacing writing resolv.conf directly with using netconfig if present.

71a4b90... by Ryan Harper

Move network_state check up to top of _render_dns

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:485384fe14caf0a3da01dfd7d5c79027e2c00161
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1141/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1141//rebuild

review: Approve (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:ac38c650c1b6cb9df4021786d772450470f17aff
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1176/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1176//rebuild

review: Approve (continuous-integration)
Revision history for this message
Dan Watkins (oddbloke) wrote :

One nit inline, so leaving this to Ryan to merge (whether or not the nit is addressed). Thanks!

review: Approve
6ac5b74... by Ryan Harper

Clarify content variable names

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:6ac5b74e1a91cfad0edb999bfbbad9715ccd68a2
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1182/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1182//rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
2index be5dede..1708990 100644
3--- a/cloudinit/net/sysconfig.py
4+++ b/cloudinit/net/sysconfig.py
5@@ -578,6 +578,10 @@ class Renderer(renderer.Renderer):
6
7 @staticmethod
8 def _render_dns(network_state, existing_dns_path=None):
9+ # skip writing resolv.conf if network_state doesn't include any input.
10+ if not any([len(network_state.dns_nameservers),
11+ len(network_state.dns_searchdomains)]):
12+ return None
13 content = resolv_conf.ResolvConf("")
14 if existing_dns_path and os.path.isfile(existing_dns_path):
15 content = resolv_conf.ResolvConf(util.load_file(existing_dns_path))
16@@ -585,8 +589,6 @@ class Renderer(renderer.Renderer):
17 content.add_nameserver(nameserver)
18 for searchdomain in network_state.dns_searchdomains:
19 content.add_search_domain(searchdomain)
20- if not str(content):
21- return None
22 header = _make_header(';')
23 content_str = str(content)
24 if not content_str.startswith(header):
25diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
26index e578992..92c7c3c 100644
27--- a/tests/unittests/test_net.py
28+++ b/tests/unittests/test_net.py
29@@ -2701,6 +2701,10 @@ USERCTL=no
30 ns = network_state.parse_net_config_data(CONFIG_V1_EXPLICIT_LOOPBACK)
31 render_dir = self.tmp_path("render")
32 os.makedirs(render_dir)
33+ # write an etc/resolv.conf and expect it to not be modified
34+ resolvconf = os.path.join(render_dir, 'etc/resolv.conf')
35+ resolvconf_content = "# Original Content"
36+ util.write_file(resolvconf, resolvconf_content)
37 renderer = self._get_renderer()
38 renderer.render_network_state(ns, target=render_dir)
39 found = dir2dict(render_dir)
40@@ -2718,6 +2722,8 @@ TYPE=Ethernet
41 USERCTL=no
42 """
43 self.assertEqual(expected, found[nspath + 'ifcfg-eth0'])
44+ # a dhcp only config should not modify resolv.conf
45+ self.assertEqual(resolvconf_content, found['/etc/resolv.conf'])
46
47 def test_bond_config(self):
48 expected_name = 'expected_sysconfig_rhel'
49@@ -3202,6 +3208,10 @@ USERCTL=no
50 ns = network_state.parse_net_config_data(CONFIG_V1_EXPLICIT_LOOPBACK)
51 render_dir = self.tmp_path("render")
52 os.makedirs(render_dir)
53+ # write an etc/resolv.conf and expect it to not be modified
54+ resolvconf = os.path.join(render_dir, 'etc/resolv.conf')
55+ resolvconf_content = "# Original Content"
56+ util.write_file(resolvconf, resolvconf_content)
57 renderer = self._get_renderer()
58 renderer.render_network_state(ns, target=render_dir)
59 found = dir2dict(render_dir)
60@@ -3219,6 +3229,8 @@ TYPE=Ethernet
61 USERCTL=no
62 """
63 self.assertEqual(expected, found[nspath + 'ifcfg-eth0'])
64+ # a dhcp only config should not modify resolv.conf
65+ self.assertEqual(resolvconf_content, found['/etc/resolv.conf'])
66
67 def test_bond_config(self):
68 expected_name = 'expected_sysconfig_opensuse'

Subscribers

People subscribed via source and target branches