Merge lp:~blake-rouse/maas/dns-triggers into lp:~maas-committers/maas/trunk
- dns-triggers
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Blake Rouse | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 4852 | ||||
Proposed branch: | lp:~blake-rouse/maas/dns-triggers | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Diff against target: |
1170 lines (+1023/-11) 6 files modified
src/maasserver/sequence.py (+21/-2) src/maasserver/tests/test_sequence.py (+2/-2) src/maasserver/triggers/system.py (+244/-0) src/maasserver/triggers/tests/helper.py (+23/-0) src/maasserver/triggers/tests/test_system.py (+36/-6) src/maasserver/triggers/tests/test_system_listener.py (+697/-1) |
||||
To merge this branch: | bzr merge lp:~blake-rouse/maas/dns-triggers | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Mike Pontillo | Pending | ||
Review via email: mp+290383@code.launchpad.net |
This proposal supersedes a proposal from 2016-03-25.
Commit message
Add triggers for the DNS HA system.
Description of the change
LaMont Jones (lamont) wrote : Posted in a previous version of this proposal | # |
Mike Pontillo (mpontillo) wrote : Posted in a previous version of this proposal | # |
Looks pretty good, but please see my questions below regarding a possible race condition when getting the first value from a sequence.
And some general gripes about triggers and trigger registration.
Blake Rouse (blake-rouse) : Posted in a previous version of this proposal | # |
MAAS Lander (maas-lander) wrote : Posted in a previous version of this proposal | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Blake Rouse (blake-rouse) wrote : | # |
Had to resubmit because launchpad said it was still analyzing the diff that I pushed 4 hours ago.
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~blake-rouse/maas/dns-triggers into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Get:2 http://
Hit:3 http://
Hit:4 http://
Get:5 http://
Get:6 http://
Get:7 http://
Fetched 19.1 MB in 3s (5,787 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-1ubuntu1).
archdetect-deb is already the newest version (1.114ubuntu4).
authbind is already the newest version (2.1.1+nmu1).
bind9 is already the newest version (1:9.10.
bind9utils is already the newest version (1:9.10.
build-essential is already the newest version (12.1ubuntu2).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubun
dh-apport is already the newest version (2.20-0ubuntu3).
dh-systemd is already the newest version (1.29ubuntu1).
distro-info is already the newest version (0.14build1).
dnsutils is already the newest version (1:9.10.
firefox is already the newest version (45.0.1+
freeipmi-tools is already the newest version ...
Preview Diff
1 | === modified file 'src/maasserver/sequence.py' |
2 | --- src/maasserver/sequence.py 2016-03-25 14:52:23 +0000 |
3 | +++ src/maasserver/sequence.py 2016-03-30 13:52:37 +0000 |
4 | @@ -20,6 +20,7 @@ |
5 | from provisioningserver.utils import typed |
6 | from psycopg2.errorcodes import ( |
7 | DUPLICATE_TABLE, |
8 | + NUMERIC_VALUE_OUT_OF_RANGE, |
9 | OBJECT_NOT_IN_PREREQUISITE_STATE, |
10 | UNDEFINED_TABLE, |
11 | ) |
12 | @@ -169,8 +170,26 @@ |
13 | return cursor.fetchone()[0] |
14 | except (utils.OperationalError, utils.ProgrammingError) as error: |
15 | if is_postgres_error(error, OBJECT_NOT_IN_PREREQUISITE_STATE): |
16 | - # There is no current value for the sequence. |
17 | - return None |
18 | + # There is no current value for the sequence in this session. |
19 | + # Perform nextval with setval to follow so we can get the |
20 | + # current value of the sequence. |
21 | + try: |
22 | + with transaction.atomic(): |
23 | + with connection.cursor() as cursor: |
24 | + cursor.execute( |
25 | + "SELECT setval(%s, nextval(%s) - %s);", |
26 | + [self.name, self.name, self.increment]) |
27 | + cursor.execute("SELECT currval(%s)", [self.name]) |
28 | + return cursor.fetchone()[0] |
29 | + except utils.DataError as error: |
30 | + if is_postgres_error(error, NUMERIC_VALUE_OUT_OF_RANGE): |
31 | + # The sequence was just created so calling nextval, |
32 | + # minusing the interval is placing it below the |
33 | + # minimum. The current value is the minimum. |
34 | + return ( |
35 | + self.minvalue if self.minvalue is not None else 1) |
36 | + else: |
37 | + raise |
38 | elif is_postgres_error(error, UNDEFINED_TABLE): |
39 | # The sequence does not exist, hence has no current value. |
40 | return None |
41 | |
42 | === modified file 'src/maasserver/tests/test_sequence.py' |
43 | --- src/maasserver/tests/test_sequence.py 2016-03-25 14:52:23 +0000 |
44 | +++ src/maasserver/tests/test_sequence.py 2016-03-30 13:52:37 +0000 |
45 | @@ -157,11 +157,11 @@ |
46 | seq = Sequence(name) |
47 | self.assertEqual(None, seq.current()) |
48 | |
49 | - def test_current_returns_none_when_no_current_value(self): |
50 | + def test_current_returns_minimum_value_when_no_current_value(self): |
51 | name = factory.make_name('seq', sep='') |
52 | seq = Sequence(name) |
53 | seq.create() |
54 | - self.assertEqual(None, seq.current()) |
55 | + self.assertEqual(1, seq.current()) |
56 | |
57 | def test_current_returns_current_value(self): |
58 | name = factory.make_name('seq', sep='') |
59 | |
60 | === modified file 'src/maasserver/triggers/system.py' |
61 | --- src/maasserver/triggers/system.py 2016-03-25 14:52:23 +0000 |
62 | +++ src/maasserver/triggers/system.py 2016-03-30 13:52:37 +0000 |
63 | @@ -15,6 +15,7 @@ |
64 | |
65 | from textwrap import dedent |
66 | |
67 | +from maasserver.dns.config import zone_serial |
68 | from maasserver.triggers import ( |
69 | register_procedure, |
70 | register_trigger, |
71 | @@ -781,6 +782,122 @@ |
72 | $$ LANGUAGE plpgsql; |
73 | """) |
74 | |
75 | +# Triggered when a subnet is updated. Increments the zone serial and notifies |
76 | +# that DNS needs to be updated. Only watches changes on the cidr and rdns_mode. |
77 | +DNS_SUBNET_UPDATE = dedent("""\ |
78 | + CREATE OR REPLACE FUNCTION sys_dns_subnet_update() |
79 | + RETURNS trigger as $$ |
80 | + BEGIN |
81 | + IF OLD.cidr != NEW.cidr OR OLD.rdns_mode != NEW.rdns_mode THEN |
82 | + -- Increment the zone serial. |
83 | + PERFORM nextval('maasserver_zone_serial_seq'); |
84 | + PERFORM pg_notify('sys_dns', ''); |
85 | + END IF; |
86 | + RETURN NEW; |
87 | + END; |
88 | + $$ LANGUAGE plpgsql; |
89 | + """) |
90 | + |
91 | +# Triggered when a node is updated. Increments the zone serial and notifies |
92 | +# that DNS needs to be updated. Only watches changes on the hostname and |
93 | +# linked domain for the node. |
94 | +DNS_NODE_UPDATE = dedent("""\ |
95 | + CREATE OR REPLACE FUNCTION sys_dns_node_update() |
96 | + RETURNS trigger as $$ |
97 | + BEGIN |
98 | + IF OLD.hostname != NEW.hostname OR OLD.domain_id != NEW.domain_id THEN |
99 | + -- Increment the zone serial. |
100 | + PERFORM nextval('maasserver_zone_serial_seq'); |
101 | + PERFORM pg_notify('sys_dns', ''); |
102 | + END IF; |
103 | + RETURN NEW; |
104 | + END; |
105 | + $$ LANGUAGE plpgsql; |
106 | + """) |
107 | + |
108 | + |
109 | +# Triggered when a interface is updated. Increments the zone serial and |
110 | +# notifies that DNS needs to be updated. Only watches changes on the name and |
111 | +# the node that the interface belongs to. |
112 | +DNS_INTERFACE_UPDATE = dedent("""\ |
113 | + CREATE OR REPLACE FUNCTION sys_dns_interface_update() |
114 | + RETURNS trigger as $$ |
115 | + BEGIN |
116 | + IF (OLD.name != NEW.name OR |
117 | + (OLD.node_id IS NULL AND NEW.node_id IS NOT NULL) OR |
118 | + (OLD.node_id IS NOT NULL AND NEW.node_id IS NULL) OR |
119 | + (OLD.node_id != NEW.node_id)) THEN |
120 | + -- Increment the zone serial. |
121 | + PERFORM nextval('maasserver_zone_serial_seq'); |
122 | + PERFORM pg_notify('sys_dns', ''); |
123 | + END IF; |
124 | + RETURN NEW; |
125 | + END; |
126 | + $$ LANGUAGE plpgsql; |
127 | + """) |
128 | + |
129 | + |
130 | +# Triggered when a config is inserted. Increments the zone serial and notifies |
131 | +# that DNS needs to be updated. Only watches for inserts on config |
132 | +# upstream_dns, default_dns_ttl, and windows_kms_host. |
133 | +DNS_CONFIG_INSERT = dedent("""\ |
134 | + CREATE OR REPLACE FUNCTION sys_dns_config_insert() |
135 | + RETURNS trigger as $$ |
136 | + BEGIN |
137 | + -- Only care about the |
138 | + IF (NEW.name = 'upstream_dns' OR |
139 | + NEW.name = 'default_dns_ttl' OR |
140 | + NEW.name = 'windows_kms_host') THEN |
141 | + -- Increment the zone serial. |
142 | + PERFORM nextval('maasserver_zone_serial_seq'); |
143 | + PERFORM pg_notify('sys_dns', ''); |
144 | + END IF; |
145 | + RETURN NEW; |
146 | + END; |
147 | + $$ LANGUAGE plpgsql; |
148 | + """) |
149 | + |
150 | +# Triggered when a config is updated. Increments the zone serial and notifies |
151 | +# that DNS needs to be updated. Only watches for updates on config |
152 | +# upstream_dns, default_dns_ttl, and windows_kms_host. |
153 | +DNS_CONFIG_UPDATE = dedent("""\ |
154 | + CREATE OR REPLACE FUNCTION sys_dns_config_update() |
155 | + RETURNS trigger as $$ |
156 | + BEGIN |
157 | + -- Only care about the upstream_dns, default_dns_ttl, and |
158 | + -- windows_kms_host. |
159 | + IF (OLD.value != NEW.value AND ( |
160 | + NEW.name = 'upstream_dns' OR |
161 | + NEW.name = 'default_dns_ttl' OR |
162 | + NEW.name = 'windows_kms_host')) THEN |
163 | + -- Increment the zone serial. |
164 | + PERFORM nextval('maasserver_zone_serial_seq'); |
165 | + PERFORM pg_notify('sys_dns', ''); |
166 | + END IF; |
167 | + RETURN NEW; |
168 | + END; |
169 | + $$ LANGUAGE plpgsql; |
170 | + """) |
171 | + |
172 | + |
173 | +def render_sys_dns_procedure(proc_name, on_delete=False): |
174 | + """Render a database procedure with name `proc_name` that increments |
175 | + the zone serial and notifies that a DNS update is needed. |
176 | + |
177 | + :param proc_name: Name of the procedure. |
178 | + :param on_delete: True when procedure will be used as a delete trigger. |
179 | + """ |
180 | + return dedent("""\ |
181 | + CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$ |
182 | + BEGIN |
183 | + -- Increment the zone serial. |
184 | + PERFORM nextval('maasserver_zone_serial_seq'); |
185 | + PERFORM pg_notify('sys_dns', ''); |
186 | + RETURN %s; |
187 | + END; |
188 | + $$ LANGUAGE plpgsql; |
189 | + """ % (proc_name, 'NEW' if not on_delete else 'OLD')) |
190 | + |
191 | |
192 | @transactional |
193 | def register_system_triggers(): |
194 | @@ -871,3 +988,130 @@ |
195 | register_procedure(DHCP_SNIPPET_DELETE) |
196 | register_trigger( |
197 | "maasserver_dhcpsnippet", "sys_dhcp_snippet_delete", "delete") |
198 | + |
199 | + # DNS |
200 | + # The zone serial is used in the 'sys_dns' triggers. Ensure that it exists |
201 | + # before creating the triggers. |
202 | + zone_serial.create_if_not_exists() |
203 | + |
204 | + ## Domain |
205 | + register_procedure( |
206 | + render_sys_dns_procedure("sys_dns_domain_insert")) |
207 | + register_trigger( |
208 | + "maasserver_domain", "sys_dns_domain_insert", "insert") |
209 | + register_procedure( |
210 | + render_sys_dns_procedure("sys_dns_domain_update")) |
211 | + register_trigger( |
212 | + "maasserver_domain", "sys_dns_domain_update", "update") |
213 | + register_procedure( |
214 | + render_sys_dns_procedure("sys_dns_domain_delete", on_delete=True)) |
215 | + register_trigger( |
216 | + "maasserver_domain", "sys_dns_domain_delete", "delete") |
217 | + |
218 | + ## StaticIPAddress |
219 | + register_procedure( |
220 | + render_sys_dns_procedure("sys_dns_staticipaddress_update")) |
221 | + register_trigger( |
222 | + "maasserver_staticipaddress", |
223 | + "sys_dns_staticipaddress_update", "update") |
224 | + |
225 | + ## Interface -> StaticIPAddress |
226 | + register_procedure( |
227 | + render_sys_dns_procedure("sys_dns_nic_ip_link")) |
228 | + register_trigger( |
229 | + "maasserver_interface_ip_addresses", |
230 | + "sys_dns_nic_ip_link", "insert") |
231 | + register_procedure( |
232 | + render_sys_dns_procedure( |
233 | + "sys_dns_nic_ip_unlink", on_delete=True)) |
234 | + register_trigger( |
235 | + "maasserver_interface_ip_addresses", |
236 | + "sys_dns_nic_ip_unlink", "delete") |
237 | + |
238 | + ## DNSResource |
239 | + register_procedure( |
240 | + render_sys_dns_procedure("sys_dns_dnsresource_insert")) |
241 | + register_trigger( |
242 | + "maasserver_dnsresource", |
243 | + "sys_dns_dnsresource_insert", "insert") |
244 | + register_procedure( |
245 | + render_sys_dns_procedure("sys_dns_dnsresource_update")) |
246 | + register_trigger( |
247 | + "maasserver_dnsresource", |
248 | + "sys_dns_dnsresource_update", "update") |
249 | + register_procedure( |
250 | + render_sys_dns_procedure("sys_dns_dnsresource_delete", on_delete=True)) |
251 | + register_trigger( |
252 | + "maasserver_dnsresource", |
253 | + "sys_dns_dnsresource_delete", "delete") |
254 | + |
255 | + ## DNSResource -> StaticIPAddress |
256 | + register_procedure( |
257 | + render_sys_dns_procedure("sys_dns_dnsresource_ip_link")) |
258 | + register_trigger( |
259 | + "maasserver_dnsresource_ip_addresses", |
260 | + "sys_dns_dnsresource_ip_link", "insert") |
261 | + register_procedure( |
262 | + render_sys_dns_procedure( |
263 | + "sys_dns_dnsresource_ip_unlink", on_delete=True)) |
264 | + register_trigger( |
265 | + "maasserver_dnsresource_ip_addresses", |
266 | + "sys_dns_dnsresource_ip_unlink", "delete") |
267 | + |
268 | + ## DNSData |
269 | + register_procedure( |
270 | + render_sys_dns_procedure("sys_dns_dnsdata_insert")) |
271 | + register_trigger( |
272 | + "maasserver_dnsdata", |
273 | + "sys_dns_dnsdata_insert", "insert") |
274 | + register_procedure( |
275 | + render_sys_dns_procedure("sys_dns_dnsdata_update")) |
276 | + register_trigger( |
277 | + "maasserver_dnsdata", |
278 | + "sys_dns_dnsdata_update", "update") |
279 | + register_procedure( |
280 | + render_sys_dns_procedure("sys_dns_dnsdata_delete", on_delete=True)) |
281 | + register_trigger( |
282 | + "maasserver_dnsdata", |
283 | + "sys_dns_dnsdata_delete", "delete") |
284 | + |
285 | + ## Subnet |
286 | + register_procedure( |
287 | + render_sys_dns_procedure("sys_dns_subnet_insert")) |
288 | + register_trigger( |
289 | + "maasserver_subnet", |
290 | + "sys_dns_subnet_insert", "insert") |
291 | + register_procedure(DNS_SUBNET_UPDATE) |
292 | + register_trigger( |
293 | + "maasserver_subnet", |
294 | + "sys_dns_subnet_update", "update") |
295 | + register_procedure( |
296 | + render_sys_dns_procedure("sys_dns_subnet_delete", on_delete=True)) |
297 | + register_trigger( |
298 | + "maasserver_subnet", |
299 | + "sys_dns_subnet_delete", "delete") |
300 | + |
301 | + ## Node |
302 | + register_procedure(DNS_NODE_UPDATE) |
303 | + register_trigger( |
304 | + "maasserver_node", |
305 | + "sys_dns_node_update", "update") |
306 | + register_procedure( |
307 | + render_sys_dns_procedure("sys_dns_node_delete", on_delete=True)) |
308 | + register_trigger( |
309 | + "maasserver_node", |
310 | + "sys_dns_node_delete", "delete") |
311 | + |
312 | + ## Interface |
313 | + register_procedure(DNS_INTERFACE_UPDATE) |
314 | + register_trigger( |
315 | + "maasserver_interface", |
316 | + "sys_dns_interface_update", "update") |
317 | + |
318 | + ## Config |
319 | + register_procedure(DNS_CONFIG_INSERT) |
320 | + register_procedure(DNS_CONFIG_UPDATE) |
321 | + register_trigger( |
322 | + "maasserver_config", "sys_dns_config_insert", "insert") |
323 | + register_trigger( |
324 | + "maasserver_config", "sys_dns_config_update", "update") |
325 | |
326 | === modified file 'src/maasserver/triggers/tests/helper.py' |
327 | --- src/maasserver/triggers/tests/helper.py 2016-03-29 17:02:00 +0000 |
328 | +++ src/maasserver/triggers/tests/helper.py 2016-03-30 13:52:37 +0000 |
329 | @@ -8,6 +8,7 @@ |
330 | |
331 | from crochet import wait_for |
332 | from django.contrib.auth.models import User |
333 | +from maasserver.dns.config import zone_serial |
334 | from maasserver.enum import ( |
335 | INTERFACE_TYPE, |
336 | NODE_TYPE, |
337 | @@ -52,7 +53,9 @@ |
338 | reload_object, |
339 | transactional, |
340 | ) |
341 | +from maasserver.utils.threads import deferToDatabase |
342 | from metadataserver.models import NodeResult |
343 | +from twisted.internet.defer import inlineCallbacks |
344 | |
345 | |
346 | wait_for_reactor = wait_for(30) # 30 seconds. |
347 | @@ -365,6 +368,12 @@ |
348 | return factory.make_Interface(INTERFACE_TYPE.PHYSICAL, **params) |
349 | |
350 | @transactional |
351 | + def create_unknown_interface(self, params=None): |
352 | + if params is None: |
353 | + params = {} |
354 | + return factory.make_Interface(INTERFACE_TYPE.UNKNOWN, **params) |
355 | + |
356 | + @transactional |
357 | def delete_interface(self, id): |
358 | interface = Interface.objects.get(id=id) |
359 | interface.delete() |
360 | @@ -624,3 +633,17 @@ |
361 | @transactional |
362 | def reload_object(self, obj): |
363 | return reload_object(obj) |
364 | + |
365 | + |
366 | +class DNSHelpersMixin: |
367 | + """Helper to get the zone serial and to assert it was incremented.""" |
368 | + |
369 | + def get_zone_serial_current(self): |
370 | + return deferToDatabase(transactional(zone_serial.current)) |
371 | + |
372 | + @inlineCallbacks |
373 | + def assertZoneSerialIncrement(self, previous): |
374 | + current = yield deferToDatabase(transactional(zone_serial.current)) |
375 | + self.assertTrue( |
376 | + current > previous, |
377 | + "Zone serial was not incremented.") |
378 | |
379 | === modified file 'src/maasserver/triggers/tests/test_system.py' |
380 | --- src/maasserver/triggers/tests/test_system.py 2016-02-10 20:24:35 +0000 |
381 | +++ src/maasserver/triggers/tests/test_system.py 2016-03-30 13:52:37 +0000 |
382 | @@ -8,9 +8,11 @@ |
383 | from contextlib import closing |
384 | |
385 | from django.db import connection |
386 | +from maasserver.dns.config import zone_serial |
387 | from maasserver.testing.testcase import MAASServerTestCase |
388 | from maasserver.triggers.system import register_system_triggers |
389 | from maasserver.utils.orm import psql_array |
390 | +from maastesting.matchers import MockCalledOnceWith |
391 | |
392 | |
393 | class TestTriggers(MAASServerTestCase): |
394 | @@ -31,6 +33,28 @@ |
395 | "staticipaddress_sys_dhcp_staticipaddress_delete", |
396 | "interface_sys_dhcp_interface_update", |
397 | "node_sys_dhcp_node_update", |
398 | + "dhcpsnippet_sys_dhcp_snippet_insert", |
399 | + "dhcpsnippet_sys_dhcp_snippet_update", |
400 | + "dhcpsnippet_sys_dhcp_snippet_delete", |
401 | + "domain_sys_dns_domain_insert", |
402 | + "domain_sys_dns_domain_update", |
403 | + "domain_sys_dns_domain_delete", |
404 | + "staticipaddress_sys_dns_staticipaddress_update", |
405 | + "interface_ip_addresses_sys_dns_nic_ip_link", |
406 | + "interface_ip_addresses_sys_dns_nic_ip_unlink", |
407 | + "dnsresource_sys_dns_dnsresource_insert", |
408 | + "dnsresource_sys_dns_dnsresource_update", |
409 | + "dnsresource_sys_dns_dnsresource_delete", |
410 | + "dnsresource_ip_addresses_sys_dns_dnsresource_ip_link", |
411 | + "dnsresource_ip_addresses_sys_dns_dnsresource_ip_unlink", |
412 | + "dnsdata_sys_dns_dnsdata_insert", |
413 | + "dnsdata_sys_dns_dnsdata_update", |
414 | + "dnsdata_sys_dns_dnsdata_delete", |
415 | + "node_sys_dns_node_update", |
416 | + "node_sys_dns_node_delete", |
417 | + "interface_sys_dns_interface_update", |
418 | + "config_sys_dns_config_insert", |
419 | + "config_sys_dns_config_update", |
420 | ] |
421 | sql, args = psql_array(triggers, sql_type="text") |
422 | with closing(connection.cursor()) as cursor: |
423 | @@ -42,12 +66,18 @@ |
424 | # Note: if this test fails, a trigger may have been added, but not |
425 | # added to the list of expected triggers. |
426 | triggers_found = [trigger[0] for trigger in db_triggers] |
427 | + missing_triggers = [ |
428 | + trigger |
429 | + for trigger in triggers |
430 | + if trigger not in triggers_found |
431 | + ] |
432 | self.assertEqual( |
433 | len(triggers), len(db_triggers), |
434 | - "Missing %s triggers in the database. Triggers found: %s" % ( |
435 | - len(triggers) - len(db_triggers), triggers_found)) |
436 | + "Missing %s triggers in the database. Triggers missing: %s" % ( |
437 | + len(triggers) - len(db_triggers), missing_triggers)) |
438 | |
439 | - self.assertItemsEqual( |
440 | - triggers, triggers_found, |
441 | - "Missing triggers in the database. Triggers found: %s" % ( |
442 | - triggers_found)) |
443 | + def test_register_system_triggers_ensures_zone_serial(self): |
444 | + mock_create = self.patch( |
445 | + zone_serial, "create_if_not_exists") |
446 | + register_system_triggers() |
447 | + self.assertThat(mock_create, MockCalledOnceWith()) |
448 | |
449 | === modified file 'src/maasserver/triggers/tests/test_system_listener.py' |
450 | --- src/maasserver/triggers/tests/test_system_listener.py 2016-03-25 14:52:23 +0000 |
451 | +++ src/maasserver/triggers/tests/test_system_listener.py 2016-03-30 13:52:37 +0000 |
452 | @@ -10,17 +10,29 @@ |
453 | datetime, |
454 | timedelta, |
455 | ) |
456 | +import random |
457 | |
458 | from crochet import wait_for |
459 | from django.db import connection as db_connection |
460 | from maasserver.enum import ( |
461 | + INTERFACE_TYPE, |
462 | IPADDRESS_TYPE, |
463 | IPRANGE_TYPE, |
464 | + RDNS_MODE, |
465 | +) |
466 | +from maasserver.models.config import Config |
467 | +from maasserver.models.interface import ( |
468 | + Interface, |
469 | + PhysicalInterface, |
470 | + UnknownInterface, |
471 | ) |
472 | from maasserver.testing.factory import factory |
473 | from maasserver.testing.testcase import MAASTransactionServerTestCase |
474 | from maasserver.triggers.system import register_system_triggers |
475 | -from maasserver.triggers.tests.helper import TransactionalHelpersMixin |
476 | +from maasserver.triggers.tests.helper import ( |
477 | + DNSHelpersMixin, |
478 | + TransactionalHelpersMixin, |
479 | +) |
480 | from maasserver.utils.orm import transactional |
481 | from maasserver.utils.threads import deferToDatabase |
482 | from netaddr import IPAddress |
483 | @@ -2270,3 +2282,687 @@ |
484 | yield dv.get(timeout=2) |
485 | finally: |
486 | yield listener.stopService() |
487 | + |
488 | + |
489 | +class TestDNSDomainListener( |
490 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
491 | + DNSHelpersMixin): |
492 | + """End-to-end test for the DNS triggers code.""" |
493 | + |
494 | + @wait_for_reactor |
495 | + @inlineCallbacks |
496 | + def test_sends_message_for_domain_insert(self): |
497 | + yield deferToDatabase(register_system_triggers) |
498 | + zone_serial = yield self.get_zone_serial_current() |
499 | + dv = DeferredValue() |
500 | + listener = self.make_listener_without_delay() |
501 | + listener.register( |
502 | + "sys_dns", lambda *args: dv.set(args)) |
503 | + yield listener.startService() |
504 | + try: |
505 | + yield deferToDatabase(self.create_domain) |
506 | + yield dv.get(timeout=2) |
507 | + yield self.assertZoneSerialIncrement(zone_serial) |
508 | + finally: |
509 | + yield listener.stopService() |
510 | + |
511 | + @wait_for_reactor |
512 | + @inlineCallbacks |
513 | + def test_sends_message_for_domain_update(self): |
514 | + yield deferToDatabase(register_system_triggers) |
515 | + domain = yield deferToDatabase(self.create_domain) |
516 | + zone_serial = yield self.get_zone_serial_current() |
517 | + dv = DeferredValue() |
518 | + listener = self.make_listener_without_delay() |
519 | + listener.register( |
520 | + "sys_dns", lambda *args: dv.set(args)) |
521 | + yield listener.startService() |
522 | + try: |
523 | + yield deferToDatabase(self.update_domain, domain.id, { |
524 | + "name": factory.make_name("domain"), |
525 | + }) |
526 | + yield dv.get(timeout=2) |
527 | + yield self.assertZoneSerialIncrement(zone_serial) |
528 | + finally: |
529 | + yield listener.stopService() |
530 | + |
531 | + @wait_for_reactor |
532 | + @inlineCallbacks |
533 | + def test_sends_message_for_domain_delete(self): |
534 | + yield deferToDatabase(register_system_triggers) |
535 | + domain = yield deferToDatabase(self.create_domain) |
536 | + zone_serial = yield self.get_zone_serial_current() |
537 | + dv = DeferredValue() |
538 | + listener = self.make_listener_without_delay() |
539 | + listener.register( |
540 | + "sys_dns", lambda *args: dv.set(args)) |
541 | + yield listener.startService() |
542 | + try: |
543 | + yield deferToDatabase(self.delete_domain, domain.id) |
544 | + yield dv.get(timeout=2) |
545 | + yield self.assertZoneSerialIncrement(zone_serial) |
546 | + finally: |
547 | + yield listener.stopService() |
548 | + |
549 | + |
550 | +class TestDNSStaticIPAddressListener( |
551 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
552 | + DNSHelpersMixin): |
553 | + """End-to-end test for the DNS triggers code.""" |
554 | + |
555 | + @wait_for_reactor |
556 | + @inlineCallbacks |
557 | + def test_sends_message_for_staticipaddress_update(self): |
558 | + yield deferToDatabase(register_system_triggers) |
559 | + sip = yield deferToDatabase(self.create_staticipaddress) |
560 | + zone_serial = yield self.get_zone_serial_current() |
561 | + dv = DeferredValue() |
562 | + listener = self.make_listener_without_delay() |
563 | + listener.register( |
564 | + "sys_dns", lambda *args: dv.set(args)) |
565 | + yield listener.startService() |
566 | + try: |
567 | + yield deferToDatabase(self.update_staticipaddress, sip.id, { |
568 | + "alloc_type": IPADDRESS_TYPE.STICKY, |
569 | + }) |
570 | + yield dv.get(timeout=2) |
571 | + yield self.assertZoneSerialIncrement(zone_serial) |
572 | + finally: |
573 | + yield listener.stopService() |
574 | + |
575 | + |
576 | +class TestDNSInterfaceStaticIPAddressListener( |
577 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
578 | + DNSHelpersMixin): |
579 | + """End-to-end test for the DNS triggers code.""" |
580 | + |
581 | + @wait_for_reactor |
582 | + @inlineCallbacks |
583 | + def test_sends_message_for_interface_staticipaddress_link(self): |
584 | + yield deferToDatabase(register_system_triggers) |
585 | + interface = yield deferToDatabase(self.create_interface) |
586 | + zone_serial = yield self.get_zone_serial_current() |
587 | + dv = DeferredValue() |
588 | + listener = self.make_listener_without_delay() |
589 | + listener.register( |
590 | + "sys_dns", lambda *args: dv.set(args)) |
591 | + yield listener.startService() |
592 | + try: |
593 | + yield deferToDatabase(self.create_staticipaddress, { |
594 | + "interface": interface, |
595 | + }) |
596 | + yield dv.get(timeout=2) |
597 | + yield self.assertZoneSerialIncrement(zone_serial) |
598 | + finally: |
599 | + yield listener.stopService() |
600 | + |
601 | + @wait_for_reactor |
602 | + @inlineCallbacks |
603 | + def test_sends_message_for_interface_staticipaddress_unlink(self): |
604 | + yield deferToDatabase(register_system_triggers) |
605 | + interface = yield deferToDatabase(self.create_interface) |
606 | + sip = yield deferToDatabase(self.create_staticipaddress, { |
607 | + "interface": interface, |
608 | + }) |
609 | + zone_serial = yield self.get_zone_serial_current() |
610 | + dv = DeferredValue() |
611 | + listener = self.make_listener_without_delay() |
612 | + listener.register( |
613 | + "sys_dns", lambda *args: dv.set(args)) |
614 | + yield listener.startService() |
615 | + try: |
616 | + yield deferToDatabase(self.delete_staticipaddress, sip.id) |
617 | + yield dv.get(timeout=2) |
618 | + yield self.assertZoneSerialIncrement(zone_serial) |
619 | + finally: |
620 | + yield listener.stopService() |
621 | + |
622 | + |
623 | +class TestDNSDNSResourceListener( |
624 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
625 | + DNSHelpersMixin): |
626 | + """End-to-end test for the DNS triggers code.""" |
627 | + |
628 | + @wait_for_reactor |
629 | + @inlineCallbacks |
630 | + def test_sends_message_for_dnsresource_insert(self): |
631 | + yield deferToDatabase(register_system_triggers) |
632 | + zone_serial = yield self.get_zone_serial_current() |
633 | + dv = DeferredValue() |
634 | + listener = self.make_listener_without_delay() |
635 | + listener.register( |
636 | + "sys_dns", lambda *args: dv.set(args)) |
637 | + yield listener.startService() |
638 | + try: |
639 | + yield deferToDatabase(self.create_dnsresource) |
640 | + yield dv.get(timeout=2) |
641 | + yield self.assertZoneSerialIncrement(zone_serial) |
642 | + finally: |
643 | + yield listener.stopService() |
644 | + |
645 | + @wait_for_reactor |
646 | + @inlineCallbacks |
647 | + def test_sends_message_for_dnsresource_update(self): |
648 | + yield deferToDatabase(register_system_triggers) |
649 | + resource = yield deferToDatabase(self.create_dnsresource) |
650 | + zone_serial = yield self.get_zone_serial_current() |
651 | + dv = DeferredValue() |
652 | + listener = self.make_listener_without_delay() |
653 | + listener.register( |
654 | + "sys_dns", lambda *args: dv.set(args)) |
655 | + yield listener.startService() |
656 | + try: |
657 | + yield deferToDatabase(self.update_dnsresource, resource.id, { |
658 | + "name": factory.make_name("resource"), |
659 | + }) |
660 | + yield dv.get(timeout=2) |
661 | + yield self.assertZoneSerialIncrement(zone_serial) |
662 | + finally: |
663 | + yield listener.stopService() |
664 | + |
665 | + @wait_for_reactor |
666 | + @inlineCallbacks |
667 | + def test_sends_message_for_dnsresource_delete(self): |
668 | + yield deferToDatabase(register_system_triggers) |
669 | + resource = yield deferToDatabase(self.create_dnsresource) |
670 | + zone_serial = yield self.get_zone_serial_current() |
671 | + dv = DeferredValue() |
672 | + listener = self.make_listener_without_delay() |
673 | + listener.register( |
674 | + "sys_dns", lambda *args: dv.set(args)) |
675 | + yield listener.startService() |
676 | + try: |
677 | + yield deferToDatabase(self.delete_dnsresource, resource.id) |
678 | + yield dv.get(timeout=2) |
679 | + yield self.assertZoneSerialIncrement(zone_serial) |
680 | + finally: |
681 | + yield listener.stopService() |
682 | + |
683 | + |
684 | +class TestDNSDNSResourceStaticIPAddressListener( |
685 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
686 | + DNSHelpersMixin): |
687 | + """End-to-end test for the DNS triggers code.""" |
688 | + |
689 | + @wait_for_reactor |
690 | + @inlineCallbacks |
691 | + def test_sends_message_for_dnsresource_staticipaddress_link(self): |
692 | + yield deferToDatabase(register_system_triggers) |
693 | + resource = yield deferToDatabase(self.create_dnsresource) |
694 | + sip = yield deferToDatabase(self.create_staticipaddress) |
695 | + zone_serial = yield self.get_zone_serial_current() |
696 | + dv = DeferredValue() |
697 | + listener = self.make_listener_without_delay() |
698 | + listener.register( |
699 | + "sys_dns", lambda *args: dv.set(args)) |
700 | + yield listener.startService() |
701 | + try: |
702 | + yield deferToDatabase(resource.ip_addresses.add, sip) |
703 | + yield dv.get(timeout=2) |
704 | + yield self.assertZoneSerialIncrement(zone_serial) |
705 | + finally: |
706 | + yield listener.stopService() |
707 | + |
708 | + @wait_for_reactor |
709 | + @inlineCallbacks |
710 | + def test_sends_message_for_dnsresource_staticipaddress_unlink(self): |
711 | + yield deferToDatabase(register_system_triggers) |
712 | + resource = yield deferToDatabase(self.create_dnsresource) |
713 | + sip = yield deferToDatabase(self.create_staticipaddress) |
714 | + yield deferToDatabase(resource.ip_addresses.add, sip) |
715 | + zone_serial = yield self.get_zone_serial_current() |
716 | + dv = DeferredValue() |
717 | + listener = self.make_listener_without_delay() |
718 | + listener.register( |
719 | + "sys_dns", lambda *args: dv.set(args)) |
720 | + yield listener.startService() |
721 | + try: |
722 | + yield deferToDatabase(resource.ip_addresses.remove, sip) |
723 | + yield dv.get(timeout=2) |
724 | + yield self.assertZoneSerialIncrement(zone_serial) |
725 | + finally: |
726 | + yield listener.stopService() |
727 | + |
728 | + |
729 | +class TestDNSDNSDataListener( |
730 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
731 | + DNSHelpersMixin): |
732 | + """End-to-end test for the DNS triggers code.""" |
733 | + |
734 | + @wait_for_reactor |
735 | + @inlineCallbacks |
736 | + def test_sends_message_for_dnsdata_insert(self): |
737 | + yield deferToDatabase(register_system_triggers) |
738 | + zone_serial = yield self.get_zone_serial_current() |
739 | + dv = DeferredValue() |
740 | + listener = self.make_listener_without_delay() |
741 | + listener.register( |
742 | + "sys_dns", lambda *args: dv.set(args)) |
743 | + yield listener.startService() |
744 | + try: |
745 | + yield deferToDatabase(self.create_dnsdata) |
746 | + yield dv.get(timeout=2) |
747 | + yield self.assertZoneSerialIncrement(zone_serial) |
748 | + finally: |
749 | + yield listener.stopService() |
750 | + |
751 | + @wait_for_reactor |
752 | + @inlineCallbacks |
753 | + def test_sends_message_for_dnsdata_update(self): |
754 | + yield deferToDatabase(register_system_triggers) |
755 | + data = yield deferToDatabase(self.create_dnsdata, { |
756 | + "rrtype": "TXT", |
757 | + "rrdata": factory.make_name("txt"), |
758 | + }) |
759 | + zone_serial = yield self.get_zone_serial_current() |
760 | + dv = DeferredValue() |
761 | + listener = self.make_listener_without_delay() |
762 | + listener.register( |
763 | + "sys_dns", lambda *args: dv.set(args)) |
764 | + yield listener.startService() |
765 | + try: |
766 | + yield deferToDatabase(self.update_dnsdata, data.id, { |
767 | + "rrdata": factory.make_name("txt"), |
768 | + }) |
769 | + yield dv.get(timeout=2) |
770 | + yield self.assertZoneSerialIncrement(zone_serial) |
771 | + finally: |
772 | + yield listener.stopService() |
773 | + |
774 | + @wait_for_reactor |
775 | + @inlineCallbacks |
776 | + def test_sends_message_for_dnsdata_delete(self): |
777 | + yield deferToDatabase(register_system_triggers) |
778 | + data = yield deferToDatabase(self.create_dnsdata) |
779 | + zone_serial = yield self.get_zone_serial_current() |
780 | + dv = DeferredValue() |
781 | + listener = self.make_listener_without_delay() |
782 | + listener.register( |
783 | + "sys_dns", lambda *args: dv.set(args)) |
784 | + yield listener.startService() |
785 | + try: |
786 | + yield deferToDatabase(self.delete_dnsdata, data.id) |
787 | + yield dv.get(timeout=2) |
788 | + yield self.assertZoneSerialIncrement(zone_serial) |
789 | + finally: |
790 | + yield listener.stopService() |
791 | + |
792 | + |
793 | +class TestDNSSubnetListener( |
794 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
795 | + DNSHelpersMixin): |
796 | + """End-to-end test for the DNS triggers code.""" |
797 | + |
798 | + @wait_for_reactor |
799 | + @inlineCallbacks |
800 | + def test_sends_message_for_subnet_insert(self): |
801 | + yield deferToDatabase(register_system_triggers) |
802 | + zone_serial = yield self.get_zone_serial_current() |
803 | + dv = DeferredValue() |
804 | + listener = self.make_listener_without_delay() |
805 | + listener.register( |
806 | + "sys_dns", lambda *args: dv.set(args)) |
807 | + yield listener.startService() |
808 | + try: |
809 | + yield deferToDatabase(self.create_subnet) |
810 | + yield dv.get(timeout=2) |
811 | + yield self.assertZoneSerialIncrement(zone_serial) |
812 | + finally: |
813 | + yield listener.stopService() |
814 | + |
815 | + @wait_for_reactor |
816 | + @inlineCallbacks |
817 | + def test_sends_message_for_subnet_cidr_update(self): |
818 | + yield deferToDatabase(register_system_triggers) |
819 | + subnet = yield deferToDatabase(self.create_subnet) |
820 | + zone_serial = yield self.get_zone_serial_current() |
821 | + dv = DeferredValue() |
822 | + listener = self.make_listener_without_delay() |
823 | + listener.register( |
824 | + "sys_dns", lambda *args: dv.set(args)) |
825 | + yield listener.startService() |
826 | + try: |
827 | + network = factory.make_ip4_or_6_network() |
828 | + yield deferToDatabase(self.update_subnet, subnet.id, { |
829 | + "cidr": str(network.cidr), |
830 | + "gateway_ip": factory.pick_ip_in_network(network), |
831 | + "dns_servers": [], |
832 | + }) |
833 | + yield dv.get(timeout=2) |
834 | + yield self.assertZoneSerialIncrement(zone_serial) |
835 | + finally: |
836 | + yield listener.stopService() |
837 | + |
838 | + @wait_for_reactor |
839 | + @inlineCallbacks |
840 | + def test_sends_message_for_subnet_rdns_mode_update(self): |
841 | + yield deferToDatabase(register_system_triggers) |
842 | + subnet = yield deferToDatabase(self.create_subnet) |
843 | + zone_serial = yield self.get_zone_serial_current() |
844 | + dv = DeferredValue() |
845 | + listener = self.make_listener_without_delay() |
846 | + listener.register( |
847 | + "sys_dns", lambda *args: dv.set(args)) |
848 | + yield listener.startService() |
849 | + try: |
850 | + yield deferToDatabase(self.update_subnet, subnet.id, { |
851 | + "rdns_mode": factory.pick_enum( |
852 | + RDNS_MODE, but_not=[subnet.rdns_mode]), |
853 | + }) |
854 | + yield dv.get(timeout=2) |
855 | + yield self.assertZoneSerialIncrement(zone_serial) |
856 | + finally: |
857 | + yield listener.stopService() |
858 | + |
859 | + @wait_for_reactor |
860 | + @inlineCallbacks |
861 | + def test_sends_message_for_subnet_delete(self): |
862 | + yield deferToDatabase(register_system_triggers) |
863 | + subnet = yield deferToDatabase(self.create_subnet) |
864 | + zone_serial = yield self.get_zone_serial_current() |
865 | + dv = DeferredValue() |
866 | + listener = self.make_listener_without_delay() |
867 | + listener.register( |
868 | + "sys_dns", lambda *args: dv.set(args)) |
869 | + yield listener.startService() |
870 | + try: |
871 | + yield deferToDatabase(self.delete_subnet, subnet.id) |
872 | + yield dv.get(timeout=2) |
873 | + yield self.assertZoneSerialIncrement(zone_serial) |
874 | + finally: |
875 | + yield listener.stopService() |
876 | + |
877 | + |
878 | +class TestDNSNodeListener( |
879 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
880 | + DNSHelpersMixin): |
881 | + """End-to-end test for the DNS triggers code.""" |
882 | + |
883 | + @wait_for_reactor |
884 | + @inlineCallbacks |
885 | + def test_sends_message_for_node_update_hostname(self): |
886 | + yield deferToDatabase(register_system_triggers) |
887 | + node = yield deferToDatabase(self.create_node) |
888 | + zone_serial = yield self.get_zone_serial_current() |
889 | + dv = DeferredValue() |
890 | + listener = self.make_listener_without_delay() |
891 | + listener.register( |
892 | + "sys_dns", lambda *args: dv.set(args)) |
893 | + yield listener.startService() |
894 | + try: |
895 | + yield deferToDatabase(self.update_node, node.system_id, { |
896 | + "hostname": factory.make_name("hostname"), |
897 | + }) |
898 | + yield dv.get(timeout=2) |
899 | + yield self.assertZoneSerialIncrement(zone_serial) |
900 | + finally: |
901 | + yield listener.stopService() |
902 | + |
903 | + @wait_for_reactor |
904 | + @inlineCallbacks |
905 | + def test_sends_message_for_node_update_domain(self): |
906 | + yield deferToDatabase(register_system_triggers) |
907 | + node = yield deferToDatabase(self.create_node) |
908 | + domain = yield deferToDatabase(self.create_domain) |
909 | + zone_serial = yield self.get_zone_serial_current() |
910 | + dv = DeferredValue() |
911 | + listener = self.make_listener_without_delay() |
912 | + listener.register( |
913 | + "sys_dns", lambda *args: dv.set(args)) |
914 | + yield listener.startService() |
915 | + try: |
916 | + yield deferToDatabase(self.update_node, node.system_id, { |
917 | + "domain": domain, |
918 | + }) |
919 | + yield dv.get(timeout=2) |
920 | + yield self.assertZoneSerialIncrement(zone_serial) |
921 | + finally: |
922 | + yield listener.stopService() |
923 | + |
924 | + @wait_for_reactor |
925 | + @inlineCallbacks |
926 | + def test_sends_message_for_node_delete(self): |
927 | + yield deferToDatabase(register_system_triggers) |
928 | + node = yield deferToDatabase(self.create_node) |
929 | + zone_serial = yield self.get_zone_serial_current() |
930 | + dv = DeferredValue() |
931 | + listener = self.make_listener_without_delay() |
932 | + listener.register( |
933 | + "sys_dns", lambda *args: dv.set(args)) |
934 | + yield listener.startService() |
935 | + try: |
936 | + yield deferToDatabase(self.delete_node, node.system_id) |
937 | + yield dv.get(timeout=2) |
938 | + yield self.assertZoneSerialIncrement(zone_serial) |
939 | + finally: |
940 | + yield listener.stopService() |
941 | + |
942 | + |
943 | +class TestDNSInterfaceListener( |
944 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
945 | + DNSHelpersMixin): |
946 | + """End-to-end test for the DNS triggers code.""" |
947 | + |
948 | + @transactional |
949 | + def migrate_unknown_to_physical(self, id, node): |
950 | + nic = Interface.objects.get(id=id) |
951 | + nic.type = INTERFACE_TYPE.PHYSICAL |
952 | + nic.node = node |
953 | + nic.__class__ = PhysicalInterface |
954 | + nic.save() |
955 | + |
956 | + @transactional |
957 | + def migrate_physical_to_unknown(self, id): |
958 | + nic = Interface.objects.get(id=id) |
959 | + nic.type = INTERFACE_TYPE.UNKNOWN |
960 | + nic.node = None |
961 | + nic.__class__ = UnknownInterface |
962 | + nic.save() |
963 | + |
964 | + @wait_for_reactor |
965 | + @inlineCallbacks |
966 | + def test_sends_message_for_interface_update_name(self): |
967 | + yield deferToDatabase(register_system_triggers) |
968 | + interface = yield deferToDatabase(self.create_interface) |
969 | + zone_serial = yield self.get_zone_serial_current() |
970 | + dv = DeferredValue() |
971 | + listener = self.make_listener_without_delay() |
972 | + listener.register( |
973 | + "sys_dns", lambda *args: dv.set(args)) |
974 | + yield listener.startService() |
975 | + try: |
976 | + yield deferToDatabase(self.update_interface, interface.id, { |
977 | + "name": factory.make_name("name"), |
978 | + }) |
979 | + yield dv.get(timeout=2) |
980 | + yield self.assertZoneSerialIncrement(zone_serial) |
981 | + finally: |
982 | + yield listener.stopService() |
983 | + |
984 | + @wait_for_reactor |
985 | + @inlineCallbacks |
986 | + def test_sends_message_for_unknown_to_physical(self): |
987 | + yield deferToDatabase(register_system_triggers) |
988 | + interface = yield deferToDatabase(self.create_unknown_interface) |
989 | + node = yield deferToDatabase(self.create_node) |
990 | + zone_serial = yield self.get_zone_serial_current() |
991 | + dv = DeferredValue() |
992 | + listener = self.make_listener_without_delay() |
993 | + listener.register( |
994 | + "sys_dns", lambda *args: dv.set(args)) |
995 | + yield listener.startService() |
996 | + try: |
997 | + yield deferToDatabase( |
998 | + self.migrate_unknown_to_physical, interface.id, node) |
999 | + yield dv.get(timeout=2) |
1000 | + yield self.assertZoneSerialIncrement(zone_serial) |
1001 | + finally: |
1002 | + yield listener.stopService() |
1003 | + |
1004 | + @wait_for_reactor |
1005 | + @inlineCallbacks |
1006 | + def test_sends_message_for_physical_to_unknown(self): |
1007 | + yield deferToDatabase(register_system_triggers) |
1008 | + interface = yield deferToDatabase(self.create_interface) |
1009 | + zone_serial = yield self.get_zone_serial_current() |
1010 | + dv = DeferredValue() |
1011 | + listener = self.make_listener_without_delay() |
1012 | + listener.register( |
1013 | + "sys_dns", lambda *args: dv.set(args)) |
1014 | + yield listener.startService() |
1015 | + try: |
1016 | + yield deferToDatabase( |
1017 | + self.migrate_physical_to_unknown, interface.id) |
1018 | + yield dv.get(timeout=2) |
1019 | + yield self.assertZoneSerialIncrement(zone_serial) |
1020 | + finally: |
1021 | + yield listener.stopService() |
1022 | + |
1023 | + @wait_for_reactor |
1024 | + @inlineCallbacks |
1025 | + def test_sends_message_for_interface_changing_to_new_node(self): |
1026 | + yield deferToDatabase(register_system_triggers) |
1027 | + interface = yield deferToDatabase(self.create_interface) |
1028 | + node = yield deferToDatabase(self.create_node) |
1029 | + zone_serial = yield self.get_zone_serial_current() |
1030 | + dv = DeferredValue() |
1031 | + listener = self.make_listener_without_delay() |
1032 | + listener.register( |
1033 | + "sys_dns", lambda *args: dv.set(args)) |
1034 | + yield listener.startService() |
1035 | + try: |
1036 | + yield deferToDatabase( |
1037 | + self.update_interface, interface.id, {"node": node}) |
1038 | + yield dv.get(timeout=2) |
1039 | + yield self.assertZoneSerialIncrement(zone_serial) |
1040 | + finally: |
1041 | + yield listener.stopService() |
1042 | + |
1043 | + |
1044 | +class TestDNSConfigListener( |
1045 | + MAASTransactionServerTestCase, TransactionalHelpersMixin, |
1046 | + DNSHelpersMixin): |
1047 | + """End-to-end test for the DNS triggers code.""" |
1048 | + |
1049 | + @wait_for_reactor |
1050 | + @inlineCallbacks |
1051 | + def test_sends_message_for_config_upstream_dns_insert(self): |
1052 | + yield deferToDatabase(register_system_triggers) |
1053 | + zone_serial = yield self.get_zone_serial_current() |
1054 | + dv = DeferredValue() |
1055 | + listener = self.make_listener_without_delay() |
1056 | + listener.register( |
1057 | + "sys_dns", lambda *args: dv.set(args)) |
1058 | + yield listener.startService() |
1059 | + try: |
1060 | + yield deferToDatabase( |
1061 | + Config.objects.set_config, |
1062 | + "upstream_dns", factory.make_ip_address()) |
1063 | + yield dv.get(timeout=2) |
1064 | + yield self.assertZoneSerialIncrement(zone_serial) |
1065 | + finally: |
1066 | + yield listener.stopService() |
1067 | + |
1068 | + @wait_for_reactor |
1069 | + @inlineCallbacks |
1070 | + def test_sends_message_for_config_default_dns_ttl_insert(self): |
1071 | + yield deferToDatabase(register_system_triggers) |
1072 | + zone_serial = yield self.get_zone_serial_current() |
1073 | + dv = DeferredValue() |
1074 | + listener = self.make_listener_without_delay() |
1075 | + listener.register( |
1076 | + "sys_dns", lambda *args: dv.set(args)) |
1077 | + yield listener.startService() |
1078 | + try: |
1079 | + yield deferToDatabase( |
1080 | + Config.objects.set_config, |
1081 | + "default_dns_ttl", random.randint(10, 1000)) |
1082 | + yield dv.get(timeout=2) |
1083 | + yield self.assertZoneSerialIncrement(zone_serial) |
1084 | + finally: |
1085 | + yield listener.stopService() |
1086 | + |
1087 | + @wait_for_reactor |
1088 | + @inlineCallbacks |
1089 | + def test_sends_message_for_config_windows_kms_host_insert(self): |
1090 | + yield deferToDatabase(register_system_triggers) |
1091 | + zone_serial = yield self.get_zone_serial_current() |
1092 | + dv = DeferredValue() |
1093 | + listener = self.make_listener_without_delay() |
1094 | + listener.register( |
1095 | + "sys_dns", lambda *args: dv.set(args)) |
1096 | + yield listener.startService() |
1097 | + try: |
1098 | + yield deferToDatabase( |
1099 | + Config.objects.set_config, |
1100 | + "windows_kms_host", factory.make_name("kms")) |
1101 | + yield dv.get(timeout=2) |
1102 | + yield self.assertZoneSerialIncrement(zone_serial) |
1103 | + finally: |
1104 | + yield listener.stopService() |
1105 | + |
1106 | + @wait_for_reactor |
1107 | + @inlineCallbacks |
1108 | + def test_sends_message_for_config_upstream_dns_update(self): |
1109 | + yield deferToDatabase(register_system_triggers) |
1110 | + yield deferToDatabase( |
1111 | + Config.objects.set_config, |
1112 | + "upstream_dns", factory.make_ip_address()) |
1113 | + zone_serial = yield self.get_zone_serial_current() |
1114 | + dv = DeferredValue() |
1115 | + listener = self.make_listener_without_delay() |
1116 | + listener.register( |
1117 | + "sys_dns", lambda *args: dv.set(args)) |
1118 | + yield listener.startService() |
1119 | + try: |
1120 | + yield deferToDatabase( |
1121 | + Config.objects.set_config, |
1122 | + "upstream_dns", factory.make_ip_address()) |
1123 | + yield dv.get(timeout=2) |
1124 | + yield self.assertZoneSerialIncrement(zone_serial) |
1125 | + finally: |
1126 | + yield listener.stopService() |
1127 | + |
1128 | + @wait_for_reactor |
1129 | + @inlineCallbacks |
1130 | + def test_sends_message_for_config_default_dns_ttl_update(self): |
1131 | + yield deferToDatabase(register_system_triggers) |
1132 | + yield deferToDatabase( |
1133 | + Config.objects.set_config, |
1134 | + "default_dns_ttl", random.randint(10, 1000)) |
1135 | + zone_serial = yield self.get_zone_serial_current() |
1136 | + dv = DeferredValue() |
1137 | + listener = self.make_listener_without_delay() |
1138 | + listener.register( |
1139 | + "sys_dns", lambda *args: dv.set(args)) |
1140 | + yield listener.startService() |
1141 | + try: |
1142 | + yield deferToDatabase( |
1143 | + Config.objects.set_config, |
1144 | + "default_dns_ttl", random.randint(10, 1000)) |
1145 | + yield dv.get(timeout=2) |
1146 | + yield self.assertZoneSerialIncrement(zone_serial) |
1147 | + finally: |
1148 | + yield listener.stopService() |
1149 | + |
1150 | + @wait_for_reactor |
1151 | + @inlineCallbacks |
1152 | + def test_sends_message_for_config_windows_kms_host_update(self): |
1153 | + yield deferToDatabase(register_system_triggers) |
1154 | + yield deferToDatabase( |
1155 | + Config.objects.set_config, |
1156 | + "windows_kms_host", factory.make_name("kms")) |
1157 | + zone_serial = yield self.get_zone_serial_current() |
1158 | + dv = DeferredValue() |
1159 | + listener = self.make_listener_without_delay() |
1160 | + listener.register( |
1161 | + "sys_dns", lambda *args: dv.set(args)) |
1162 | + yield listener.startService() |
1163 | + try: |
1164 | + yield deferToDatabase( |
1165 | + Config.objects.set_config, |
1166 | + "windows_kms_host", factory.make_name("kms")) |
1167 | + yield dv.get(timeout=2) |
1168 | + yield self.assertZoneSerialIncrement(zone_serial) |
1169 | + finally: |
1170 | + yield listener.stopService() |
Nothing leaps out at me in this, screaming "fix me!"