Merge ~cgrabowski/maas:fix_node_dns_generation into maas:master
- Git
- lp:~cgrabowski/maas
- fix_node_dns_generation
- Merge into master
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) |
||||
Related bugs: |
|
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
Description of the change
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_node_
STATUS: FAILED
LOG: http://
COMMIT: e950d5a272b42cb
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_node_
STATUS: FAILED
LOG: http://
COMMIT: c8c4b4d634b5c89
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_node_
STATUS: FAILED
LOG: http://
COMMIT: f2376c5ede9cde3
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_node_
STATUS: SUCCESS
COMMIT: 51dbe7cbbb977ff
Alberto Donato (ack) wrote : | # |
some questions/
Christian Grabowski (cgrabowski) : | # |
- 7b669f7... by Christian Grabowski
-
simplify triggers with join statements
- 01ca1f1... by Christian Grabowski
-
use domain related to node
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_node_
STATUS: SUCCESS
COMMIT: bd9f0a6dfeb01de
Alberto Donato (ack) wrote : | # |
+1, thanks for addressing the comments.
Two minor nits inline
Christian Grabowski (cgrabowski) : | # |
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_node_
STATUS: SUCCESS
COMMIT: 01ca1f1b193f5e2
Preview Diff
1 | diff --git a/src/maasserver/dns/config.py b/src/maasserver/dns/config.py | |||
2 | index c484570..a0390c0 100644 | |||
3 | --- a/src/maasserver/dns/config.py | |||
4 | +++ b/src/maasserver/dns/config.py | |||
5 | @@ -21,6 +21,7 @@ from maasserver.models.dnsdata import DNSData | |||
6 | 21 | from maasserver.models.dnspublication import DNSPublication | 21 | from maasserver.models.dnspublication import DNSPublication |
7 | 22 | from maasserver.models.dnsresource import DNSResource | 22 | from maasserver.models.dnsresource import DNSResource |
8 | 23 | from maasserver.models.domain import Domain | 23 | from maasserver.models.domain import Domain |
9 | 24 | from maasserver.models.interface import Interface | ||
10 | 24 | from maasserver.models.node import RackController | 25 | from maasserver.models.node import RackController |
11 | 25 | from maasserver.models.subnet import Subnet | 26 | from maasserver.models.subnet import Subnet |
12 | 26 | from provisioningserver.dns.actions import ( | 27 | from provisioningserver.dns.actions import ( |
13 | @@ -348,7 +349,7 @@ def process_dns_update_notify(message): | |||
14 | 348 | case _: | 349 | case _: |
15 | 349 | # special case where we know an IP has been deleted but, we can't fetch the value | 350 | # special case where we know an IP has been deleted but, we can't fetch the value |
16 | 350 | # and the rrecord may still have other answers | 351 | # and the rrecord may still have other answers |
18 | 351 | if op == "DELETE-IP": | 352 | if op == "DELETE-IP" or op == "DELETE-IFACE-IP": |
19 | 352 | updates.append( | 353 | updates.append( |
20 | 353 | DynamicDNSUpdate.create_from_trigger( | 354 | DynamicDNSUpdate.create_from_trigger( |
21 | 354 | operation="DELETE", | 355 | operation="DELETE", |
22 | @@ -366,23 +367,42 @@ def process_dns_update_notify(message): | |||
23 | 366 | rectype="AAAA", | 367 | rectype="AAAA", |
24 | 367 | ) | 368 | ) |
25 | 368 | ) | 369 | ) |
29 | 369 | resource = DNSResource.objects.get( | 370 | |
30 | 370 | name=update_list[2], domain__name=zone | 371 | ttl = None |
31 | 371 | ) | 372 | ip_addresses = [] |
32 | 373 | if op == "DELETE-IP": | ||
33 | 374 | resource = DNSResource.objects.get( | ||
34 | 375 | name=update_list[2], domain__name=zone | ||
35 | 376 | ) | ||
36 | 377 | ttl = ( | ||
37 | 378 | int(resource.address_ttl) | ||
38 | 379 | if resource.address_ttl | ||
39 | 380 | else None | ||
40 | 381 | ) | ||
41 | 382 | ip_addresses = list( | ||
42 | 383 | resource.ip_addresses.exclude(ip__isnull=True) | ||
43 | 384 | ) | ||
44 | 385 | else: | ||
45 | 386 | iface_id = int(update_list[-1]) | ||
46 | 387 | iface = Interface.objects.get(id=iface_id) | ||
47 | 388 | default_domain = Domain.objects.get_default_domain() | ||
48 | 389 | ttl = ( | ||
49 | 390 | int(default_domain.ttl) if default_domain.ttl else None | ||
50 | 391 | ) | ||
51 | 392 | ip_addresses = list( | ||
52 | 393 | iface.ip_addresses.exclude(ip__isnull=True) | ||
53 | 394 | ) | ||
54 | 372 | updates += [ | 395 | updates += [ |
55 | 373 | DynamicDNSUpdate.create_from_trigger( | 396 | DynamicDNSUpdate.create_from_trigger( |
56 | 374 | operation="INSERT", | 397 | operation="INSERT", |
57 | 375 | zone=zone, | 398 | zone=zone, |
58 | 376 | name=name, | 399 | name=name, |
59 | 377 | rectype=rectype, | 400 | rectype=rectype, |
63 | 378 | ttl=int(resource.address_ttl) | 401 | ttl=ttl, |
61 | 379 | if resource.address_ttl | ||
62 | 380 | else None, | ||
64 | 381 | answer=ip.ip, | 402 | answer=ip.ip, |
65 | 382 | ) | 403 | ) |
67 | 383 | for ip in resource.ip_addresses.all() | 404 | for ip in ip_addresses |
68 | 384 | ] | 405 | ] |
69 | 385 | |||
70 | 386 | elif len(update_list) > 4: # has an answer | 406 | elif len(update_list) > 4: # has an answer |
71 | 387 | updates.append( | 407 | updates.append( |
72 | 388 | DynamicDNSUpdate.create_from_trigger( | 408 | DynamicDNSUpdate.create_from_trigger( |
73 | diff --git a/src/maasserver/dns/tests/test_config.py b/src/maasserver/dns/tests/test_config.py | |||
74 | index 9a2835d..0a96814 100644 | |||
75 | --- a/src/maasserver/dns/tests/test_config.py | |||
76 | +++ b/src/maasserver/dns/tests/test_config.py | |||
77 | @@ -873,7 +873,10 @@ class TestProcessDNSUpdateNotify(MAASServerTestCase): | |||
78 | 873 | domain = factory.make_Domain() | 873 | domain = factory.make_Domain() |
79 | 874 | resource = factory.make_DNSResource(domain=domain) | 874 | resource = factory.make_DNSResource(domain=domain) |
80 | 875 | ip = resource.ip_addresses.first().ip | 875 | ip = resource.ip_addresses.first().ip |
82 | 876 | ip2 = factory.make_StaticIPAddress() | 876 | subnet = factory.make_Subnet() |
83 | 877 | ip2 = factory.make_StaticIPAddress( | ||
84 | 878 | subnet=subnet, ip=subnet.get_next_ip_for_allocation()[0] | ||
85 | 879 | ) | ||
86 | 877 | resource.ip_addresses.add(ip2) | 880 | resource.ip_addresses.add(ip2) |
87 | 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}" |
88 | 879 | resource.ip_addresses.first().delete() | 882 | resource.ip_addresses.first().delete() |
89 | @@ -902,3 +905,37 @@ class TestProcessDNSUpdateNotify(MAASServerTestCase): | |||
90 | 902 | ], | 905 | ], |
91 | 903 | result, | 906 | result, |
92 | 904 | ) | 907 | ) |
93 | 908 | |||
94 | 909 | def test_delete_iface_ip(self): | ||
95 | 910 | domain = factory.make_Domain() | ||
96 | 911 | node = factory.make_Node_with_Interface_on_Subnet() | ||
97 | 912 | iface = node.current_config.interface_set.first() | ||
98 | 913 | ip1 = iface.ip_addresses.first() | ||
99 | 914 | ip2 = factory.make_StaticIPAddress(interface=iface) | ||
100 | 915 | ip1.delete() | ||
101 | 916 | message = f"DELETE-IFACE-IP {domain.name} {node.hostname} A {domain.ttl if domain.ttl else 60} {iface.id}" | ||
102 | 917 | result, _ = process_dns_update_notify(message) | ||
103 | 918 | self.assertCountEqual( | ||
104 | 919 | [ | ||
105 | 920 | DynamicDNSUpdate( | ||
106 | 921 | operation="DELETE", | ||
107 | 922 | zone=domain.name, | ||
108 | 923 | name=f"{node.hostname}.{domain.name}", | ||
109 | 924 | rectype="A", | ||
110 | 925 | ), | ||
111 | 926 | DynamicDNSUpdate( | ||
112 | 927 | operation="DELETE", | ||
113 | 928 | zone=domain.name, | ||
114 | 929 | name=f"{node.hostname}.{domain.name}", | ||
115 | 930 | rectype="AAAA", | ||
116 | 931 | ), | ||
117 | 932 | DynamicDNSUpdate( | ||
118 | 933 | operation="INSERT", | ||
119 | 934 | zone=domain.name, | ||
120 | 935 | name=f"{node.hostname}.{domain.name}", | ||
121 | 936 | rectype="A" if IPAddress(ip2.ip).version == 4 else "AAAA", | ||
122 | 937 | answer=ip2.ip, | ||
123 | 938 | ), | ||
124 | 939 | ], | ||
125 | 940 | result, | ||
126 | 941 | ) | ||
127 | diff --git a/src/maasserver/triggers/system.py b/src/maasserver/triggers/system.py | |||
128 | index a18fe8a..3f7f328 100644 | |||
129 | --- a/src/maasserver/triggers/system.py | |||
130 | +++ b/src/maasserver/triggers/system.py | |||
131 | @@ -2054,6 +2054,124 @@ def render_dns_dynamic_update_subnet_procedure(op): | |||
132 | 2054 | ) | 2054 | ) |
133 | 2055 | 2055 | ||
134 | 2056 | 2056 | ||
135 | 2057 | def render_dns_dynamic_update_interface_static_ip_address(op): | ||
136 | 2058 | return dedent( | ||
137 | 2059 | f"""\ | ||
138 | 2060 | CREATE OR REPLACE FUNCTION sys_dns_updates_interface_ip_{op}() | ||
139 | 2061 | RETURNS trigger as $$ | ||
140 | 2062 | DECLARE | ||
141 | 2063 | current_hostname text; | ||
142 | 2064 | domain text; | ||
143 | 2065 | iface_name text; | ||
144 | 2066 | ip_addr text; | ||
145 | 2067 | address_ttl int; | ||
146 | 2068 | BEGIN | ||
147 | 2069 | ASSERT TG_WHEN = 'AFTER', 'May only run as an AFTER trigger'; | ||
148 | 2070 | ASSERT TG_LEVEL <> 'STATEMENT', 'Should not be used as a STATEMENT level trigger', TG_NAME; | ||
149 | 2071 | IF (TG_OP = 'INSERT' AND TG_LEVEL = 'ROW') THEN | ||
150 | 2072 | SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl | ||
151 | 2073 | FROM maasserver_interface AS iface | ||
152 | 2074 | JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id | ||
153 | 2075 | JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=NEW.interface_id; | ||
154 | 2076 | SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=NEW.staticipaddress_id; | ||
155 | 2077 | PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr); | ||
156 | 2078 | PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr); | ||
157 | 2079 | ELSIF (TG_OP = 'DELETE' AND TG_LEVEL = 'ROW') THEN | ||
158 | 2080 | IF EXISTS(SELECT id FROM maasserver_interface WHERE id=OLD.interface_id) THEN | ||
159 | 2081 | SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl | ||
160 | 2082 | FROM maasserver_interface AS iface | ||
161 | 2083 | JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id | ||
162 | 2084 | JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=OLD.interface_id; | ||
163 | 2085 | IF EXISTS(SELECT id FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id) THEN | ||
164 | 2086 | SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id; | ||
165 | 2087 | PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || current_hostname || ' A ' || ip_addr); | ||
166 | 2088 | PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || ip_addr); | ||
167 | 2089 | ELSE | ||
168 | 2090 | PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' A ' || OLD.interface_id); | ||
169 | 2091 | PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' AAAA ' || OLD.interface_id); | ||
170 | 2092 | END IF; | ||
171 | 2093 | END IF; | ||
172 | 2094 | END IF; | ||
173 | 2095 | RETURN NULL; | ||
174 | 2096 | END; | ||
175 | 2097 | $$ LANGUAGE plpgsql; | ||
176 | 2098 | """ | ||
177 | 2099 | ) | ||
178 | 2100 | |||
179 | 2101 | |||
180 | 2102 | dns_dynamic_update_static_ip_address_update = dedent( | ||
181 | 2103 | """\ | ||
182 | 2104 | CREATE OR REPLACE FUNCTION sys_dns_updates_ip_update() | ||
183 | 2105 | RETURNS trigger as $$ | ||
184 | 2106 | DECLARE | ||
185 | 2107 | current_hostname text; | ||
186 | 2108 | domain text; | ||
187 | 2109 | iface_name text; | ||
188 | 2110 | address_ttl int; | ||
189 | 2111 | current_interface_id bigint; | ||
190 | 2112 | BEGIN | ||
191 | 2113 | IF NEW IS DISTINCT FROM OLD THEN | ||
192 | 2114 | IF EXISTS(SELECT id FROM maasserver_interface_ip_addresses WHERE staticipaddress_id=NEW.id) THEN | ||
193 | 2115 | SELECT interface_id INTO current_interface_id FROM maasserver_interface_ip_addresses WHERE staticipaddress_id=NEW.id; | ||
194 | 2116 | SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl | ||
195 | 2117 | FROM maasserver_interface AS iface | ||
196 | 2118 | JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id | ||
197 | 2119 | JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=current_interface_id; | ||
198 | 2120 | IF OLD.ip IS NOT NULL THEN | ||
199 | 2121 | PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || current_hostname || ' A ' || host(OLD.ip)); | ||
200 | 2122 | PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || host(OLD.ip)); | ||
201 | 2123 | END IF; | ||
202 | 2124 | PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || current_hostname || ' A ' || address_ttl || ' ' || host(NEW.ip)); | ||
203 | 2125 | PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || address_ttl || ' ' || host(NEW.ip)); | ||
204 | 2126 | END IF; | ||
205 | 2127 | END IF; | ||
206 | 2128 | RETURN NULL; | ||
207 | 2129 | END; | ||
208 | 2130 | $$ LANGUAGE plpgsql; | ||
209 | 2131 | """ | ||
210 | 2132 | ) | ||
211 | 2133 | |||
212 | 2134 | dns_dynamic_update_node_delete = dedent( | ||
213 | 2135 | """\ | ||
214 | 2136 | CREATE OR REPLACE FUNCTION sys_dns_updates_maasserver_node_delete() | ||
215 | 2137 | RETURNS trigger as $$ | ||
216 | 2138 | DECLARE | ||
217 | 2139 | hostname text; | ||
218 | 2140 | domain text; | ||
219 | 2141 | address_ttl int; | ||
220 | 2142 | BEGIN | ||
221 | 2143 | SELECT name, COALESCE(ttl, 0) INTO domain, address_ttl FROM maasserver_domain WHERE id=OLD.domain_id; | ||
222 | 2144 | PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || OLD.hostname || ' A'); | ||
223 | 2145 | RETURN NULL; | ||
224 | 2146 | END; | ||
225 | 2147 | $$ LANGUAGE plpgsql; | ||
226 | 2148 | """ | ||
227 | 2149 | ) | ||
228 | 2150 | |||
229 | 2151 | |||
230 | 2152 | dns_dynamic_update_interface_delete = dedent( | ||
231 | 2153 | """\ | ||
232 | 2154 | CREATE OR REPLACE FUNCTION sys_dns_updates_maasserver_interface_delete() | ||
233 | 2155 | RETURNS trigger as $$ | ||
234 | 2156 | DECLARE | ||
235 | 2157 | current_hostname text; | ||
236 | 2158 | current_domain_id bigint; | ||
237 | 2159 | domain text; | ||
238 | 2160 | current_node_id bigint; | ||
239 | 2161 | BEGIN | ||
240 | 2162 | IF EXISTS(SELECT id FROM maasserver_nodeconfig WHERE id=OLD.node_config_id) THEN | ||
241 | 2163 | SELECT node_id INTO current_node_id FROM maasserver_nodeconfig WHERE id=OLD.node_config_id; | ||
242 | 2164 | SELECT hostname, domain_id INTO current_hostname, current_domain_id FROM maasserver_node WHERE id=current_node_id; | ||
243 | 2165 | SELECT name INTO domain FROM maasserver_domain WHERE id=current_domain_id; | ||
244 | 2166 | PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || OLD.name || '.' || current_hostname || ' A'); | ||
245 | 2167 | END IF; | ||
246 | 2168 | RETURN NULL; | ||
247 | 2169 | END; | ||
248 | 2170 | $$ LANGUAGE plpgsql; | ||
249 | 2171 | """ | ||
250 | 2172 | ) | ||
251 | 2173 | |||
252 | 2174 | |||
253 | 2057 | def render_sys_proxy_procedure(proc_name, on_delete=False): | 2175 | def render_sys_proxy_procedure(proc_name, on_delete=False): |
254 | 2058 | """Render a database procedure with name `proc_name` that notifies that a | 2176 | """Render a database procedure with name `proc_name` that notifies that a |
255 | 2059 | proxy update is needed. | 2177 | proxy update is needed. |
256 | @@ -2403,3 +2521,37 @@ def register_system_triggers(): | |||
257 | 2403 | "sys_dns_updates_maasserver_subnet_delete", | 2521 | "sys_dns_updates_maasserver_subnet_delete", |
258 | 2404 | "delete", | 2522 | "delete", |
259 | 2405 | ) | 2523 | ) |
260 | 2524 | register_procedure( | ||
261 | 2525 | render_dns_dynamic_update_interface_static_ip_address("insert") | ||
262 | 2526 | ) | ||
263 | 2527 | register_trigger( | ||
264 | 2528 | "maasserver_interface_ip_addresses", | ||
265 | 2529 | "sys_dns_updates_interface_ip_insert", | ||
266 | 2530 | "insert", | ||
267 | 2531 | ) | ||
268 | 2532 | register_procedure( | ||
269 | 2533 | render_dns_dynamic_update_interface_static_ip_address("delete") | ||
270 | 2534 | ) | ||
271 | 2535 | register_trigger( | ||
272 | 2536 | "maasserver_interface_ip_addresses", | ||
273 | 2537 | "sys_dns_updates_interface_ip_delete", | ||
274 | 2538 | "delete", | ||
275 | 2539 | ) | ||
276 | 2540 | register_procedure(dns_dynamic_update_static_ip_address_update) | ||
277 | 2541 | register_trigger( | ||
278 | 2542 | "maasserver_staticipaddress", | ||
279 | 2543 | "sys_dns_updates_ip_update", | ||
280 | 2544 | "update", | ||
281 | 2545 | ) | ||
282 | 2546 | register_procedure(dns_dynamic_update_node_delete) | ||
283 | 2547 | register_trigger( | ||
284 | 2548 | "maasserver_node", | ||
285 | 2549 | "sys_dns_updates_maasserver_node_delete", | ||
286 | 2550 | "delete", | ||
287 | 2551 | ) | ||
288 | 2552 | register_procedure(dns_dynamic_update_interface_delete) | ||
289 | 2553 | register_trigger( | ||
290 | 2554 | "maasserver_interface", | ||
291 | 2555 | "sys_dns_updates_maasserver_interface_delete", | ||
292 | 2556 | "delete", | ||
293 | 2557 | ) | ||
294 | diff --git a/src/maasserver/triggers/tests/test_init.py b/src/maasserver/triggers/tests/test_init.py | |||
295 | index e4fb3ed..34395f1 100644 | |||
296 | --- a/src/maasserver/triggers/tests/test_init.py | |||
297 | +++ b/src/maasserver/triggers/tests/test_init.py | |||
298 | @@ -91,14 +91,18 @@ class TestTriggersUsed(MAASServerTestCase): | |||
299 | 91 | "domain_sys_dns_updates_maasserver_domain_update", | 91 | "domain_sys_dns_updates_maasserver_domain_update", |
300 | 92 | "interface_ip_addresses_sys_dns_nic_ip_link", | 92 | "interface_ip_addresses_sys_dns_nic_ip_link", |
301 | 93 | "interface_ip_addresses_sys_dns_nic_ip_unlink", | 93 | "interface_ip_addresses_sys_dns_nic_ip_unlink", |
302 | 94 | "interface_ip_addresses_sys_dns_updates_interface_ip_insert", | ||
303 | 95 | "interface_ip_addresses_sys_dns_updates_interface_ip_delete", | ||
304 | 94 | "interface_sys_dhcp_interface_update", | 96 | "interface_sys_dhcp_interface_update", |
305 | 95 | "interface_sys_dns_interface_update", | 97 | "interface_sys_dns_interface_update", |
306 | 98 | "interface_sys_dns_updates_maasserver_interface_delete", | ||
307 | 96 | "iprange_sys_dhcp_iprange_delete", | 99 | "iprange_sys_dhcp_iprange_delete", |
308 | 97 | "iprange_sys_dhcp_iprange_insert", | 100 | "iprange_sys_dhcp_iprange_insert", |
309 | 98 | "iprange_sys_dhcp_iprange_update", | 101 | "iprange_sys_dhcp_iprange_update", |
310 | 99 | "node_sys_dhcp_node_update", | 102 | "node_sys_dhcp_node_update", |
311 | 100 | "node_sys_dns_node_delete", | 103 | "node_sys_dns_node_delete", |
312 | 101 | "node_sys_dns_node_update", | 104 | "node_sys_dns_node_update", |
313 | 105 | "node_sys_dns_updates_maasserver_node_delete", | ||
314 | 102 | "rbacsync_sys_rbac_sync", | 106 | "rbacsync_sys_rbac_sync", |
315 | 103 | "regionrackrpcconnection_sys_core_rpc_delete", | 107 | "regionrackrpcconnection_sys_core_rpc_delete", |
316 | 104 | "regionrackrpcconnection_sys_core_rpc_insert", | 108 | "regionrackrpcconnection_sys_core_rpc_insert", |
317 | @@ -109,6 +113,7 @@ class TestTriggersUsed(MAASServerTestCase): | |||
318 | 109 | "staticipaddress_sys_dhcp_staticipaddress_insert", | 113 | "staticipaddress_sys_dhcp_staticipaddress_insert", |
319 | 110 | "staticipaddress_sys_dhcp_staticipaddress_update", | 114 | "staticipaddress_sys_dhcp_staticipaddress_update", |
320 | 111 | "staticipaddress_sys_dns_staticipaddress_update", | 115 | "staticipaddress_sys_dns_staticipaddress_update", |
321 | 116 | "staticipaddress_sys_dns_updates_ip_update", | ||
322 | 112 | "subnet_sys_dns_updates_maasserver_subnet_delete", | 117 | "subnet_sys_dns_updates_maasserver_subnet_delete", |
323 | 113 | "subnet_sys_dns_updates_maasserver_subnet_insert", | 118 | "subnet_sys_dns_updates_maasserver_subnet_insert", |
324 | 114 | "subnet_sys_dns_updates_maasserver_subnet_update", | 119 | "subnet_sys_dns_updates_maasserver_subnet_update", |
325 | diff --git a/src/maasserver/triggers/tests/test_system.py b/src/maasserver/triggers/tests/test_system.py | |||
326 | index d5222b4..4337984 100644 | |||
327 | --- a/src/maasserver/triggers/tests/test_system.py | |||
328 | +++ b/src/maasserver/triggers/tests/test_system.py | |||
329 | @@ -7,6 +7,8 @@ from contextlib import closing | |||
330 | 7 | from django.db import connection | 7 | from django.db import connection |
331 | 8 | from twisted.internet.defer import inlineCallbacks | 8 | from twisted.internet.defer import inlineCallbacks |
332 | 9 | 9 | ||
333 | 10 | from maasserver.enum import NODE_STATUS | ||
334 | 11 | from maasserver.models import Domain | ||
335 | 10 | from maasserver.models.dnspublication import zone_serial | 12 | from maasserver.models.dnspublication import zone_serial |
336 | 11 | from maasserver.testing.factory import factory | 13 | from maasserver.testing.factory import factory |
337 | 12 | from maasserver.testing.testcase import ( | 14 | from maasserver.testing.testcase import ( |
338 | @@ -367,3 +369,272 @@ class TestSysDNSUpdates( | |||
339 | 367 | finally: | 369 | finally: |
340 | 368 | self.stop_reading() | 370 | self.stop_reading() |
341 | 369 | yield self.postgres_listener_service.stopService() | 371 | yield self.postgres_listener_service.stopService() |
342 | 372 | |||
343 | 373 | @wait_for_reactor | ||
344 | 374 | @inlineCallbacks | ||
345 | 375 | def test_dns_dynamic_update_interface_static_ip_address_insert(self): | ||
346 | 376 | listener = self.make_listener_without_delay() | ||
347 | 377 | yield self.set_service(listener) | ||
348 | 378 | yield deferToDatabase( | ||
349 | 379 | self.register_trigger, | ||
350 | 380 | "maasserver_interface_ip_addresses", | ||
351 | 381 | "sys_dns_updates", | ||
352 | 382 | ops=("insert",), | ||
353 | 383 | trigger="sys_dns_updates_interface_ip_insert", | ||
354 | 384 | ) | ||
355 | 385 | vlan = yield deferToDatabase(self.create_vlan) | ||
356 | 386 | subnet = yield deferToDatabase( | ||
357 | 387 | self.create_subnet, params={"vlan": vlan} | ||
358 | 388 | ) | ||
359 | 389 | self.start_reading() | ||
360 | 390 | try: | ||
361 | 391 | node = yield deferToDatabase( | ||
362 | 392 | self.create_node_with_interface, | ||
363 | 393 | params={"subnet": subnet, "status": NODE_STATUS.DEPLOYED}, | ||
364 | 394 | ) | ||
365 | 395 | domain = yield deferToDatabase(Domain.objects.get_default_domain) | ||
366 | 396 | expected_iface = yield deferToDatabase( | ||
367 | 397 | lambda: node.current_config.interface_set.first() | ||
368 | 398 | ) | ||
369 | 399 | expected_ip = yield deferToDatabase( | ||
370 | 400 | lambda: self.create_staticipaddress( | ||
371 | 401 | params={ | ||
372 | 402 | "ip": subnet.get_next_ip_for_allocation()[0], | ||
373 | 403 | "interface": expected_iface, | ||
374 | 404 | "subnet": subnet, | ||
375 | 405 | } | ||
376 | 406 | ) | ||
377 | 407 | ) | ||
378 | 408 | msg1 = yield self.get_notify("sys_dns_updates") | ||
379 | 409 | self.assertEqual( | ||
380 | 410 | msg1, | ||
381 | 411 | f"INSERT {domain.name} {node.hostname} A 0 {expected_ip.ip}", | ||
382 | 412 | ) | ||
383 | 413 | msg2 = yield self.get_notify("sys_dns_updates") | ||
384 | 414 | self.assertEqual( | ||
385 | 415 | msg2, | ||
386 | 416 | f"INSERT {domain.name} {expected_iface.name}.{node.hostname} A 0 {expected_ip.ip}", | ||
387 | 417 | ) | ||
388 | 418 | finally: | ||
389 | 419 | self.stop_reading() | ||
390 | 420 | yield self.postgres_listener_service.stopService() | ||
391 | 421 | |||
392 | 422 | @wait_for_reactor | ||
393 | 423 | @inlineCallbacks | ||
394 | 424 | def test_dns_dynamic_update_interface_static_ip_address_insert_with_non_default_domain( | ||
395 | 425 | self, | ||
396 | 426 | ): | ||
397 | 427 | listener = self.make_listener_without_delay() | ||
398 | 428 | yield self.set_service(listener) | ||
399 | 429 | yield deferToDatabase( | ||
400 | 430 | self.register_trigger, | ||
401 | 431 | "maasserver_interface_ip_addresses", | ||
402 | 432 | "sys_dns_updates", | ||
403 | 433 | ops=("insert",), | ||
404 | 434 | trigger="sys_dns_updates_interface_ip_insert", | ||
405 | 435 | ) | ||
406 | 436 | vlan = yield deferToDatabase(self.create_vlan) | ||
407 | 437 | subnet = yield deferToDatabase( | ||
408 | 438 | self.create_subnet, params={"vlan": vlan} | ||
409 | 439 | ) | ||
410 | 440 | domain = yield deferToDatabase(self.create_domain) | ||
411 | 441 | self.start_reading() | ||
412 | 442 | try: | ||
413 | 443 | node = yield deferToDatabase( | ||
414 | 444 | self.create_node_with_interface, | ||
415 | 445 | params={ | ||
416 | 446 | "subnet": subnet, | ||
417 | 447 | "status": NODE_STATUS.DEPLOYED, | ||
418 | 448 | "domain": domain, | ||
419 | 449 | }, | ||
420 | 450 | ) | ||
421 | 451 | expected_iface = yield deferToDatabase( | ||
422 | 452 | lambda: node.current_config.interface_set.first() | ||
423 | 453 | ) | ||
424 | 454 | expected_ip = yield deferToDatabase( | ||
425 | 455 | lambda: self.create_staticipaddress( | ||
426 | 456 | params={ | ||
427 | 457 | "ip": subnet.get_next_ip_for_allocation()[0], | ||
428 | 458 | "interface": expected_iface, | ||
429 | 459 | "subnet": subnet, | ||
430 | 460 | } | ||
431 | 461 | ) | ||
432 | 462 | ) | ||
433 | 463 | msg1 = yield self.get_notify("sys_dns_updates") | ||
434 | 464 | self.assertEqual( | ||
435 | 465 | msg1, | ||
436 | 466 | f"INSERT {domain.name} {node.hostname} A 0 {expected_ip.ip}", | ||
437 | 467 | ) | ||
438 | 468 | msg2 = yield self.get_notify("sys_dns_updates") | ||
439 | 469 | self.assertEqual( | ||
440 | 470 | msg2, | ||
441 | 471 | f"INSERT {domain.name} {expected_iface.name}.{node.hostname} A 0 {expected_ip.ip}", | ||
442 | 472 | ) | ||
443 | 473 | finally: | ||
444 | 474 | self.stop_reading() | ||
445 | 475 | yield self.postgres_listener_service.stopService() | ||
446 | 476 | |||
447 | 477 | @wait_for_reactor | ||
448 | 478 | @inlineCallbacks | ||
449 | 479 | def test_dns_dynamic_update_interface_static_ip_address_delete(self): | ||
450 | 480 | listener = self.make_listener_without_delay() | ||
451 | 481 | yield self.set_service(listener) | ||
452 | 482 | yield deferToDatabase( | ||
453 | 483 | self.register_trigger, | ||
454 | 484 | "maasserver_interface_ip_addresses", | ||
455 | 485 | "sys_dns_updates", | ||
456 | 486 | ops=("delete",), | ||
457 | 487 | trigger="sys_dns_updates_interface_ip_delete", | ||
458 | 488 | ) | ||
459 | 489 | vlan = yield deferToDatabase(self.create_vlan) | ||
460 | 490 | subnet = yield deferToDatabase( | ||
461 | 491 | self.create_subnet, params={"vlan": vlan} | ||
462 | 492 | ) | ||
463 | 493 | node = yield deferToDatabase( | ||
464 | 494 | self.create_node_with_interface, | ||
465 | 495 | params={"subnet": subnet, "status": NODE_STATUS.DEPLOYED}, | ||
466 | 496 | ) | ||
467 | 497 | domain = yield deferToDatabase(Domain.objects.get_default_domain) | ||
468 | 498 | iface = yield deferToDatabase( | ||
469 | 499 | lambda: node.current_config.interface_set.first() | ||
470 | 500 | ) | ||
471 | 501 | ip1 = yield deferToDatabase( | ||
472 | 502 | lambda: self.create_staticipaddress( | ||
473 | 503 | params={ | ||
474 | 504 | "ip": subnet.get_next_ip_for_allocation()[0], | ||
475 | 505 | "interface": iface, | ||
476 | 506 | "subnet": subnet, | ||
477 | 507 | } | ||
478 | 508 | ) | ||
479 | 509 | ) | ||
480 | 510 | self.start_reading() | ||
481 | 511 | try: | ||
482 | 512 | yield deferToDatabase(iface.unlink_ip_address, ip1) | ||
483 | 513 | msg1 = yield self.get_notify("sys_dns_updates") | ||
484 | 514 | self.assertEqual( | ||
485 | 515 | msg1, f"DELETE {domain.name} {node.hostname} A {ip1.ip}" | ||
486 | 516 | ) | ||
487 | 517 | msg2 = yield self.get_notify("sys_dns_updates") | ||
488 | 518 | self.assertEqual( | ||
489 | 519 | msg2, | ||
490 | 520 | f"DELETE {domain.name} {iface.name}.{node.hostname} A {ip1.ip}", | ||
491 | 521 | ) | ||
492 | 522 | finally: | ||
493 | 523 | self.stop_reading() | ||
494 | 524 | yield self.postgres_listener_service.stopService() | ||
495 | 525 | |||
496 | 526 | @wait_for_reactor | ||
497 | 527 | @inlineCallbacks | ||
498 | 528 | def test_dns_dynamc_update_ip_update(self): | ||
499 | 529 | listener = self.make_listener_without_delay() | ||
500 | 530 | yield self.set_service(listener) | ||
501 | 531 | yield deferToDatabase( | ||
502 | 532 | self.register_trigger, | ||
503 | 533 | "maasserver_staticipaddress", | ||
504 | 534 | "sys_dns_updates", | ||
505 | 535 | ops=("update",), | ||
506 | 536 | trigger="sys_dns_updates_ip_update", | ||
507 | 537 | ) | ||
508 | 538 | vlan = yield deferToDatabase(self.create_vlan) | ||
509 | 539 | subnet = yield deferToDatabase( | ||
510 | 540 | self.create_subnet, params={"vlan": vlan} | ||
511 | 541 | ) | ||
512 | 542 | node = yield deferToDatabase( | ||
513 | 543 | self.create_node_with_interface, | ||
514 | 544 | params={"subnet": subnet, "status": NODE_STATUS.DEPLOYED}, | ||
515 | 545 | ) | ||
516 | 546 | domain = yield deferToDatabase(Domain.objects.get_default_domain) | ||
517 | 547 | iface = yield deferToDatabase( | ||
518 | 548 | lambda: node.current_config.interface_set.first() | ||
519 | 549 | ) | ||
520 | 550 | ip = yield deferToDatabase( | ||
521 | 551 | lambda: self.create_staticipaddress( | ||
522 | 552 | params={ | ||
523 | 553 | "ip": subnet.get_next_ip_for_allocation()[0], | ||
524 | 554 | "interface": iface, | ||
525 | 555 | "subnet": subnet, | ||
526 | 556 | } | ||
527 | 557 | ) | ||
528 | 558 | ) | ||
529 | 559 | old_ip = ip.ip | ||
530 | 560 | |||
531 | 561 | def _set_new_ip(): | ||
532 | 562 | ip.ip = subnet.get_next_ip_for_allocation()[0] | ||
533 | 563 | ip.save() | ||
534 | 564 | |||
535 | 565 | self.start_reading() | ||
536 | 566 | try: | ||
537 | 567 | yield deferToDatabase(_set_new_ip) | ||
538 | 568 | msg1 = yield self.get_notify("sys_dns_updates") | ||
539 | 569 | self.assertEqual( | ||
540 | 570 | msg1, f"DELETE {domain.name} {node.hostname} A {old_ip}" | ||
541 | 571 | ) | ||
542 | 572 | msg2 = yield self.get_notify("sys_dns_updates") | ||
543 | 573 | self.assertEqual( | ||
544 | 574 | msg2, | ||
545 | 575 | f"DELETE {domain.name} {iface.name}.{node.hostname} A {old_ip}", | ||
546 | 576 | ) | ||
547 | 577 | msg3 = yield self.get_notify("sys_dns_updates") | ||
548 | 578 | self.assertEqual( | ||
549 | 579 | msg3, f"INSERT {domain.name} {node.hostname} A 0 {ip.ip}" | ||
550 | 580 | ) | ||
551 | 581 | msg4 = yield self.get_notify("sys_dns_updates") | ||
552 | 582 | self.assertEqual( | ||
553 | 583 | msg4, | ||
554 | 584 | f"INSERT {domain.name} {iface.name}.{node.hostname} A 0 {ip.ip}", | ||
555 | 585 | ) | ||
556 | 586 | finally: | ||
557 | 587 | self.stop_reading() | ||
558 | 588 | yield self.postgres_listener_service.stopService() | ||
559 | 589 | |||
560 | 590 | @wait_for_reactor | ||
561 | 591 | @inlineCallbacks | ||
562 | 592 | def test_dns_dynamic_update_node_delete(self): | ||
563 | 593 | listener = self.make_listener_without_delay() | ||
564 | 594 | yield self.set_service(listener) | ||
565 | 595 | yield deferToDatabase( | ||
566 | 596 | self.register_trigger, | ||
567 | 597 | "maasserver_node", | ||
568 | 598 | "sys_dns_updates", | ||
569 | 599 | ops=("delete",), | ||
570 | 600 | ) | ||
571 | 601 | node = yield deferToDatabase(self.create_node) | ||
572 | 602 | domain = yield deferToDatabase(Domain.objects.get_default_domain) | ||
573 | 603 | self.start_reading() | ||
574 | 604 | try: | ||
575 | 605 | yield deferToDatabase(node.delete) | ||
576 | 606 | msg = yield self.get_notify("sys_dns_updates") | ||
577 | 607 | self.assertEqual(msg, f"DELETE {domain.name} {node.hostname} A") | ||
578 | 608 | finally: | ||
579 | 609 | self.stop_reading() | ||
580 | 610 | yield self.postgres_listener_service.stopService() | ||
581 | 611 | |||
582 | 612 | @wait_for_reactor | ||
583 | 613 | @inlineCallbacks | ||
584 | 614 | def test_dns_dynamic_update_interface_delete(self): | ||
585 | 615 | listener = self.make_listener_without_delay() | ||
586 | 616 | yield self.set_service(listener) | ||
587 | 617 | yield deferToDatabase( | ||
588 | 618 | self.register_trigger, | ||
589 | 619 | "maasserver_node", | ||
590 | 620 | "sys_dns_updates", | ||
591 | 621 | ops=("delete",), | ||
592 | 622 | ) | ||
593 | 623 | subnet = yield deferToDatabase(self.create_subnet) | ||
594 | 624 | node = yield deferToDatabase( | ||
595 | 625 | self.create_node_with_interface, params={"subnet": subnet} | ||
596 | 626 | ) | ||
597 | 627 | domain = yield deferToDatabase(Domain.objects.get_default_domain) | ||
598 | 628 | iface = yield deferToDatabase( | ||
599 | 629 | lambda: node.current_config.interface_set.first() | ||
600 | 630 | ) | ||
601 | 631 | self.start_reading() | ||
602 | 632 | try: | ||
603 | 633 | yield deferToDatabase(iface.delete) | ||
604 | 634 | msg = yield self.get_notify("sys_dns_updates") | ||
605 | 635 | self.assertEqual( | ||
606 | 636 | msg, f"DELETE {domain.name} {iface.name}.{node.hostname} A" | ||
607 | 637 | ) | ||
608 | 638 | finally: | ||
609 | 639 | self.stop_reading() | ||
610 | 640 | yield self.postgres_listener_service.stopService() | ||
611 | diff --git a/src/provisioningserver/dns/zoneconfig.py b/src/provisioningserver/dns/zoneconfig.py | |||
612 | index 13dca69..eed539a 100644 | |||
613 | --- a/src/provisioningserver/dns/zoneconfig.py | |||
614 | +++ b/src/provisioningserver/dns/zoneconfig.py | |||
615 | @@ -7,6 +7,7 @@ | |||
616 | 7 | from datetime import datetime | 7 | from datetime import datetime |
617 | 8 | from itertools import chain | 8 | from itertools import chain |
618 | 9 | import os | 9 | import os |
619 | 10 | from pathlib import Path | ||
620 | 10 | 11 | ||
621 | 11 | from netaddr import IPAddress, IPNetwork, spanning_cidr | 12 | from netaddr import IPAddress, IPNetwork, spanning_cidr |
622 | 12 | from netaddr.core import AddrFormatError | 13 | from netaddr.core import AddrFormatError |
623 | @@ -323,6 +324,7 @@ class DNSForwardZoneConfig(DomainConfigBase): | |||
624 | 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): |
625 | 324 | self.dynamic_update(zi) | 325 | self.dynamic_update(zi) |
626 | 325 | else: | 326 | else: |
627 | 327 | Path(f"{zi.target_path}.jnl").unlink(missing_ok=True) | ||
628 | 326 | self.requires_reload = True | 328 | self.requires_reload = True |
629 | 327 | self.write_zone_file( | 329 | self.write_zone_file( |
630 | 328 | zi.target_path, | 330 | zi.target_path, |
631 | @@ -612,6 +614,7 @@ class DNSReverseZoneConfig(DomainConfigBase): | |||
632 | 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): |
633 | 613 | self.dynamic_update(zi) | 615 | self.dynamic_update(zi) |
634 | 614 | else: | 616 | else: |
635 | 617 | Path(f"{zi.target_path}.jnl").unlink(missing_ok=True) | ||
636 | 615 | self.requires_reload = True | 618 | self.requires_reload = True |
637 | 616 | self.write_zone_file( | 619 | self.write_zone_file( |
638 | 617 | zi.target_path, | 620 | zi.target_path, |
UNIT TESTS dns_generation lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas
-b fix_node_
STATUS: FAILED maas-ci. internal: 8080/job/ maas-tester/ 1610/consoleTex t e865c4356e2e624 e4f312f7de
LOG: http://
COMMIT: c66c10c229362a9