Merge ~mpontillo/maas:version-info-updates-and-triggers into maas:master
- Git
- lp:~mpontillo/maas
- version-info-updates-and-triggers
- Merge into master
Proposed by
Mike Pontillo
Status: | Merged |
---|---|
Approved by: | Mike Pontillo |
Approved revision: | b040b7ccab7cffe27fbce2ac149ac6d012fc2d5a |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~mpontillo/maas:version-info-updates-and-triggers |
Merge into: | maas:master |
Diff against target: |
908 lines (+312/-207) 11 files modified
src/maasserver/models/node.py (+18/-8) src/maasserver/static/partials/node-details.html (+7/-0) src/maasserver/triggers/__init__.py (+102/-10) src/maasserver/triggers/tests/test_init.py (+3/-0) src/maasserver/triggers/tests/test_websocket_listener.py (+105/-0) src/maasserver/triggers/websocket.py (+54/-186) src/maasserver/websockets/handlers/controller.py (+4/-1) src/maasserver/websockets/handlers/node.py (+2/-2) src/maasserver/websockets/handlers/tests/test_controller.py (+10/-0) src/provisioningserver/refresh/__init__.py (+3/-0) src/provisioningserver/refresh/tests/test_refresh.py (+4/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lee Trager (community) | Approve | ||
Review via email: mp+329864@code.launchpad.net |
Commit message
Trigger and websocket work for controller verison
* Add triggers for ControllerInfo model. (Only fire triggers
if the version was updated.)
* Add version information to Controller handler.
* Add version reporting to controller refresh.
* Add version display on controller details page.
* Refactor trigger addition code to add register_triggers() method.
* Drive-by fix to process_sys_info() to prevent updating fields
that did not change.
Description of the change
To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote : | # |
Revision history for this message
Mike Pontillo (mpontillo) wrote : | # |
Quick reply; thanks.
Revision history for this message
Lee Trager (ltrager) wrote : | # |
Looks good just one question below.
review:
Needs Information
Revision history for this message
Mike Pontillo (mpontillo) wrote : | # |
Thanks for taking a look; I've replied to your question inline below.
Revision history for this message
Lee Trager (ltrager) wrote : | # |
Thanks for the explanation. LGTM!
review:
Approve
There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py | |||
2 | index 63e689b..1ec195c 100644 | |||
3 | --- a/src/maasserver/models/node.py | |||
4 | +++ b/src/maasserver/models/node.py | |||
5 | @@ -4822,23 +4822,33 @@ class Controller(Node): | |||
6 | 4822 | @transactional | 4822 | @transactional |
7 | 4823 | def _process_sys_info(self, response): | 4823 | def _process_sys_info(self, response): |
8 | 4824 | update_fields = [] | 4824 | update_fields = [] |
11 | 4825 | if response['hostname'] != '': | 4825 | hostname = response.get('hostname') |
12 | 4826 | self.hostname = response['hostname'] | 4826 | if hostname and self.hostname != hostname: |
13 | 4827 | self.hostname = hostname | ||
14 | 4827 | update_fields.append('hostname') | 4828 | update_fields.append('hostname') |
17 | 4828 | if response['architecture'] != '': | 4829 | architecture = response.get('architecture') |
18 | 4829 | self.architecture = response['architecture'] | 4830 | if architecture and self.architecture != architecture: |
19 | 4831 | self.architecture = architecture | ||
20 | 4830 | update_fields.append('architecture') | 4832 | update_fields.append('architecture') |
23 | 4831 | if response['osystem'] != '': | 4833 | osystem = response.get('osystem') |
24 | 4832 | self.osystem = response['osystem'] | 4834 | if osystem and self.osystem != osystem: |
25 | 4835 | self.osystem = osystem | ||
26 | 4833 | update_fields.append('osystem') | 4836 | update_fields.append('osystem') |
28 | 4834 | if response['distro_series'] != '': | 4837 | distro_series = response.get('distro_series') |
29 | 4838 | if distro_series and self.distro_series != distro_series: | ||
30 | 4835 | self.distro_series = response['distro_series'] | 4839 | self.distro_series = response['distro_series'] |
31 | 4836 | update_fields.append('distro_series') | 4840 | update_fields.append('distro_series') |
32 | 4841 | maas_version = response.get('maas_version') | ||
33 | 4842 | if maas_version and self.version != maas_version: | ||
34 | 4843 | # Circular imports. | ||
35 | 4844 | from maasserver.models import ControllerInfo | ||
36 | 4845 | ControllerInfo.objects.set_version(self, maas_version) | ||
37 | 4837 | # MAAS 2.3+ will send an empty dictionary on purpose, but older | 4846 | # MAAS 2.3+ will send an empty dictionary on purpose, but older |
38 | 4838 | # versions of the MAAS rack will send real data (and it might arrive | 4847 | # versions of the MAAS rack will send real data (and it might arrive |
39 | 4839 | # in a more timely manner than the UpdateInterfaces call from the | 4848 | # in a more timely manner than the UpdateInterfaces call from the |
40 | 4840 | # NetworksMonitoringService). | 4849 | # NetworksMonitoringService). |
42 | 4841 | if response['interfaces'] != {}: | 4850 | interfaces = response.get('interfaces', {}) |
43 | 4851 | if len(interfaces) > 0: | ||
44 | 4842 | self.update_interfaces(response['interfaces']) | 4852 | self.update_interfaces(response['interfaces']) |
45 | 4843 | if len(update_fields) > 0: | 4853 | if len(update_fields) > 0: |
46 | 4844 | self.save(update_fields=update_fields) | 4854 | self.save(update_fields=update_fields) |
47 | diff --git a/src/maasserver/static/partials/node-details.html b/src/maasserver/static/partials/node-details.html | |||
48 | index ccaffa0..66619a1 100755 | |||
49 | --- a/src/maasserver/static/partials/node-details.html | |||
50 | +++ b/src/maasserver/static/partials/node-details.html | |||
51 | @@ -321,6 +321,13 @@ | |||
52 | 321 | aria-label="A region controller controls MAAS services like DNS and runs the database.

A rack controller controls hosts and images and runs network services
like DHCP for connected VLANs." | 321 | aria-label="A region controller controls MAAS services like DNS and runs the database.

A rack controller controls hosts and images and runs network services
like DHCP for connected VLANs." |
53 | 322 | data-ng-show="node.node_type == 4"></i> | 322 | data-ng-show="node.node_type == 4"></i> |
54 | 323 | </dd> | 323 | </dd> |
55 | 324 | <dt class="two-col">MAAS Version</dt> | ||
56 | 325 | <dd class="four-col last-col" data-ng-show="node.version"> | ||
57 | 326 | {$ node.version $} | ||
58 | 327 | </dd> | ||
59 | 328 | <dd class="four-col last-col u-text--subtle" data-ng-show="!node.version"> | ||
60 | 329 | Unknown (< 2.3.0) | ||
61 | 330 | </dd> | ||
62 | 324 | <dt class="two-col" data-ng-show="node.node_type == 2 || node.node_type == 4">Last image sync</dt> | 331 | <dt class="two-col" data-ng-show="node.node_type == 2 || node.node_type == 4">Last image sync</dt> |
63 | 325 | <dd class="four-col last-col" data-ng-show="node.node_type == 2 || node.node_type == 4"> | 332 | <dd class="four-col last-col" data-ng-show="node.node_type == 2 || node.node_type == 4"> |
64 | 326 | {$ node.last_image_sync || 'never' $} | 333 | {$ node.last_image_sync || 'never' $} |
65 | diff --git a/src/maasserver/triggers/__init__.py b/src/maasserver/triggers/__init__.py | |||
66 | index 88323f2..f84a1db 100644 | |||
67 | --- a/src/maasserver/triggers/__init__.py | |||
68 | +++ b/src/maasserver/triggers/__init__.py | |||
69 | @@ -29,21 +29,113 @@ def register_procedure(procedure): | |||
70 | 29 | cursor.execute(procedure) | 29 | cursor.execute(procedure) |
71 | 30 | 30 | ||
72 | 31 | 31 | ||
74 | 32 | def register_trigger(table, procedure, event, params=None, when="after"): | 32 | # Mappings for (postgres_event_type, maas_notification_type, pg_obj) for |
75 | 33 | # trigger notification events. Three conventions are currently in-use in MAAS. | ||
76 | 34 | |||
77 | 35 | # Event names: create/update/delete. | ||
78 | 36 | # The majority of triggers use this convention; this is the default. | ||
79 | 37 | EVENTS_CUD = ( | ||
80 | 38 | ('insert', 'create', 'NEW'), | ||
81 | 39 | ('update', 'update', 'NEW'), | ||
82 | 40 | ('delete', 'delete', 'OLD'), | ||
83 | 41 | ) | ||
84 | 42 | |||
85 | 43 | # Event names: insert/update/delete. | ||
86 | 44 | EVENTS_IUD = ( | ||
87 | 45 | ('insert', 'insert', 'NEW'), | ||
88 | 46 | ('update', 'update', 'NEW'), | ||
89 | 47 | ('delete', 'delete', 'OLD'), | ||
90 | 48 | ) | ||
91 | 49 | |||
92 | 50 | # Event names: link/update/unlink. | ||
93 | 51 | EVENTS_LUU = ( | ||
94 | 52 | ('insert', 'link', 'NEW'), | ||
95 | 53 | ('update', 'update', 'NEW'), | ||
96 | 54 | ('delete', 'unlink', 'OLD'), | ||
97 | 55 | ) | ||
98 | 56 | |||
99 | 57 | |||
100 | 58 | def register_triggers( | ||
101 | 59 | table, event_prefix, params=None, fields=None, events=None, | ||
102 | 60 | when="after"): | ||
103 | 61 | """Registers a set of triggers for insert, update, and delete. | ||
104 | 62 | |||
105 | 63 | Event names will be determined based on MAAS convention, unless the | ||
106 | 64 | convention is passed in via the `events` parameter. Predefined conventions | ||
107 | 65 | in-use in MAAS are provided via the EVENTS_* constants. | ||
108 | 66 | |||
109 | 67 | :param table: The table name to create the trigger on. | ||
110 | 68 | :param event_prefix: The event prefix for the trigger. For example, if | ||
111 | 69 | the table is maasserver_subnet, 'subnet' might be an appropriate event | ||
112 | 70 | prefix. | ||
113 | 71 | :param params: A dictionary of parameters that should be ANDed together to | ||
114 | 72 | form the initial WHEN clause. | ||
115 | 73 | :param fields: A list of fields whose values will be checked for changes | ||
116 | 74 | before the trigger fires. If None is specified, all fields in the row | ||
117 | 75 | will be checked. | ||
118 | 76 | :param events: A tuple in the format of the EVENTS_* constants indicating | ||
119 | 77 | which convention to use for notification names. | ||
120 | 78 | :param when: When the trigger should fire relative to the row update. The | ||
121 | 79 | default is AFTER, but postgresql also supports BEFORE and INSTEAD OF. | ||
122 | 80 | """ | ||
123 | 81 | if events is None: | ||
124 | 82 | events = EVENTS_CUD | ||
125 | 83 | for pg_event, maas_event_type, pg_obj in events: | ||
126 | 84 | event_params = None | ||
127 | 85 | if params is not None: | ||
128 | 86 | event_params = {} | ||
129 | 87 | for key, value in params.items(): | ||
130 | 88 | event_params['%s.%s' % (pg_obj, key)] = value | ||
131 | 89 | register_trigger( | ||
132 | 90 | table, '%s_%s_notify' % (event_prefix, maas_event_type), | ||
133 | 91 | pg_event, event_params, fields, when) | ||
134 | 92 | |||
135 | 93 | |||
136 | 94 | def _make_when_clause(is_update, params, fields): | ||
137 | 95 | """Generates a WHEN clause for the trigger. | ||
138 | 96 | |||
139 | 97 | :param is_update: If true, this trigger is for update. (not insert/delete) | ||
140 | 98 | :param params: A dictionary of parameters that should be ANDed together to | ||
141 | 99 | form the initial WHEN clause. | ||
142 | 100 | :param fields: A list of fields whose values will be checked for changes | ||
143 | 101 | before the trigger fires. If None is specified, all fields in the row | ||
144 | 102 | will be checked. | ||
145 | 103 | :return: the WHEN clause to use in the trigger. | ||
146 | 104 | """ | ||
147 | 105 | when_clause = '' | ||
148 | 106 | if params is not None or (fields is not None and is_update): | ||
149 | 107 | if params is None: | ||
150 | 108 | params = {} | ||
151 | 109 | if fields is None: | ||
152 | 110 | fields = [] | ||
153 | 111 | when_clause = 'WHEN (' | ||
154 | 112 | when_clause += ' AND '.join([ | ||
155 | 113 | "%s = '%s'" % (key, value) | ||
156 | 114 | for key, value in params.items() | ||
157 | 115 | ]) | ||
158 | 116 | if is_update and len(fields) > 0: | ||
159 | 117 | if len(params) > 0: | ||
160 | 118 | when_clause += " AND (" | ||
161 | 119 | when_clause += ' OR '.join([ | ||
162 | 120 | "NEW.%s IS DISTINCT FROM OLD.%s" % (field, field) | ||
163 | 121 | for field in fields | ||
164 | 122 | ]) | ||
165 | 123 | if len(params) > 0: | ||
166 | 124 | when_clause += ")" | ||
167 | 125 | when_clause += ")" | ||
168 | 126 | return when_clause | ||
169 | 127 | |||
170 | 128 | |||
171 | 129 | def register_trigger( | ||
172 | 130 | table, procedure, event, params=None, fields=None, when="after"): | ||
173 | 33 | """Register `trigger` on `table` if it doesn't exist.""" | 131 | """Register `trigger` on `table` if it doesn't exist.""" |
174 | 34 | # Strip the "maasserver_" off the front of the table name. | 132 | # Strip the "maasserver_" off the front of the table name. |
175 | 35 | table_name = table | 133 | table_name = table |
176 | 36 | if table.startswith("maasserver_"): | 134 | if table.startswith("maasserver_"): |
177 | 37 | table_name = table_name[11:] | 135 | table_name = table_name[11:] |
178 | 38 | trigger_name = "%s_%s" % (table_name, procedure) | 136 | trigger_name = "%s_%s" % (table_name, procedure) |
187 | 39 | if params is not None: | 137 | is_update = (event == "update") |
188 | 40 | filter = 'WHEN (' + ''.join( | 138 | when_clause = _make_when_clause(is_update, params, fields) |
181 | 41 | [ | ||
182 | 42 | "%s = '%s'" % (key, value) | ||
183 | 43 | for key, value in params.items() | ||
184 | 44 | ]) + ')' | ||
185 | 45 | else: | ||
186 | 46 | filter = '' | ||
189 | 47 | trigger_sql = dedent("""\ | 139 | trigger_sql = dedent("""\ |
190 | 48 | DROP TRIGGER IF EXISTS %s ON %s; | 140 | DROP TRIGGER IF EXISTS %s ON %s; |
191 | 49 | CREATE TRIGGER %s | 141 | CREATE TRIGGER %s |
192 | @@ -58,7 +150,7 @@ def register_trigger(table, procedure, event, params=None, when="after"): | |||
193 | 58 | when.upper(), | 150 | when.upper(), |
194 | 59 | event.upper(), | 151 | event.upper(), |
195 | 60 | table, | 152 | table, |
197 | 61 | filter, | 153 | when_clause, |
198 | 62 | procedure, | 154 | procedure, |
199 | 63 | ) | 155 | ) |
200 | 64 | with closing(connection.cursor()) as cursor: | 156 | with closing(connection.cursor()) as cursor: |
201 | diff --git a/src/maasserver/triggers/tests/test_init.py b/src/maasserver/triggers/tests/test_init.py | |||
202 | index a0256c4..3f291cb 100644 | |||
203 | --- a/src/maasserver/triggers/tests/test_init.py | |||
204 | +++ b/src/maasserver/triggers/tests/test_init.py | |||
205 | @@ -125,6 +125,9 @@ class TestTriggersUsed(MAASServerTestCase): | |||
206 | 125 | "config_config_update_notify", | 125 | "config_config_update_notify", |
207 | 126 | "config_sys_proxy_config_use_peer_proxy_insert", | 126 | "config_sys_proxy_config_use_peer_proxy_insert", |
208 | 127 | "config_sys_proxy_config_use_peer_proxy_update", | 127 | "config_sys_proxy_config_use_peer_proxy_update", |
209 | 128 | 'controllerinfo_controllerinfo_link_notify', | ||
210 | 129 | 'controllerinfo_controllerinfo_unlink_notify', | ||
211 | 130 | 'controllerinfo_controllerinfo_update_notify', | ||
212 | 128 | "dhcpsnippet_dhcpsnippet_create_notify", | 131 | "dhcpsnippet_dhcpsnippet_create_notify", |
213 | 129 | "dhcpsnippet_dhcpsnippet_delete_notify", | 132 | "dhcpsnippet_dhcpsnippet_delete_notify", |
214 | 130 | "dhcpsnippet_dhcpsnippet_update_notify", | 133 | "dhcpsnippet_dhcpsnippet_update_notify", |
215 | diff --git a/src/maasserver/triggers/tests/test_websocket_listener.py b/src/maasserver/triggers/tests/test_websocket_listener.py | |||
216 | index 8877fcc..c40a3c6 100644 | |||
217 | --- a/src/maasserver/triggers/tests/test_websocket_listener.py | |||
218 | +++ b/src/maasserver/triggers/tests/test_websocket_listener.py | |||
219 | @@ -18,6 +18,7 @@ from maasserver.enum import ( | |||
220 | 18 | NODE_TYPE, | 18 | NODE_TYPE, |
221 | 19 | ) | 19 | ) |
222 | 20 | from maasserver.listener import PostgresListenerService | 20 | from maasserver.listener import PostgresListenerService |
223 | 21 | from maasserver.models import ControllerInfo | ||
224 | 21 | from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE | 22 | from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE |
225 | 22 | from maasserver.models.config import Config | 23 | from maasserver.models.config import Config |
226 | 23 | from maasserver.models.node import Node | 24 | from maasserver.models.node import Node |
227 | @@ -36,7 +37,9 @@ from provisioningserver.utils.twisted import ( | |||
228 | 36 | FOREVER, | 37 | FOREVER, |
229 | 37 | synchronous, | 38 | synchronous, |
230 | 38 | ) | 39 | ) |
231 | 40 | from testtools import ExpectedException | ||
232 | 39 | from twisted.internet.defer import ( | 41 | from twisted.internet.defer import ( |
233 | 42 | CancelledError, | ||
234 | 40 | DeferredList, | 43 | DeferredList, |
235 | 41 | DeferredQueue, | 44 | DeferredQueue, |
236 | 42 | inlineCallbacks, | 45 | inlineCallbacks, |
237 | @@ -219,6 +222,108 @@ class TestNodeListener( | |||
238 | 219 | yield listener.stopService() | 222 | yield listener.stopService() |
239 | 220 | 223 | ||
240 | 221 | 224 | ||
241 | 225 | class TestControllerListener( | ||
242 | 226 | MAASTransactionServerTestCase, TransactionalHelpersMixin): | ||
243 | 227 | """End-to-end test of both the listeners code and the triggers code.""" | ||
244 | 228 | |||
245 | 229 | scenarios = ( | ||
246 | 230 | ('rack', { | ||
247 | 231 | 'params': {'node_type': NODE_TYPE.RACK_CONTROLLER}, | ||
248 | 232 | 'listener': 'controller', | ||
249 | 233 | }), | ||
250 | 234 | ('region_and_rack', { | ||
251 | 235 | 'params': {'node_type': NODE_TYPE.REGION_AND_RACK_CONTROLLER}, | ||
252 | 236 | 'listener': 'controller', | ||
253 | 237 | }), | ||
254 | 238 | ('region', { | ||
255 | 239 | 'params': {'node_type': NODE_TYPE.REGION_CONTROLLER}, | ||
256 | 240 | 'listener': 'controller', | ||
257 | 241 | }), | ||
258 | 242 | ) | ||
259 | 243 | |||
260 | 244 | def set_version(self, controller, version): | ||
261 | 245 | ControllerInfo.objects.set_version(controller, version) | ||
262 | 246 | |||
263 | 247 | def set_interface_update_info(self, controller, interfaces, hints): | ||
264 | 248 | ControllerInfo.objects.set_interface_update_info( | ||
265 | 249 | controller, interfaces, hints) | ||
266 | 250 | |||
267 | 251 | def delete_controllerinfo(self, controller): | ||
268 | 252 | ControllerInfo.objects.filter(node=controller).delete() | ||
269 | 253 | |||
270 | 254 | @wait_for_reactor | ||
271 | 255 | @inlineCallbacks | ||
272 | 256 | def test__calls_handler_on_controllerinfo_insert(self): | ||
273 | 257 | yield deferToDatabase(register_websocket_triggers) | ||
274 | 258 | listener = self.make_listener_without_delay() | ||
275 | 259 | dv = DeferredValue() | ||
276 | 260 | params = self.params.copy() | ||
277 | 261 | controller = yield deferToDatabase(self.create_node, params) | ||
278 | 262 | listener.register(self.listener, lambda *args: dv.set(args)) | ||
279 | 263 | yield listener.startService() | ||
280 | 264 | try: | ||
281 | 265 | yield deferToDatabase( | ||
282 | 266 | self.set_version, controller, factory.make_string()) | ||
283 | 267 | yield dv.get(timeout=2) | ||
284 | 268 | finally: | ||
285 | 269 | yield listener.stopService() | ||
286 | 270 | |||
287 | 271 | @wait_for_reactor | ||
288 | 272 | @inlineCallbacks | ||
289 | 273 | def test__calls_handler_on_controllerinfo_version_update(self): | ||
290 | 274 | yield deferToDatabase(register_websocket_triggers) | ||
291 | 275 | listener = self.make_listener_without_delay() | ||
292 | 276 | dv = DeferredValue() | ||
293 | 277 | params = self.params.copy() | ||
294 | 278 | controller = yield deferToDatabase(self.create_node, params) | ||
295 | 279 | yield deferToDatabase(self.set_version, controller, '') | ||
296 | 280 | listener.register(self.listener, lambda *args: dv.set(args)) | ||
297 | 281 | yield listener.startService() | ||
298 | 282 | try: | ||
299 | 283 | yield deferToDatabase( | ||
300 | 284 | self.set_version, controller, factory.make_string()) | ||
301 | 285 | yield dv.get(timeout=2) | ||
302 | 286 | finally: | ||
303 | 287 | yield listener.stopService() | ||
304 | 288 | |||
305 | 289 | @wait_for_reactor | ||
306 | 290 | @inlineCallbacks | ||
307 | 291 | def test__skips_notify_on_controllerinfo_interface_update(self): | ||
308 | 292 | yield deferToDatabase(register_websocket_triggers) | ||
309 | 293 | listener = self.make_listener_without_delay() | ||
310 | 294 | dv = DeferredValue() | ||
311 | 295 | params = self.params.copy() | ||
312 | 296 | controller = yield deferToDatabase(self.create_node, params) | ||
313 | 297 | yield deferToDatabase(self.set_version, controller, '') | ||
314 | 298 | listener.register(self.listener, lambda *args: dv.set(args)) | ||
315 | 299 | yield listener.startService() | ||
316 | 300 | try: | ||
317 | 301 | yield deferToDatabase( | ||
318 | 302 | self.set_interface_update_info, controller, '{]', '{}') | ||
319 | 303 | with ExpectedException(CancelledError): | ||
320 | 304 | yield dv.get(timeout=0.2) | ||
321 | 305 | finally: | ||
322 | 306 | yield listener.stopService() | ||
323 | 307 | |||
324 | 308 | @wait_for_reactor | ||
325 | 309 | @inlineCallbacks | ||
326 | 310 | def test__calls_handler_on_controllerinfo_delete(self): | ||
327 | 311 | yield deferToDatabase(register_websocket_triggers) | ||
328 | 312 | listener = self.make_listener_without_delay() | ||
329 | 313 | dv = DeferredValue() | ||
330 | 314 | params = self.params.copy() | ||
331 | 315 | controller = yield deferToDatabase(self.create_node, params) | ||
332 | 316 | yield deferToDatabase(self.set_version, controller, '') | ||
333 | 317 | listener.register(self.listener, lambda *args: dv.set(args)) | ||
334 | 318 | yield listener.startService() | ||
335 | 319 | try: | ||
336 | 320 | yield deferToDatabase( | ||
337 | 321 | self.delete_controllerinfo, controller) | ||
338 | 322 | yield dv.get(timeout=2) | ||
339 | 323 | finally: | ||
340 | 324 | yield listener.stopService() | ||
341 | 325 | |||
342 | 326 | |||
343 | 222 | class TestDeviceWithParentListener( | 327 | class TestDeviceWithParentListener( |
344 | 223 | MAASTransactionServerTestCase, TransactionalHelpersMixin): | 328 | MAASTransactionServerTestCase, TransactionalHelpersMixin): |
345 | 224 | """End-to-end test of both the listeners code and the triggers code.""" | 329 | """End-to-end test of both the listeners code and the triggers code.""" |
346 | diff --git a/src/maasserver/triggers/websocket.py b/src/maasserver/triggers/websocket.py | |||
347 | index 0e9df27..0ec50e4 100644 | |||
348 | --- a/src/maasserver/triggers/websocket.py | |||
349 | +++ b/src/maasserver/triggers/websocket.py | |||
350 | @@ -22,8 +22,11 @@ from maasserver.enum import ( | |||
351 | 22 | NODE_TYPE, | 22 | NODE_TYPE, |
352 | 23 | ) | 23 | ) |
353 | 24 | from maasserver.triggers import ( | 24 | from maasserver.triggers import ( |
354 | 25 | EVENTS_IUD, | ||
355 | 26 | EVENTS_LUU, | ||
356 | 25 | register_procedure, | 27 | register_procedure, |
357 | 26 | register_trigger, | 28 | register_trigger, |
358 | 29 | register_triggers, | ||
359 | 27 | ) | 30 | ) |
360 | 28 | from maasserver.utils.orm import transactional | 31 | from maasserver.utils.orm import transactional |
361 | 29 | 32 | ||
362 | @@ -1175,21 +1178,27 @@ def register_websocket_triggers(): | |||
363 | 1175 | '%s_delete_notify' % proc_name_prefix, | 1178 | '%s_delete_notify' % proc_name_prefix, |
364 | 1176 | '%s_delete' % event_name_prefix, | 1179 | '%s_delete' % event_name_prefix, |
365 | 1177 | 'OLD.system_id')) | 1180 | 'OLD.system_id')) |
381 | 1178 | register_trigger( | 1181 | register_triggers( |
382 | 1179 | "maasserver_node", | 1182 | "maasserver_node", proc_name_prefix, {'node_type': node_type}) |
383 | 1180 | "%s_create_notify" % proc_name_prefix, | 1183 | |
384 | 1181 | "insert", | 1184 | # ControllerInfo notifications |
385 | 1182 | {'NEW.node_type': node_type}) | 1185 | register_procedure( |
386 | 1183 | register_trigger( | 1186 | render_node_related_notification_procedure( |
387 | 1184 | "maasserver_node", | 1187 | 'controllerinfo_link_notify', 'NEW.node_id')) |
388 | 1185 | "%s_update_notify" % proc_name_prefix, | 1188 | register_procedure( |
389 | 1186 | "update", | 1189 | render_node_related_notification_procedure( |
390 | 1187 | {'NEW.node_type': node_type}) | 1190 | 'controllerinfo_update_notify', 'NEW.node_id')) |
391 | 1188 | register_trigger( | 1191 | register_procedure( |
392 | 1189 | "maasserver_node", | 1192 | render_node_related_notification_procedure( |
393 | 1190 | "%s_delete_notify" % proc_name_prefix, | 1193 | 'controllerinfo_unlink_notify', 'OLD.node_id')) |
394 | 1191 | "delete", | 1194 | register_triggers( |
395 | 1192 | {'OLD.node_type': node_type}) | 1195 | "maasserver_controllerinfo", |
396 | 1196 | "controllerinfo", | ||
397 | 1197 | # Trigger only fires for version information on update; it doesn't | ||
398 | 1198 | # care when the other metadata is updated. | ||
399 | 1199 | fields=('version',), | ||
400 | 1200 | events=EVENTS_LUU | ||
401 | 1201 | ) | ||
402 | 1193 | 1202 | ||
403 | 1194 | # Config table | 1203 | # Config table |
404 | 1195 | register_procedure( | 1204 | register_procedure( |
405 | @@ -1201,12 +1210,7 @@ def register_websocket_triggers(): | |||
406 | 1201 | register_procedure( | 1210 | register_procedure( |
407 | 1202 | render_notification_procedure( | 1211 | render_notification_procedure( |
408 | 1203 | 'config_delete_notify', 'config_delete', 'OLD.id')) | 1212 | 'config_delete_notify', 'config_delete', 'OLD.id')) |
415 | 1204 | register_trigger( | 1213 | register_triggers("maasserver_config", "config") |
410 | 1205 | "maasserver_config", "config_create_notify", "insert") | ||
411 | 1206 | register_trigger( | ||
412 | 1207 | "maasserver_config", "config_update_notify", "update") | ||
413 | 1208 | register_trigger( | ||
414 | 1209 | "maasserver_config", "config_delete_notify", "delete") | ||
416 | 1210 | 1214 | ||
417 | 1211 | # Device Node types | 1215 | # Device Node types |
418 | 1212 | register_procedure( | 1216 | register_procedure( |
419 | @@ -1218,15 +1222,8 @@ def register_websocket_triggers(): | |||
420 | 1218 | register_procedure( | 1222 | register_procedure( |
421 | 1219 | render_device_notification_procedure( | 1223 | render_device_notification_procedure( |
422 | 1220 | 'device_delete_notify', 'device_delete', 'OLD')) | 1224 | 'device_delete_notify', 'device_delete', 'OLD')) |
432 | 1221 | register_trigger( | 1225 | register_triggers( |
433 | 1222 | "maasserver_node", "device_create_notify", "insert", | 1226 | "maasserver_node", "device", {'node_type': NODE_TYPE.DEVICE}) |
425 | 1223 | {'NEW.node_type': NODE_TYPE.DEVICE}) | ||
426 | 1224 | register_trigger( | ||
427 | 1225 | "maasserver_node", "device_update_notify", "update", | ||
428 | 1226 | {'NEW.node_type': NODE_TYPE.DEVICE}) | ||
429 | 1227 | register_trigger( | ||
430 | 1228 | "maasserver_node", "device_delete_notify", "delete", | ||
431 | 1229 | {'OLD.node_type': NODE_TYPE.DEVICE}) | ||
434 | 1230 | 1227 | ||
435 | 1231 | # VLAN table | 1228 | # VLAN table |
436 | 1232 | register_procedure( | 1229 | register_procedure( |
437 | @@ -1238,12 +1235,7 @@ def register_websocket_triggers(): | |||
438 | 1238 | register_procedure( | 1235 | register_procedure( |
439 | 1239 | render_notification_procedure( | 1236 | render_notification_procedure( |
440 | 1240 | 'vlan_delete_notify', 'vlan_delete', 'OLD.id')) | 1237 | 'vlan_delete_notify', 'vlan_delete', 'OLD.id')) |
447 | 1241 | register_trigger( | 1238 | register_triggers("maasserver_vlan", "vlan") |
442 | 1242 | "maasserver_vlan", "vlan_create_notify", "insert") | ||
443 | 1243 | register_trigger( | ||
444 | 1244 | "maasserver_vlan", "vlan_update_notify", "update") | ||
445 | 1245 | register_trigger( | ||
446 | 1246 | "maasserver_vlan", "vlan_delete_notify", "delete") | ||
448 | 1247 | 1239 | ||
449 | 1248 | # IPRange table | 1240 | # IPRange table |
450 | 1249 | register_procedure( | 1241 | register_procedure( |
451 | @@ -1255,12 +1247,7 @@ def register_websocket_triggers(): | |||
452 | 1255 | register_procedure( | 1247 | register_procedure( |
453 | 1256 | render_notification_procedure( | 1248 | render_notification_procedure( |
454 | 1257 | 'iprange_delete_notify', 'iprange_delete', 'OLD.id')) | 1249 | 'iprange_delete_notify', 'iprange_delete', 'OLD.id')) |
461 | 1258 | register_trigger( | 1250 | register_triggers("maasserver_iprange", "iprange") |
456 | 1259 | "maasserver_iprange", "iprange_create_notify", "insert") | ||
457 | 1260 | register_trigger( | ||
458 | 1261 | "maasserver_iprange", "iprange_update_notify", "update") | ||
459 | 1262 | register_trigger( | ||
460 | 1263 | "maasserver_iprange", "iprange_delete_notify", "delete") | ||
462 | 1264 | 1251 | ||
463 | 1265 | # Neighbour table | 1252 | # Neighbour table |
464 | 1266 | register_procedure( | 1253 | register_procedure( |
465 | @@ -1272,12 +1259,7 @@ def register_websocket_triggers(): | |||
466 | 1272 | register_procedure( | 1259 | register_procedure( |
467 | 1273 | render_notification_procedure( | 1260 | render_notification_procedure( |
468 | 1274 | 'neighbour_delete_notify', 'neighbour_delete', 'OLD.ip')) | 1261 | 'neighbour_delete_notify', 'neighbour_delete', 'OLD.ip')) |
475 | 1275 | register_trigger( | 1262 | register_triggers("maasserver_neighbour", "neighbour") |
470 | 1276 | "maasserver_neighbour", "neighbour_create_notify", "insert") | ||
471 | 1277 | register_trigger( | ||
472 | 1278 | "maasserver_neighbour", "neighbour_update_notify", "update") | ||
473 | 1279 | register_trigger( | ||
474 | 1280 | "maasserver_neighbour", "neighbour_delete_notify", "delete") | ||
476 | 1281 | 1263 | ||
477 | 1282 | # StaticRoute table | 1264 | # StaticRoute table |
478 | 1283 | register_procedure( | 1265 | register_procedure( |
479 | @@ -1289,12 +1271,7 @@ def register_websocket_triggers(): | |||
480 | 1289 | register_procedure( | 1271 | register_procedure( |
481 | 1290 | render_notification_procedure( | 1272 | render_notification_procedure( |
482 | 1291 | 'staticroute_delete_notify', 'staticroute_delete', 'OLD.id')) | 1273 | 'staticroute_delete_notify', 'staticroute_delete', 'OLD.id')) |
489 | 1292 | register_trigger( | 1274 | register_triggers("maasserver_staticroute", "staticroute") |
484 | 1293 | "maasserver_staticroute", "staticroute_create_notify", "insert") | ||
485 | 1294 | register_trigger( | ||
486 | 1295 | "maasserver_staticroute", "staticroute_update_notify", "update") | ||
487 | 1296 | register_trigger( | ||
488 | 1297 | "maasserver_staticroute", "staticroute_delete_notify", "delete") | ||
490 | 1298 | 1275 | ||
491 | 1299 | # Fabric table | 1276 | # Fabric table |
492 | 1300 | register_procedure( | 1277 | register_procedure( |
493 | @@ -1306,12 +1283,7 @@ def register_websocket_triggers(): | |||
494 | 1306 | register_procedure( | 1283 | register_procedure( |
495 | 1307 | render_notification_procedure( | 1284 | render_notification_procedure( |
496 | 1308 | 'fabric_delete_notify', 'fabric_delete', 'OLD.id')) | 1285 | 'fabric_delete_notify', 'fabric_delete', 'OLD.id')) |
503 | 1309 | register_trigger( | 1286 | register_triggers("maasserver_fabric", "fabric") |
498 | 1310 | "maasserver_fabric", "fabric_create_notify", "insert") | ||
499 | 1311 | register_trigger( | ||
500 | 1312 | "maasserver_fabric", "fabric_update_notify", "update") | ||
501 | 1313 | register_trigger( | ||
502 | 1314 | "maasserver_fabric", "fabric_delete_notify", "delete") | ||
504 | 1315 | 1287 | ||
505 | 1316 | # Space table | 1288 | # Space table |
506 | 1317 | register_procedure( | 1289 | register_procedure( |
507 | @@ -1323,12 +1295,7 @@ def register_websocket_triggers(): | |||
508 | 1323 | register_procedure( | 1295 | register_procedure( |
509 | 1324 | render_notification_procedure( | 1296 | render_notification_procedure( |
510 | 1325 | 'space_delete_notify', 'space_delete', 'OLD.id')) | 1297 | 'space_delete_notify', 'space_delete', 'OLD.id')) |
517 | 1326 | register_trigger( | 1298 | register_triggers("maasserver_space", "space") |
512 | 1327 | "maasserver_space", "space_create_notify", "insert") | ||
513 | 1328 | register_trigger( | ||
514 | 1329 | "maasserver_space", "space_update_notify", "update") | ||
515 | 1330 | register_trigger( | ||
516 | 1331 | "maasserver_space", "space_delete_notify", "delete") | ||
518 | 1332 | 1299 | ||
519 | 1333 | # Subnet table | 1300 | # Subnet table |
520 | 1334 | register_procedure( | 1301 | register_procedure( |
521 | @@ -1340,12 +1307,7 @@ def register_websocket_triggers(): | |||
522 | 1340 | register_procedure( | 1307 | register_procedure( |
523 | 1341 | render_notification_procedure( | 1308 | render_notification_procedure( |
524 | 1342 | 'subnet_delete_notify', 'subnet_delete', 'OLD.id')) | 1309 | 'subnet_delete_notify', 'subnet_delete', 'OLD.id')) |
531 | 1343 | register_trigger( | 1310 | register_triggers("maasserver_subnet", "subnet") |
526 | 1344 | "maasserver_subnet", "subnet_create_notify", "insert") | ||
527 | 1345 | register_trigger( | ||
528 | 1346 | "maasserver_subnet", "subnet_update_notify", "update") | ||
529 | 1347 | register_trigger( | ||
530 | 1348 | "maasserver_subnet", "subnet_delete_notify", "delete") | ||
532 | 1349 | 1311 | ||
533 | 1350 | # Subnet node notifications | 1312 | # Subnet node notifications |
534 | 1351 | register_procedure( | 1313 | register_procedure( |
535 | @@ -1421,15 +1383,8 @@ def register_websocket_triggers(): | |||
536 | 1421 | register_procedure( | 1383 | register_procedure( |
537 | 1422 | STATIC_IP_ADDRESS_DOMAIN_NOTIFY % ( | 1384 | STATIC_IP_ADDRESS_DOMAIN_NOTIFY % ( |
538 | 1423 | 'ipaddress_domain_delete_notify', 'OLD.id')) | 1385 | 'ipaddress_domain_delete_notify', 'OLD.id')) |
548 | 1424 | register_trigger( | 1386 | register_triggers( |
549 | 1425 | "maasserver_staticipaddress", | 1387 | "maasserver_staticipaddress", "ipaddress_domain", events=EVENTS_IUD) |
541 | 1426 | "ipaddress_domain_insert_notify", "insert") | ||
542 | 1427 | register_trigger( | ||
543 | 1428 | "maasserver_staticipaddress", | ||
544 | 1429 | "ipaddress_domain_update_notify", "update") | ||
545 | 1430 | register_trigger( | ||
546 | 1431 | "maasserver_staticipaddress", | ||
547 | 1432 | "ipaddress_domain_delete_notify", "delete") | ||
550 | 1433 | 1388 | ||
551 | 1434 | # IP range subnet notifications | 1389 | # IP range subnet notifications |
552 | 1435 | register_procedure( | 1390 | register_procedure( |
553 | @@ -1438,15 +1393,8 @@ def register_websocket_triggers(): | |||
554 | 1438 | IP_RANGE_SUBNET_UPDATE_NOTIFY % 'iprange_subnet_update_notify') | 1393 | IP_RANGE_SUBNET_UPDATE_NOTIFY % 'iprange_subnet_update_notify') |
555 | 1439 | register_procedure( | 1394 | register_procedure( |
556 | 1440 | IP_RANGE_SUBNET_DELETE_NOTIFY % 'iprange_subnet_delete_notify') | 1395 | IP_RANGE_SUBNET_DELETE_NOTIFY % 'iprange_subnet_delete_notify') |
566 | 1441 | register_trigger( | 1396 | register_triggers( |
567 | 1442 | "maasserver_iprange", | 1397 | "maasserver_iprange", "iprange_subnet", events=EVENTS_IUD) |
559 | 1443 | "iprange_subnet_insert_notify", "insert") | ||
560 | 1444 | register_trigger( | ||
561 | 1445 | "maasserver_iprange", | ||
562 | 1446 | "iprange_subnet_update_notify", "update") | ||
563 | 1447 | register_trigger( | ||
564 | 1448 | "maasserver_iprange", | ||
565 | 1449 | "iprange_subnet_delete_notify", "delete") | ||
568 | 1450 | 1398 | ||
569 | 1451 | # Pod notifications | 1399 | # Pod notifications |
570 | 1452 | register_procedure( | 1400 | register_procedure( |
571 | @@ -1457,15 +1405,7 @@ def register_websocket_triggers(): | |||
572 | 1457 | BMC_TYPE.POD, BMC_TYPE.POD, BMC_TYPE.BMC)) | 1405 | BMC_TYPE.POD, BMC_TYPE.POD, BMC_TYPE.BMC)) |
573 | 1458 | register_procedure( | 1406 | register_procedure( |
574 | 1459 | POD_DELETE_NOTIFY % ('pod_delete_notify', BMC_TYPE.POD)) | 1407 | POD_DELETE_NOTIFY % ('pod_delete_notify', BMC_TYPE.POD)) |
584 | 1460 | register_trigger( | 1408 | register_triggers("maasserver_bmc", "pod", events=EVENTS_IUD) |
576 | 1461 | "maasserver_bmc", | ||
577 | 1462 | "pod_insert_notify", "insert") | ||
578 | 1463 | register_trigger( | ||
579 | 1464 | "maasserver_bmc", | ||
580 | 1465 | "pod_update_notify", "update") | ||
581 | 1466 | register_trigger( | ||
582 | 1467 | "maasserver_bmc", | ||
583 | 1468 | "pod_delete_notify", "delete") | ||
585 | 1469 | 1409 | ||
586 | 1470 | # Node pod notifications | 1410 | # Node pod notifications |
587 | 1471 | register_procedure( | 1411 | register_procedure( |
588 | @@ -1475,15 +1415,7 @@ def register_websocket_triggers(): | |||
589 | 1475 | 'node_pod_update_notify', BMC_TYPE.POD, BMC_TYPE.POD)) | 1415 | 'node_pod_update_notify', BMC_TYPE.POD, BMC_TYPE.POD)) |
590 | 1476 | register_procedure( | 1416 | register_procedure( |
591 | 1477 | NODE_POD_DELETE_NOTIFY % ('node_pod_delete_notify', BMC_TYPE.POD)) | 1417 | NODE_POD_DELETE_NOTIFY % ('node_pod_delete_notify', BMC_TYPE.POD)) |
601 | 1478 | register_trigger( | 1418 | register_triggers("maasserver_node", "node_pod", events=EVENTS_IUD) |
593 | 1479 | "maasserver_node", | ||
594 | 1480 | "node_pod_insert_notify", "insert") | ||
595 | 1481 | register_trigger( | ||
596 | 1482 | "maasserver_node", | ||
597 | 1483 | "node_pod_update_notify", "update") | ||
598 | 1484 | register_trigger( | ||
599 | 1485 | "maasserver_node", | ||
600 | 1486 | "node_pod_delete_notify", "delete") | ||
602 | 1487 | 1419 | ||
603 | 1488 | # DNSData table | 1420 | # DNSData table |
604 | 1489 | register_procedure( | 1421 | register_procedure( |
605 | @@ -1496,15 +1428,8 @@ def register_websocket_triggers(): | |||
606 | 1496 | register_procedure( | 1428 | register_procedure( |
607 | 1497 | DNSDATA_DOMAIN_NOTIFY % ( | 1429 | DNSDATA_DOMAIN_NOTIFY % ( |
608 | 1498 | 'dnsdata_domain_delete_notify', 'OLD.dnsresource_id')) | 1430 | 'dnsdata_domain_delete_notify', 'OLD.dnsresource_id')) |
618 | 1499 | register_trigger( | 1431 | register_triggers( |
619 | 1500 | "maasserver_dnsdata", | 1432 | "maasserver_dnsdata", "dnsdata_domain", events=EVENTS_IUD) |
611 | 1501 | "dnsdata_domain_insert_notify", "insert") | ||
612 | 1502 | register_trigger( | ||
613 | 1503 | "maasserver_dnsdata", | ||
614 | 1504 | "dnsdata_domain_update_notify", "update") | ||
615 | 1505 | register_trigger( | ||
616 | 1506 | "maasserver_dnsdata", | ||
617 | 1507 | "dnsdata_domain_delete_notify", "delete") | ||
620 | 1508 | 1433 | ||
621 | 1509 | # DNSResource table | 1434 | # DNSResource table |
622 | 1510 | register_procedure( | 1435 | register_procedure( |
623 | @@ -1515,15 +1440,8 @@ def register_websocket_triggers(): | |||
624 | 1515 | register_procedure( | 1440 | register_procedure( |
625 | 1516 | DNSRESOURCE_DOMAIN_NOTIFY % ( | 1441 | DNSRESOURCE_DOMAIN_NOTIFY % ( |
626 | 1517 | 'dnsresource_domain_delete_notify', 'OLD')) | 1442 | 'dnsresource_domain_delete_notify', 'OLD')) |
636 | 1518 | register_trigger( | 1443 | register_triggers( |
637 | 1519 | "maasserver_dnsresource", | 1444 | "maasserver_dnsresource", "dnsresource_domain", events=EVENTS_IUD) |
629 | 1520 | "dnsresource_domain_insert_notify", "insert") | ||
630 | 1521 | register_trigger( | ||
631 | 1522 | "maasserver_dnsresource", | ||
632 | 1523 | "dnsresource_domain_update_notify", "update") | ||
633 | 1524 | register_trigger( | ||
634 | 1525 | "maasserver_dnsresource", | ||
635 | 1526 | "dnsresource_domain_delete_notify", "delete") | ||
638 | 1527 | 1445 | ||
639 | 1528 | # Domain table | 1446 | # Domain table |
640 | 1529 | register_procedure( | 1447 | register_procedure( |
641 | @@ -1542,12 +1460,7 @@ def register_websocket_triggers(): | |||
642 | 1542 | 'domain_delete_notify', 'domain_delete', 'OLD.id')) | 1460 | 'domain_delete_notify', 'domain_delete', 'OLD.id')) |
643 | 1543 | register_trigger( | 1461 | register_trigger( |
644 | 1544 | "maasserver_domain", "domain_node_update_notify", "update") | 1462 | "maasserver_domain", "domain_node_update_notify", "update") |
651 | 1545 | register_trigger( | 1463 | register_triggers("maasserver_domain", "domain") |
646 | 1546 | "maasserver_domain", "domain_create_notify", "insert") | ||
647 | 1547 | register_trigger( | ||
648 | 1548 | "maasserver_domain", "domain_update_notify", "update") | ||
649 | 1549 | register_trigger( | ||
650 | 1550 | "maasserver_domain", "domain_delete_notify", "delete") | ||
652 | 1551 | 1464 | ||
653 | 1552 | # MAC static ip address table, update to linked domain via dnsresource | 1465 | # MAC static ip address table, update to linked domain via dnsresource |
654 | 1553 | register_procedure( | 1466 | register_procedure( |
655 | @@ -1573,12 +1486,7 @@ def register_websocket_triggers(): | |||
656 | 1573 | register_procedure( | 1486 | register_procedure( |
657 | 1574 | render_notification_procedure( | 1487 | render_notification_procedure( |
658 | 1575 | 'zone_delete_notify', 'zone_delete', 'OLD.id')) | 1488 | 'zone_delete_notify', 'zone_delete', 'OLD.id')) |
665 | 1576 | register_trigger( | 1489 | register_triggers("maasserver_zone", "zone") |
660 | 1577 | "maasserver_zone", "zone_create_notify", "insert") | ||
661 | 1578 | register_trigger( | ||
662 | 1579 | "maasserver_zone", "zone_update_notify", "update") | ||
663 | 1580 | register_trigger( | ||
664 | 1581 | "maasserver_zone", "zone_delete_notify", "delete") | ||
666 | 1582 | 1490 | ||
667 | 1583 | # Service table | 1491 | # Service table |
668 | 1584 | register_procedure( | 1492 | register_procedure( |
669 | @@ -1590,12 +1498,7 @@ def register_websocket_triggers(): | |||
670 | 1590 | register_procedure( | 1498 | register_procedure( |
671 | 1591 | render_notification_procedure( | 1499 | render_notification_procedure( |
672 | 1592 | 'service_delete_notify', 'service_delete', 'OLD.id')) | 1500 | 'service_delete_notify', 'service_delete', 'OLD.id')) |
679 | 1593 | register_trigger( | 1501 | register_triggers("maasserver_service", "service") |
674 | 1594 | "maasserver_service", "service_create_notify", "insert") | ||
675 | 1595 | register_trigger( | ||
676 | 1596 | "maasserver_service", "service_update_notify", "update") | ||
677 | 1597 | register_trigger( | ||
678 | 1598 | "maasserver_service", "service_delete_notify", "delete") | ||
680 | 1599 | 1502 | ||
681 | 1600 | # Tag table | 1503 | # Tag table |
682 | 1601 | register_procedure( | 1504 | register_procedure( |
683 | @@ -1607,12 +1510,7 @@ def register_websocket_triggers(): | |||
684 | 1607 | register_procedure( | 1510 | register_procedure( |
685 | 1608 | render_notification_procedure( | 1511 | render_notification_procedure( |
686 | 1609 | 'tag_delete_notify', 'tag_delete', 'OLD.id')) | 1512 | 'tag_delete_notify', 'tag_delete', 'OLD.id')) |
693 | 1610 | register_trigger( | 1513 | register_triggers("maasserver_tag", "tag") |
688 | 1611 | "maasserver_tag", "tag_create_notify", "insert") | ||
689 | 1612 | register_trigger( | ||
690 | 1613 | "maasserver_tag", "tag_update_notify", "update") | ||
691 | 1614 | register_trigger( | ||
692 | 1615 | "maasserver_tag", "tag_delete_notify", "delete") | ||
694 | 1616 | 1514 | ||
695 | 1617 | # Node tag link table | 1515 | # Node tag link table |
696 | 1618 | register_procedure( | 1516 | register_procedure( |
697 | @@ -1647,12 +1545,7 @@ def register_websocket_triggers(): | |||
698 | 1647 | register_procedure( | 1545 | register_procedure( |
699 | 1648 | render_notification_procedure( | 1546 | render_notification_procedure( |
700 | 1649 | 'user_delete_notify', 'user_delete', 'OLD.id')) | 1547 | 'user_delete_notify', 'user_delete', 'OLD.id')) |
707 | 1650 | register_trigger( | 1548 | register_triggers("auth_user", "user") |
702 | 1651 | "auth_user", "user_create_notify", "insert") | ||
703 | 1652 | register_trigger( | ||
704 | 1653 | "auth_user", "user_update_notify", "update") | ||
705 | 1654 | register_trigger( | ||
706 | 1655 | "auth_user", "user_delete_notify", "delete") | ||
708 | 1656 | 1549 | ||
709 | 1657 | # Events table | 1550 | # Events table |
710 | 1658 | register_procedure( | 1551 | register_procedure( |
711 | @@ -1928,12 +1821,7 @@ def register_websocket_triggers(): | |||
712 | 1928 | register_procedure( | 1821 | register_procedure( |
713 | 1929 | render_notification_procedure( | 1822 | render_notification_procedure( |
714 | 1930 | 'sshkey_delete_notify', 'sshkey_delete', 'OLD.id')) | 1823 | 'sshkey_delete_notify', 'sshkey_delete', 'OLD.id')) |
721 | 1931 | register_trigger( | 1824 | register_triggers("maasserver_sshkey", "sshkey") |
716 | 1932 | "maasserver_sshkey", "sshkey_create_notify", "insert") | ||
717 | 1933 | register_trigger( | ||
718 | 1934 | "maasserver_sshkey", "sshkey_update_notify", "update") | ||
719 | 1935 | register_trigger( | ||
720 | 1936 | "maasserver_sshkey", "sshkey_delete_notify", "delete") | ||
722 | 1937 | 1825 | ||
723 | 1938 | # SSL key table, update to linked user. | 1826 | # SSL key table, update to linked user. |
724 | 1939 | register_procedure( | 1827 | register_procedure( |
725 | @@ -1957,12 +1845,7 @@ def register_websocket_triggers(): | |||
726 | 1957 | register_procedure( | 1845 | register_procedure( |
727 | 1958 | render_notification_procedure( | 1846 | render_notification_procedure( |
728 | 1959 | 'dhcpsnippet_delete_notify', 'dhcpsnippet_delete', 'OLD.id')) | 1847 | 'dhcpsnippet_delete_notify', 'dhcpsnippet_delete', 'OLD.id')) |
735 | 1960 | register_trigger( | 1848 | register_triggers("maasserver_dhcpsnippet", "dhcpsnippet") |
730 | 1961 | "maasserver_dhcpsnippet", "dhcpsnippet_create_notify", "insert") | ||
731 | 1962 | register_trigger( | ||
732 | 1963 | "maasserver_dhcpsnippet", "dhcpsnippet_update_notify", "update") | ||
733 | 1964 | register_trigger( | ||
734 | 1965 | "maasserver_dhcpsnippet", "dhcpsnippet_delete_notify", "delete") | ||
736 | 1966 | 1849 | ||
737 | 1967 | # PackageRepository table | 1850 | # PackageRepository table |
738 | 1968 | register_procedure( | 1851 | register_procedure( |
739 | @@ -1977,15 +1860,7 @@ def register_websocket_triggers(): | |||
740 | 1977 | render_notification_procedure( | 1860 | render_notification_procedure( |
741 | 1978 | 'packagerepository_delete_notify', 'packagerepository_delete', | 1861 | 'packagerepository_delete_notify', 'packagerepository_delete', |
742 | 1979 | 'OLD.id')) | 1862 | 'OLD.id')) |
752 | 1980 | register_trigger( | 1863 | register_triggers("maasserver_packagerepository", "packagerepository") |
744 | 1981 | "maasserver_packagerepository", "packagerepository_create_notify", | ||
745 | 1982 | "insert") | ||
746 | 1983 | register_trigger( | ||
747 | 1984 | "maasserver_packagerepository", "packagerepository_update_notify", | ||
748 | 1985 | "update") | ||
749 | 1986 | register_trigger( | ||
750 | 1987 | "maasserver_packagerepository", "packagerepository_delete_notify", | ||
751 | 1988 | "delete") | ||
753 | 1989 | 1864 | ||
754 | 1990 | # Node type change. | 1865 | # Node type change. |
755 | 1991 | register_procedure(node_type_change()) | 1866 | register_procedure(node_type_change()) |
756 | @@ -2002,12 +1877,7 @@ def register_websocket_triggers(): | |||
757 | 2002 | register_procedure( | 1877 | register_procedure( |
758 | 2003 | render_notification_procedure( | 1878 | render_notification_procedure( |
759 | 2004 | 'notification_delete_notify', 'notification_delete', 'OLD.id')) | 1879 | 'notification_delete_notify', 'notification_delete', 'OLD.id')) |
766 | 2005 | register_trigger( | 1880 | register_triggers("maasserver_notification", "notification") |
761 | 2006 | "maasserver_notification", "notification_create_notify", "insert") | ||
762 | 2007 | register_trigger( | ||
763 | 2008 | "maasserver_notification", "notification_update_notify", "update") | ||
764 | 2009 | register_trigger( | ||
765 | 2010 | "maasserver_notification", "notification_delete_notify", "delete") | ||
767 | 2011 | 1881 | ||
768 | 2012 | # NotificationDismissal table. | 1882 | # NotificationDismissal table. |
769 | 2013 | register_procedure( | 1883 | register_procedure( |
770 | @@ -2028,6 +1898,4 @@ def register_websocket_triggers(): | |||
771 | 2028 | register_procedure( | 1898 | register_procedure( |
772 | 2029 | render_notification_procedure( | 1899 | render_notification_procedure( |
773 | 2030 | 'script_delete_notify', 'script_delete', 'OLD.id')) | 1900 | 'script_delete_notify', 'script_delete', 'OLD.id')) |
777 | 2031 | register_trigger('metadataserver_script', 'script_create_notify', 'insert') | 1901 | register_triggers('metadataserver_script', 'script') |
775 | 2032 | register_trigger('metadataserver_script', 'script_update_notify', 'update') | ||
776 | 2033 | register_trigger('metadataserver_script', 'script_delete_notify', 'delete') | ||
778 | diff --git a/src/maasserver/websockets/handlers/controller.py b/src/maasserver/websockets/handlers/controller.py | |||
779 | index ca85333..6edc6f0 100644 | |||
780 | --- a/src/maasserver/websockets/handlers/controller.py | |||
781 | +++ b/src/maasserver/websockets/handlers/controller.py | |||
782 | @@ -23,7 +23,9 @@ class ControllerHandler(MachineHandler): | |||
783 | 23 | class Meta(MachineHandler.Meta): | 23 | class Meta(MachineHandler.Meta): |
784 | 24 | abstract = False | 24 | abstract = False |
785 | 25 | queryset = node_prefetch( | 25 | queryset = node_prefetch( |
787 | 26 | Controller.controllers.all().prefetch_related("interface_set")) | 26 | Controller.controllers.all().prefetch_related("interface_set"), |
788 | 27 | 'controllerinfo' | ||
789 | 28 | ) | ||
790 | 27 | allowed_methods = [ | 29 | allowed_methods = [ |
791 | 28 | 'list', | 30 | 'list', |
792 | 29 | 'get', | 31 | 'get', |
793 | @@ -89,6 +91,7 @@ class ControllerHandler(MachineHandler): | |||
794 | 89 | 91 | ||
795 | 90 | def dehydrate(self, obj, data, for_list=False): | 92 | def dehydrate(self, obj, data, for_list=False): |
796 | 91 | data = super().dehydrate(obj, data, for_list=for_list) | 93 | data = super().dehydrate(obj, data, for_list=for_list) |
797 | 94 | data["version"] = obj.version | ||
798 | 92 | data["vlan_ids"] = [ | 95 | data["vlan_ids"] = [ |
799 | 93 | interface.vlan_id | 96 | interface.vlan_id |
800 | 94 | for interface in obj.interface_set.all() | 97 | for interface in obj.interface_set.all() |
801 | diff --git a/src/maasserver/websockets/handlers/node.py b/src/maasserver/websockets/handlers/node.py | |||
802 | index 12bb3c3..5014fa8 100644 | |||
803 | --- a/src/maasserver/websockets/handlers/node.py | |||
804 | +++ b/src/maasserver/websockets/handlers/node.py | |||
805 | @@ -45,10 +45,10 @@ from metadataserver.enum import RESULT_TYPE | |||
806 | 45 | from provisioningserver.tags import merge_details_cleanly | 45 | from provisioningserver.tags import merge_details_cleanly |
807 | 46 | 46 | ||
808 | 47 | 47 | ||
810 | 48 | def node_prefetch(queryset): | 48 | def node_prefetch(queryset, *args): |
811 | 49 | return ( | 49 | return ( |
812 | 50 | queryset | 50 | queryset |
814 | 51 | .select_related('boot_interface', 'owner', 'zone', 'domain') | 51 | .select_related('boot_interface', 'owner', 'zone', 'domain', *args) |
815 | 52 | .prefetch_related('blockdevice_set__iscsiblockdevice') | 52 | .prefetch_related('blockdevice_set__iscsiblockdevice') |
816 | 53 | .prefetch_related('blockdevice_set__physicalblockdevice') | 53 | .prefetch_related('blockdevice_set__physicalblockdevice') |
817 | 54 | .prefetch_related('blockdevice_set__virtualblockdevice') | 54 | .prefetch_related('blockdevice_set__virtualblockdevice') |
818 | diff --git a/src/maasserver/websockets/handlers/tests/test_controller.py b/src/maasserver/websockets/handlers/tests/test_controller.py | |||
819 | index 111ed57..ad628e9 100644 | |||
820 | --- a/src/maasserver/websockets/handlers/tests/test_controller.py | |||
821 | +++ b/src/maasserver/websockets/handlers/tests/test_controller.py | |||
822 | @@ -7,6 +7,7 @@ __all__ = [] | |||
823 | 7 | 7 | ||
824 | 8 | from maasserver.enum import NODE_TYPE | 8 | from maasserver.enum import NODE_TYPE |
825 | 9 | from maasserver.forms import ControllerForm | 9 | from maasserver.forms import ControllerForm |
826 | 10 | from maasserver.models import ControllerInfo | ||
827 | 10 | from maasserver.testing.factory import factory | 11 | from maasserver.testing.factory import factory |
828 | 11 | from maasserver.testing.testcase import MAASServerTestCase | 12 | from maasserver.testing.testcase import MAASServerTestCase |
829 | 12 | from maasserver.websockets.base import dehydrate_datetime | 13 | from maasserver.websockets.base import dehydrate_datetime |
830 | @@ -96,6 +97,15 @@ class TestControllerHandler(MAASServerTestCase): | |||
831 | 96 | handler = ControllerHandler(owner, {}) | 97 | handler = ControllerHandler(owner, {}) |
832 | 97 | self.assertTrue(handler.dehydrate_show_os_info(rack)) | 98 | self.assertTrue(handler.dehydrate_show_os_info(rack)) |
833 | 98 | 99 | ||
834 | 100 | def test_dehydrate_includes_version(self): | ||
835 | 101 | owner = factory.make_admin() | ||
836 | 102 | handler = ControllerHandler(owner, {}) | ||
837 | 103 | rack = factory.make_RackController() | ||
838 | 104 | version = factory.make_string() | ||
839 | 105 | ControllerInfo.objects.set_version(rack, version) | ||
840 | 106 | result = handler.list({}) | ||
841 | 107 | self.assertEqual(version, result[0].get('version')) | ||
842 | 108 | |||
843 | 99 | 109 | ||
844 | 100 | class TestControllerHandlerScenarios(MAASServerTestCase): | 110 | class TestControllerHandlerScenarios(MAASServerTestCase): |
845 | 101 | 111 | ||
846 | diff --git a/src/provisioningserver/refresh/__init__.py b/src/provisioningserver/refresh/__init__.py | |||
847 | index a377038..bf05f10 100644 | |||
848 | --- a/src/provisioningserver/refresh/__init__.py | |||
849 | +++ b/src/provisioningserver/refresh/__init__.py | |||
850 | @@ -2,6 +2,7 @@ | |||
851 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
852 | 3 | 3 | ||
853 | 4 | """Functionality to refresh rack controller hardware and networking details.""" | 4 | """Functionality to refresh rack controller hardware and networking details.""" |
854 | 5 | |||
855 | 5 | import os | 6 | import os |
856 | 6 | import socket | 7 | import socket |
857 | 7 | import stat | 8 | import stat |
858 | @@ -25,6 +26,7 @@ from provisioningserver.utils.shell import ( | |||
859 | 25 | ExternalProcessError, | 26 | ExternalProcessError, |
860 | 26 | ) | 27 | ) |
861 | 27 | from provisioningserver.utils.twisted import synchronous | 28 | from provisioningserver.utils.twisted import synchronous |
862 | 29 | from provisioningserver.utils.version import get_maas_version | ||
863 | 28 | 30 | ||
864 | 29 | 31 | ||
865 | 30 | maaslog = get_maas_logger("refresh") | 32 | maaslog = get_maas_logger("refresh") |
866 | @@ -77,6 +79,7 @@ def get_sys_info(): | |||
867 | 77 | 'architecture': get_architecture(), | 79 | 'architecture': get_architecture(), |
868 | 78 | 'osystem': osystem, | 80 | 'osystem': osystem, |
869 | 79 | 'distro_series': distro_series, | 81 | 'distro_series': distro_series, |
870 | 82 | 'maas_version': get_maas_version(), | ||
871 | 80 | # In MAAS 2.3+, the NetworksMonitoringService is solely responsible for | 83 | # In MAAS 2.3+, the NetworksMonitoringService is solely responsible for |
872 | 81 | # interface update, because interface updates need to include beaconing | 84 | # interface update, because interface updates need to include beaconing |
873 | 82 | # data. The key and empty dictionary are necessary for backward | 85 | # data. The key and empty dictionary are necessary for backward |
874 | diff --git a/src/provisioningserver/refresh/tests/test_refresh.py b/src/provisioningserver/refresh/tests/test_refresh.py | |||
875 | index ff6b759..d03cac1 100644 | |||
876 | --- a/src/provisioningserver/refresh/tests/test_refresh.py | |||
877 | +++ b/src/provisioningserver/refresh/tests/test_refresh.py | |||
878 | @@ -25,6 +25,7 @@ from provisioningserver.refresh.maas_api_helper import ( | |||
879 | 25 | MD_VERSION, | 25 | MD_VERSION, |
880 | 26 | SignalException, | 26 | SignalException, |
881 | 27 | ) | 27 | ) |
882 | 28 | from provisioningserver.utils.version import get_maas_version | ||
883 | 28 | from testtools.matchers import ( | 29 | from testtools.matchers import ( |
884 | 29 | Contains, | 30 | Contains, |
885 | 30 | DirExists, | 31 | DirExists, |
886 | @@ -82,6 +83,7 @@ class TestHelpers(MAASTestCase): | |||
887 | 82 | 'architecture': architecture, | 83 | 'architecture': architecture, |
888 | 83 | 'osystem': osystem, | 84 | 'osystem': osystem, |
889 | 84 | 'distro_series': distro_series, | 85 | 'distro_series': distro_series, |
890 | 86 | 'maas_version': get_maas_version(), | ||
891 | 85 | 'interfaces': {}, | 87 | 'interfaces': {}, |
892 | 86 | }, Equals(refresh.get_sys_info())) | 88 | }, Equals(refresh.get_sys_info())) |
893 | 87 | 89 | ||
894 | @@ -105,6 +107,7 @@ class TestHelpers(MAASTestCase): | |||
895 | 105 | 'architecture': architecture, | 107 | 'architecture': architecture, |
896 | 106 | 'osystem': osystem, | 108 | 'osystem': osystem, |
897 | 107 | 'distro_series': distro_series, | 109 | 'distro_series': distro_series, |
898 | 110 | 'maas_version': get_maas_version(), | ||
899 | 108 | 'interfaces': {}, | 111 | 'interfaces': {}, |
900 | 109 | }, Equals(refresh.get_sys_info())) | 112 | }, Equals(refresh.get_sys_info())) |
901 | 110 | 113 | ||
902 | @@ -120,6 +123,7 @@ class TestHelpers(MAASTestCase): | |||
903 | 120 | 'architecture': architecture, | 123 | 'architecture': architecture, |
904 | 121 | 'osystem': '', | 124 | 'osystem': '', |
905 | 122 | 'distro_series': '', | 125 | 'distro_series': '', |
906 | 126 | 'maas_version': get_maas_version(), | ||
907 | 123 | 'interfaces': {}, | 127 | 'interfaces': {}, |
908 | 124 | }, Equals(refresh.get_sys_info())) | 128 | }, Equals(refresh.get_sys_info())) |
909 | 125 | 129 |
quick comment :)