write dns info to networkd

Write dns info to networkd so it can be consumed by resolved if resolved
is enabled.

Change-Id: Ia7b55e9a538cc6f060bc08da85123d7bb3a4f73e
This commit is contained in:
Matthew Thode 2018-10-12 11:40:54 -05:00 committed by Clark Boylan
parent 9f629b8531
commit 84f6dd118a
4 changed files with 116 additions and 11 deletions

View File

@ -31,6 +31,16 @@ from glean import systemlock
from glean import utils
from glean._vendor import distro
try:
import configparser
except ImportError:
import ConfigParser as configparser
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
log = logging.getLogger("glean")
@ -312,7 +322,7 @@ def write_redhat_interfaces(interfaces, sys_interfaces, distro):
return files_to_write
def _write_networkd_interface(name, interfaces, files_struct=dict()):
def _write_networkd_interface(name, interfaces, args, files_struct=dict()):
vlans = []
for interface in interfaces:
iname = name
@ -340,6 +350,15 @@ def _write_networkd_interface(name, interfaces, files_struct=dict()):
('bond_mode' in interface)):
if '[Network]' not in files_struct[network_file]:
files_struct[network_file]['[Network]'] = list()
if 'services' in interface:
for service in interface['services']:
if service['type'] == 'dns':
if not args.skip_dns:
files_struct[network_file]['[Network]'].append(
'DNS={address}'.format(
address=service['address']
)
)
# dhcp network, set to yes if both dhcp6 and dhcp4 are set
if interface['type'] == 'ipv4_dhcp':
if 'DHCP=ipv6' in files_struct[network_file]['[Network]']:
@ -492,7 +511,7 @@ def _write_networkd_interface(name, interfaces, files_struct=dict()):
return files_struct
def write_networkd_interfaces(interfaces, sys_interfaces):
def write_networkd_interfaces(interfaces, sys_interfaces, args):
files_to_write = dict()
gen_intfs = {}
files_struct = dict()
@ -531,7 +550,7 @@ def write_networkd_interfaces(interfaces, sys_interfaces):
intf.get('link', intf['id']) for intf in interfs
if 'bond_mode' in intf)
files_struct = _write_networkd_interface(
interface_name, interfs, files_struct)
interface_name, interfs, args, files_struct)
for mac, iname in sorted(
sys_interfaces.items(), key=lambda x: x[1]):
@ -545,7 +564,7 @@ def write_networkd_interfaces(interfaces, sys_interfaces):
continue
interface = {'type': 'ipv4_dhcp', 'mac_address': mac}
files_struct = _write_networkd_interface(
iname, [interface], files_struct)
iname, [interface], args, files_struct)
for networkd_file in files_struct:
file_contents = '# Automatically generated, do not edit\n'
@ -912,10 +931,30 @@ def write_debian_interfaces(interfaces, sys_interfaces):
def write_dns_info(dns_servers):
results = ""
resolve_confs = {}
resolv_nameservers = ""
for server in dns_servers:
results += "nameserver {0}\n".format(server)
return {'/etc/resolv.conf': results}
resolv_nameservers += "nameserver {0}\n".format(server)
resolve_confs['/etc/resolv.conf'] = resolv_nameservers
# set up resolved if available
if os.path.isfile('/etc/systemd/resolved.conf'):
# read the existing config so we only overwrite what's needed
resolved_conf = configparser.ConfigParser()
resolved_conf.read('/etc/systemd/resolved.conf')
# create config section if not created
if not resolved_conf.has_section('Resolve'):
resolved_conf.add_section('Resolve')
# write space separated dns servers
resolved_conf.set('Resolve', 'DNS', " ".join(dns_servers))
# use stringio to output the resulting config to string
# configparser only outputs to file descriptors
resolved_conf_fd = StringIO("")
resolved_conf.write(resolved_conf_fd)
resolved_conf_output = resolved_conf_fd.getvalue()
resolved_conf_fd.close()
# add the config to files to be written
resolve_confs['/etc/systemd/resolved.conf'] = resolved_conf_output
return resolve_confs
def get_config_drive_interfaces(net):
@ -1012,7 +1051,7 @@ def write_static_network_info(
)
elif args.distro in 'networkd':
files_to_write.update(
write_networkd_interfaces(interfaces, sys_interfaces)
write_networkd_interfaces(interfaces, sys_interfaces, args)
)
else:
return False

View File

@ -43,7 +43,17 @@
}
],
"ip_address": "2001:4802:7807:103:be76:4eff:fe20:d72f",
"id": "network1"
"id": "network1",
"services": [
{
"address": "1111:2222:3333:4444::1234",
"type": "dns"
},
{
"address": "1.2.3.4",
"type": "dns"
}
]
},
{
"network_id": "11111111-1111-1111-1111-111111111111",

View File

@ -0,0 +1,52 @@
### Write /etc/resolv.conf
nameserver 69.20.0.196
nameserver 69.20.0.164
### Write /etc/systemd/network/eth0.network
# Automatically generated, do not edit
[Match]
MACAddress=bc:76:4e:20:d7:2f
Name=eth0
[Network]
DNS=1.2.3.4
DNS=1111:2222:3333:4444::1234
IPv6AcceptRA=no
[Address]
Address=146.20.110.113/24
[Address]
Address=2001:4802:7807:103:be76:4eff:fe20:d72f/64
[Route]
Destination=0.0.0.0/0
Gateway=146.20.110.1
[Route]
Destination=::/0
Gateway=fe80::def
[Route]
Destination=fd30::/48
Gateway=fe80::f001
### Write /etc/systemd/network/eth1.network
# Automatically generated, do not edit
[Match]
MACAddress=bc:76:4e:20:d7:33
Name=eth1
[Network]
IPv6AcceptRA=no
[Address]
Address=10.210.32.174/19
[Route]
Destination=10.176.0.0/12
Gateway=10.210.32.1
[Route]
Destination=10.208.0.0/12
Gateway=10.210.32.1

View File

@ -85,7 +85,7 @@ class TestGlean(base.BaseTestCase):
'/etc/conf.d', '/etc/init.d', '/etc/sysconfig/network',
'/etc/systemd/network')
mock_files = ('/etc/resolv.conf', '/etc/hostname', '/etc/hosts',
'/bin/systemctl')
'/etc/systemd/resolved.conf', '/bin/systemctl')
if (path.startswith(mock_dirs) or path in mock_files):
try:
mock_handle = self.file_handle_mocks[path]
@ -193,6 +193,9 @@ class TestGlean(base.BaseTestCase):
output_filename = '%s.%s.network.out' % (provider, distro.lower())
output_path = os.path.join(sample_data_path, 'test', output_filename)
if not skip_dns:
if os.path.exists(output_path + '.dns'):
output_path = output_path + '.dns'
# Generate a list of (dest, content) into write_blocks to assert
write_blocks = []
@ -260,7 +263,8 @@ class TestGlean(base.BaseTestCase):
# comes up with "--interface". This simulates that.
def test_glean_systemd(self):
with mock.patch('glean.systemlock.Lock'):
self._assert_distro_provider(self.distro, self.style, 'eth0')
self._assert_distro_provider(self.distro, self.style,
'eth0', skip_dns=True)
def test_glean_skip_dns(self):
with mock.patch('glean.systemlock.Lock'):