From ab36aacfb2f98d865d9e03df81f9102b04d307dd Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Tue, 5 Nov 2024 04:07:36 +0530 Subject: [PATCH] Prevent NM from handling DNS when network interfaces have DNS config (#5846) RH-Author: Ani Sinha RH-MergeRequest: 117: Prevent NM from handling DNS when network interfaces have DNS config (#5846) RH-Jira: RHEL-65769 RH-Acked-by: Emanuele Giuseppe Esposito RH-Acked-by: Miroslav Rezanina RH-Commit: [1/1] cc175ec567ba5500f2a69d7943e8d5ee5c3822c8 (anisinha/cloud-init) In the change under PR #5401, we use global DNS configuration as well as DNS and search domain information from interface config and use it to populate /etc/resolv.conf. Therefore, if either or both global DNS/search domain config is present along with per-interface DNS/search domain information, we should add a network manager configuration to prevent network manager from manipulating /etc/resolv.conf. This is in addition to what we already do when only global DNS data is configured. Fixes bug added in 1b8030e0 . Signed-off-by: Ani Sinha (cherry picked from commit 2df49b652471999434f06d9d83ed9db8b4055895) --- cloudinit/net/sysconfig.py | 26 +++++- tests/unittests/test_net.py | 158 ++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 4 deletions(-) diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py index 96652e15..363d052a 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py @@ -907,17 +907,35 @@ class Renderer(renderer.Renderer): @staticmethod def _render_networkmanager_conf(network_state, templates=None): + iface_dns = False content = networkmanager_conf.NetworkManagerConf("") + # check if there is interface specific DNS information configured + for iface in network_state.iter_interfaces(): + for subnet in iface["subnets"]: + if "dns_nameservers" in subnet or "dns_search" in subnet: + iface_dns = True + break + if ( + not iface_dns + and "dns" in iface + and (iface["dns"]["nameservers"] or iface["dns"]["search"]) + ): + iface_dns = True + break - # If DNS server information is provided, configure - # NetworkManager to not manage dns, so that /etc/resolv.conf - # does not get clobbered. + # If DNS server and/or dns search information is provided either + # globally or per interface basis, configure NetworkManager to + # not manage dns, so that /etc/resolv.conf does not get clobbered. # This is not required for NetworkManager renderer as it # does not write /etc/resolv.conf directly. DNS information is # written to the interface keyfile and NetworkManager is then # responsible for using the DNS information from the keyfile, # including managing /etc/resolv.conf. - if network_state.dns_nameservers: + if ( + network_state.dns_nameservers + or network_state.dns_searchdomains + or iface_dns + ): content.set_section_keypair("main", "dns", "none") if len(content) == 0: diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py index 8a75c42b..215807ba 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -967,6 +967,164 @@ dns = none ), ], }, + { + "in_data": { + "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 +""".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. +# +AUTOCONNECT_PRIORITY=120 +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 +""".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.12; +dns-search=example3.com; + +""".lstrip(), + ), + ], + }, { "in_data": { "services": [{"type": "dns", "address": "172.19.0.12"}], -- 2.39.3