Skip to content

Commit

Permalink
feat(sysconfig): Add DNS from interface config to resolv.conf (#5401)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ani-sinha committed Jun 20, 2024
1 parent 92f187a commit 1b8030e
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 6 deletions.
52 changes: 47 additions & 5 deletions cloudinit/net/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,11 +824,53 @@ def _render_vlan_interfaces(cls, network_state, iface_contents, flavor):

@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
Expand All @@ -837,9 +879,9 @@ def _render_dns(network_state, existing_dns_path=None):
content = resolv_conf.ResolvConf(
util.load_text_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)
Expand Down
183 changes: 182 additions & 1 deletion tests/unittests/test_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@
}
],
"ip_address": "172.19.1.34",
"dns_search": ["testweb.com"],
"dns_nameservers": ["172.19.0.13"],
"id": "network0",
}
],
Expand Down Expand Up @@ -549,7 +551,9 @@
"""
; Created by cloud-init automatically, do not edit.
;
nameserver 172.19.0.13
nameserver 172.19.0.12
search testweb.com
""".lstrip(),
),
(
Expand Down Expand Up @@ -580,6 +584,8 @@
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
Expand All @@ -594,7 +600,173 @@
"""
; 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(),
),
(
Expand Down Expand Up @@ -645,14 +817,21 @@
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"}],
"services": [
{
"type": "dns",
"address": "172.19.0.12",
"search": "example.com",
}
],
"networks": [
{
"network_id": "public-ipv4",
Expand Down Expand Up @@ -713,6 +892,7 @@
; Created by cloud-init automatically, do not edit.
;
nameserver 172.19.0.12
search example.com
""".lstrip(),
),
(
Expand Down Expand Up @@ -760,6 +940,7 @@
; Created by cloud-init automatically, do not edit.
;
nameserver 172.19.0.12
search example.com
""".lstrip(),
),
(
Expand Down

0 comments on commit 1b8030e

Please sign in to comment.