Merge lp:~allenap/maas/ntp-reconfigure-when-external-only-changed into lp:~maas-committers/maas/trunk

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 5434
Proposed branch: lp:~allenap/maas/ntp-reconfigure-when-external-only-changed
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 169 lines (+124/-3)
2 files modified
src/maasserver/triggers/system.py (+6/-3)
src/maasserver/triggers/tests/test_system_listener.py (+118/-0)
To merge this branch: bzr merge lp:~allenap/maas/ntp-reconfigure-when-external-only-changed
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+307556@code.launchpad.net

Commit message

Reconfigure DHCP when ntp_external_only is modified.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/triggers/system.py'
2--- src/maasserver/triggers/system.py 2016-07-30 01:17:54 +0000
3+++ src/maasserver/triggers/system.py 2016-10-04 12:23:29 +0000
4@@ -788,6 +788,8 @@
5 BEGIN
6 IF NEW.name = 'ntp_servers' THEN
7 PERFORM sys_dhcp_update_all_vlans();
8+ ELSIF NEW.name = 'ntp_external_only' THEN
9+ PERFORM sys_dhcp_update_all_vlans();
10 END IF;
11 RETURN NEW;
12 END;
13@@ -798,7 +800,8 @@
14 CREATE OR REPLACE FUNCTION sys_dhcp_config_ntp_servers_update()
15 RETURNS trigger as $$
16 BEGIN
17- IF OLD.name = 'ntp_servers' OR NEW.name = 'ntp_servers' THEN
18+ IF OLD.name IN ('ntp_servers', 'ntp_external_only')
19+ OR NEW.name IN ('ntp_servers', 'ntp_external_only') THEN
20 IF OLD.value != NEW.value THEN
21 PERFORM sys_dhcp_update_all_vlans();
22 END IF;
23@@ -812,7 +815,7 @@
24 CREATE OR REPLACE FUNCTION sys_dhcp_config_ntp_servers_delete()
25 RETURNS trigger as $$
26 BEGIN
27- IF OLD.name = 'ntp_servers' THEN
28+ IF OLD.name IN ('ntp_servers', 'ntp_external_only') THEN
29 PERFORM sys_dhcp_update_all_vlans();
30 END IF;
31 RETURN NEW;
32@@ -1125,7 +1128,7 @@
33 register_trigger(
34 "maasserver_dhcpsnippet", "sys_dhcp_snippet_delete", "delete")
35
36- # - Config/ntp_servers
37+ # - Config/ntp_servers (and ntp_external_only)
38 register_procedure(DHCP_CONFIG_NTP_SERVERS_INSERT)
39 register_trigger(
40 "maasserver_config", "sys_dhcp_config_ntp_servers_insert", "insert")
41
42=== modified file 'src/maasserver/triggers/tests/test_system_listener.py'
43--- src/maasserver/triggers/tests/test_system_listener.py 2016-07-30 01:17:54 +0000
44+++ src/maasserver/triggers/tests/test_system_listener.py 2016-10-04 12:23:29 +0000
45@@ -2402,6 +2402,124 @@
46 yield listener.stopService()
47
48
49+class TestDHCPConfigNTPExternalListener(
50+ MAASTransactionServerTestCase, TransactionalHelpersMixin):
51+ """End-to-end test for the DHCP triggers code.
52+
53+ This tests the notifications issued by the database when NTP is configured
54+ for external-only, or vice-versa.
55+ """
56+
57+ def set_ntp_external_only(self, external_only):
58+ return deferToDatabase(
59+ Config.objects.set_config, "ntp_external_only",
60+ bool(external_only))
61+
62+ def clear_ntp_external_only(self):
63+ return deferToDatabase(
64+ lambda: Config.objects.filter(name="ntp_external_only").delete())
65+
66+ def make_racks(self):
67+ return [
68+ self.create_vlan({
69+ "dhcp_on": True,
70+ "primary_rack": self.create_rack_controller(),
71+ "secondary_rack": self.create_rack_controller(),
72+ }),
73+ self.create_vlan({
74+ "dhcp_on": True,
75+ "primary_rack": self.create_rack_controller(),
76+ "secondary_rack": None,
77+ }),
78+ ]
79+
80+ def listen_for_sys_dhcp(self, *rack_ids):
81+ """Create a database listener for 'sys_dhcp_$id' for each rack.
82+
83+ Return the listener and a mapping from the given rack IDs to the
84+ DeferredValues that will capture messages.
85+ """
86+ dsetter = lambda dv: (lambda *args: dv.set(args))
87+ dvalues = {rack_id: DeferredValue() for rack_id in rack_ids}
88+ listener = self.make_listener_without_delay()
89+ for rack_id, dv in dvalues.items():
90+ listener.register("sys_dhcp_%s" % rack_id, dsetter(dv))
91+ return listener, dvalues
92+
93+ def wait_for_dvalues(self, dvalues):
94+ d = DeferredList(
95+ (dv.get(timeout=2) for dv in dvalues),
96+ consumeErrors=True)
97+
98+ def unpack(results):
99+ # Return the first failure, if there is one. We do this in
100+ # preference to fireOnOneErrback=True because at this point we
101+ # know that all the Deferreds that went into the DeferredList have
102+ # fired; fireOnOneErrback may result in the test completing before
103+ # all have fired, about which the test runner will complain.
104+ for success, result in results:
105+ if not success:
106+ return result
107+
108+ return d.addCallback(unpack)
109+
110+ @wait_for_reactor
111+ @inlineCallbacks
112+ def test_alerts_all_racks_when_ntp_external_only_set(self):
113+ yield self.clear_ntp_external_only()
114+ yield deferToDatabase(register_system_triggers)
115+
116+ vlan1, vlan2 = yield deferToDatabase(self.make_racks)
117+ listener, rack_dvs = self.listen_for_sys_dhcp(
118+ vlan1.primary_rack_id, vlan1.secondary_rack_id,
119+ vlan2.primary_rack_id)
120+
121+ yield listener.startService()
122+ try:
123+ yield self.set_ntp_external_only(True)
124+ yield self.wait_for_dvalues(rack_dvs.values())
125+ finally:
126+ yield listener.stopService()
127+
128+ @wait_for_reactor
129+ @inlineCallbacks
130+ def test_alerts_all_racks_when_ntp_external_only_updated(self):
131+ ntp_external_only = factory.pick_bool()
132+ yield self.set_ntp_external_only(ntp_external_only)
133+ yield deferToDatabase(register_system_triggers)
134+
135+ vlan1, vlan2 = yield deferToDatabase(self.make_racks)
136+ listener, rack_dvs = self.listen_for_sys_dhcp(
137+ vlan1.primary_rack_id, vlan1.secondary_rack_id,
138+ vlan2.primary_rack_id)
139+
140+ yield listener.startService()
141+ try:
142+ yield self.set_ntp_external_only(not ntp_external_only)
143+ yield self.wait_for_dvalues(rack_dvs.values())
144+ finally:
145+ yield listener.stopService()
146+
147+ @wait_for_reactor
148+ @inlineCallbacks
149+ def test_alerts_all_racks_when_ntp_server_deleted(self):
150+ ntp_external_only = factory.pick_bool()
151+ yield self.set_ntp_external_only(ntp_external_only)
152+ yield deferToDatabase(register_system_triggers)
153+
154+ vlan1, vlan2 = yield deferToDatabase(self.make_racks)
155+ listener, rack_dvs = self.listen_for_sys_dhcp(
156+ vlan1.primary_rack_id, vlan1.secondary_rack_id,
157+ vlan2.primary_rack_id)
158+
159+ yield listener.startService()
160+ try:
161+ yield self.clear_ntp_external_only()
162+ yield self.wait_for_dvalues(rack_dvs.values())
163+ finally:
164+ yield listener.stopService()
165+
166+
167 class TestDNSDomainListener(
168 MAASTransactionServerTestCase, TransactionalHelpersMixin,
169 DNSHelpersMixin):