Merge ~cgrabowski/maas:fix_node_dns_generation into maas:master

Proposed by Christian Grabowski
Status: Merged
Approved by: Christian Grabowski
Approved revision: 01ca1f1b193f5e2b27df61f9eda65e79797b6fc7
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:fix_node_dns_generation
Merge into: maas:master
Diff against target: 638 lines (+498/-10)
6 files modified
src/maasserver/dns/config.py (+29/-9)
src/maasserver/dns/tests/test_config.py (+38/-1)
src/maasserver/triggers/system.py (+152/-0)
src/maasserver/triggers/tests/test_init.py (+5/-0)
src/maasserver/triggers/tests/test_system.py (+271/-0)
src/provisioningserver/dns/zoneconfig.py (+3/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Alberto Donato (community) Approve
Review via email: mp+434522@code.launchpad.net

Commit message

add trigger when existing static ip updates

add DELETE-IFACE-IP

add triggers for interface to ip dynamic DNS updates

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/1610/consoleText
COMMIT: c66c10c229362a9e865c4356e2e624e4f312f7de

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/1611/consoleText
COMMIT: e950d5a272b42cb444abae3b482690504f266dc8

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/1612/consoleText
COMMIT: c8c4b4d634b5c89345272355e6eb78420865a6be

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/1613/consoleText
COMMIT: f2376c5ede9cde358aae0488a1029ef1c3bc7933

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 51dbe7cbbb977ff8052c6ac4f3b4672e60eae648

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

some questions/suggestions inline

review: Needs Information
Revision history for this message
Christian Grabowski (cgrabowski) :
7b669f7... by Christian Grabowski

simplify triggers with join statements

01ca1f1... by Christian Grabowski

use domain related to node

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: bd9f0a6dfeb01dee5735b88e2b93fd7b2368d18d

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

+1, thanks for addressing the comments.

Two minor nits inline

review: Approve
Revision history for this message
Christian Grabowski (cgrabowski) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_node_dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 01ca1f1b193f5e2b27df61f9eda65e79797b6fc7

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/dns/config.py b/src/maasserver/dns/config.py
index c484570..a0390c0 100644
--- a/src/maasserver/dns/config.py
+++ b/src/maasserver/dns/config.py
@@ -21,6 +21,7 @@ from maasserver.models.dnsdata import DNSData
21from maasserver.models.dnspublication import DNSPublication21from maasserver.models.dnspublication import DNSPublication
22from maasserver.models.dnsresource import DNSResource22from maasserver.models.dnsresource import DNSResource
23from maasserver.models.domain import Domain23from maasserver.models.domain import Domain
24from maasserver.models.interface import Interface
24from maasserver.models.node import RackController25from maasserver.models.node import RackController
25from maasserver.models.subnet import Subnet26from maasserver.models.subnet import Subnet
26from provisioningserver.dns.actions import (27from provisioningserver.dns.actions import (
@@ -348,7 +349,7 @@ def process_dns_update_notify(message):
348 case _:349 case _:
349 # special case where we know an IP has been deleted but, we can't fetch the value350 # special case where we know an IP has been deleted but, we can't fetch the value
350 # and the rrecord may still have other answers351 # and the rrecord may still have other answers
351 if op == "DELETE-IP":352 if op == "DELETE-IP" or op == "DELETE-IFACE-IP":
352 updates.append(353 updates.append(
353 DynamicDNSUpdate.create_from_trigger(354 DynamicDNSUpdate.create_from_trigger(
354 operation="DELETE",355 operation="DELETE",
@@ -366,23 +367,42 @@ def process_dns_update_notify(message):
366 rectype="AAAA",367 rectype="AAAA",
367 )368 )
368 )369 )
369 resource = DNSResource.objects.get(370
370 name=update_list[2], domain__name=zone371 ttl = None
371 )372 ip_addresses = []
373 if op == "DELETE-IP":
374 resource = DNSResource.objects.get(
375 name=update_list[2], domain__name=zone
376 )
377 ttl = (
378 int(resource.address_ttl)
379 if resource.address_ttl
380 else None
381 )
382 ip_addresses = list(
383 resource.ip_addresses.exclude(ip__isnull=True)
384 )
385 else:
386 iface_id = int(update_list[-1])
387 iface = Interface.objects.get(id=iface_id)
388 default_domain = Domain.objects.get_default_domain()
389 ttl = (
390 int(default_domain.ttl) if default_domain.ttl else None
391 )
392 ip_addresses = list(
393 iface.ip_addresses.exclude(ip__isnull=True)
394 )
372 updates += [395 updates += [
373 DynamicDNSUpdate.create_from_trigger(396 DynamicDNSUpdate.create_from_trigger(
374 operation="INSERT",397 operation="INSERT",
375 zone=zone,398 zone=zone,
376 name=name,399 name=name,
377 rectype=rectype,400 rectype=rectype,
378 ttl=int(resource.address_ttl)401 ttl=ttl,
379 if resource.address_ttl
380 else None,
381 answer=ip.ip,402 answer=ip.ip,
382 )403 )
383 for ip in resource.ip_addresses.all()404 for ip in ip_addresses
384 ]405 ]
385
386 elif len(update_list) > 4: # has an answer406 elif len(update_list) > 4: # has an answer
387 updates.append(407 updates.append(
388 DynamicDNSUpdate.create_from_trigger(408 DynamicDNSUpdate.create_from_trigger(
diff --git a/src/maasserver/dns/tests/test_config.py b/src/maasserver/dns/tests/test_config.py
index 9a2835d..0a96814 100644
--- a/src/maasserver/dns/tests/test_config.py
+++ b/src/maasserver/dns/tests/test_config.py
@@ -873,7 +873,10 @@ class TestProcessDNSUpdateNotify(MAASServerTestCase):
873 domain = factory.make_Domain()873 domain = factory.make_Domain()
874 resource = factory.make_DNSResource(domain=domain)874 resource = factory.make_DNSResource(domain=domain)
875 ip = resource.ip_addresses.first().ip875 ip = resource.ip_addresses.first().ip
876 ip2 = factory.make_StaticIPAddress()876 subnet = factory.make_Subnet()
877 ip2 = factory.make_StaticIPAddress(
878 subnet=subnet, ip=subnet.get_next_ip_for_allocation()[0]
879 )
877 resource.ip_addresses.add(ip2)880 resource.ip_addresses.add(ip2)
878 message = f"DELETE-IP {domain.name} {resource.name} A {resource.address_ttl if resource.address_ttl else 60} {ip}"881 message = f"DELETE-IP {domain.name} {resource.name} A {resource.address_ttl if resource.address_ttl else 60} {ip}"
879 resource.ip_addresses.first().delete()882 resource.ip_addresses.first().delete()
@@ -902,3 +905,37 @@ class TestProcessDNSUpdateNotify(MAASServerTestCase):
902 ],905 ],
903 result,906 result,
904 )907 )
908
909 def test_delete_iface_ip(self):
910 domain = factory.make_Domain()
911 node = factory.make_Node_with_Interface_on_Subnet()
912 iface = node.current_config.interface_set.first()
913 ip1 = iface.ip_addresses.first()
914 ip2 = factory.make_StaticIPAddress(interface=iface)
915 ip1.delete()
916 message = f"DELETE-IFACE-IP {domain.name} {node.hostname} A {domain.ttl if domain.ttl else 60} {iface.id}"
917 result, _ = process_dns_update_notify(message)
918 self.assertCountEqual(
919 [
920 DynamicDNSUpdate(
921 operation="DELETE",
922 zone=domain.name,
923 name=f"{node.hostname}.{domain.name}",
924 rectype="A",
925 ),
926 DynamicDNSUpdate(
927 operation="DELETE",
928 zone=domain.name,
929 name=f"{node.hostname}.{domain.name}",
930 rectype="AAAA",
931 ),
932 DynamicDNSUpdate(
933 operation="INSERT",
934 zone=domain.name,
935 name=f"{node.hostname}.{domain.name}",
936 rectype="A" if IPAddress(ip2.ip).version == 4 else "AAAA",
937 answer=ip2.ip,
938 ),
939 ],
940 result,
941 )
diff --git a/src/maasserver/triggers/system.py b/src/maasserver/triggers/system.py
index a18fe8a..3f7f328 100644
--- a/src/maasserver/triggers/system.py
+++ b/src/maasserver/triggers/system.py
@@ -2054,6 +2054,124 @@ def render_dns_dynamic_update_subnet_procedure(op):
2054 )2054 )
20552055
20562056
2057def render_dns_dynamic_update_interface_static_ip_address(op):
2058 return dedent(
2059 f"""\
2060 CREATE OR REPLACE FUNCTION sys_dns_updates_interface_ip_{op}()
2061 RETURNS trigger as $$
2062 DECLARE
2063 current_hostname text;
2064 domain text;
2065 iface_name text;
2066 ip_addr text;
2067 address_ttl int;
2068 BEGIN
2069 ASSERT TG_WHEN = 'AFTER', 'May only run as an AFTER trigger';
2070 ASSERT TG_LEVEL <> 'STATEMENT', 'Should not be used as a STATEMENT level trigger', TG_NAME;
2071 IF (TG_OP = 'INSERT' AND TG_LEVEL = 'ROW') THEN
2072 SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl
2073 FROM maasserver_interface AS iface
2074 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id
2075 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=NEW.interface_id;
2076 SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=NEW.staticipaddress_id;
2077 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr);
2078 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr);
2079 ELSIF (TG_OP = 'DELETE' AND TG_LEVEL = 'ROW') THEN
2080 IF EXISTS(SELECT id FROM maasserver_interface WHERE id=OLD.interface_id) THEN
2081 SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl
2082 FROM maasserver_interface AS iface
2083 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id
2084 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=OLD.interface_id;
2085 IF EXISTS(SELECT id FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id) THEN
2086 SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id;
2087 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || current_hostname || ' A ' || ip_addr);
2088 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || ip_addr);
2089 ELSE
2090 PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' A ' || OLD.interface_id);
2091 PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' AAAA ' || OLD.interface_id);
2092 END IF;
2093 END IF;
2094 END IF;
2095 RETURN NULL;
2096 END;
2097 $$ LANGUAGE plpgsql;
2098 """
2099 )
2100
2101
2102dns_dynamic_update_static_ip_address_update = dedent(
2103 """\
2104 CREATE OR REPLACE FUNCTION sys_dns_updates_ip_update()
2105 RETURNS trigger as $$
2106 DECLARE
2107 current_hostname text;
2108 domain text;
2109 iface_name text;
2110 address_ttl int;
2111 current_interface_id bigint;
2112 BEGIN
2113 IF NEW IS DISTINCT FROM OLD THEN
2114 IF EXISTS(SELECT id FROM maasserver_interface_ip_addresses WHERE staticipaddress_id=NEW.id) THEN
2115 SELECT interface_id INTO current_interface_id FROM maasserver_interface_ip_addresses WHERE staticipaddress_id=NEW.id;
2116 SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl
2117 FROM maasserver_interface AS iface
2118 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id
2119 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=current_interface_id;
2120 IF OLD.ip IS NOT NULL THEN
2121 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || current_hostname || ' A ' || host(OLD.ip));
2122 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || host(OLD.ip));
2123 END IF;
2124 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || current_hostname || ' A ' || address_ttl || ' ' || host(NEW.ip));
2125 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || address_ttl || ' ' || host(NEW.ip));
2126 END IF;
2127 END IF;
2128 RETURN NULL;
2129 END;
2130 $$ LANGUAGE plpgsql;
2131 """
2132)
2133
2134dns_dynamic_update_node_delete = dedent(
2135 """\
2136 CREATE OR REPLACE FUNCTION sys_dns_updates_maasserver_node_delete()
2137 RETURNS trigger as $$
2138 DECLARE
2139 hostname text;
2140 domain text;
2141 address_ttl int;
2142 BEGIN
2143 SELECT name, COALESCE(ttl, 0) INTO domain, address_ttl FROM maasserver_domain WHERE id=OLD.domain_id;
2144 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || OLD.hostname || ' A');
2145 RETURN NULL;
2146 END;
2147 $$ LANGUAGE plpgsql;
2148 """
2149)
2150
2151
2152dns_dynamic_update_interface_delete = dedent(
2153 """\
2154 CREATE OR REPLACE FUNCTION sys_dns_updates_maasserver_interface_delete()
2155 RETURNS trigger as $$
2156 DECLARE
2157 current_hostname text;
2158 current_domain_id bigint;
2159 domain text;
2160 current_node_id bigint;
2161 BEGIN
2162 IF EXISTS(SELECT id FROM maasserver_nodeconfig WHERE id=OLD.node_config_id) THEN
2163 SELECT node_id INTO current_node_id FROM maasserver_nodeconfig WHERE id=OLD.node_config_id;
2164 SELECT hostname, domain_id INTO current_hostname, current_domain_id FROM maasserver_node WHERE id=current_node_id;
2165 SELECT name INTO domain FROM maasserver_domain WHERE id=current_domain_id;
2166 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || OLD.name || '.' || current_hostname || ' A');
2167 END IF;
2168 RETURN NULL;
2169 END;
2170 $$ LANGUAGE plpgsql;
2171 """
2172)
2173
2174
2057def render_sys_proxy_procedure(proc_name, on_delete=False):2175def render_sys_proxy_procedure(proc_name, on_delete=False):
2058 """Render a database procedure with name `proc_name` that notifies that a2176 """Render a database procedure with name `proc_name` that notifies that a
2059 proxy update is needed.2177 proxy update is needed.
@@ -2403,3 +2521,37 @@ def register_system_triggers():
2403 "sys_dns_updates_maasserver_subnet_delete",2521 "sys_dns_updates_maasserver_subnet_delete",
2404 "delete",2522 "delete",
2405 )2523 )
2524 register_procedure(
2525 render_dns_dynamic_update_interface_static_ip_address("insert")
2526 )
2527 register_trigger(
2528 "maasserver_interface_ip_addresses",
2529 "sys_dns_updates_interface_ip_insert",
2530 "insert",
2531 )
2532 register_procedure(
2533 render_dns_dynamic_update_interface_static_ip_address("delete")
2534 )
2535 register_trigger(
2536 "maasserver_interface_ip_addresses",
2537 "sys_dns_updates_interface_ip_delete",
2538 "delete",
2539 )
2540 register_procedure(dns_dynamic_update_static_ip_address_update)
2541 register_trigger(
2542 "maasserver_staticipaddress",
2543 "sys_dns_updates_ip_update",
2544 "update",
2545 )
2546 register_procedure(dns_dynamic_update_node_delete)
2547 register_trigger(
2548 "maasserver_node",
2549 "sys_dns_updates_maasserver_node_delete",
2550 "delete",
2551 )
2552 register_procedure(dns_dynamic_update_interface_delete)
2553 register_trigger(
2554 "maasserver_interface",
2555 "sys_dns_updates_maasserver_interface_delete",
2556 "delete",
2557 )
diff --git a/src/maasserver/triggers/tests/test_init.py b/src/maasserver/triggers/tests/test_init.py
index e4fb3ed..34395f1 100644
--- a/src/maasserver/triggers/tests/test_init.py
+++ b/src/maasserver/triggers/tests/test_init.py
@@ -91,14 +91,18 @@ class TestTriggersUsed(MAASServerTestCase):
91 "domain_sys_dns_updates_maasserver_domain_update",91 "domain_sys_dns_updates_maasserver_domain_update",
92 "interface_ip_addresses_sys_dns_nic_ip_link",92 "interface_ip_addresses_sys_dns_nic_ip_link",
93 "interface_ip_addresses_sys_dns_nic_ip_unlink",93 "interface_ip_addresses_sys_dns_nic_ip_unlink",
94 "interface_ip_addresses_sys_dns_updates_interface_ip_insert",
95 "interface_ip_addresses_sys_dns_updates_interface_ip_delete",
94 "interface_sys_dhcp_interface_update",96 "interface_sys_dhcp_interface_update",
95 "interface_sys_dns_interface_update",97 "interface_sys_dns_interface_update",
98 "interface_sys_dns_updates_maasserver_interface_delete",
96 "iprange_sys_dhcp_iprange_delete",99 "iprange_sys_dhcp_iprange_delete",
97 "iprange_sys_dhcp_iprange_insert",100 "iprange_sys_dhcp_iprange_insert",
98 "iprange_sys_dhcp_iprange_update",101 "iprange_sys_dhcp_iprange_update",
99 "node_sys_dhcp_node_update",102 "node_sys_dhcp_node_update",
100 "node_sys_dns_node_delete",103 "node_sys_dns_node_delete",
101 "node_sys_dns_node_update",104 "node_sys_dns_node_update",
105 "node_sys_dns_updates_maasserver_node_delete",
102 "rbacsync_sys_rbac_sync",106 "rbacsync_sys_rbac_sync",
103 "regionrackrpcconnection_sys_core_rpc_delete",107 "regionrackrpcconnection_sys_core_rpc_delete",
104 "regionrackrpcconnection_sys_core_rpc_insert",108 "regionrackrpcconnection_sys_core_rpc_insert",
@@ -109,6 +113,7 @@ class TestTriggersUsed(MAASServerTestCase):
109 "staticipaddress_sys_dhcp_staticipaddress_insert",113 "staticipaddress_sys_dhcp_staticipaddress_insert",
110 "staticipaddress_sys_dhcp_staticipaddress_update",114 "staticipaddress_sys_dhcp_staticipaddress_update",
111 "staticipaddress_sys_dns_staticipaddress_update",115 "staticipaddress_sys_dns_staticipaddress_update",
116 "staticipaddress_sys_dns_updates_ip_update",
112 "subnet_sys_dns_updates_maasserver_subnet_delete",117 "subnet_sys_dns_updates_maasserver_subnet_delete",
113 "subnet_sys_dns_updates_maasserver_subnet_insert",118 "subnet_sys_dns_updates_maasserver_subnet_insert",
114 "subnet_sys_dns_updates_maasserver_subnet_update",119 "subnet_sys_dns_updates_maasserver_subnet_update",
diff --git a/src/maasserver/triggers/tests/test_system.py b/src/maasserver/triggers/tests/test_system.py
index d5222b4..4337984 100644
--- a/src/maasserver/triggers/tests/test_system.py
+++ b/src/maasserver/triggers/tests/test_system.py
@@ -7,6 +7,8 @@ from contextlib import closing
7from django.db import connection7from django.db import connection
8from twisted.internet.defer import inlineCallbacks8from twisted.internet.defer import inlineCallbacks
99
10from maasserver.enum import NODE_STATUS
11from maasserver.models import Domain
10from maasserver.models.dnspublication import zone_serial12from maasserver.models.dnspublication import zone_serial
11from maasserver.testing.factory import factory13from maasserver.testing.factory import factory
12from maasserver.testing.testcase import (14from maasserver.testing.testcase import (
@@ -367,3 +369,272 @@ class TestSysDNSUpdates(
367 finally:369 finally:
368 self.stop_reading()370 self.stop_reading()
369 yield self.postgres_listener_service.stopService()371 yield self.postgres_listener_service.stopService()
372
373 @wait_for_reactor
374 @inlineCallbacks
375 def test_dns_dynamic_update_interface_static_ip_address_insert(self):
376 listener = self.make_listener_without_delay()
377 yield self.set_service(listener)
378 yield deferToDatabase(
379 self.register_trigger,
380 "maasserver_interface_ip_addresses",
381 "sys_dns_updates",
382 ops=("insert",),
383 trigger="sys_dns_updates_interface_ip_insert",
384 )
385 vlan = yield deferToDatabase(self.create_vlan)
386 subnet = yield deferToDatabase(
387 self.create_subnet, params={"vlan": vlan}
388 )
389 self.start_reading()
390 try:
391 node = yield deferToDatabase(
392 self.create_node_with_interface,
393 params={"subnet": subnet, "status": NODE_STATUS.DEPLOYED},
394 )
395 domain = yield deferToDatabase(Domain.objects.get_default_domain)
396 expected_iface = yield deferToDatabase(
397 lambda: node.current_config.interface_set.first()
398 )
399 expected_ip = yield deferToDatabase(
400 lambda: self.create_staticipaddress(
401 params={
402 "ip": subnet.get_next_ip_for_allocation()[0],
403 "interface": expected_iface,
404 "subnet": subnet,
405 }
406 )
407 )
408 msg1 = yield self.get_notify("sys_dns_updates")
409 self.assertEqual(
410 msg1,
411 f"INSERT {domain.name} {node.hostname} A 0 {expected_ip.ip}",
412 )
413 msg2 = yield self.get_notify("sys_dns_updates")
414 self.assertEqual(
415 msg2,
416 f"INSERT {domain.name} {expected_iface.name}.{node.hostname} A 0 {expected_ip.ip}",
417 )
418 finally:
419 self.stop_reading()
420 yield self.postgres_listener_service.stopService()
421
422 @wait_for_reactor
423 @inlineCallbacks
424 def test_dns_dynamic_update_interface_static_ip_address_insert_with_non_default_domain(
425 self,
426 ):
427 listener = self.make_listener_without_delay()
428 yield self.set_service(listener)
429 yield deferToDatabase(
430 self.register_trigger,
431 "maasserver_interface_ip_addresses",
432 "sys_dns_updates",
433 ops=("insert",),
434 trigger="sys_dns_updates_interface_ip_insert",
435 )
436 vlan = yield deferToDatabase(self.create_vlan)
437 subnet = yield deferToDatabase(
438 self.create_subnet, params={"vlan": vlan}
439 )
440 domain = yield deferToDatabase(self.create_domain)
441 self.start_reading()
442 try:
443 node = yield deferToDatabase(
444 self.create_node_with_interface,
445 params={
446 "subnet": subnet,
447 "status": NODE_STATUS.DEPLOYED,
448 "domain": domain,
449 },
450 )
451 expected_iface = yield deferToDatabase(
452 lambda: node.current_config.interface_set.first()
453 )
454 expected_ip = yield deferToDatabase(
455 lambda: self.create_staticipaddress(
456 params={
457 "ip": subnet.get_next_ip_for_allocation()[0],
458 "interface": expected_iface,
459 "subnet": subnet,
460 }
461 )
462 )
463 msg1 = yield self.get_notify("sys_dns_updates")
464 self.assertEqual(
465 msg1,
466 f"INSERT {domain.name} {node.hostname} A 0 {expected_ip.ip}",
467 )
468 msg2 = yield self.get_notify("sys_dns_updates")
469 self.assertEqual(
470 msg2,
471 f"INSERT {domain.name} {expected_iface.name}.{node.hostname} A 0 {expected_ip.ip}",
472 )
473 finally:
474 self.stop_reading()
475 yield self.postgres_listener_service.stopService()
476
477 @wait_for_reactor
478 @inlineCallbacks
479 def test_dns_dynamic_update_interface_static_ip_address_delete(self):
480 listener = self.make_listener_without_delay()
481 yield self.set_service(listener)
482 yield deferToDatabase(
483 self.register_trigger,
484 "maasserver_interface_ip_addresses",
485 "sys_dns_updates",
486 ops=("delete",),
487 trigger="sys_dns_updates_interface_ip_delete",
488 )
489 vlan = yield deferToDatabase(self.create_vlan)
490 subnet = yield deferToDatabase(
491 self.create_subnet, params={"vlan": vlan}
492 )
493 node = yield deferToDatabase(
494 self.create_node_with_interface,
495 params={"subnet": subnet, "status": NODE_STATUS.DEPLOYED},
496 )
497 domain = yield deferToDatabase(Domain.objects.get_default_domain)
498 iface = yield deferToDatabase(
499 lambda: node.current_config.interface_set.first()
500 )
501 ip1 = yield deferToDatabase(
502 lambda: self.create_staticipaddress(
503 params={
504 "ip": subnet.get_next_ip_for_allocation()[0],
505 "interface": iface,
506 "subnet": subnet,
507 }
508 )
509 )
510 self.start_reading()
511 try:
512 yield deferToDatabase(iface.unlink_ip_address, ip1)
513 msg1 = yield self.get_notify("sys_dns_updates")
514 self.assertEqual(
515 msg1, f"DELETE {domain.name} {node.hostname} A {ip1.ip}"
516 )
517 msg2 = yield self.get_notify("sys_dns_updates")
518 self.assertEqual(
519 msg2,
520 f"DELETE {domain.name} {iface.name}.{node.hostname} A {ip1.ip}",
521 )
522 finally:
523 self.stop_reading()
524 yield self.postgres_listener_service.stopService()
525
526 @wait_for_reactor
527 @inlineCallbacks
528 def test_dns_dynamc_update_ip_update(self):
529 listener = self.make_listener_without_delay()
530 yield self.set_service(listener)
531 yield deferToDatabase(
532 self.register_trigger,
533 "maasserver_staticipaddress",
534 "sys_dns_updates",
535 ops=("update",),
536 trigger="sys_dns_updates_ip_update",
537 )
538 vlan = yield deferToDatabase(self.create_vlan)
539 subnet = yield deferToDatabase(
540 self.create_subnet, params={"vlan": vlan}
541 )
542 node = yield deferToDatabase(
543 self.create_node_with_interface,
544 params={"subnet": subnet, "status": NODE_STATUS.DEPLOYED},
545 )
546 domain = yield deferToDatabase(Domain.objects.get_default_domain)
547 iface = yield deferToDatabase(
548 lambda: node.current_config.interface_set.first()
549 )
550 ip = yield deferToDatabase(
551 lambda: self.create_staticipaddress(
552 params={
553 "ip": subnet.get_next_ip_for_allocation()[0],
554 "interface": iface,
555 "subnet": subnet,
556 }
557 )
558 )
559 old_ip = ip.ip
560
561 def _set_new_ip():
562 ip.ip = subnet.get_next_ip_for_allocation()[0]
563 ip.save()
564
565 self.start_reading()
566 try:
567 yield deferToDatabase(_set_new_ip)
568 msg1 = yield self.get_notify("sys_dns_updates")
569 self.assertEqual(
570 msg1, f"DELETE {domain.name} {node.hostname} A {old_ip}"
571 )
572 msg2 = yield self.get_notify("sys_dns_updates")
573 self.assertEqual(
574 msg2,
575 f"DELETE {domain.name} {iface.name}.{node.hostname} A {old_ip}",
576 )
577 msg3 = yield self.get_notify("sys_dns_updates")
578 self.assertEqual(
579 msg3, f"INSERT {domain.name} {node.hostname} A 0 {ip.ip}"
580 )
581 msg4 = yield self.get_notify("sys_dns_updates")
582 self.assertEqual(
583 msg4,
584 f"INSERT {domain.name} {iface.name}.{node.hostname} A 0 {ip.ip}",
585 )
586 finally:
587 self.stop_reading()
588 yield self.postgres_listener_service.stopService()
589
590 @wait_for_reactor
591 @inlineCallbacks
592 def test_dns_dynamic_update_node_delete(self):
593 listener = self.make_listener_without_delay()
594 yield self.set_service(listener)
595 yield deferToDatabase(
596 self.register_trigger,
597 "maasserver_node",
598 "sys_dns_updates",
599 ops=("delete",),
600 )
601 node = yield deferToDatabase(self.create_node)
602 domain = yield deferToDatabase(Domain.objects.get_default_domain)
603 self.start_reading()
604 try:
605 yield deferToDatabase(node.delete)
606 msg = yield self.get_notify("sys_dns_updates")
607 self.assertEqual(msg, f"DELETE {domain.name} {node.hostname} A")
608 finally:
609 self.stop_reading()
610 yield self.postgres_listener_service.stopService()
611
612 @wait_for_reactor
613 @inlineCallbacks
614 def test_dns_dynamic_update_interface_delete(self):
615 listener = self.make_listener_without_delay()
616 yield self.set_service(listener)
617 yield deferToDatabase(
618 self.register_trigger,
619 "maasserver_node",
620 "sys_dns_updates",
621 ops=("delete",),
622 )
623 subnet = yield deferToDatabase(self.create_subnet)
624 node = yield deferToDatabase(
625 self.create_node_with_interface, params={"subnet": subnet}
626 )
627 domain = yield deferToDatabase(Domain.objects.get_default_domain)
628 iface = yield deferToDatabase(
629 lambda: node.current_config.interface_set.first()
630 )
631 self.start_reading()
632 try:
633 yield deferToDatabase(iface.delete)
634 msg = yield self.get_notify("sys_dns_updates")
635 self.assertEqual(
636 msg, f"DELETE {domain.name} {iface.name}.{node.hostname} A"
637 )
638 finally:
639 self.stop_reading()
640 yield self.postgres_listener_service.stopService()
diff --git a/src/provisioningserver/dns/zoneconfig.py b/src/provisioningserver/dns/zoneconfig.py
index 13dca69..eed539a 100644
--- a/src/provisioningserver/dns/zoneconfig.py
+++ b/src/provisioningserver/dns/zoneconfig.py
@@ -7,6 +7,7 @@
7from datetime import datetime7from datetime import datetime
8from itertools import chain8from itertools import chain
9import os9import os
10from pathlib import Path
1011
11from netaddr import IPAddress, IPNetwork, spanning_cidr12from netaddr import IPAddress, IPNetwork, spanning_cidr
12from netaddr.core import AddrFormatError13from netaddr.core import AddrFormatError
@@ -323,6 +324,7 @@ class DNSForwardZoneConfig(DomainConfigBase):
323 if not self.force_config_write and self.zone_file_exists(zi):324 if not self.force_config_write and self.zone_file_exists(zi):
324 self.dynamic_update(zi)325 self.dynamic_update(zi)
325 else:326 else:
327 Path(f"{zi.target_path}.jnl").unlink(missing_ok=True)
326 self.requires_reload = True328 self.requires_reload = True
327 self.write_zone_file(329 self.write_zone_file(
328 zi.target_path,330 zi.target_path,
@@ -612,6 +614,7 @@ class DNSReverseZoneConfig(DomainConfigBase):
612 if not self.force_config_write and self.zone_file_exists(zi):614 if not self.force_config_write and self.zone_file_exists(zi):
613 self.dynamic_update(zi)615 self.dynamic_update(zi)
614 else:616 else:
617 Path(f"{zi.target_path}.jnl").unlink(missing_ok=True)
615 self.requires_reload = True618 self.requires_reload = True
616 self.write_zone_file(619 self.write_zone_file(
617 zi.target_path,620 zi.target_path,

Subscribers

People subscribed via source and target branches