From 31b63085f52c5c3e91f47d12e3cc080a2fbe524d Mon Sep 17 00:00:00 2001 From: gbenhaim Date: Tue, 15 May 2018 21:22:07 +0300 Subject: [PATCH] [WIP] Allow to specify dns forwarders Signed-off-by: gbenhaim --- lago/prefix.py | 3 +- lago/providers/libvirt/network.py | 107 +++++++++++++++++++++--------- 2 files changed, 78 insertions(+), 32 deletions(-) diff --git a/lago/prefix.py b/lago/prefix.py index e51722a5..ae7c44be 100644 --- a/lago/prefix.py +++ b/lago/prefix.py @@ -390,10 +390,11 @@ def _add_dns_records(self, conf, mgmts): LOGGER.debug('Using network %s as main DNS server', dns_mgmt) forward = conf['nets'][dns_mgmt].get('gw') dns_records = {} + for net_name, net_spec in nets.iteritems(): dns_records.update(net_spec['mapping'].copy()) if net_name not in mgmts: - net_spec['dns_forward'] = forward + net_spec['dns_forwarders'] = [{'addr': forward}] for mgmt in mgmts: if nets[mgmt].get('dns_records'): diff --git a/lago/providers/libvirt/network.py b/lago/providers/libvirt/network.py index 66e024c5..9946d860 100644 --- a/lago/providers/libvirt/network.py +++ b/lago/providers/libvirt/network.py @@ -145,35 +145,70 @@ def spec(self): return deepcopy(self._spec) -class NATNetwork(Network): - def _generate_dns_forward(self, forward_ip): - dns = ET.Element('dns', forwardPlainNames='yes') - dns.append(ET.Element('forwarder', addr=forward_ip)) - return dns +class LibvirtDNS(object): + def __init__(self, enable=True, forward_plain_names=True): + if enable: + self._dns = ET.Element( + 'dns', + forwardPlainNames='yes' if forward_plain_names else 'no' + ) + else: + self._dns = ET.Element('dns', enable='no') + + @classmethod + def generate_dns_forward(cls, forwarders): + dns = cls() + dns.add_forwarders(*forwarders) + + return dns.get_xml_object() + + @classmethod + def generate_dns_disable(cls): + dns = cls(enable=False) - def _generate_dns_disable(self): - dns = ET.Element('dns', enable='no') - return dns + return dns.get_xml_object() + + @classmethod + def generate_default_dns(cls): + return cls().get_xml_object() + + @classmethod + def generate_main_dns( + cls, records, forwarders, ipv6_prefix, forward_plain_names + ): + dns = cls(forward_plain_names=False) - def _generate_main_dns(self, records, subnet, forward_plain='no'): - dns = ET.Element('dns', forwardPlainNames=forward_plain) reverse_records = defaultdict(list) - ipv6_prefix = self._ipv6_prefix(subnet=subnet) for hostname, ip in records.iteritems(): reverse_records[ip] = reverse_records[ip] + [hostname] + for ip, hostnames in reverse_records.iteritems(): - record_ipv4 = ET.Element('host', ip=ip) - record_ipv6 = ET.Element('host', ip=ipv6_prefix + ip) - for hostname in sorted(hostnames): - host = ET.Element('hostname') - host.text = hostname - record_ipv4.append(host) - record_ipv6.append(deepcopy(host)) - dns.append(record_ipv4) - dns.append(record_ipv6) - - return dns + dns.add_host(ip, *hostnames) + dns.add_host(ipv6_prefix + ip, *hostnames) + + dns.add_forwarders(forwarders) + + return dns.get_xml_object() + def add_forwarders(self, *forwarders): + for forwarder in forwarders: + self._dns.append(ET.Element('forwarder', **forwarder)) + + def add_host(self, ip, *hostnames): + host_element = ET.Element('host', ip) + + for hostname in sorted(hostnames): + hostname_element = ET.Element('hostname') + hostname_element.text = hostname + host_element.append(host_element) + + self._dns.append(host_element) + + def get_xml_object(self): + return deepcopy(self._dns) + + +class NATNetwork(Network): def _ipv6_prefix(self, subnet, const='fd8f:1391:3a82:'): return '{0}{1}::'.format(const, subnet) @@ -260,16 +295,24 @@ def make_ipv4(last): localOnly='yes' ) net_xml.append(domain_xml) + net_xml.append( - self._generate_main_dns(self._spec['dns_records'], subnet) + LibvirtDNS.generate_main_dns( + self._spec['dns_records'], + self._spec['dns_forwarders'], + ipv6_prefix, + forward_plain_names=False + ) ) else: if self.libvirt_con.getLibVersion() < 2002000: net_xml.append( - self._generate_dns_forward(self._spec['dns_forward']) + LibvirtDNS.generate_dns_forward( + self._spec['dns_forwarders'] + ) ) else: - net_xml.append(self._generate_dns_disable()) + net_xml.append(LibvirtDNS.generate_dns_disable()) else: LOGGER.debug( 'Generating network XML with compatibility prior to %s', @@ -286,14 +329,16 @@ def make_ipv4(last): ) net_xml.append(domain_xml) - net_xml.append( - self._generate_main_dns( - self._spec['mapping'], subnet, forward_plain='yes' - ) + dns_element = LibvirtDNS.generate_main_dns( + self._spec['mapping'], + [], + subnet, + forward_plain_names=True, ) + + net_xml.append(dns_element) else: - dns = ET.Element('dns', forwardPlainNames='yes', enable='yes') - net_xml.append(dns) + net_xml.append(LibvirtDNS.generate_default_dns()) LOGGER.debug( 'Generated Network XML\n {0}'.format(