summaryrefslogtreecommitdiff
path: root/cloudinit/net/network_state.py
diff options
context:
space:
mode:
authorJames Falcon <TheRealFalcon@users.noreply.github.com>2021-06-17 16:44:55 -0500
committerGitHub <noreply@github.com>2021-06-17 15:44:55 -0600
commitabd2da5777195e7e432b0d53a3f7f29d071dd50e (patch)
treed08a094ccaca374b8a2ab6caa23890e417ac1133 /cloudinit/net/network_state.py
parentfbcb224bc12495ba200ab107246349d802c5d8e6 (diff)
downloadvyos-cloud-init-abd2da5777195e7e432b0d53a3f7f29d071dd50e.tar.gz
vyos-cloud-init-abd2da5777195e7e432b0d53a3f7f29d071dd50e.zip
Fix DNS in NetworkState (SC-133) (#923)
v1 network config currently has no concept of interface-specific DNS, which is required for certain renderers. To fix this, added an optional 'interface' key on the v1 nameserver definition. If specified, it makes the DNS settings specific to the interface. Otherwise, it will be defined as global DNS as it always has. Additionally, DNS for v2 wasn't being recognized correctly. For DNS defined on a particular interface, these settings now also go into the global DNS settings as they were intended.
Diffstat (limited to 'cloudinit/net/network_state.py')
-rw-r--r--cloudinit/net/network_state.py66
1 files changed, 51 insertions, 15 deletions
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index e8bf9e39..8018cfb9 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -237,6 +237,7 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
self._network_state = copy.deepcopy(self.initial_network_state)
self._network_state['config'] = config
self._parsed = False
+ self._interface_dns_map = {}
@property
def network_state(self):
@@ -310,6 +311,21 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
LOG.warning("Skipping invalid command: %s", command,
exc_info=True)
LOG.debug(self.dump_network_state())
+ for interface, dns in self._interface_dns_map.items():
+ iface = None
+ try:
+ iface = self._network_state['interfaces'][interface]
+ except KeyError as e:
+ raise ValueError(
+ 'Nameserver specified for interface {0}, '
+ 'but interface {0} does not exist!'.format(interface)
+ ) from e
+ if iface:
+ nameservers, search = dns
+ iface['dns'] = {
+ 'addresses': nameservers,
+ 'search': search,
+ }
def parse_config_v2(self, skip_broken=True):
for command_type, command in self._config.items():
@@ -526,21 +542,40 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
def handle_infiniband(self, command):
self.handle_physical(command)
- @ensure_command_keys(['address'])
- def handle_nameserver(self, command):
- dns = self._network_state.get('dns')
+ def _parse_dns(self, command):
+ nameservers = []
+ search = []
if 'address' in command:
addrs = command['address']
if not type(addrs) == list:
addrs = [addrs]
for addr in addrs:
- dns['nameservers'].append(addr)
+ nameservers.append(addr)
if 'search' in command:
paths = command['search']
if not isinstance(paths, list):
paths = [paths]
for path in paths:
- dns['search'].append(path)
+ search.append(path)
+ return nameservers, search
+
+ @ensure_command_keys(['address'])
+ def handle_nameserver(self, command):
+ dns = self._network_state.get('dns')
+ nameservers, search = self._parse_dns(command)
+ if 'interface' in command:
+ self._interface_dns_map[command['interface']] = (
+ nameservers, search
+ )
+ else:
+ dns['nameservers'].extend(nameservers)
+ dns['search'].extend(search)
+
+ @ensure_command_keys(['address'])
+ def _handle_individual_nameserver(self, command, iface):
+ _iface = self._network_state.get('interfaces')
+ nameservers, search = self._parse_dns(command)
+ _iface[iface]['dns'] = {'nameservers': nameservers, 'search': search}
@ensure_command_keys(['destination'])
def handle_route(self, command):
@@ -706,16 +741,17 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
def _v2_common(self, cfg):
LOG.debug('v2_common: handling config:\n%s', cfg)
- if 'nameservers' in cfg:
- search = cfg.get('nameservers').get('search', [])
- dns = cfg.get('nameservers').get('addresses', [])
- name_cmd = {'type': 'nameserver'}
- if len(search) > 0:
- name_cmd.update({'search': search})
- if len(dns) > 0:
- name_cmd.update({'addresses': dns})
- LOG.debug('v2(nameserver) -> v1(nameserver):\n%s', name_cmd)
- self.handle_nameserver(name_cmd)
+ for iface, dev_cfg in cfg.items():
+ if 'nameservers' in dev_cfg:
+ search = dev_cfg.get('nameservers').get('search', [])
+ dns = dev_cfg.get('nameservers').get('addresses', [])
+ name_cmd = {'type': 'nameserver'}
+ if len(search) > 0:
+ name_cmd.update({'search': search})
+ if len(dns) > 0:
+ name_cmd.update({'address': dns})
+ self.handle_nameserver(name_cmd)
+ self._handle_individual_nameserver(name_cmd, iface)
def _handle_bond_bridge(self, command, cmd_type=None):
"""Common handler for bond and bridge types"""