Merge lp:~lamont/maas/bug-1581224 into lp:maas/trunk

Proposed by LaMont Jones on 2016-06-02
Status: Merged
Approved by: LaMont Jones on 2016-06-02
Approved revision: 5062
Merged at revision: 5062
Proposed branch: lp:~lamont/maas/bug-1581224
Merge into: lp:maas/trunk
Diff against target: 285 lines (+194/-2)
5 files modified
src/maasserver/static/js/angular/controllers/domain_details.js (+4/-1)
src/maasserver/testing/factory.py (+5/-1)
src/maasserver/triggers/testing.py (+4/-0)
src/maasserver/triggers/tests/test_websocket_listener.py (+114/-0)
src/maasserver/triggers/websocket.py (+67/-0)
To merge this branch: bzr merge lp:~lamont/maas/bug-1581224
Reviewer Review Type Date Requested Status
Mike Pontillo (community) 2016-06-02 Approve on 2016-06-02
Review via email: mp+296343@code.launchpad.net

Commit message

Database triggers were missing for dnsresource_ip_addresses and interface_ip_addresses m2m tables.

Description of the change

Database triggers were missing for dnsresource_ip_addresses and interface_ip_addresses m2m tables.

To post a comment you must log in.
Mike Pontillo (mpontillo) wrote :

Looks good to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/static/js/angular/controllers/domain_details.js'
2--- src/maasserver/static/js/angular/controllers/domain_details.js 2016-04-29 08:04:27 +0000
3+++ src/maasserver/static/js/angular/controllers/domain_details.js 2016-06-02 16:07:14 +0000
4@@ -44,7 +44,10 @@
5
6 // Return true if this is the default domain.
7 $scope.isDefaultDomain = function() {
8- return $scope.domain.id === 0;
9+ if(angular.isObject($scope.domain)) {
10+ return $scope.domain.id === 0;
11+ }
12+ return false;
13 };
14
15 // Called to check if the space can be deleted.
16
17=== modified file 'src/maasserver/testing/factory.py'
18--- src/maasserver/testing/factory.py 2016-06-02 14:44:04 +0000
19+++ src/maasserver/testing/factory.py 2016-06-02 16:07:14 +0000
20@@ -720,7 +720,8 @@
21
22 def make_StaticIPAddress(self, ip=UNDEFINED,
23 alloc_type=IPADDRESS_TYPE.AUTO, interface=None,
24- user=None, subnet=None, **kwargs):
25+ user=None, subnet=None, dnsresource=None,
26+ **kwargs):
27 """Create and return a StaticIPAddress model object.
28
29 If a non-None `interface` is passed, connect this IP address to the
30@@ -748,6 +749,9 @@
31 if interface is not None:
32 interface.ip_addresses.add(ipaddress)
33 interface.save()
34+ if dnsresource is not None:
35+ dnsresource.ip_addresses.add(ipaddress)
36+ dnsresource.save()
37 if hostname is not None:
38 if not isinstance(hostname, (tuple, list)):
39 hostname = [hostname]
40
41=== modified file 'src/maasserver/triggers/testing.py'
42--- src/maasserver/triggers/testing.py 2016-04-29 10:33:55 +0000
43+++ src/maasserver/triggers/testing.py 2016-06-02 16:07:14 +0000
44@@ -178,6 +178,10 @@
45 dnsresource.delete()
46
47 @transactional
48+ def get_first_staticipaddress(self, obj):
49+ return obj.ip_addresses.first()
50+
51+ @transactional
52 def create_dnsdata(self, params=None):
53 if params is None:
54 params = {}
55
56=== modified file 'src/maasserver/triggers/tests/test_websocket_listener.py'
57--- src/maasserver/triggers/tests/test_websocket_listener.py 2016-05-26 07:09:10 +0000
58+++ src/maasserver/triggers/tests/test_websocket_listener.py 2016-06-02 16:07:14 +0000
59@@ -1398,6 +1398,73 @@
60
61 @wait_for_reactor
62 @inlineCallbacks
63+ def test__calls_handler_with_update_on_node_ip_address_addition(self):
64+ domain = yield deferToDatabase(self.create_domain)
65+ yield deferToDatabase(register_websocket_triggers)
66+ params = {
67+ 'node_type': NODE_TYPE.MACHINE,
68+ 'domain': domain,
69+ }
70+ node = yield deferToDatabase(self.create_node, params)
71+ interface = yield deferToDatabase(
72+ self.create_interface, {
73+ "node": node})
74+ subnet = yield deferToDatabase(self.create_subnet)
75+
76+ selected_ip = factory.pick_ip_in_network(subnet.get_ipnetwork())
77+ listener = PostgresListenerService()
78+ dv = DeferredValue()
79+ listener.register("domain", lambda *args: dv.set(args))
80+ yield listener.startService()
81+ try:
82+ yield deferToDatabase(
83+ self.create_staticipaddress, {
84+ "alloc_type": IPADDRESS_TYPE.STICKY,
85+ "interface": interface,
86+ "subnet": subnet,
87+ "ip": selected_ip})
88+ yield dv.get(timeout=2)
89+ self.assertEqual(('update', '%s' % domain.id), dv.value)
90+ finally:
91+ yield listener.stopService()
92+
93+ @wait_for_reactor
94+ @inlineCallbacks
95+ def test__calls_handler_with_update_on_node_ip_address_removal(self):
96+ domain = yield deferToDatabase(self.create_domain)
97+ yield deferToDatabase(register_websocket_triggers)
98+ params = {
99+ 'node_type': NODE_TYPE.MACHINE,
100+ 'domain': domain,
101+ }
102+ node = yield deferToDatabase(self.create_node, params)
103+ interface = yield deferToDatabase(
104+ self.create_interface, {
105+ "node": node})
106+ subnet = yield deferToDatabase(self.create_subnet)
107+ selected_ip = factory.pick_ip_in_network(subnet.get_ipnetwork())
108+ ipaddress = yield deferToDatabase(
109+ self.create_staticipaddress, {
110+ "alloc_type": IPADDRESS_TYPE.STICKY,
111+ "interface": interface,
112+ "subnet": subnet,
113+ "ip": selected_ip,
114+ })
115+
116+ listener = PostgresListenerService()
117+ dv = DeferredValue()
118+ listener.register("domain", lambda *args: dv.set(args))
119+ yield listener.startService()
120+ try:
121+ yield deferToDatabase(
122+ self.delete_staticipaddress, ipaddress.id)
123+ yield dv.get(timeout=2)
124+ self.assertEqual(('update', '%s' % domain.id), dv.value)
125+ finally:
126+ yield listener.stopService()
127+
128+ @wait_for_reactor
129+ @inlineCallbacks
130 def test__calls_handler_on_dnsresource_create_notification(self):
131 domain = yield deferToDatabase(self.create_domain)
132 yield deferToDatabase(register_websocket_triggers)
133@@ -1415,6 +1482,53 @@
134
135 @wait_for_reactor
136 @inlineCallbacks
137+ def test__calls_handler_on_dnsresource_address_addition(self):
138+ domain = yield deferToDatabase(self.create_domain)
139+ yield deferToDatabase(register_websocket_triggers)
140+ listener = self.make_listener_without_delay()
141+ dv = DeferredValue()
142+ dnsrr = yield deferToDatabase(
143+ self.create_dnsresource, {
144+ "domain": domain, "no_ip_addresses": True})
145+ subnet = yield deferToDatabase(self.create_subnet)
146+ listener.register("domain", lambda *args: dv.set(args))
147+
148+ yield listener.startService()
149+ selected_ip = factory.pick_ip_in_network(subnet.get_ipnetwork())
150+ try:
151+ yield deferToDatabase(
152+ self.create_staticipaddress, {
153+ "alloc_type": IPADDRESS_TYPE.STICKY,
154+ "dnsresource": dnsrr,
155+ "subnet": subnet,
156+ "ip": selected_ip,
157+ })
158+ yield dv.get(timeout=2)
159+ self.assertEqual(('update', '%s' % domain.id), dv.value)
160+ finally:
161+ yield listener.stopService()
162+
163+ @wait_for(360000)
164+ @inlineCallbacks
165+ def test__calls_handler_on_dnsresource_address_removal(self):
166+ domain = yield deferToDatabase(self.create_domain)
167+ yield deferToDatabase(register_websocket_triggers)
168+ dnsrr = yield deferToDatabase(self.create_dnsresource, {
169+ 'domain': domain})
170+ listener = self.make_listener_without_delay()
171+ dv = DeferredValue()
172+ listener.register("domain", lambda *args: dv.set(args))
173+ staticip = yield deferToDatabase(self.get_first_staticipaddress, dnsrr)
174+ yield listener.startService()
175+ try:
176+ yield deferToDatabase(self.delete_staticipaddress, staticip.id)
177+ yield dv.get(timeout=2)
178+ self.assertEqual(('update', '%s' % domain.id), dv.value)
179+ finally:
180+ yield listener.stopService()
181+
182+ @wait_for_reactor
183+ @inlineCallbacks
184 def test__calls_handler_on_dnsresource_update_notification(self):
185 domain = yield deferToDatabase(self.create_domain)
186 yield deferToDatabase(register_websocket_triggers)
187
188=== modified file 'src/maasserver/triggers/websocket.py'
189--- src/maasserver/triggers/websocket.py 2016-05-24 07:30:16 +0000
190+++ src/maasserver/triggers/websocket.py 2016-06-02 16:07:14 +0000
191@@ -132,6 +132,26 @@
192
193
194 # Procedure that is called when a static ip address is linked or unlinked to
195+# an Interface. Sends a notify message for domain_update
196+INTERFACE_IP_ADDRESS_DOMAIN_NOTIFY = dedent("""\
197+ CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
198+ DECLARE
199+ domain RECORD;
200+ BEGIN
201+ SELECT maasserver_domain.id INTO domain
202+ FROM maasserver_node, maasserver_interface, maasserver_domain
203+ WHERE maasserver_node.id = maasserver_interface.node_id
204+ AND maasserver_domain.id = maasserver_node.domain_id
205+ AND maasserver_interface.id = %s;
206+
207+ PERFORM pg_notify('domain_update',CAST(domain.id AS text));
208+ RETURN NEW;
209+ END;
210+ $$ LANGUAGE plpgsql;
211+ """)
212+
213+
214+# Procedure that is called when a static ip address is linked or unlinked to
215 # an Interface. Sends a notify message for machine_update or device_update
216 # depending on if the node type is node.
217 INTERFACE_IP_ADDRESS_NODE_NOTIFY = dedent("""\
218@@ -708,6 +728,25 @@
219 """)
220
221
222+# Procedure that is called when a static ip address is linked or unlinked to
223+# an Interface. Sends a notify message for domain_update
224+DNSRESOURCE_IP_ADDRESS_DOMAIN_NOTIFY = dedent("""\
225+ CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
226+ DECLARE
227+ domain RECORD;
228+ BEGIN
229+ SELECT maasserver_domain.id INTO domain
230+ FROM maasserver_dnsresource, maasserver_domain
231+ WHERE maasserver_domain.id = maasserver_dnsresource.domain_id
232+ AND maasserver_dnsresource.id = %s;
233+
234+ PERFORM pg_notify('domain_update',CAST(domain.id AS text));
235+ RETURN NEW;
236+ END;
237+ $$ LANGUAGE plpgsql;
238+ """)
239+
240+
241 def render_notification_procedure(proc_name, event_name, cast):
242 return dedent("""\
243 CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
244@@ -1114,6 +1153,20 @@
245 register_trigger(
246 "maasserver_domain", "domain_delete_notify", "delete")
247
248+ # MAC static ip address table, update to linked domain via dnsresource
249+ register_procedure(
250+ DNSRESOURCE_IP_ADDRESS_DOMAIN_NOTIFY % (
251+ 'rrset_sipaddress_link_notify', 'NEW.dnsresource_id'))
252+ register_procedure(
253+ DNSRESOURCE_IP_ADDRESS_DOMAIN_NOTIFY % (
254+ 'rrset_sipaddress_unlink_notify', 'OLD.dnsresource_id'))
255+ register_trigger(
256+ "maasserver_dnsresource_ip_addresses",
257+ "rrset_sipaddress_link_notify", "insert")
258+ register_trigger(
259+ "maasserver_dnsresource_ip_addresses",
260+ "rrset_sipaddress_unlink_notify", "delete")
261+
262 # Zone table
263 register_procedure(
264 render_notification_procedure(
265@@ -1247,6 +1300,20 @@
266 "maasserver_interface_ip_addresses",
267 "nd_sipaddress_unlink_notify", "delete")
268
269+ # MAC static ip address table, update to linked domain via node.
270+ register_procedure(
271+ INTERFACE_IP_ADDRESS_DOMAIN_NOTIFY % (
272+ 'nd_sipaddress_dns_link_notify', 'NEW.interface_id'))
273+ register_procedure(
274+ INTERFACE_IP_ADDRESS_DOMAIN_NOTIFY % (
275+ 'nd_sipaddress_dns_unlink_notify', 'OLD.interface_id'))
276+ register_trigger(
277+ "maasserver_interface_ip_addresses",
278+ "nd_sipaddress_dns_link_notify", "insert")
279+ register_trigger(
280+ "maasserver_interface_ip_addresses",
281+ "nd_sipaddress_dns_unlink_notify", "delete")
282+
283 # Node result table, update to linked node.
284 register_procedure(
285 render_node_related_notification_procedure(