← Back to team overview

sts-sponsors team mailing list archive

[Merge] ~cgrabowski/maas:backport_fix_missing_reverse_records into maas:3.3

 

Christian Grabowski has proposed merging ~cgrabowski/maas:backport_fix_missing_reverse_records into maas:3.3.

Commit message:
use zone_info.zone_name instead of domain to freeze/thaw reverse updates
fix default ttls
(cherry picked from commit d4b96129a725fda571a05a67efecde937cb55da2)



Requested reviews:
  Christian Grabowski (cgrabowski)

For more details, see:
https://code.launchpad.net/~cgrabowski/maas/+git/maas/+merge/436339
-- 
Your team MAAS Committers is subscribed to branch maas:3.3.
diff --git a/src/maasserver/triggers/system.py b/src/maasserver/triggers/system.py
index 8e5ba5a..9aa7e41 100644
--- a/src/maasserver/triggers/system.py
+++ b/src/maasserver/triggers/system.py
@@ -2143,7 +2143,7 @@ def render_dns_dynamic_update_node(op):
           domain text;
           address_ttl int;
         BEGIN
-          IF ((TG_OP = 'INSERT' OR  TG_OP = 'UPDATE') AND TG_LEVEL = 'ROW') THEN
+          IF ((TG_OP = 'INSERT' OR TG_OP = 'UPDATE') AND TG_LEVEL = 'ROW') THEN
               IF NEW.node_type <> {NODE_TYPE.DEVICE} AND NEW.node_type <> {NODE_TYPE.MACHINE} THEN
                   PERFORM pg_notify('sys_dns_updates', 'RELOAD');
               END IF;
diff --git a/src/provisioningserver/dns/actions.py b/src/provisioningserver/dns/actions.py
index 7749ff5..64fffda 100644
--- a/src/provisioningserver/dns/actions.py
+++ b/src/provisioningserver/dns/actions.py
@@ -4,6 +4,7 @@
 """Low-level actions to manage the DNS service, like reloading zones."""
 
 from collections.abc import Sequence
+from contextlib import contextmanager, nullcontext
 from subprocess import CalledProcessError, TimeoutExpired
 from time import sleep
 
@@ -84,6 +85,18 @@ def bind_thaw_zone(zone=None, timeout=2):
         raise
 
 
+@contextmanager
+def freeze_thaw_zone(required, zone=None, timeout=2):
+    if not required:
+        yield nullcontext()
+    else:
+        bind_freeze_zone(zone=zone, timeout=timeout)
+        try:
+            yield
+        finally:
+            bind_thaw_zone(zone=zone, timeout=timeout)
+
+
 def bind_reload(timeout=2):
     """Ask BIND to reload its configuration and all zone files.  This operation
     is 'best effort' (with logging) as the server may not be running, and there
diff --git a/src/provisioningserver/dns/config.py b/src/provisioningserver/dns/config.py
index 729b570..6e11f73 100644
--- a/src/provisioningserver/dns/config.py
+++ b/src/provisioningserver/dns/config.py
@@ -62,6 +62,8 @@ class DynamicDNSUpdate:
         else:
             if ip.version == 6:
                 rectype = "AAAA"
+        if kwargs.get("ttl") == 0:  # default ttl
+            kwargs["ttl"] = 30
         return cls(answer=answer, rectype=rectype, **kwargs)
 
     @classmethod
diff --git a/src/provisioningserver/dns/tests/test_zoneconfig.py b/src/provisioningserver/dns/tests/test_zoneconfig.py
index 10ee0f7..f747a53 100644
--- a/src/provisioningserver/dns/tests/test_zoneconfig.py
+++ b/src/provisioningserver/dns/tests/test_zoneconfig.py
@@ -8,6 +8,7 @@ from itertools import chain
 import os.path
 import random
 from tempfile import mktemp
+from unittest.mock import call
 
 from netaddr import IPAddress, IPNetwork, IPRange
 from testtools.matchers import (
@@ -488,6 +489,42 @@ class TestDNSForwardZoneConfig(MAASTestCase):
             stdin=expected_stdin.encode("ascii"),
         )
 
+    def test_full_reload_calls_freeze_thaw(self):
+        patch_zone_file_config_path(self)
+        execute_rndc_command = self.patch(actions, "execute_rndc_command")
+        domain = factory.make_string()
+        network = factory.make_ipv4_network()
+        ipv4_hostname = factory.make_name("host")
+        ipv4_ip = factory.pick_ip_in_network(network)
+        ipv6_hostname = factory.make_name("host")
+        ipv6_ip = factory.make_ipv6_address()
+        ipv6_network = factory.make_ipv6_network()
+        dynamic_range = IPRange(ipv6_network.first, ipv6_network.last)
+        ttl = random.randint(10, 300)
+        mapping = {
+            ipv4_hostname: HostnameIPMapping(None, ttl, {ipv4_ip}),
+            ipv6_hostname: HostnameIPMapping(None, ttl, {ipv6_ip}),
+        }
+        dns_zone_config = DNSForwardZoneConfig(
+            domain,
+            serial=random.randint(1, 100),
+            mapping=mapping,
+            default_ttl=ttl,
+            dynamic_ranges=[dynamic_range],
+        )
+        self.patch(dns_zone_config, "get_GENERATE_directives")
+        self.patch(actions, "run_command")
+        dns_zone_config.write_config()
+        dns_zone_config.force_config_write = True
+        dns_zone_config.write_config()
+        self.assertCountEqual(
+            execute_rndc_command.call_args_list,
+            [
+                call(("freeze", domain), timeout=2),
+                call(("thaw", domain), timeout=2),
+            ],
+        )
+
 
 class TestDNSReverseZoneConfig(MAASTestCase):
     """Tests for DNSReverseZoneConfig."""
@@ -1077,6 +1114,30 @@ class TestDNSReverseZoneConfig(MAASTestCase):
             stdin=expected_stdin.encode("ascii"),
         )
 
+    def test_full_reload_calls_freeze_thaw(self):
+        patch_zone_file_config_path(self)
+        execute_rndc_command = self.patch(
+            provisioningserver.dns.actions, "execute_rndc_command"
+        )
+        domain = factory.make_string()
+        network = IPNetwork("10.0.0.0/24")
+        zone = DNSReverseZoneConfig(
+            domain,
+            serial=random.randint(1, 100),
+            network=network,
+        )
+        self.patch(actions, "run_command")
+        zone.write_config()
+        zone.force_config_write = True
+        zone.write_config()
+        self.assertCountEqual(
+            execute_rndc_command.call_args_list,
+            [
+                call(("freeze", "0.0.10.in-addr.arpa"), timeout=2),
+                call(("thaw", "0.0.10.in-addr.arpa"), timeout=2),
+            ],
+        )
+
 
 class TestDNSReverseZoneConfig_GetGenerateDirectives(MAASTestCase):
     """Tests for `DNSReverseZoneConfig.get_GENERATE_directives()`."""
diff --git a/src/provisioningserver/dns/zoneconfig.py b/src/provisioningserver/dns/zoneconfig.py
index 59e714b..93f2504 100644
--- a/src/provisioningserver/dns/zoneconfig.py
+++ b/src/provisioningserver/dns/zoneconfig.py
@@ -12,11 +12,7 @@ from pathlib import Path
 from netaddr import IPAddress, IPNetwork, spanning_cidr
 from netaddr.core import AddrFormatError
 
-from provisioningserver.dns.actions import (
-    bind_freeze_zone,
-    bind_thaw_zone,
-    NSUpdateCommand,
-)
+from provisioningserver.dns.actions import freeze_thaw_zone, NSUpdateCommand
 from provisioningserver.dns.config import (
     compose_zone_file_config_path,
     render_dns_template,
@@ -338,9 +334,7 @@ class DNSForwardZoneConfig(DomainConfigBase):
                 Path(f"{zi.target_path}.jnl").unlink(missing_ok=True)
                 self.requires_reload = True
                 needs_freeze_thaw = self.zone_file_exists(zi)
-                if needs_freeze_thaw:
-                    bind_freeze_zone(zone=self.domain)
-                try:
+                with freeze_thaw_zone(needs_freeze_thaw, zone=zi.zone_name):
                     self.write_zone_file(
                         zi.target_path,
                         self.make_parameters(),
@@ -359,9 +353,6 @@ class DNSForwardZoneConfig(DomainConfigBase):
                             "generate_directives": {"A": generate_directives},
                         },
                     )
-                finally:
-                    if needs_freeze_thaw:
-                        bind_thaw_zone(zone=self.domain)
 
 
 class DNSReverseZoneConfig(DomainConfigBase):
@@ -634,23 +625,25 @@ class DNSReverseZoneConfig(DomainConfigBase):
             else:
                 Path(f"{zi.target_path}.jnl").unlink(missing_ok=True)
                 self.requires_reload = True
-                self.write_zone_file(
-                    zi.target_path,
-                    self.make_parameters(),
-                    {
-                        "mappings": {
-                            "PTR": self.get_PTR_mapping(
-                                self._mapping, zi.subnetwork
-                            )
-                        },
-                        "other_mapping": [],
-                        "generate_directives": {
-                            "PTR": generate_directives,
-                            "CNAME": self.get_rfc2317_GENERATE_directives(
-                                zi.subnetwork,
-                                self._rfc2317_ranges,
-                                self.domain,
-                            ),
+                needs_freeze_thaw = self.zone_file_exists(zi)
+                with freeze_thaw_zone(needs_freeze_thaw, zone=zi.zone_name):
+                    self.write_zone_file(
+                        zi.target_path,
+                        self.make_parameters(),
+                        {
+                            "mappings": {
+                                "PTR": self.get_PTR_mapping(
+                                    self._mapping, zi.subnetwork
+                                )
+                            },
+                            "other_mapping": [],
+                            "generate_directives": {
+                                "PTR": generate_directives,
+                                "CNAME": self.get_rfc2317_GENERATE_directives(
+                                    zi.subnetwork,
+                                    self._rfc2317_ranges,
+                                    self.domain,
+                                ),
+                            },
                         },
-                    },
-                )
+                    )

References