Merge lp:~maas-maintainers/maas/maas-ha into lp:~maas-committers/maas/trunk
- maas-ha
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Blake Rouse |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4570 |
Proposed branch: | lp:~maas-maintainers/maas/maas-ha |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
2841 lines (+582/-382) 37 files modified
src/maasserver/api/interfaces.py (+8/-7) src/maasserver/api/nodes.py (+0/-6) src/maasserver/api/tests/test_devices.py (+45/-45) src/maasserver/api/tests/test_events.py (+5/-2) src/maasserver/api/tests/test_interfaces.py (+20/-17) src/maasserver/api/tests/test_node.py (+11/-10) src/maasserver/api/tests/test_nodes.py (+7/-12) src/maasserver/enum.py (+15/-0) src/maasserver/fixtures/dev_fixture.yaml (+11/-11) src/maasserver/forms.py (+2/-1) src/maasserver/migrations/builtin/maasserver/0003_add_node_type_to_node.py (+22/-0) src/maasserver/migrations/builtin/maasserver/0004_migrate_installable_to_node_type.py (+29/-0) src/maasserver/migrations/builtin/maasserver/0005_delete_installable_from_node.py (+21/-0) src/maasserver/models/__init__.py (+5/-2) src/maasserver/models/interface.py (+4/-3) src/maasserver/models/node.py (+30/-16) src/maasserver/models/signals/power.py (+0/-5) src/maasserver/models/staticipaddress.py (+1/-1) src/maasserver/models/tests/test_node.py (+58/-21) src/maasserver/models/tests/test_staticipaddress.py (+1/-1) src/maasserver/models/tests/test_zone.py (+37/-12) src/maasserver/models/zone.py (+10/-4) src/maasserver/node_action.py (+28/-27) src/maasserver/rpc/nodes.py (+0/-2) src/maasserver/rpc/tests/test_nodes.py (+4/-4) src/maasserver/static/partials/subnet-details.html (+9/-2) src/maasserver/testing/factory.py (+19/-10) src/maasserver/tests/test_auth.py (+4/-4) src/maasserver/tests/test_listener.py (+23/-22) src/maasserver/tests/test_node_action.py (+13/-12) src/maasserver/triggers.py (+115/-103) src/maasserver/websockets/handlers/device.py (+3/-2) src/maasserver/websockets/handlers/general.py (+4/-4) src/maasserver/websockets/handlers/node.py (+5/-5) src/maasserver/websockets/handlers/tests/test_device.py (+4/-2) src/maasserver/websockets/handlers/tests/test_general.py (+3/-3) src/maasserver/websockets/handlers/tests/test_node.py (+6/-4) |
To merge this branch: | bzr merge lp:~maas-maintainers/maas/maas-ha |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Review via email: mp+280969@code.launchpad.net |
Commit message
Merge the HA integration branch.
Description of the change
Now that 1.10 has been split this can be merged into trunk.
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~maas-maintainers/maas/maas-ha into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Get:2 http://
Hit:3 http://
Hit:4 http://
Hit:5 http://
Get:6 http://
Get:7 http://
Get:8 http://
Get:9 http://
Get:10 http://
Fetched 22.2 MB in 9s (2,321 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
The following packages were automatically installed and are no longer required:
libc-ares-dev libc-ares2 libisl13 libv8-3.14-dev libv8-3.14.5
linux-
linux-
linux-
Use 'sudo apt autoremove' to remove them.
The following packages will be upgraded:
libgtk2.0-0 libgtk2.0-common
2 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,896 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://
Get:2 http://
Fetched 1,896 kB in 0s (8,660 kB/s)
(Reading database ...
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 186568 files and directories currently installed.)
Preparing to unpack .../libgtk2.
Unpacking libgtk2.0-common (2.24.29-1ubuntu1) over (2.24.28-1ubuntu1) ...
Preparing to unpack .../libgtk2.
Unpacking libgtk2.0-0:amd64 (2.24.29-1ubuntu1) over (2.24.28-1ubuntu1) ...
Processing triggers for libc-bin (2.21-0ubuntu5) ...
Setting up libgtk2.0-common (2.24.29-1ubuntu1) ...
Setting up libgtk2.0-0:amd64 (2.24.29-1ubuntu1) ...
Processing triggers for libc-bin (2.21-0ubuntu...
Preview Diff
1 | === modified file 'src/maasserver/api/interfaces.py' |
2 | --- src/maasserver/api/interfaces.py 2015-12-07 16:37:36 +0000 |
3 | +++ src/maasserver/api/interfaces.py 2015-12-18 15:12:10 +0000 |
4 | @@ -13,6 +13,7 @@ |
5 | INTERFACE_TYPE, |
6 | NODE_PERMISSION, |
7 | NODE_STATUS, |
8 | + NODE_TYPE, |
9 | ) |
10 | from maasserver.exceptions import ( |
11 | MAASAPIValidationError, |
12 | @@ -106,8 +107,8 @@ |
13 | """ |
14 | node = Node.objects.get_node_or_404( |
15 | system_id, request.user, NODE_PERMISSION.EDIT) |
16 | - # Installable nodes require the node needs to be in the correct state. |
17 | - if node.installable: |
18 | + # machine type nodes require the node needs to be in the correct state. |
19 | + if node.node_type == NODE_TYPE.MACHINE: |
20 | raise_error_for_invalid_state_on_allocated_operations( |
21 | node, request.user, "create") |
22 | form = PhysicalInterfaceForm(node=node, data=request.data) |
23 | @@ -371,7 +372,7 @@ |
24 | """ |
25 | interface = Interface.objects.get_interface_or_404( |
26 | system_id, interface_id, request.user, NODE_PERMISSION.EDIT) |
27 | - if interface.get_node().installable: |
28 | + if interface.get_node().node_type == NODE_TYPE.MACHINE: |
29 | # This node needs to be in the correct state to modify |
30 | # the interface. |
31 | raise_error_for_invalid_state_on_allocated_operations( |
32 | @@ -401,7 +402,7 @@ |
33 | """ |
34 | interface = Interface.objects.get_interface_or_404( |
35 | system_id, interface_id, request.user, NODE_PERMISSION.EDIT) |
36 | - if interface.get_node().installable: |
37 | + if interface.get_node().node_type == NODE_TYPE.MACHINE: |
38 | # This node needs to be in the correct state to modify |
39 | # the interface. |
40 | raise_error_for_invalid_state_on_allocated_operations( |
41 | @@ -443,7 +444,7 @@ |
42 | interface = Interface.objects.get_interface_or_404( |
43 | system_id, interface_id, request.user, NODE_PERMISSION.EDIT) |
44 | node = interface.get_node() |
45 | - if node.installable: |
46 | + if node.node_type == NODE_TYPE.MACHINE: |
47 | # This node needs to be in the correct state to modify |
48 | # the interface. |
49 | raise_error_for_invalid_state_on_allocated_operations( |
50 | @@ -474,7 +475,7 @@ |
51 | """ |
52 | interface = Interface.objects.get_interface_or_404( |
53 | system_id, interface_id, request.user, NODE_PERMISSION.EDIT) |
54 | - if interface.get_node().installable: |
55 | + if interface.get_node().node_type == NODE_TYPE.MACHINE: |
56 | # This node needs to be in the correct state to modify |
57 | # the interface. |
58 | raise_error_for_invalid_state_on_allocated_operations( |
59 | @@ -501,7 +502,7 @@ |
60 | """ |
61 | interface = Interface.objects.get_interface_or_404( |
62 | system_id, interface_id, request.user, NODE_PERMISSION.EDIT) |
63 | - if interface.get_node().installable: |
64 | + if interface.get_node().node_type == NODE_TYPE.MACHINE: |
65 | # This node needs to be in the correct state to modify |
66 | # the interface. |
67 | raise_error_for_invalid_state_on_allocated_operations( |
68 | |
69 | === modified file 'src/maasserver/api/nodes.py' |
70 | --- src/maasserver/api/nodes.py 2015-12-05 17:02:05 +0000 |
71 | +++ src/maasserver/api/nodes.py 2015-12-18 15:12:10 +0000 |
72 | @@ -761,7 +761,6 @@ |
73 | :return: a dict whose key is "state" with a value of one of |
74 | 'on' or 'off'. |
75 | |
76 | - Returns 400 if the node is not installable. |
77 | Returns 404 if the node is not found. |
78 | Returns 503 (with explanatory text) if the power state could not |
79 | be queried. |
80 | @@ -776,11 +775,6 @@ |
81 | addTask = eventloop.services.getServiceNamed("database-tasks").addTask |
82 | |
83 | node = get_object_or_404(Node, system_id=system_id) |
84 | - if not node.installable: |
85 | - raise MAASAPIBadRequest( |
86 | - "%s: Unable to query power state; not an installable node" % |
87 | - node.hostname) |
88 | - |
89 | ng = node.nodegroup |
90 | |
91 | try: |
92 | |
93 | === modified file 'src/maasserver/api/tests/test_devices.py' |
94 | --- src/maasserver/api/tests/test_devices.py 2015-12-09 02:02:23 +0000 |
95 | +++ src/maasserver/api/tests/test_devices.py 2015-12-18 15:12:10 +0000 |
96 | @@ -14,6 +14,7 @@ |
97 | INTERFACE_TYPE, |
98 | IPADDRESS_TYPE, |
99 | NODE_STATUS, |
100 | + NODE_TYPE, |
101 | NODEGROUP_STATUS, |
102 | NODEGROUPINTERFACE_MANAGEMENT, |
103 | ) |
104 | @@ -64,10 +65,10 @@ |
105 | device = Node.devices.get(system_id=system_id) |
106 | self.assertEqual(hostname, device.hostname) |
107 | self.assertIsNone(device.parent) |
108 | - self.assertFalse(device.installable) |
109 | - self.assertEqual(NodeGroup.objects.ensure_master(), device.nodegroup) |
110 | - self.assertEqual(self.logged_in_user, device.owner) |
111 | - self.assertEqual( |
112 | + self.assertEquals(device.node_type, NODE_TYPE.DEVICE) |
113 | + self.assertEquals(NodeGroup.objects.ensure_master(), device.nodegroup) |
114 | + self.assertEquals(self.logged_in_user, device.owner) |
115 | + self.assertEquals( |
116 | macs, |
117 | {nic.mac_address for nic in device.interface_set.all()}) |
118 | |
119 | @@ -90,9 +91,9 @@ |
120 | http.client.OK, response.status_code, response.content) |
121 | system_id = json_load_bytes(response.content)['system_id'] |
122 | device = Node.devices.get(system_id=system_id) |
123 | - self.assertEqual(hostname, device.hostname) |
124 | - self.assertEqual(parent, device.parent) |
125 | - self.assertFalse(device.installable) |
126 | + self.assertEquals(hostname, device.hostname) |
127 | + self.assertEquals(parent, device.parent) |
128 | + self.assertEqual(device.node_type, NODE_TYPE.DEVICE) |
129 | |
130 | def test_POST_returns_limited_fields(self): |
131 | response = self.client.post( |
132 | @@ -120,8 +121,8 @@ |
133 | def create_devices(self, owner, nodegroup=None, nb=3): |
134 | return [ |
135 | factory.make_Node( |
136 | - nodegroup=nodegroup, interface=True, installable=False, |
137 | - owner=owner) |
138 | + nodegroup=nodegroup, interface=True, |
139 | + node_type=NODE_TYPE.DEVICE, owner=owner) |
140 | for _ in range(nb) |
141 | ] |
142 | |
143 | @@ -213,7 +214,7 @@ |
144 | |
145 | def test_POST_method_doesnt_exist(self): |
146 | device = factory.make_Node( |
147 | - installable=False, owner=self.logged_in_user) |
148 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
149 | |
150 | response = self.client.post(get_device_uri(device)) |
151 | self.assertEqual( |
152 | @@ -221,7 +222,7 @@ |
153 | |
154 | def test_GET_reads_device(self): |
155 | device = factory.make_Node( |
156 | - installable=False, owner=self.logged_in_user) |
157 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
158 | |
159 | response = self.client.get(get_device_uri(device)) |
160 | self.assertEqual( |
161 | @@ -231,7 +232,7 @@ |
162 | |
163 | def test_PUT_updates_device_hostname(self): |
164 | device = factory.make_Node( |
165 | - installable=False, owner=self.logged_in_user) |
166 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
167 | new_hostname = factory.make_name('hostname') |
168 | |
169 | response = self.client.put( |
170 | @@ -245,7 +246,8 @@ |
171 | def test_PUT_updates_device_parent(self): |
172 | parent = factory.make_Node() |
173 | device = factory.make_Node( |
174 | - installable=False, owner=self.logged_in_user, parent=parent) |
175 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user, |
176 | + parent=parent) |
177 | new_parent = factory.make_Node() |
178 | |
179 | response = self.client.put( |
180 | @@ -258,7 +260,7 @@ |
181 | |
182 | def test_PUT_rejects_edit_if_not_permitted(self): |
183 | device = factory.make_Node( |
184 | - installable=False, owner=factory.make_User()) |
185 | + node_type=NODE_TYPE.DEVICE, owner=factory.make_User()) |
186 | old_hostname = device.hostname |
187 | |
188 | response = self.client.put( |
189 | @@ -269,7 +271,7 @@ |
190 | |
191 | def test_DELETE_removes_device(self): |
192 | device = factory.make_Node( |
193 | - installable=False, owner=self.logged_in_user) |
194 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
195 | response = self.client.delete(get_device_uri(device)) |
196 | self.assertEqual( |
197 | http.client.NO_CONTENT, response.status_code, response.content) |
198 | @@ -277,7 +279,7 @@ |
199 | |
200 | def test_DELETE_rejects_deletion_if_not_permitted(self): |
201 | device = factory.make_Node( |
202 | - installable=False, owner=factory.make_User()) |
203 | + node_type=NODE_TYPE.DEVICE, owner=factory.make_User()) |
204 | response = self.client.delete(get_device_uri(device)) |
205 | self.assertEqual(http.client.FORBIDDEN, response.status_code) |
206 | self.assertEqual(device, reload_object(device)) |
207 | @@ -292,9 +294,9 @@ |
208 | ng, management=NODEGROUPINTERFACE_MANAGEMENT.DHCP_AND_DNS) |
209 | parent = factory.make_Node_with_Interface_on_Subnet( |
210 | nodegroup=ng, subnet=ngi.subnet) |
211 | - device = factory.make_Node( |
212 | - installable=False, parent=parent, interface=True, |
213 | - disable_ipv4=False, owner=self.logged_in_user) |
214 | + device = factory.make_Device( |
215 | + parent=parent, interface=True, disable_ipv4=False, |
216 | + owner=self.logged_in_user) |
217 | # Silence 'update_host_maps'. |
218 | self.patch_autospec(interface_module, "update_host_maps") |
219 | response = self.client.post( |
220 | @@ -313,9 +315,9 @@ |
221 | ng, management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED) |
222 | parent = factory.make_Node_with_Interface_on_Subnet( |
223 | nodegroup=ng, subnet=ngi.subnet) |
224 | - device = factory.make_Node( |
225 | - installable=False, parent=parent, interface=True, |
226 | - disable_ipv4=False, owner=self.logged_in_user) |
227 | + device = factory.make_Device( |
228 | + parent=parent, interface=True, disable_ipv4=False, |
229 | + owner=self.logged_in_user) |
230 | # Silence 'update_host_maps'. |
231 | self.patch_autospec(interface_module, "update_host_maps") |
232 | response = self.client.post( |
233 | @@ -337,9 +339,9 @@ |
234 | ngi.save() |
235 | parent = factory.make_Node_with_Interface_on_Subnet( |
236 | nodegroup=ng, subnet=subnet, unmanaged=True) |
237 | - device = factory.make_Node( |
238 | - installable=False, parent=parent, interface=True, |
239 | - disable_ipv4=False, owner=self.logged_in_user) |
240 | + device = factory.make_Device( |
241 | + parent=parent, interface=True, disable_ipv4=False, |
242 | + owner=self.logged_in_user) |
243 | # Silence 'update_host_maps'. |
244 | self.patch_autospec(interface_module, "update_host_maps") |
245 | response = self.client.post( |
246 | @@ -384,7 +386,7 @@ |
247 | def test__claims_ip_address_from_cluster_interface(self): |
248 | parent = factory.make_Node_with_Interface_on_Subnet() |
249 | device = factory.make_Node( |
250 | - installable=False, parent=parent, interface=True, |
251 | + node_type=NODE_TYPE.DEVICE, parent=parent, interface=True, |
252 | disable_ipv4=False, owner=self.logged_in_user) |
253 | # Silence 'update_host_maps'. |
254 | self.patch_autospec(interface_module, "update_host_maps") |
255 | @@ -401,7 +403,7 @@ |
256 | def test__rejected_if_not_permitted(self): |
257 | parent = factory.make_Node_with_Interface_on_Subnet() |
258 | device = factory.make_Node( |
259 | - installable=False, parent=parent, interface=True, |
260 | + node_type=NODE_TYPE.DEVICE, parent=parent, interface=True, |
261 | disable_ipv4=False, owner=factory.make_User()) |
262 | self.patch_autospec(interface_module, "update_host_maps") |
263 | response = self.client.post( |
264 | @@ -411,7 +413,7 @@ |
265 | def test_creates_ip_with_random_ip(self): |
266 | requested_address = factory.make_ip_address() |
267 | device = factory.make_Node( |
268 | - installable=False, interface=True, disable_ipv4=False, |
269 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
270 | owner=self.logged_in_user) |
271 | # Silence 'update_host_maps'. |
272 | self.patch_autospec(interface_module, "update_host_maps") |
273 | @@ -432,9 +434,8 @@ |
274 | ) |
275 | |
276 | def test_503_if_no_subnet_found(self): |
277 | - device = factory.make_Node( |
278 | - installable=False, interface=True, disable_ipv4=False, |
279 | - owner=self.logged_in_user) |
280 | + device = factory.make_Device( |
281 | + interface=True, disable_ipv4=False, owner=self.logged_in_user) |
282 | # Silence 'update_host_maps'. |
283 | self.patch_autospec(interface_module, "update_host_maps") |
284 | response = self.client.post( |
285 | @@ -450,9 +451,8 @@ |
286 | def test_503_if_no_ip_found(self, claim_static_ips): |
287 | claim_static_ips.side_effect = [list()] |
288 | |
289 | - device = factory.make_Node( |
290 | - installable=False, interface=True, disable_ipv4=False, |
291 | - owner=self.logged_in_user) |
292 | + device = factory.make_Device( |
293 | + interface=True, disable_ipv4=False, owner=self.logged_in_user) |
294 | # Silence 'update_host_maps'. |
295 | self.patch_autospec(interface_module, "update_host_maps") |
296 | response = self.client.post( |
297 | @@ -467,7 +467,7 @@ |
298 | def test_creates_ip_for_specific_mac(self): |
299 | requested_address = factory.make_ip_address() |
300 | device = factory.make_Node( |
301 | - installable=False, interface=True, disable_ipv4=False, |
302 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
303 | owner=self.logged_in_user) |
304 | second_nic = factory.make_Interface( |
305 | INTERFACE_TYPE.PHYSICAL, node=device) |
306 | @@ -493,7 +493,7 @@ |
307 | def test_rejects_invalid_ip(self): |
308 | requested_address = factory.make_name('bogus') |
309 | device = factory.make_Node( |
310 | - installable=False, interface=True, disable_ipv4=False, |
311 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
312 | owner=self.logged_in_user) |
313 | interface = device.interface_set.all()[0] |
314 | response = self.client.post( |
315 | @@ -512,7 +512,7 @@ |
316 | mac_address = factory.make_name('bogus') |
317 | requested_address = factory.make_ip_address() |
318 | device = factory.make_Node( |
319 | - installable=False, interface=True, disable_ipv4=False, |
320 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
321 | owner=self.logged_in_user) |
322 | response = self.client.post( |
323 | get_device_uri(device), |
324 | @@ -531,13 +531,13 @@ |
325 | def test_rejects_unrelated_mac(self): |
326 | # Create an other device. |
327 | other_device = factory.make_Node( |
328 | - installable=False, interface=True, disable_ipv4=False, |
329 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
330 | owner=factory.make_User()) |
331 | other_nic = other_device.interface_set.all()[0] |
332 | |
333 | requested_address = factory.make_ip_address() |
334 | device = factory.make_Node( |
335 | - installable=False, interface=True, disable_ipv4=False, |
336 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
337 | owner=self.logged_in_user) |
338 | # Silence 'update_host_maps'. |
339 | self.patch_autospec(interface_module, "update_host_maps") |
340 | @@ -558,7 +558,7 @@ |
341 | def test__releases_ip_address(self): |
342 | parent = factory.make_Node_with_Interface_on_Subnet() |
343 | device = factory.make_Node( |
344 | - installable=False, parent=parent, interface=True, |
345 | + node_type=NODE_TYPE.DEVICE, parent=parent, interface=True, |
346 | disable_ipv4=False, owner=self.logged_in_user) |
347 | # Silence 'update_host_maps' and 'remove_host_maps' |
348 | self.patch_autospec(interface_module, "update_host_maps") |
349 | @@ -579,7 +579,7 @@ |
350 | |
351 | def test__rejects_invalid_ip(self): |
352 | device = factory.make_Node( |
353 | - installable=False, interface=True, disable_ipv4=False, |
354 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
355 | owner=self.logged_in_user) |
356 | response = self.client.post( |
357 | get_device_uri(device), |
358 | @@ -595,7 +595,7 @@ |
359 | |
360 | def test__rejects_empty_ip(self): |
361 | device = factory.make_Node( |
362 | - installable=False, interface=True, disable_ipv4=False, |
363 | + node_type=NODE_TYPE.DEVICE, interface=True, disable_ipv4=False, |
364 | owner=self.logged_in_user) |
365 | response = self.client.post( |
366 | get_device_uri(device), |
367 | @@ -616,7 +616,7 @@ |
368 | network = factory._make_random_network(slash=24) |
369 | subnet = factory.make_Subnet(cidr=str(network.cidr)) |
370 | device = factory.make_Node_with_Interface_on_Subnet( |
371 | - installable=False, subnet=subnet, |
372 | + node_type=NODE_TYPE.DEVICE, subnet=subnet, |
373 | disable_ipv4=False, owner=self.logged_in_user) |
374 | for _ in range(4): |
375 | extra_nic = factory.make_Interface( |
376 | @@ -643,7 +643,7 @@ |
377 | network = factory._make_random_network(slash=24) |
378 | subnet = factory.make_Subnet(cidr=str(network.cidr)) |
379 | device = factory.make_Node_with_Interface_on_Subnet( |
380 | - installable=False, subnet=subnet, |
381 | + node_type=NODE_TYPE.DEVICE, subnet=subnet, |
382 | disable_ipv4=False, owner=self.logged_in_user) |
383 | extra_nic = factory.make_Interface( |
384 | INTERFACE_TYPE.PHYSICAL, node=device) |
385 | @@ -675,7 +675,7 @@ |
386 | def test__rejected_if_not_permitted(self): |
387 | parent = factory.make_Node_with_Interface_on_Subnet() |
388 | device = factory.make_Node( |
389 | - installable=False, parent=parent, interface=True, |
390 | + node_type=NODE_TYPE.DEVICE, parent=parent, interface=True, |
391 | disable_ipv4=False, owner=factory.make_User()) |
392 | # Silence 'update_host_maps' and 'remove_host_maps' |
393 | self.patch_autospec(interface_module, "update_host_maps") |
394 | |
395 | === modified file 'src/maasserver/api/tests/test_events.py' |
396 | --- src/maasserver/api/tests/test_events.py 2015-12-04 08:25:27 +0000 |
397 | +++ src/maasserver/api/tests/test_events.py 2015-12-18 15:12:10 +0000 |
398 | @@ -19,7 +19,10 @@ |
399 | from django.core.urlresolvers import reverse |
400 | from maasserver.api import events as events_module |
401 | from maasserver.api.tests.test_nodes import RequestFixture |
402 | -from maasserver.enum import INTERFACE_TYPE |
403 | +from maasserver.enum import ( |
404 | + INTERFACE_TYPE, |
405 | + NODE_TYPE, |
406 | +) |
407 | from maasserver.models.eventtype import LOGGING_LEVELS |
408 | from maasserver.testing.api import APITestCase |
409 | from maasserver.testing.factory import factory |
410 | @@ -311,7 +314,7 @@ |
411 | |
412 | # Create devices. |
413 | device_nodes = [ |
414 | - factory.make_Node(installable=False) |
415 | + factory.make_Node(node_type=NODE_TYPE.DEVICE) |
416 | for _ in range(3)] |
417 | [factory.make_Event(node=node) for node in device_nodes] |
418 | |
419 | |
420 | === modified file 'src/maasserver/api/tests/test_interfaces.py' |
421 | --- src/maasserver/api/tests/test_interfaces.py 2015-12-07 16:37:36 +0000 |
422 | +++ src/maasserver/api/tests/test_interfaces.py 2015-12-18 15:12:10 +0000 |
423 | @@ -14,6 +14,7 @@ |
424 | INTERFACE_TYPE, |
425 | IPADDRESS_TYPE, |
426 | NODE_STATUS, |
427 | + NODE_TYPE, |
428 | ) |
429 | from maasserver.models import Interface |
430 | from maasserver.testing.api import APITestCase |
431 | @@ -93,8 +94,8 @@ |
432 | |
433 | def test_read_on_device(self): |
434 | parent = factory.make_Node() |
435 | - device = factory.make_Node( |
436 | - owner=self.logged_in_user, installable=False, parent=parent) |
437 | + device = factory.make_Device( |
438 | + owner=self.logged_in_user, parent=parent) |
439 | interface = factory.make_Interface( |
440 | INTERFACE_TYPE.PHYSICAL, node=device) |
441 | uri = get_interfaces_uri(device) |
442 | @@ -140,8 +141,8 @@ |
443 | |
444 | def test_create_physical_on_device(self): |
445 | parent = factory.make_Node() |
446 | - device = factory.make_Node( |
447 | - owner=self.logged_in_user, installable=False, parent=parent) |
448 | + device = factory.make_Device( |
449 | + owner=self.logged_in_user, parent=parent) |
450 | mac = factory.make_mac_address() |
451 | name = factory.make_name("eth") |
452 | vlan = factory.make_VLAN() |
453 | @@ -333,7 +334,8 @@ |
454 | def test_create_bond_404_on_device(self): |
455 | parent = factory.make_Node() |
456 | device = factory.make_Node( |
457 | - owner=self.logged_in_user, installable=False, parent=parent) |
458 | + owner=self.logged_in_user, parent=parent, |
459 | + node_type=NODE_TYPE.DEVICE) |
460 | uri = get_interfaces_uri(device) |
461 | response = self.client.post(uri, { |
462 | "op": "create_bond", |
463 | @@ -448,7 +450,8 @@ |
464 | def test_create_vlan_404_on_device(self): |
465 | parent = factory.make_Node() |
466 | device = factory.make_Node( |
467 | - owner=self.logged_in_user, installable=False, parent=parent) |
468 | + owner=self.logged_in_user, parent=parent, |
469 | + node_type=NODE_TYPE.DEVICE) |
470 | uri = get_interfaces_uri(device) |
471 | response = self.client.post(uri, { |
472 | "op": "create_vlan", |
473 | @@ -606,7 +609,7 @@ |
474 | |
475 | def test_read_device_interface(self): |
476 | parent = factory.make_Node() |
477 | - device = factory.make_Node(installable=False, parent=parent) |
478 | + device = factory.make_Device(parent=parent) |
479 | interface = factory.make_Interface( |
480 | INTERFACE_TYPE.PHYSICAL, node=device) |
481 | uri = get_interface_uri(interface) |
482 | @@ -646,8 +649,8 @@ |
483 | |
484 | def test_update_device_physical_interface(self): |
485 | node = factory.make_Node() |
486 | - device = factory.make_Node( |
487 | - owner=self.logged_in_user, installable=False, parent=node) |
488 | + device = factory.make_Device( |
489 | + owner=self.logged_in_user, parent=node) |
490 | interface = factory.make_Interface( |
491 | INTERFACE_TYPE.PHYSICAL, node=device) |
492 | new_name = factory.make_name("name") |
493 | @@ -749,8 +752,8 @@ |
494 | |
495 | def test_delete_deletes_device_interface(self): |
496 | parent = factory.make_Node() |
497 | - device = factory.make_Node( |
498 | - owner=self.logged_in_user, installable=False, parent=parent) |
499 | + device = factory.make_Device( |
500 | + owner=self.logged_in_user, parent=parent) |
501 | interface = factory.make_Interface( |
502 | INTERFACE_TYPE.PHYSICAL, node=device) |
503 | uri = get_interface_uri(interface) |
504 | @@ -826,8 +829,8 @@ |
505 | |
506 | def test_link_subnet_creates_link_on_device(self): |
507 | parent = factory.make_Node() |
508 | - device = factory.make_Node( |
509 | - owner=self.logged_in_user, installable=False, parent=parent) |
510 | + device = factory.make_Device( |
511 | + owner=self.logged_in_user, parent=parent) |
512 | interface = factory.make_Interface( |
513 | INTERFACE_TYPE.PHYSICAL, node=device) |
514 | subnet = factory.make_Subnet(vlan=interface.vlan) |
515 | @@ -847,8 +850,8 @@ |
516 | |
517 | def test_link_subnet_on_device_only_allows_static(self): |
518 | parent = factory.make_Node() |
519 | - device = factory.make_Node( |
520 | - owner=self.logged_in_user, installable=False, parent=parent) |
521 | + device = factory.make_Device( |
522 | + owner=self.logged_in_user, parent=parent) |
523 | interface = factory.make_Interface( |
524 | INTERFACE_TYPE.PHYSICAL, node=device) |
525 | for link_type in [ |
526 | @@ -941,8 +944,8 @@ |
527 | |
528 | def test_unlink_subnet_deletes_link_on_device(self): |
529 | parent = factory.make_Node() |
530 | - device = factory.make_Node( |
531 | - owner=self.logged_in_user, installable=False, parent=parent) |
532 | + device = factory.make_Device( |
533 | + owner=self.logged_in_user, parent=parent) |
534 | interface = factory.make_Interface( |
535 | INTERFACE_TYPE.PHYSICAL, node=device) |
536 | subnet = factory.make_Subnet() |
537 | |
538 | === modified file 'src/maasserver/api/tests/test_node.py' |
539 | --- src/maasserver/api/tests/test_node.py 2015-12-04 11:46:07 +0000 |
540 | +++ src/maasserver/api/tests/test_node.py 2015-12-18 15:12:10 +0000 |
541 | @@ -23,6 +23,7 @@ |
542 | NODE_STATUS, |
543 | NODE_STATUS_CHOICES, |
544 | NODE_STATUS_CHOICES_DICT, |
545 | + NODE_TYPE, |
546 | POWER_STATE, |
547 | ) |
548 | from maasserver.fields import ( |
549 | @@ -299,7 +300,7 @@ |
550 | |
551 | def test_GET_rejects_device(self): |
552 | node = factory.make_Node( |
553 | - installable=False, owner=self.logged_in_user) |
554 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
555 | response = self.client.get(self.get_node_uri(node)) |
556 | self.assertEqual( |
557 | http.client.NOT_FOUND, response.status_code, response.content) |
558 | @@ -352,7 +353,7 @@ |
559 | |
560 | def test_POST_stop_rejects_device(self): |
561 | node = factory.make_Node( |
562 | - installable=False, owner=self.logged_in_user) |
563 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
564 | response = self.client.post(self.get_node_uri(node), {'op': 'stop'}) |
565 | self.assertEqual( |
566 | http.client.NOT_FOUND, response.status_code, response.content) |
567 | @@ -455,7 +456,7 @@ |
568 | |
569 | def test_POST_start_rejects_device(self): |
570 | node = factory.make_Node( |
571 | - installable=False, owner=self.logged_in_user) |
572 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
573 | response = self.client.post(self.get_node_uri(node), {'op': 'start'}) |
574 | self.assertEqual( |
575 | http.client.NOT_FOUND, response.status_code, response.content) |
576 | @@ -724,7 +725,7 @@ |
577 | |
578 | def test_POST_release_rejects_device(self): |
579 | node = factory.make_Node( |
580 | - installable=False, owner=self.logged_in_user) |
581 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
582 | response = self.client.post(self.get_node_uri(node), {'op': 'release'}) |
583 | self.assertEqual( |
584 | http.client.NOT_FOUND, response.status_code, response.content) |
585 | @@ -931,7 +932,7 @@ |
586 | def test_PUT_rejects_device(self): |
587 | self.become_admin() |
588 | node = factory.make_Node( |
589 | - installable=False, owner=self.logged_in_user) |
590 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
591 | response = self.client.put(self.get_node_uri(node)) |
592 | self.assertEqual( |
593 | http.client.NOT_FOUND, response.status_code, response.content) |
594 | @@ -1389,7 +1390,7 @@ |
595 | |
596 | def test_DELETE_rejects_device(self): |
597 | node = factory.make_Node( |
598 | - installable=False, owner=self.logged_in_user) |
599 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
600 | response = self.client.delete(self.get_node_uri(node)) |
601 | self.assertEqual( |
602 | http.client.NOT_FOUND, response.status_code, response.content) |
603 | @@ -1717,8 +1718,8 @@ |
604 | network = factory._make_random_network(slash=24) |
605 | subnet = factory.make_Subnet(cidr=str(network.cidr)) |
606 | node = factory.make_Node_with_Interface_on_Subnet( |
607 | - status=NODE_STATUS.ALLOCATED, installable=True, subnet=subnet, |
608 | - disable_ipv4=False, owner=self.logged_in_user) |
609 | + status=NODE_STATUS.ALLOCATED, node_type=NODE_TYPE.MACHINE, |
610 | + subnet=subnet, disable_ipv4=False, owner=self.logged_in_user) |
611 | boot_interface = node.get_boot_interface() |
612 | # Silence 'update_host_maps' and 'remove_host_maps' |
613 | self.patch(interface_module, "update_host_maps") |
614 | @@ -1739,8 +1740,8 @@ |
615 | network = factory._make_random_network(slash=24) |
616 | subnet = factory.make_Subnet(cidr=str(network.cidr)) |
617 | node = factory.make_Node_with_Interface_on_Subnet( |
618 | - status=NODE_STATUS.ALLOCATED, installable=True, subnet=subnet, |
619 | - disable_ipv4=False, owner=self.logged_in_user) |
620 | + status=NODE_STATUS.ALLOCATED, node_type=NODE_TYPE.MACHINE, |
621 | + subnet=subnet, disable_ipv4=False, owner=self.logged_in_user) |
622 | boot_interface = node.get_boot_interface() |
623 | # Silence 'update_host_maps' and 'remove_host_maps' |
624 | self.patch(interface_module, "update_host_maps") |
625 | |
626 | === modified file 'src/maasserver/api/tests/test_nodes.py' |
627 | --- src/maasserver/api/tests/test_nodes.py 2015-12-04 08:25:27 +0000 |
628 | +++ src/maasserver/api/tests/test_nodes.py 2015-12-18 15:12:10 +0000 |
629 | @@ -24,6 +24,7 @@ |
630 | INTERFACE_TYPE, |
631 | NODE_STATUS, |
632 | NODE_STATUS_CHOICES_DICT, |
633 | + NODE_TYPE, |
634 | NODEGROUP_STATUS, |
635 | NODEGROUPINTERFACE_MANAGEMENT, |
636 | POWER_STATE, |
637 | @@ -329,7 +330,7 @@ |
638 | for _ in range(3)] |
639 | # Create devices. |
640 | nodes = [ |
641 | - factory.make_Node(installable=False) |
642 | + factory.make_Node(node_type=NODE_TYPE.DEVICE) |
643 | for _ in range(3)] |
644 | |
645 | query = RequestFixture({}, '') |
646 | @@ -690,7 +691,7 @@ |
647 | for _ in range(3)] |
648 | # Create devices. |
649 | nodes = [ |
650 | - factory.make_Node(installable=False) |
651 | + factory.make_Node(node_type=NODE_TYPE.DEVICE) |
652 | for _ in range(3)] |
653 | response = self.client.get(reverse('nodes_handler'), {'op': 'list'}) |
654 | self.assertEqual(http.client.OK, response.status_code) |
655 | @@ -1548,7 +1549,7 @@ |
656 | |
657 | def test_POST_accept_fails_for_device(self): |
658 | self.become_admin() |
659 | - factory.make_Node(installable=False) |
660 | + factory.make_Node(node_type=NODE_TYPE.DEVICE) |
661 | node_id = factory.make_string() |
662 | response = self.client.post( |
663 | reverse('nodes_handler'), {'op': 'accept', 'nodes': [node_id]}) |
664 | @@ -1610,7 +1611,7 @@ |
665 | |
666 | def test_POST_release_ignores_devices(self): |
667 | node_ids = { |
668 | - factory.make_Node(installable=False).system_id |
669 | + factory.make_Node(node_type=NODE_TYPE.DEVICE).system_id |
670 | for _ in range(3) |
671 | } |
672 | response = self.client.post( |
673 | @@ -1922,7 +1923,7 @@ |
674 | |
675 | def test_GET_rejects_devices(self): |
676 | owned_node = factory.make_Node( |
677 | - installable=False, owner=self.logged_in_user) |
678 | + node_type=NODE_TYPE.DEVICE, owner=self.logged_in_user) |
679 | response = self.client.get( |
680 | self.endpoint, |
681 | {'op': 'deployment_status', 'nodes': [owned_node.system_id]}) |
682 | @@ -2094,7 +2095,7 @@ |
683 | def test__catches_no_connection_error(self): |
684 | getClientFor = self.patch(nodes_module, 'getClientFor') |
685 | getClientFor.side_effect = NoConnectionsAvailable() |
686 | - node = factory.make_Node(power_state=POWER_STATE.ON) |
687 | + node = factory.make_Node(power_state=POWER_STATE.ON, power_type=None) |
688 | |
689 | response = self.client.get( |
690 | self.get_node_uri(node), {"op": "query_power_state"}) |
691 | @@ -2167,12 +2168,6 @@ |
692 | # The node's power state is now "unknown". |
693 | self.assertPowerState(node, POWER_STATE.UNKNOWN) |
694 | |
695 | - def test__returns_400_if_device(self): |
696 | - device = factory.make_Device() |
697 | - response = self.client.get( |
698 | - self.get_node_uri(device), {"op": "query_power_state"}) |
699 | - self.assertResponseCode(http.client.BAD_REQUEST, response) |
700 | - |
701 | def test__returns_actual_state(self): |
702 | node = factory.make_Node(power_type="ipmi") |
703 | random_state = random.choice(["on", "off", "error"]) |
704 | |
705 | === modified file 'src/maasserver/enum.py' |
706 | --- src/maasserver/enum.py 2015-12-01 18:12:59 +0000 |
707 | +++ src/maasserver/enum.py 2015-12-18 15:12:10 +0000 |
708 | @@ -127,6 +127,21 @@ |
709 | ] |
710 | |
711 | |
712 | +class NODE_TYPE: |
713 | + """ Valid node types.""" |
714 | + DEFAULT = 0 |
715 | + MACHINE = 0 |
716 | + DEVICE = 1 |
717 | + RACK_CONTROLLER = 2 |
718 | + |
719 | + |
720 | +NODE_TYPE_CHOICES = ( |
721 | + (NODE_TYPE.MACHINE, "Machine"), |
722 | + (NODE_TYPE.DEVICE, "Device"), |
723 | + (NODE_TYPE.RACK_CONTROLLER, "Rack controller"), |
724 | +) |
725 | + |
726 | + |
727 | class NODE_PERMISSION: |
728 | """Permissions relating to nodes.""" |
729 | VIEW = 'view_node' |
730 | |
731 | === modified file 'src/maasserver/fixtures/dev_fixture.yaml' |
732 | --- src/maasserver/fixtures/dev_fixture.yaml 2015-12-17 09:32:42 +0000 |
733 | +++ src/maasserver/fixtures/dev_fixture.yaml 2015-12-18 15:12:10 +0000 |
734 | @@ -1248,7 +1248,7 @@ |
735 | gateway_link_ipv6: null |
736 | hostname: mild-chicken |
737 | hwe_kernel: '' |
738 | - installable: true |
739 | + node_type: 0 |
740 | license_key: '' |
741 | memory: 1024 |
742 | min_hwe_kernel: '' |
743 | @@ -1290,7 +1290,7 @@ |
744 | gateway_link_ipv6: null |
745 | hostname: powerless-slip |
746 | hwe_kernel: hwe-t |
747 | - installable: true |
748 | + node_type: 0 |
749 | license_key: '' |
750 | memory: 1024 |
751 | min_hwe_kernel: '' |
752 | @@ -1332,7 +1332,7 @@ |
753 | gateway_link_ipv6: null |
754 | hostname: frightening-visitor |
755 | hwe_kernel: '' |
756 | - installable: true |
757 | + node_type: 0 |
758 | license_key: '' |
759 | memory: 1024 |
760 | min_hwe_kernel: '' |
761 | @@ -1374,7 +1374,7 @@ |
762 | gateway_link_ipv6: null |
763 | hostname: lanky-chickens |
764 | hwe_kernel: '' |
765 | - installable: true |
766 | + node_type: 0 |
767 | license_key: '' |
768 | memory: 1024 |
769 | min_hwe_kernel: '' |
770 | @@ -1416,7 +1416,7 @@ |
771 | gateway_link_ipv6: null |
772 | hostname: squiggly-bomb |
773 | hwe_kernel: '' |
774 | - installable: true |
775 | + node_type: 0 |
776 | license_key: '' |
777 | memory: 1024 |
778 | min_hwe_kernel: '' |
779 | @@ -1458,7 +1458,7 @@ |
780 | gateway_link_ipv6: null |
781 | hostname: definite-worm |
782 | hwe_kernel: hwe-t |
783 | - installable: true |
784 | + node_type: 0 |
785 | license_key: '' |
786 | memory: 1024 |
787 | min_hwe_kernel: '' |
788 | @@ -1500,7 +1500,7 @@ |
789 | gateway_link_ipv6: null |
790 | hostname: variable-brush |
791 | hwe_kernel: '' |
792 | - installable: true |
793 | + node_type: 0 |
794 | license_key: '' |
795 | memory: 1024 |
796 | min_hwe_kernel: '' |
797 | @@ -1542,7 +1542,7 @@ |
798 | gateway_link_ipv6: null |
799 | hostname: urban-railway |
800 | hwe_kernel: '' |
801 | - installable: true |
802 | + node_type: 0 |
803 | license_key: '' |
804 | memory: 1024 |
805 | min_hwe_kernel: '' |
806 | @@ -1584,7 +1584,7 @@ |
807 | gateway_link_ipv6: null |
808 | hostname: test-device |
809 | hwe_kernel: null |
810 | - installable: false |
811 | + node_type: 1 |
812 | license_key: null |
813 | memory: 0 |
814 | min_hwe_kernel: null |
815 | @@ -1626,7 +1626,7 @@ |
816 | gateway_link_ipv6: null |
817 | hostname: test2-device |
818 | hwe_kernel: null |
819 | - installable: false |
820 | + node_type: 1 |
821 | license_key: null |
822 | memory: 0 |
823 | min_hwe_kernel: null |
824 | @@ -1666,7 +1666,7 @@ |
825 | gateway_link_ipv6: null |
826 | hostname: test3-device |
827 | hwe_kernel: null |
828 | - installable: false |
829 | + node_type: 1 |
830 | license_key: null |
831 | memory: 0 |
832 | min_hwe_kernel: null |
833 | |
834 | === modified file 'src/maasserver/forms.py' |
835 | --- src/maasserver/forms.py 2015-12-01 18:12:59 +0000 |
836 | +++ src/maasserver/forms.py 2015-12-18 15:12:10 +0000 |
837 | @@ -86,6 +86,7 @@ |
838 | NODE_BOOT, |
839 | NODE_BOOT_CHOICES, |
840 | NODE_STATUS, |
841 | + NODE_TYPE, |
842 | NODEGROUPINTERFACE_MANAGEMENT, |
843 | NODEGROUPINTERFACE_MANAGEMENT_CHOICES, |
844 | ) |
845 | @@ -775,7 +776,7 @@ |
846 | |
847 | def save(self, commit=True): |
848 | device = super(DeviceForm, self).save(commit=False) |
849 | - device.installable = False |
850 | + device.node_type = NODE_TYPE.DEVICE |
851 | if self.new_device: |
852 | # Set the owner: devices are owned by their creator. |
853 | device.owner = self.request.user |
854 | |
855 | === added file 'src/maasserver/migrations/builtin/maasserver/0003_add_node_type_to_node.py' |
856 | --- src/maasserver/migrations/builtin/maasserver/0003_add_node_type_to_node.py 1970-01-01 00:00:00 +0000 |
857 | +++ src/maasserver/migrations/builtin/maasserver/0003_add_node_type_to_node.py 2015-12-18 15:12:10 +0000 |
858 | @@ -0,0 +1,22 @@ |
859 | +# -*- coding: utf-8 -*- |
860 | +from __future__ import unicode_literals |
861 | + |
862 | +from django.db import ( |
863 | + migrations, |
864 | + models, |
865 | +) |
866 | + |
867 | + |
868 | +class Migration(migrations.Migration): |
869 | + |
870 | + dependencies = [ |
871 | + ('maasserver', '0002_remove_candidate_name_model'), |
872 | + ] |
873 | + |
874 | + operations = [ |
875 | + migrations.AddField( |
876 | + model_name='node', |
877 | + name='node_type', |
878 | + field=models.IntegerField(default=0, editable=False, choices=[(0, 'Machine'), (1, 'Device'), (2, 'Rack controller')]), |
879 | + ), |
880 | + ] |
881 | |
882 | === added file 'src/maasserver/migrations/builtin/maasserver/0004_migrate_installable_to_node_type.py' |
883 | --- src/maasserver/migrations/builtin/maasserver/0004_migrate_installable_to_node_type.py 1970-01-01 00:00:00 +0000 |
884 | +++ src/maasserver/migrations/builtin/maasserver/0004_migrate_installable_to_node_type.py 2015-12-18 15:12:10 +0000 |
885 | @@ -0,0 +1,29 @@ |
886 | +# -*- coding: utf-8 -*- |
887 | +from __future__ import unicode_literals |
888 | + |
889 | +from django.db import ( |
890 | + migrations, |
891 | + models, |
892 | +) |
893 | +from maasserver.enum import NODE_TYPE |
894 | + |
895 | + |
896 | +def convert_installable_to_node_type(apps, schema_editor): |
897 | + Node = apps.get_model("maasserver", "Node") |
898 | + for node in Node.objects.all(): |
899 | + if node.installable: |
900 | + node.node_type = NODE_TYPE.MACHINE |
901 | + else: |
902 | + node.node_type = NODE_TYPE.DEVICE |
903 | + node.save(update_fields=['node_type']) |
904 | + |
905 | + |
906 | +class Migration(migrations.Migration): |
907 | + |
908 | + dependencies = [ |
909 | + ('maasserver', '0003_add_node_type_to_node'), |
910 | + ] |
911 | + |
912 | + operations = [ |
913 | + migrations.RunPython(convert_installable_to_node_type), |
914 | + ] |
915 | |
916 | === added file 'src/maasserver/migrations/builtin/maasserver/0005_delete_installable_from_node.py' |
917 | --- src/maasserver/migrations/builtin/maasserver/0005_delete_installable_from_node.py 1970-01-01 00:00:00 +0000 |
918 | +++ src/maasserver/migrations/builtin/maasserver/0005_delete_installable_from_node.py 2015-12-18 15:12:10 +0000 |
919 | @@ -0,0 +1,21 @@ |
920 | +# -*- coding: utf-8 -*- |
921 | +from __future__ import unicode_literals |
922 | + |
923 | +from django.db import ( |
924 | + migrations, |
925 | + models, |
926 | +) |
927 | + |
928 | + |
929 | +class Migration(migrations.Migration): |
930 | + |
931 | + dependencies = [ |
932 | + ('maasserver', '0004_migrate_installable_to_node_type'), |
933 | + ] |
934 | + |
935 | + operations = [ |
936 | + migrations.RemoveField( |
937 | + model_name='node', |
938 | + name='installable', |
939 | + ), |
940 | + ] |
941 | |
942 | === modified file 'src/maasserver/models/__init__.py' |
943 | --- src/maasserver/models/__init__.py 2015-12-07 16:37:36 +0000 |
944 | +++ src/maasserver/models/__init__.py 2015-12-18 15:12:10 +0000 |
945 | @@ -56,7 +56,10 @@ |
946 | ) |
947 | from django.db.models.signals import post_save |
948 | from maasserver import logger |
949 | -from maasserver.enum import NODE_PERMISSION |
950 | +from maasserver.enum import ( |
951 | + NODE_PERMISSION, |
952 | + NODE_TYPE, |
953 | +) |
954 | from maasserver.models.blockdevice import BlockDevice |
955 | from maasserver.models.bootresource import BootResource |
956 | from maasserver.models.bootresourcefile import BootResourceFile |
957 | @@ -260,7 +263,7 @@ |
958 | elif perm in NODE_PERMISSION.EDIT: |
959 | # A device can be editted by its owner a node must be admin. |
960 | node = obj.get_node() |
961 | - if node is None or node.installable: |
962 | + if node is None or node.node_type == NODE_TYPE.MACHINE: |
963 | return user.is_superuser |
964 | else: |
965 | return node.owner == user |
966 | |
967 | === modified file 'src/maasserver/models/interface.py' |
968 | --- src/maasserver/models/interface.py 2015-12-11 01:48:39 +0000 |
969 | +++ src/maasserver/models/interface.py 2015-12-18 15:12:10 +0000 |
970 | @@ -40,6 +40,7 @@ |
971 | INTERFACE_TYPE, |
972 | INTERFACE_TYPE_CHOICES, |
973 | IPADDRESS_TYPE, |
974 | + NODE_TYPE, |
975 | NODEGROUPINTERFACE_MANAGEMENT, |
976 | ) |
977 | from maasserver.exceptions import ( |
978 | @@ -540,7 +541,7 @@ |
979 | """ |
980 | is_on_device_with_parent = ( |
981 | self.node is not None and |
982 | - not self.node.installable and |
983 | + self.node.node_type == NODE_TYPE.DEVICE and |
984 | self.node.parent is not None) |
985 | if is_on_device_with_parent: |
986 | # Use the parents cluster interfaces. |
987 | @@ -566,7 +567,7 @@ |
988 | """ |
989 | is_on_device_with_parent = ( |
990 | self.node is not None and |
991 | - not self.node.installable and |
992 | + self.node.node_type == NODE_TYPE.DEVICE and |
993 | self.node.parent is not None) |
994 | if is_on_device_with_parent: |
995 | # Use the parents cluster interfaces. |
996 | @@ -1387,7 +1388,7 @@ |
997 | interface belongs to a Device). Otherwise, return None. |
998 | """ |
999 | if (self.node is not None and |
1000 | - not self.node.installable and |
1001 | + self.node.node_type == NODE_TYPE.DEVICE and |
1002 | self.node.parent is not None): |
1003 | return self.node.parent |
1004 | else: |
1005 | |
1006 | === modified file 'src/maasserver/models/node.py' |
1007 | --- src/maasserver/models/node.py 2015-12-09 01:24:24 +0000 |
1008 | +++ src/maasserver/models/node.py 2015-12-18 15:12:10 +0000 |
1009 | @@ -65,6 +65,8 @@ |
1010 | NODE_STATUS, |
1011 | NODE_STATUS_CHOICES, |
1012 | NODE_STATUS_CHOICES_DICT, |
1013 | + NODE_TYPE, |
1014 | + NODE_TYPE_CHOICES, |
1015 | POWER_STATE, |
1016 | POWER_STATE_CHOICES, |
1017 | PRESEED_TYPE, |
1018 | @@ -400,19 +402,25 @@ |
1019 | |
1020 | |
1021 | class GeneralManager(BaseNodeManager): |
1022 | - """All the nodes: installable and non-installable together.""" |
1023 | + """All the node types:""" |
1024 | |
1025 | |
1026 | class NodeManager(BaseNodeManager): |
1027 | - """Installable nodes (i.e. non-devices objects).""" |
1028 | + """Nodes (i.e. deployable objects).""" |
1029 | |
1030 | - extra_filters = {'installable': True} |
1031 | + extra_filters = {'node_type': NODE_TYPE.MACHINE} |
1032 | |
1033 | |
1034 | class DeviceManager(BaseNodeManager): |
1035 | - """Devices are all the non-installable nodes.""" |
1036 | - |
1037 | - extra_filters = {'installable': False} |
1038 | + """Devices are all the non-deployable nodes.""" |
1039 | + |
1040 | + extra_filters = {'node_type': NODE_TYPE.DEVICE} |
1041 | + |
1042 | + |
1043 | +class RackControllerManager(BaseNodeManager): |
1044 | + """Rack controllers are nodes which are used by MAAS to deploy nodes.""" |
1045 | + |
1046 | + extra_filters = {'node_type': NODE_TYPE.RACK_CONTROLLER} |
1047 | |
1048 | |
1049 | def patch_pgarray_types(): |
1050 | @@ -488,12 +496,11 @@ |
1051 | :ivar system_id: The unique identifier for this `Node`. |
1052 | (e.g. 'node-41eba45e-4cfa-11e1-a052-00225f89f211'). |
1053 | :ivar hostname: This `Node`'s hostname. Must conform to RFCs 952 and 1123. |
1054 | - :ivar installable: An optional flag to indicate if this node can be |
1055 | - installed or not. Non-installable nodes are nodes for which MAAS only |
1056 | - manages DHCP and DNS. |
1057 | + :ivar node_type: The type of node. This is used to specify if the node is |
1058 | + to be used as a node for deployment, as a device, or a rack controller |
1059 | :ivar parent: An optional parent `Node`. This node will be deleted along |
1060 | with all its resources when the parent node gets deleted or released. |
1061 | - This is only relevant for non-installable nodes. |
1062 | + This is only relevant for node types other than node. |
1063 | :ivar status: This `Node`'s status. See the vocabulary |
1064 | :class:`NODE_STATUS`. |
1065 | :ivar error_description: A human-readable description of why a node is |
1066 | @@ -557,7 +564,8 @@ |
1067 | |
1068 | hwe_kernel = CharField(max_length=31, blank=True, null=True) |
1069 | |
1070 | - installable = BooleanField(default=True, db_index=True, editable=False) |
1071 | + node_type = IntegerField( |
1072 | + choices=NODE_TYPE_CHOICES, editable=False, default=NODE_TYPE.DEFAULT) |
1073 | |
1074 | parent = ForeignKey( |
1075 | "Node", default=None, blank=True, null=True, editable=True, |
1076 | @@ -684,15 +692,18 @@ |
1077 | # the first manager defined is important: see |
1078 | # https://docs.djangoproject.com/en/1.7/topics/db/managers/ ("Default |
1079 | # managers") for details. |
1080 | - # 'objects' are all the nodes: installable and non-installable together. |
1081 | + # 'objects' are all the nodes types |
1082 | objects = GeneralManager() |
1083 | |
1084 | - # 'nodes' are all the installable nodes (i.e. non-devices objects). |
1085 | + # 'nodes' are all of nodes of type node. |
1086 | nodes = NodeManager() |
1087 | |
1088 | - # 'devices' are all the non-installable nodes. |
1089 | + # 'devices' are all of node of type device |
1090 | devices = DeviceManager() |
1091 | |
1092 | + # 'rack controller' are all of node of type rack_controller |
1093 | + rack_controllers = RackControllerManager() |
1094 | + |
1095 | def __str__(self): |
1096 | if self.hostname: |
1097 | return "%s (%s)" % (self.system_id, self.fqdn) |
1098 | @@ -1037,7 +1048,9 @@ |
1099 | raise NodeStateViolation(error_text) |
1100 | |
1101 | def clean_architecture(self, prev): |
1102 | - if self.architecture == '' and self.installable: |
1103 | + if (self.architecture == '' and |
1104 | + (self.node_type == NODE_TYPE.MACHINE or |
1105 | + self.node_type == NODE_TYPE.RACK_CONTROLLER)): |
1106 | raise ValidationError( |
1107 | {'architecture': |
1108 | ["Architecture must be defined for installable nodes."]}) |
1109 | @@ -2673,4 +2686,5 @@ |
1110 | proxy = True |
1111 | |
1112 | def __init__(self, *args, **kwargs): |
1113 | - super(Device, self).__init__(installable=False, *args, **kwargs) |
1114 | + super(Device, self).__init__(node_type=NODE_TYPE.DEVICE, |
1115 | + *args, **kwargs) |
1116 | |
1117 | === modified file 'src/maasserver/models/signals/power.py' |
1118 | --- src/maasserver/models/signals/power.py 2015-12-01 18:12:59 +0000 |
1119 | +++ src/maasserver/models/signals/power.py 2015-12-18 15:12:10 +0000 |
1120 | @@ -102,11 +102,6 @@ |
1121 | # abandon this task; there's no point even logging. |
1122 | return |
1123 | |
1124 | - if not node.installable: |
1125 | - # This is actually a device, not a node. We don't support power queries |
1126 | - # for devices. |
1127 | - return |
1128 | - |
1129 | if power_info is None: |
1130 | # The node does not have a valid power type, so we can't query it. |
1131 | # Logging this is just spam; this problem is reported elsewhere, so |
1132 | |
1133 | === modified file 'src/maasserver/models/staticipaddress.py' |
1134 | --- src/maasserver/models/staticipaddress.py 2015-12-09 01:24:24 +0000 |
1135 | +++ src/maasserver/models/staticipaddress.py 2015-12-18 15:12:10 +0000 |
1136 | @@ -794,7 +794,7 @@ |
1137 | data["node_summary"] = { |
1138 | "hostname": node.hostname, |
1139 | "system_id": node.system_id, |
1140 | - "installable": node.installable, |
1141 | + "node_type": node.node_type, |
1142 | } |
1143 | if (with_username and |
1144 | self.alloc_type != IPADDRESS_TYPE.DISCOVERED): |
1145 | |
1146 | === modified file 'src/maasserver/models/tests/test_node.py' |
1147 | --- src/maasserver/models/tests/test_node.py 2015-12-01 18:12:59 +0000 |
1148 | +++ src/maasserver/models/tests/test_node.py 2015-12-18 15:12:10 +0000 |
1149 | @@ -32,6 +32,7 @@ |
1150 | NODE_STATUS, |
1151 | NODE_STATUS_CHOICES, |
1152 | NODE_STATUS_CHOICES_DICT, |
1153 | + NODE_TYPE, |
1154 | NODEGROUP_STATUS, |
1155 | NODEGROUPINTERFACE_MANAGEMENT, |
1156 | POWER_STATE, |
1157 | @@ -147,13 +148,19 @@ |
1158 | self.assertThat(node.system_id, HasLength(41)) |
1159 | self.assertTrue(node.system_id.startswith('node-')) |
1160 | |
1161 | - def test_empty_architecture_rejected_for_installable_nodes(self): |
1162 | - self.assertRaises( |
1163 | - ValidationError, |
1164 | - factory.make_Node, installable=True, architecture='') |
1165 | - |
1166 | - def test_empty_architecture_accepted_for_non_installable_nodes(self): |
1167 | - node = factory.make_Node(installable=False, architecture='') |
1168 | + def test_empty_architecture_rejected_for_type_node(self): |
1169 | + self.assertRaises( |
1170 | + ValidationError, |
1171 | + factory.make_Node, node_type=NODE_TYPE.MACHINE, architecture='') |
1172 | + |
1173 | + def test_empty_architecture_rejected_for_type_rack_controller(self): |
1174 | + self.assertRaises( |
1175 | + ValidationError, |
1176 | + factory.make_Node, node_type=NODE_TYPE.RACK_CONTROLLER, |
1177 | + architecture='') |
1178 | + |
1179 | + def test_empty_architecture_accepted_for_type_device(self): |
1180 | + node = factory.make_Node(node_type=NODE_TYPE.DEVICE, architecture='') |
1181 | self.assertThat(node, IsInstance(Node)) |
1182 | |
1183 | def test_hostname_is_validated(self): |
1184 | @@ -1848,8 +1855,10 @@ |
1185 | node.save) |
1186 | |
1187 | def test_full_clean_checks_architecture_for_installable_nodes(self): |
1188 | - node = factory.make_Node(installable=False, architecture='') |
1189 | - node.installable = True |
1190 | + node = factory.make_Node(node_type=NODE_TYPE.DEVICE, architecture='') |
1191 | + # Set type here so we don't cause exception while creating object |
1192 | + node.node_type = factory.pick_enum( |
1193 | + NODE_TYPE, but_not=[NODE_TYPE.DEVICE]) |
1194 | exception = self.assertRaises(ValidationError, node.full_clean) |
1195 | self.assertEqual( |
1196 | exception.message_dict, |
1197 | @@ -2900,26 +2909,54 @@ |
1198 | class TestAllNodeManagers(MAASServerTestCase): |
1199 | """Test the node's managers.""" |
1200 | |
1201 | - def test_objects_lists_installable_nodes(self): |
1202 | + def test_nodes_lists_node_type_nodes(self): |
1203 | # Create nodes. |
1204 | - nodes = [factory.make_Node(installable=True) for _ in range(3)] |
1205 | + nodes = [factory.make_Node(node_type=NODE_TYPE.MACHINE) |
1206 | + for _ in range(3)] |
1207 | # Create devices. |
1208 | - [factory.make_Node(installable=False) for _ in range(3)] |
1209 | + [factory.make_Node(node_type=NODE_TYPE.DEVICE) for _ in range(3)] |
1210 | + # Create rack_controllers. |
1211 | + [factory.make_Node(node_type=NODE_TYPE.RACK_CONTROLLER) |
1212 | + for _ in range(3)] |
1213 | self.assertItemsEqual(nodes, Node.nodes.all()) |
1214 | |
1215 | - def test_devices_lists_noninstallable_nodes(self): |
1216 | + def test_devices_lists_node_type_devices(self): |
1217 | # Create nodes. |
1218 | - [factory.make_Node(installable=True) for _ in range(3)] |
1219 | + [factory.make_Node(node_type=NODE_TYPE.MACHINE) for _ in range(3)] |
1220 | # Create devices. |
1221 | - devices = [factory.make_Node(installable=False) for _ in range(3)] |
1222 | + devices = [factory.make_Node(node_type=NODE_TYPE.DEVICE) |
1223 | + for _ in range(3)] |
1224 | + # Create rack_controllers. |
1225 | + [factory.make_Node(node_type=NODE_TYPE.RACK_CONTROLLER) |
1226 | + for _ in range(3)] |
1227 | self.assertItemsEqual(devices, Node.devices.all()) |
1228 | |
1229 | - def test_all_lists_all_nodes(self): |
1230 | - # Create nodes. |
1231 | - nodes = [factory.make_Node(installable=True) for _ in range(3)] |
1232 | - # Create devices. |
1233 | - devices = [factory.make_Node(installable=False) for _ in range(3)] |
1234 | - self.assertItemsEqual(nodes + devices, Node.objects.all()) |
1235 | + def test_rack_controllers_lists_node_type_rack_controller(self): |
1236 | + # Create nodes. |
1237 | + [factory.make_Node(node_type=NODE_TYPE.MACHINE) for _ in range(3)] |
1238 | + # Create devices. |
1239 | + [factory.make_Node(node_type=NODE_TYPE.DEVICE) for _ in range(3)] |
1240 | + # Create rack_controllers. |
1241 | + rack_controllers = [ |
1242 | + factory.make_Node( |
1243 | + node_type=NODE_TYPE.RACK_CONTROLLER) |
1244 | + for _ in range(3)] |
1245 | + self.assertItemsEqual(rack_controllers, Node.rack_controllers.all()) |
1246 | + |
1247 | + def test_objects_lists_all_nodes(self): |
1248 | + # Create nodes. |
1249 | + nodes = [factory.make_Node(node_type=NODE_TYPE.MACHINE) |
1250 | + for _ in range(3)] |
1251 | + # Create devices. |
1252 | + devices = [ |
1253 | + factory.make_Node(node_type=NODE_TYPE.DEVICE) for _ in range(3)] |
1254 | + # Create rack_controllers. |
1255 | + rack_controllers = [ |
1256 | + factory.make_Node( |
1257 | + node_type=NODE_TYPE.RACK_CONTROLLER) |
1258 | + for _ in range(3)] |
1259 | + self.assertItemsEqual( |
1260 | + nodes + devices + rack_controllers, Node.objects.all()) |
1261 | |
1262 | |
1263 | class TestNodeTransitionMonitors(MAASServerTestCase): |
1264 | |
1265 | === modified file 'src/maasserver/models/tests/test_staticipaddress.py' |
1266 | --- src/maasserver/models/tests/test_staticipaddress.py 2015-12-01 18:12:59 +0000 |
1267 | +++ src/maasserver/models/tests/test_staticipaddress.py 2015-12-18 15:12:10 +0000 |
1268 | @@ -1107,4 +1107,4 @@ |
1269 | node_summary = json["node_summary"] |
1270 | self.expectThat(node_summary["hostname"], Equals(node.hostname)) |
1271 | self.expectThat(node_summary["system_id"], Equals(node.system_id)) |
1272 | - self.expectThat(node_summary["installable"], Equals(node.installable)) |
1273 | + self.expectThat(node_summary["node_type"], Equals(node.node_type)) |
1274 | |
1275 | === modified file 'src/maasserver/models/tests/test_zone.py' |
1276 | --- src/maasserver/models/tests/test_zone.py 2015-12-01 18:12:59 +0000 |
1277 | +++ src/maasserver/models/tests/test_zone.py 2015-12-18 15:12:10 +0000 |
1278 | @@ -5,6 +5,7 @@ |
1279 | |
1280 | __all__ = [] |
1281 | |
1282 | +from maasserver.enum import NODE_TYPE |
1283 | from maasserver.models.zone import ( |
1284 | DEFAULT_ZONE_NAME, |
1285 | Zone, |
1286 | @@ -72,31 +73,55 @@ |
1287 | self.assertFalse(factory.make_Zone().is_default()) |
1288 | |
1289 | def test_nodes_only_set(self): |
1290 | - """zone.nodes_olny_set has all installable nodes.""" |
1291 | + """zone.node_only_set has only type node.""" |
1292 | zone = factory.make_Zone() |
1293 | - node1 = factory.make_Node(zone=zone, installable=True) |
1294 | - node2 = factory.make_Node(zone=zone, installable=True) |
1295 | - node3 = factory.make_Node(zone=zone, installable=True) |
1296 | - device1 = factory.make_Node(zone=zone, installable=False) |
1297 | - device2 = factory.make_Node(zone=zone, installable=False) |
1298 | + node1 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1299 | + node2 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1300 | + node3 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1301 | + device1 = factory.make_Node(zone=zone, node_type=NODE_TYPE.DEVICE) |
1302 | + device2 = factory.make_Node(zone=zone, node_type=NODE_TYPE.DEVICE) |
1303 | + rack_controller = factory.make_Node( |
1304 | + zone=zone, node_type=NODE_TYPE.RACK_CONTROLLER) |
1305 | self.assertEqual(zone.node_only_set.count(), 3) |
1306 | self.assertIn(node1, zone.node_only_set) |
1307 | self.assertIn(node2, zone.node_only_set) |
1308 | self.assertIn(node3, zone.node_only_set) |
1309 | self.assertNotIn(device1, zone.node_only_set) |
1310 | self.assertNotIn(device2, zone.node_only_set) |
1311 | + self.assertNotIn(rack_controller, zone.node_only_set) |
1312 | |
1313 | def test_devices_only_set(self): |
1314 | - """zone.devices_only_set has all non-installable nodes.""" |
1315 | + """zone.devices_only_set has only type device.""" |
1316 | zone = factory.make_Zone() |
1317 | - node1 = factory.make_Node(zone=zone, installable=True) |
1318 | - node2 = factory.make_Node(zone=zone, installable=True) |
1319 | - node3 = factory.make_Node(zone=zone, installable=True) |
1320 | - device1 = factory.make_Node(zone=zone, installable=False) |
1321 | - device2 = factory.make_Node(zone=zone, installable=False) |
1322 | + node1 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1323 | + node2 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1324 | + node3 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1325 | + device1 = factory.make_Node(zone=zone, node_type=NODE_TYPE.DEVICE) |
1326 | + device2 = factory.make_Node(zone=zone, node_type=NODE_TYPE.DEVICE) |
1327 | + rack_controller = factory.make_Node( |
1328 | + zone=zone, node_type=NODE_TYPE.RACK_CONTROLLER) |
1329 | self.assertEqual(zone.device_only_set.count(), 2) |
1330 | self.assertNotIn(node1, zone.device_only_set) |
1331 | self.assertNotIn(node2, zone.device_only_set) |
1332 | self.assertNotIn(node3, zone.device_only_set) |
1333 | self.assertIn(device1, zone.device_only_set) |
1334 | self.assertIn(device2, zone.device_only_set) |
1335 | + self.assertNotIn(rack_controller, zone.node_only_set) |
1336 | + |
1337 | + def test_rack_controllers_only_set(self): |
1338 | + """zone.rack_controllers_only_set has only type rack_controller.""" |
1339 | + zone = factory.make_Zone() |
1340 | + node1 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1341 | + node2 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1342 | + node3 = factory.make_Node(zone=zone, node_type=NODE_TYPE.MACHINE) |
1343 | + device1 = factory.make_Node(zone=zone, node_type=NODE_TYPE.DEVICE) |
1344 | + device2 = factory.make_Node(zone=zone, node_type=NODE_TYPE.DEVICE) |
1345 | + rack_controller = factory.make_Node( |
1346 | + zone=zone, node_type=NODE_TYPE.RACK_CONTROLLER) |
1347 | + self.assertEqual(zone.device_only_set.count(), 2) |
1348 | + self.assertNotIn(node1, zone.rack_controller_only_set) |
1349 | + self.assertNotIn(node2, zone.rack_controller_only_set) |
1350 | + self.assertNotIn(node3, zone.rack_controller_only_set) |
1351 | + self.assertNotIn(device1, zone.rack_controller_only_set) |
1352 | + self.assertNotIn(device2, zone.rack_controller_only_set) |
1353 | + self.assertIn(rack_controller, zone.rack_controller_only_set) |
1354 | |
1355 | === modified file 'src/maasserver/models/zone.py' |
1356 | --- src/maasserver/models/zone.py 2015-12-01 18:12:59 +0000 |
1357 | +++ src/maasserver/models/zone.py 2015-12-18 15:12:10 +0000 |
1358 | @@ -19,6 +19,7 @@ |
1359 | TextField, |
1360 | ) |
1361 | from maasserver import DefaultMeta |
1362 | +from maasserver.enum import NODE_TYPE |
1363 | from maasserver.models.cleansave import CleanSave |
1364 | from maasserver.models.timestampedmodel import TimestampedModel |
1365 | |
1366 | @@ -88,10 +89,15 @@ |
1367 | |
1368 | @property |
1369 | def node_only_set(self): |
1370 | - """Returns just the installable nodes in this zone""" |
1371 | - return self.node_set.filter(installable=True) |
1372 | + """Returns just the nodes of node_type node in this zone.""" |
1373 | + return self.node_set.filter(node_type=NODE_TYPE.MACHINE) |
1374 | |
1375 | @property |
1376 | def device_only_set(self): |
1377 | - """Returns the non-installable nodes in this zone""" |
1378 | - return self.node_set.filter(installable=False) |
1379 | + """Returns just the nodes of node_type device in this zone.""" |
1380 | + return self.node_set.filter(node_type=NODE_TYPE.DEVICE) |
1381 | + |
1382 | + @property |
1383 | + def rack_controller_only_set(self): |
1384 | + """Returns just the nodes of node_type rack controller in this zone.""" |
1385 | + return self.node_set.filter(node_type=NODE_TYPE.RACK_CONTROLLER) |
1386 | |
1387 | === modified file 'src/maasserver/node_action.py' |
1388 | --- src/maasserver/node_action.py 2015-12-01 18:12:59 +0000 |
1389 | +++ src/maasserver/node_action.py 2015-12-18 15:12:10 +0000 |
1390 | @@ -30,6 +30,7 @@ |
1391 | NODE_PERMISSION, |
1392 | NODE_STATUS, |
1393 | NODE_STATUS_CHOICES_DICT, |
1394 | + NODE_TYPE, |
1395 | POWER_STATE, |
1396 | ) |
1397 | from maasserver.exceptions import ( |
1398 | @@ -82,10 +83,10 @@ |
1399 | Will be used as the label for the action's button. |
1400 | """) |
1401 | |
1402 | - installable_only = abstractproperty(""" |
1403 | - Can only be performed on a installable node. |
1404 | + node_only = abstractproperty(""" |
1405 | + Can only be performed when the node type is node. |
1406 | |
1407 | - A boolean value. True for only available for installable node, false |
1408 | + A boolean value. True for only available for node_type node, false |
1409 | otherwise. |
1410 | """) |
1411 | |
1412 | @@ -103,9 +104,9 @@ |
1413 | user has this given permission on the subject node. |
1414 | """) |
1415 | |
1416 | - # Optional installable permission that will be used when the action |
1417 | - # is being applied to a node that is installable. |
1418 | - installable_permission = None |
1419 | + # Optional node permission that will be used when the action |
1420 | + # is being applied to a node_type which is node |
1421 | + node_permission = None |
1422 | |
1423 | def __init__(self, node, user, request=None): |
1424 | """Initialize a node action. |
1425 | @@ -120,12 +121,12 @@ |
1426 | def is_actionable(self): |
1427 | """Can this action be performed? |
1428 | |
1429 | - If the node is not installable then actionable_statuses will not |
1430 | - be used, as the status doesn't matter for an uninstallable node. |
1431 | + If the node is not node_type node then actionable_statuses will not |
1432 | + be used, as the status doesn't matter for a non-node type. |
1433 | """ |
1434 | - if self.installable_only and not self.node.installable: |
1435 | + if self.node_only and not self.node.node_type == NODE_TYPE.MACHINE: |
1436 | return False |
1437 | - if self.node.installable: |
1438 | + if self.node.node_type == NODE_TYPE.MACHINE: |
1439 | return self.node.status in self.actionable_statuses |
1440 | return True |
1441 | |
1442 | @@ -151,10 +152,10 @@ |
1443 | """ |
1444 | |
1445 | def get_permission(self): |
1446 | - """Return the permission value depending on if the node is |
1447 | - installable or not.""" |
1448 | - if self.node.installable and self.installable_permission is not None: |
1449 | - return self.installable_permission |
1450 | + """Return the permission value depending on if the node_type.""" |
1451 | + if(self.node.node_type == NODE_TYPE.MACHINE and |
1452 | + self.node_permission is not None): |
1453 | + return self.node_permission |
1454 | return self.permission |
1455 | |
1456 | def is_permitted(self): |
1457 | @@ -179,8 +180,8 @@ |
1458 | display_sentence = "deleted" |
1459 | actionable_statuses = ALL_STATUSES |
1460 | permission = NODE_PERMISSION.EDIT |
1461 | - installable_permission = NODE_PERMISSION.ADMIN |
1462 | - installable_only = False |
1463 | + node_permission = NODE_PERMISSION.ADMIN |
1464 | + node_only = False |
1465 | |
1466 | def execute(self): |
1467 | """Redirect to the delete view's confirmation page. |
1468 | @@ -199,8 +200,8 @@ |
1469 | display_sentence = "Zone set" |
1470 | actionable_statuses = ALL_STATUSES |
1471 | permission = NODE_PERMISSION.EDIT |
1472 | - installable_permission = NODE_PERMISSION.ADMIN |
1473 | - installable_only = False |
1474 | + node_permission = NODE_PERMISSION.ADMIN |
1475 | + node_only = False |
1476 | |
1477 | def execute(self, zone_id=None): |
1478 | """See `NodeAction.execute`.""" |
1479 | @@ -224,7 +225,7 @@ |
1480 | NODE_STATUS.BROKEN, |
1481 | ) |
1482 | permission = NODE_PERMISSION.ADMIN |
1483 | - installable_only = True |
1484 | + node_only = True |
1485 | |
1486 | def execute( |
1487 | self, enable_ssh=False, skip_networking=False, |
1488 | @@ -255,7 +256,7 @@ |
1489 | NODE_STATUS.DEPLOYING |
1490 | ) |
1491 | permission = NODE_PERMISSION.ADMIN |
1492 | - installable_only = True |
1493 | + node_only = True |
1494 | |
1495 | def execute(self): |
1496 | """See `NodeAction.execute`.""" |
1497 | @@ -272,7 +273,7 @@ |
1498 | display_sentence = "acquired" |
1499 | actionable_statuses = (NODE_STATUS.READY, ) |
1500 | permission = NODE_PERMISSION.VIEW |
1501 | - installable_only = True |
1502 | + node_only = True |
1503 | |
1504 | def execute(self): |
1505 | """See `NodeAction.execute`.""" |
1506 | @@ -287,7 +288,7 @@ |
1507 | display_sentence = "deployed" |
1508 | actionable_statuses = (NODE_STATUS.READY, NODE_STATUS.ALLOCATED) |
1509 | permission = NODE_PERMISSION.VIEW |
1510 | - installable_only = True |
1511 | + node_only = True |
1512 | |
1513 | def execute(self, osystem=None, distro_series=None, hwe_kernel=None): |
1514 | """See `NodeAction.execute`.""" |
1515 | @@ -333,7 +334,7 @@ |
1516 | NODE_STATUS.BROKEN, |
1517 | ) |
1518 | permission = NODE_PERMISSION.EDIT |
1519 | - installable_only = True |
1520 | + node_only = True |
1521 | |
1522 | def execute(self): |
1523 | """See `NodeAction.execute`.""" |
1524 | @@ -365,7 +366,7 @@ |
1525 | # Let a user power off a node in any non-active status. |
1526 | actionable_statuses = NON_MONITORED_STATUSES |
1527 | permission = NODE_PERMISSION.EDIT |
1528 | - installable_only = True |
1529 | + node_only = True |
1530 | |
1531 | def execute(self): |
1532 | """See `NodeAction.execute`.""" |
1533 | @@ -394,7 +395,7 @@ |
1534 | NODE_STATUS.FAILED_DISK_ERASING, |
1535 | ) |
1536 | permission = NODE_PERMISSION.EDIT |
1537 | - installable_only = True |
1538 | + node_only = True |
1539 | |
1540 | def execute(self): |
1541 | """See `NodeAction.execute`.""" |
1542 | @@ -422,7 +423,7 @@ |
1543 | NODE_STATUS.DISK_ERASING, |
1544 | ] + FAILED_STATUSES |
1545 | permission = NODE_PERMISSION.EDIT |
1546 | - installable_only = True |
1547 | + node_only = True |
1548 | |
1549 | def execute(self): |
1550 | """See `NodeAction.execute`.""" |
1551 | @@ -436,7 +437,7 @@ |
1552 | display_sentence = "marked fixed" |
1553 | actionable_statuses = (NODE_STATUS.BROKEN, ) |
1554 | permission = NODE_PERMISSION.ADMIN |
1555 | - installable_only = True |
1556 | + node_only = True |
1557 | |
1558 | def execute(self): |
1559 | """See `NodeAction.execute`.""" |
1560 | |
1561 | === modified file 'src/maasserver/rpc/nodes.py' |
1562 | --- src/maasserver/rpc/nodes.py 2015-12-01 18:12:59 +0000 |
1563 | +++ src/maasserver/rpc/nodes.py 2015-12-18 15:12:10 +0000 |
1564 | @@ -74,7 +74,6 @@ |
1565 | .filter(power_state_updated=None) |
1566 | .filter(power_type__in=QUERY_POWER_TYPES) |
1567 | .exclude(status=NODE_STATUS.BROKEN) |
1568 | - .exclude(installable=False) |
1569 | ) |
1570 | nodes_checked = ( |
1571 | nodes |
1572 | @@ -82,7 +81,6 @@ |
1573 | .exclude(power_state_updated__gt=five_minutes_ago) |
1574 | .filter(power_type__in=QUERY_POWER_TYPES) |
1575 | .exclude(status=NODE_STATUS.BROKEN) |
1576 | - .exclude(installable=False) |
1577 | .order_by("power_state_updated", "system_id") |
1578 | ) |
1579 | |
1580 | |
1581 | === modified file 'src/maasserver/rpc/tests/test_nodes.py' |
1582 | --- src/maasserver/rpc/tests/test_nodes.py 2015-12-01 18:12:59 +0000 |
1583 | +++ src/maasserver/rpc/tests/test_nodes.py 2015-12-18 15:12:10 +0000 |
1584 | @@ -393,14 +393,14 @@ |
1585 | |
1586 | self.assertItemsEqual([node_queryable.system_id], system_ids) |
1587 | |
1588 | - def test__excludes_devices(self): |
1589 | + def test__excludes_no_power_type(self): |
1590 | cluster = factory.make_NodeGroup() |
1591 | node_queryable = self.make_Node(cluster) |
1592 | |
1593 | - factory.make_Device(nodegroup=cluster) |
1594 | - factory.make_Device(nodegroup=cluster, power_type="ipmi") |
1595 | + factory.make_Device(nodegroup=cluster, power_type='') |
1596 | + factory.make_Device(nodegroup=cluster, power_type='') |
1597 | factory.make_Device( |
1598 | - nodegroup=cluster, power_type="ipmi", power_state_updated=( |
1599 | + nodegroup=cluster, power_type='', power_state_updated=( |
1600 | now() - timedelta(minutes=10))) |
1601 | |
1602 | power_parameters = list_cluster_nodes_power_parameters(cluster.uuid) |
1603 | |
1604 | === modified file 'src/maasserver/static/partials/subnet-details.html' |
1605 | --- src/maasserver/static/partials/subnet-details.html 2015-10-01 03:31:04 +0000 |
1606 | +++ src/maasserver/static/partials/subnet-details.html 2015-12-18 15:12:10 +0000 |
1607 | @@ -61,8 +61,15 @@ |
1608 | <div class="table__row" data-ng-repeat="ip in subnet.ip_addresses"> |
1609 | <div class="table__data table__column--15">{$ ip.ip $}</div> |
1610 | <div class="table__data table__column--15">{$ ip.user $}</div> |
1611 | - <div class="table__data table__column--20"><a href="#/node/{$ ip.node_summary.system_id $}" data-ng-if="ip.node_summary.installable">{$ ip.node_summary.hostname $}</a><span data-ng-if="!ip.node_summary.installable">{$ ip.node_summary.hostname $}</span></div> |
1612 | - <div class="table__data table__column--15">{$ ip.node_summary.installable ? "Node" : "Device" $}</div> |
1613 | + <div class="table__data table__column--20"> |
1614 | + <!-- |
1615 | + XXX ltrager 2015-12-02 |
1616 | + node_type is an enum of node(0), device(1), or rack_controller(2). We need to create some type of Javascript enum to represent this |
1617 | + --> |
1618 | + <a href="#/node/{$ ip.node_summary.system_id $}" data-ng-if="ip.node_summary.node_type == 0">{$ ip.node_summary.hostname $}</a> |
1619 | + <span data-ng-if="ip.node_summary.node_type == 1">{$ ip.node_summary.hostname $}</span> |
1620 | + </div> |
1621 | + <div class="table__data table__column--15">{$ ip.node_summary.node_type == 0 ? "Node" : "Device" $}</div> |
1622 | <div class="table__data table__column--35" data-ng-switch="ip.alloc_type"> |
1623 | <span data-ng-switch-when="0">Automatic</span> |
1624 | <span data-ng-switch-when="1">Sticky</span> |
1625 | |
1626 | === modified file 'src/maasserver/testing/factory.py' |
1627 | --- src/maasserver/testing/factory.py 2015-12-11 01:48:39 +0000 |
1628 | +++ src/maasserver/testing/factory.py 2015-12-18 15:12:10 +0000 |
1629 | @@ -33,6 +33,7 @@ |
1630 | IPADDRESS_TYPE, |
1631 | NODE_BOOT, |
1632 | NODE_STATUS, |
1633 | + NODE_TYPE, |
1634 | NODEGROUP_STATUS, |
1635 | NODEGROUPINTERFACE_MANAGEMENT, |
1636 | PARTITION_TABLE_TYPE, |
1637 | @@ -254,22 +255,30 @@ |
1638 | finally: |
1639 | NODE_TRANSITIONS[None] = valid_initial_states |
1640 | |
1641 | - def make_Device(self, hostname=None, nodegroup=None, **kwargs): |
1642 | + def make_Device(self, hostname=None, nodegroup=None, interface=False, |
1643 | + disable_ipv4=None, vlan=None, fabric=None, **kwargs): |
1644 | if hostname is None: |
1645 | hostname = self.make_string(20) |
1646 | if nodegroup is None: |
1647 | nodegroup = self.make_NodeGroup() |
1648 | - device = Device(hostname=hostname, nodegroup=nodegroup, **kwargs) |
1649 | + if disable_ipv4 is None: |
1650 | + disable_ipv4 = self.pick_bool() |
1651 | + device = Device(hostname=hostname, nodegroup=nodegroup, |
1652 | + disable_ipv4=disable_ipv4, **kwargs) |
1653 | device.save() |
1654 | - return device |
1655 | + if interface: |
1656 | + self.make_Interface( |
1657 | + INTERFACE_TYPE.PHYSICAL, node=device, vlan=vlan, fabric=fabric) |
1658 | + return reload_object(device) |
1659 | |
1660 | def make_Node( |
1661 | self, interface=False, hostname=None, status=None, |
1662 | - architecture="i386/generic", min_hwe_kernel=None, hwe_kernel=None, |
1663 | - installable=True, updated=None, created=None, nodegroup=None, |
1664 | - routers=None, zone=None, networks=None, boot_type=None, |
1665 | - sortable_name=False, power_type=None, power_parameters=None, |
1666 | - power_state=None, power_state_updated=undefined, disable_ipv4=None, |
1667 | + architecture="i386/generic", min_hwe_kernel=None, |
1668 | + hwe_kernel=None, node_type=NODE_TYPE.MACHINE, updated=None, |
1669 | + created=None, nodegroup=None, routers=None, zone=None, |
1670 | + networks=None, boot_type=None, sortable_name=False, |
1671 | + power_type=None, power_parameters=None, power_state=None, |
1672 | + power_state_updated=undefined, disable_ipv4=None, |
1673 | with_boot_disk=True, vlan=None, fabric=None, **kwargs): |
1674 | """Make a :class:`Node`. |
1675 | |
1676 | @@ -308,7 +317,7 @@ |
1677 | node = Node( |
1678 | hostname=hostname, status=status, architecture=architecture, |
1679 | min_hwe_kernel=min_hwe_kernel, hwe_kernel=hwe_kernel, |
1680 | - installable=installable, nodegroup=nodegroup, routers=routers, |
1681 | + node_type=node_type, nodegroup=nodegroup, routers=routers, |
1682 | zone=zone, boot_type=boot_type, power_type=power_type, |
1683 | power_parameters=power_parameters, power_state=power_state, |
1684 | power_state_updated=power_state_updated, disable_ipv4=disable_ipv4, |
1685 | @@ -322,7 +331,7 @@ |
1686 | if interface: |
1687 | self.make_Interface( |
1688 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan, fabric=fabric) |
1689 | - if installable and with_boot_disk: |
1690 | + if node_type == NODE_TYPE.MACHINE and with_boot_disk: |
1691 | root_partition = self.make_Partition(node=node) |
1692 | acquired = node.status in ALLOCATED_NODE_STATUSES |
1693 | self.make_Filesystem( |
1694 | |
1695 | === modified file 'src/maasserver/tests/test_auth.py' |
1696 | --- src/maasserver/tests/test_auth.py 2015-12-07 16:37:36 +0000 |
1697 | +++ src/maasserver/tests/test_auth.py 2015-12-18 15:12:10 +0000 |
1698 | @@ -229,8 +229,8 @@ |
1699 | backend = MAASAuthorizationBackend() |
1700 | user = factory.make_User() |
1701 | parent = factory.make_Node() |
1702 | - device = factory.make_Node( |
1703 | - owner=user, installable=False, parent=parent) |
1704 | + device = factory.make_Device( |
1705 | + owner=user, parent=parent) |
1706 | interface = factory.make_Interface( |
1707 | INTERFACE_TYPE.PHYSICAL, node=device) |
1708 | self.assertTrue( |
1709 | @@ -242,8 +242,8 @@ |
1710 | user = factory.make_User() |
1711 | owner = factory.make_User() |
1712 | parent = factory.make_Node() |
1713 | - device = factory.make_Node( |
1714 | - owner=owner, installable=False, parent=parent) |
1715 | + device = factory.make_Device( |
1716 | + owner=owner, parent=parent) |
1717 | interface = factory.make_Interface( |
1718 | INTERFACE_TYPE.PHYSICAL, node=device) |
1719 | self.assertFalse( |
1720 | |
1721 | === modified file 'src/maasserver/tests/test_listener.py' |
1722 | --- src/maasserver/tests/test_listener.py 2015-12-07 14:33:41 +0000 |
1723 | +++ src/maasserver/tests/test_listener.py 2015-12-18 15:12:10 +0000 |
1724 | @@ -16,6 +16,7 @@ |
1725 | from maasserver.enum import ( |
1726 | INTERFACE_TYPE, |
1727 | IPADDRESS_TYPE, |
1728 | + NODE_TYPE, |
1729 | ) |
1730 | from maasserver.listener import ( |
1731 | PostgresListenerNotifyError, |
1732 | @@ -464,7 +465,7 @@ |
1733 | if params is None: |
1734 | params = {} |
1735 | parent = factory.make_Node(with_boot_disk=False) |
1736 | - params["installable"] = False |
1737 | + params["node_type"] = NODE_TYPE.DEVICE |
1738 | params["parent"] = parent |
1739 | device = factory.make_Node(**params) |
1740 | return device, parent |
1741 | @@ -915,11 +916,11 @@ |
1742 | |
1743 | scenarios = ( |
1744 | ('node', { |
1745 | - 'params': {'installable': True}, |
1746 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1747 | 'listener': 'node', |
1748 | }), |
1749 | ('device', { |
1750 | - 'params': {'installable': False}, |
1751 | + 'params': {'node_type': NODE_TYPE.DEVICE}, |
1752 | 'listener': 'device', |
1753 | }), |
1754 | ) |
1755 | @@ -991,7 +992,7 @@ |
1756 | try: |
1757 | yield deferToDatabase( |
1758 | self.create_node, { |
1759 | - "installable": False, |
1760 | + "node_type": NODE_TYPE.DEVICE, |
1761 | "parent": parent, |
1762 | }) |
1763 | yield dv.get(timeout=2) |
1764 | @@ -1298,11 +1299,11 @@ |
1765 | |
1766 | scenarios = ( |
1767 | ('node', { |
1768 | - 'params': {'installable': True}, |
1769 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1770 | 'listener': 'node', |
1771 | }), |
1772 | ('device', { |
1773 | - 'params': {'installable': False}, |
1774 | + 'params': {'node_type': NODE_TYPE.DEVICE}, |
1775 | 'listener': 'device', |
1776 | }), |
1777 | ) |
1778 | @@ -1545,11 +1546,11 @@ |
1779 | |
1780 | scenarios = ( |
1781 | ('node', { |
1782 | - 'params': {'installable': True}, |
1783 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1784 | 'listener': 'node', |
1785 | }), |
1786 | ('device', { |
1787 | - 'params': {'installable': False}, |
1788 | + 'params': {'node_type': NODE_TYPE.DEVICE}, |
1789 | 'listener': 'device', |
1790 | }), |
1791 | ) |
1792 | @@ -1602,11 +1603,11 @@ |
1793 | |
1794 | scenarios = ( |
1795 | ('node', { |
1796 | - 'params': {'installable': True, 'interface': True}, |
1797 | + 'params': {'node_type': NODE_TYPE.MACHINE, 'interface': True}, |
1798 | 'listener': 'node', |
1799 | }), |
1800 | ('device', { |
1801 | - 'params': {'installable': False, 'interface': True}, |
1802 | + 'params': {'node_type': NODE_TYPE.DEVICE, 'interface': True}, |
1803 | 'listener': 'device', |
1804 | }), |
1805 | ) |
1806 | @@ -1709,11 +1710,11 @@ |
1807 | |
1808 | scenarios = ( |
1809 | ('node', { |
1810 | - 'params': {'installable': True}, |
1811 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1812 | 'listener': 'node', |
1813 | }), |
1814 | ('device', { |
1815 | - 'params': {'installable': False}, |
1816 | + 'params': {'node_type': NODE_TYPE.DEVICE}, |
1817 | 'listener': 'device', |
1818 | }), |
1819 | ) |
1820 | @@ -1803,11 +1804,11 @@ |
1821 | |
1822 | scenarios = ( |
1823 | ('node', { |
1824 | - 'params': {'installable': True}, |
1825 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1826 | 'listener': 'node', |
1827 | }), |
1828 | ('device', { |
1829 | - 'params': {'installable': False}, |
1830 | + 'params': {'node_type': NODE_TYPE.DEVICE}, |
1831 | 'listener': 'device', |
1832 | }), |
1833 | ) |
1834 | @@ -2238,11 +2239,11 @@ |
1835 | |
1836 | scenarios = ( |
1837 | ('node', { |
1838 | - 'params': {'installable': True, 'interface': True}, |
1839 | + 'params': {'node_type': NODE_TYPE.MACHINE, 'interface': True}, |
1840 | 'listener': 'node', |
1841 | }), |
1842 | ('device', { |
1843 | - 'params': {'installable': False, 'interface': True}, |
1844 | + 'params': {'node_type': NODE_TYPE.DEVICE, 'interface': True}, |
1845 | 'listener': 'device', |
1846 | }), |
1847 | ) |
1848 | @@ -2590,7 +2591,7 @@ |
1849 | |
1850 | scenarios = ( |
1851 | ('node', { |
1852 | - 'params': {'installable': True}, |
1853 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1854 | 'listener': 'node', |
1855 | }), |
1856 | ) |
1857 | @@ -2704,7 +2705,7 @@ |
1858 | |
1859 | scenarios = ( |
1860 | ('node', { |
1861 | - 'params': {'installable': True}, |
1862 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1863 | 'listener': 'node', |
1864 | }), |
1865 | ) |
1866 | @@ -2776,7 +2777,7 @@ |
1867 | |
1868 | scenarios = ( |
1869 | ('node', { |
1870 | - 'params': {'installable': True}, |
1871 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1872 | 'listener': 'node', |
1873 | }), |
1874 | ) |
1875 | @@ -2849,7 +2850,7 @@ |
1876 | |
1877 | scenarios = ( |
1878 | ('node', { |
1879 | - 'params': {'installable': True}, |
1880 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1881 | 'listener': 'node', |
1882 | }), |
1883 | ) |
1884 | @@ -2926,7 +2927,7 @@ |
1885 | |
1886 | scenarios = ( |
1887 | ('node', { |
1888 | - 'params': {'installable': True, 'with_boot_disk': True}, |
1889 | + 'params': {'node_type': NODE_TYPE.MACHINE, 'with_boot_disk': True}, |
1890 | 'listener': 'node', |
1891 | }), |
1892 | ) |
1893 | @@ -3003,7 +3004,7 @@ |
1894 | |
1895 | scenarios = ( |
1896 | ('node', { |
1897 | - 'params': {'installable': True}, |
1898 | + 'params': {'node_type': NODE_TYPE.MACHINE}, |
1899 | 'listener': 'node', |
1900 | }), |
1901 | ) |
1902 | |
1903 | === modified file 'src/maasserver/tests/test_node_action.py' |
1904 | --- src/maasserver/tests/test_node_action.py 2015-12-01 18:12:59 +0000 |
1905 | +++ src/maasserver/tests/test_node_action.py 2015-12-18 15:12:10 +0000 |
1906 | @@ -13,6 +13,7 @@ |
1907 | NODE_STATUS, |
1908 | NODE_STATUS_CHOICES, |
1909 | NODE_STATUS_CHOICES_DICT, |
1910 | + NODE_TYPE, |
1911 | POWER_STATE, |
1912 | ) |
1913 | from maasserver.exceptions import NodeActionError |
1914 | @@ -70,7 +71,7 @@ |
1915 | display = "Action label" |
1916 | actionable_statuses = ALL_STATUSES |
1917 | permission = NODE_PERMISSION.VIEW |
1918 | - installable_only = False |
1919 | + node_only = False |
1920 | |
1921 | # For testing: an inhibition for inhibit() to return. |
1922 | fake_inhibition = None |
1923 | @@ -165,25 +166,25 @@ |
1924 | status=NODE_STATUS.ALLOCATED, owner=factory.make_User()) |
1925 | self.assertFalse(MyAction(node, factory.make_User()).is_permitted()) |
1926 | |
1927 | - def test_is_permitted_uses_installable_permission(self): |
1928 | + def test_is_permitted_uses_node_permission(self): |
1929 | |
1930 | class MyAction(FakeNodeAction): |
1931 | permission = NODE_PERMISSION.VIEW |
1932 | - installable_permission = NODE_PERMISSION.EDIT |
1933 | + node_permission = NODE_PERMISSION.EDIT |
1934 | |
1935 | node = factory.make_Node( |
1936 | status=NODE_STATUS.ALLOCATED, owner=factory.make_User()) |
1937 | self.assertFalse(MyAction(node, factory.make_User()).is_permitted()) |
1938 | |
1939 | - def test_is_permitted_doest_use_installable_permission_if_device(self): |
1940 | + def test_is_permitted_doest_use_node_permission_if_device(self): |
1941 | |
1942 | class MyAction(FakeNodeAction): |
1943 | permission = NODE_PERMISSION.VIEW |
1944 | - installable_permission = NODE_PERMISSION.EDIT |
1945 | + node_permission = NODE_PERMISSION.EDIT |
1946 | |
1947 | node = factory.make_Node( |
1948 | status=NODE_STATUS.ALLOCATED, owner=factory.make_User(), |
1949 | - installable=False) |
1950 | + node_type=NODE_TYPE.DEVICE) |
1951 | self.assertTrue(MyAction(node, factory.make_User()).is_permitted()) |
1952 | |
1953 | def test_inhibition_wraps_inhibit(self): |
1954 | @@ -213,22 +214,22 @@ |
1955 | action.fake_inhibition = factory.make_string() |
1956 | self.assertIsNone(action.inhibition) |
1957 | |
1958 | - def test_installable_only_is_not_actionable_if_node_isnt_installable(self): |
1959 | + def test_node_only_is_not_actionable_if_node_isnt_node_type(self): |
1960 | status = NODE_STATUS.NEW |
1961 | owner = factory.make_User() |
1962 | node = factory.make_Node( |
1963 | - owner=owner, status=status, installable=False) |
1964 | + owner=owner, status=status, node_type=NODE_TYPE.DEVICE) |
1965 | action = FakeNodeAction(node, owner) |
1966 | - action.installable_only = True |
1967 | + action.node_only = True |
1968 | self.assertFalse(action.is_actionable()) |
1969 | |
1970 | - def test_installable_only_is_actionable_if_node_is_installable(self): |
1971 | + def test_node_only_is_actionable_if_node_type_is_node(self): |
1972 | status = NODE_STATUS.NEW |
1973 | owner = factory.make_User() |
1974 | node = factory.make_Node( |
1975 | - owner=owner, status=status, installable=True) |
1976 | + owner=owner, status=status, node_type=NODE_TYPE.MACHINE) |
1977 | action = FakeNodeAction(node, owner) |
1978 | - action.installable_only = True |
1979 | + action.node_only = True |
1980 | self.assertTrue(action.is_actionable()) |
1981 | |
1982 | def test_is_actionable_checks_node_status_in_actionable_status(self): |
1983 | |
1984 | === modified file 'src/maasserver/triggers.py' |
1985 | --- src/maasserver/triggers.py 2015-12-01 18:12:59 +0000 |
1986 | +++ src/maasserver/triggers.py 2015-12-18 15:12:10 +0000 |
1987 | @@ -24,6 +24,7 @@ |
1988 | from textwrap import dedent |
1989 | |
1990 | from django.db import connection |
1991 | +from maasserver.enum import NODE_TYPE |
1992 | from maasserver.utils.orm import transactional |
1993 | |
1994 | # Note that the corresponding test module (test_triggers) only tests that the |
1995 | @@ -35,18 +36,18 @@ |
1996 | |
1997 | # Procedure that is called when a tag is added or removed from a node/device. |
1998 | # Sends a notify message for node_update or device_update depending on if the |
1999 | -# node is installable. |
2000 | +# node type is node. |
2001 | NODE_TAG_NOTIFY = dedent("""\ |
2002 | CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$ |
2003 | DECLARE |
2004 | node RECORD; |
2005 | pnode RECORD; |
2006 | BEGIN |
2007 | - SELECT system_id, installable, parent_id INTO node |
2008 | + SELECT system_id, node_type, parent_id INTO node |
2009 | FROM maasserver_node |
2010 | WHERE id = %s; |
2011 | |
2012 | - IF node.installable THEN |
2013 | + IF node.node_type = %d THEN |
2014 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2015 | ELSIF node.parent_id IS NOT NULL THEN |
2016 | SELECT system_id INTO pnode |
2017 | @@ -74,13 +75,13 @@ |
2018 | FOR node IN ( |
2019 | SELECT |
2020 | maasserver_node.system_id, |
2021 | - maasserver_node.installable, |
2022 | + maasserver_node.node_type, |
2023 | maasserver_node.parent_id |
2024 | FROM maasserver_node_tags, maasserver_node |
2025 | WHERE maasserver_node_tags.tag_id = NEW.id |
2026 | AND maasserver_node_tags.node_id = maasserver_node.id) |
2027 | LOOP |
2028 | - IF node.installable THEN |
2029 | + IF node.node_type = %d THEN |
2030 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2031 | ELSIF node.parent_id IS NOT NULL THEN |
2032 | SELECT system_id INTO pnode |
2033 | @@ -99,7 +100,7 @@ |
2034 | |
2035 | # Procedure that is called when a event is created. |
2036 | # Sends a notify message for node_update or device_update depending on if the |
2037 | -# link node is installable. |
2038 | +# link node type is a node. |
2039 | EVENT_NODE_NOTIFY = dedent("""\ |
2040 | CREATE OR REPLACE FUNCTION event_create_node_device_notify() |
2041 | RETURNS trigger AS $$ |
2042 | @@ -107,11 +108,11 @@ |
2043 | node RECORD; |
2044 | pnode RECORD; |
2045 | BEGIN |
2046 | - SELECT system_id, installable, parent_id INTO node |
2047 | + SELECT system_id, node_type, parent_id INTO node |
2048 | FROM maasserver_node |
2049 | WHERE id = NEW.node_id; |
2050 | |
2051 | - IF node.installable THEN |
2052 | + IF node.node_type = %d THEN |
2053 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2054 | ELSIF node.parent_id IS NOT NULL THEN |
2055 | SELECT system_id INTO pnode |
2056 | @@ -167,19 +168,19 @@ |
2057 | |
2058 | # Procedure that is called when a static ip address is linked or unlinked to |
2059 | # an Interface. Sends a notify message for node_update or device_update |
2060 | -# depending on if the node is installable. |
2061 | +# depending on if the node type is node. |
2062 | INTERFACE_IP_ADDRESS_NODE_NOTIFY = dedent("""\ |
2063 | CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$ |
2064 | DECLARE |
2065 | node RECORD; |
2066 | pnode RECORD; |
2067 | BEGIN |
2068 | - SELECT system_id, installable, parent_id INTO node |
2069 | + SELECT system_id, node_type, parent_id INTO node |
2070 | FROM maasserver_node, maasserver_interface |
2071 | WHERE maasserver_node.id = maasserver_interface.node_id |
2072 | AND maasserver_interface.id = %s; |
2073 | |
2074 | - IF node.installable THEN |
2075 | + IF node.node_type = %d THEN |
2076 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2077 | ELSIF node.parent_id IS NOT NULL THEN |
2078 | SELECT system_id INTO pnode |
2079 | @@ -198,8 +199,8 @@ |
2080 | # Procedure that is called when a Interface address updated. Will send |
2081 | # node_update or device_update when the Interface is moved from another node |
2082 | # to a new node. Sends a notify message for node_update or device_update |
2083 | -# depending on if the node is installable, both for the old node and the |
2084 | -# new node. |
2085 | +# depending on if the node type is node, both for the old node and the new |
2086 | +# node. |
2087 | INTERFACE_UPDATE_NODE_NOTIFY = dedent("""\ |
2088 | CREATE OR REPLACE FUNCTION nd_interface_update_notify() |
2089 | RETURNS trigger AS $$ |
2090 | @@ -208,11 +209,11 @@ |
2091 | pnode RECORD; |
2092 | BEGIN |
2093 | IF OLD.node_id != NEW.node_id THEN |
2094 | - SELECT system_id, installable, parent_id INTO node |
2095 | + SELECT system_id, node_type, parent_id INTO node |
2096 | FROM maasserver_node |
2097 | WHERE id = OLD.node_id; |
2098 | |
2099 | - IF node.installable THEN |
2100 | + IF node.node_type = %d THEN |
2101 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2102 | ELSIF node.parent_id IS NOT NULL THEN |
2103 | SELECT system_id INTO pnode |
2104 | @@ -224,11 +225,11 @@ |
2105 | END IF; |
2106 | END IF; |
2107 | |
2108 | - SELECT system_id, installable, parent_id INTO node |
2109 | + SELECT system_id, node_type, parent_id INTO node |
2110 | FROM maasserver_node |
2111 | WHERE id = NEW.node_id; |
2112 | |
2113 | - IF node.installable THEN |
2114 | + IF node.node_type = %d THEN |
2115 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2116 | ELSIF node.parent_id IS NOT NULL THEN |
2117 | SELECT system_id INTO pnode |
2118 | @@ -246,18 +247,18 @@ |
2119 | |
2120 | # Procedure that is called when a physical or virtual block device is updated. |
2121 | # Sends a notify message for node_update or device_update depending on if the |
2122 | -# node is installable. |
2123 | +# node type is node. |
2124 | PHYSICAL_OR_VIRTUAL_BLOCK_DEVICE_NODE_NOTIFY = dedent("""\ |
2125 | CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$ |
2126 | DECLARE |
2127 | node RECORD; |
2128 | BEGIN |
2129 | - SELECT system_id, installable INTO node |
2130 | + SELECT system_id, node_type INTO node |
2131 | FROM maasserver_node, maasserver_blockdevice |
2132 | WHERE maasserver_node.id = maasserver_blockdevice.node_id |
2133 | AND maasserver_blockdevice.id = %s; |
2134 | |
2135 | - IF node.installable THEN |
2136 | + IF node.node_type = %d THEN |
2137 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2138 | END IF; |
2139 | RETURN NEW; |
2140 | @@ -273,12 +274,12 @@ |
2141 | DECLARE |
2142 | node RECORD; |
2143 | BEGIN |
2144 | - SELECT system_id, installable INTO node |
2145 | + SELECT system_id, node_type INTO node |
2146 | FROM maasserver_node, maasserver_blockdevice |
2147 | WHERE maasserver_node.id = maasserver_blockdevice.node_id |
2148 | AND maasserver_blockdevice.id = %s; |
2149 | |
2150 | - IF node.installable THEN |
2151 | + IF node.node_type = %d THEN |
2152 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2153 | END IF; |
2154 | RETURN NEW; |
2155 | @@ -293,7 +294,7 @@ |
2156 | DECLARE |
2157 | node RECORD; |
2158 | BEGIN |
2159 | - SELECT system_id, installable INTO node |
2160 | + SELECT system_id, node_type INTO node |
2161 | FROM maasserver_node, |
2162 | maasserver_blockdevice, |
2163 | maasserver_partitiontable |
2164 | @@ -301,7 +302,7 @@ |
2165 | AND maasserver_blockdevice.id = maasserver_partitiontable.block_device_id |
2166 | AND maasserver_partitiontable.id = %s; |
2167 | |
2168 | - IF node.installable THEN |
2169 | + IF node.node_type = %d THEN |
2170 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2171 | END IF; |
2172 | RETURN NEW; |
2173 | @@ -316,7 +317,7 @@ |
2174 | DECLARE |
2175 | node RECORD; |
2176 | BEGIN |
2177 | - SELECT system_id, installable INTO node |
2178 | + SELECT system_id, node_type INTO node |
2179 | FROM maasserver_node, |
2180 | maasserver_blockdevice, |
2181 | maasserver_partition, |
2182 | @@ -331,7 +332,7 @@ |
2183 | maasserver_partition.partition_table_id |
2184 | AND maasserver_partition.id = %s)); |
2185 | |
2186 | - IF node.installable THEN |
2187 | + IF node.node_type = %d THEN |
2188 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2189 | END IF; |
2190 | RETURN NEW; |
2191 | @@ -346,7 +347,7 @@ |
2192 | DECLARE |
2193 | node RECORD; |
2194 | BEGIN |
2195 | - SELECT system_id, installable INTO node |
2196 | + SELECT system_id, node_type INTO node |
2197 | FROM maasserver_node, |
2198 | maasserver_blockdevice, |
2199 | maasserver_partition, |
2200 | @@ -360,7 +361,7 @@ |
2201 | AND (maasserver_filesystem.filesystem_group_id = %s |
2202 | OR maasserver_filesystem.cache_set_id = %s); |
2203 | |
2204 | - IF node.installable THEN |
2205 | + IF node.node_type = %d THEN |
2206 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2207 | END IF; |
2208 | RETURN NEW; |
2209 | @@ -375,7 +376,7 @@ |
2210 | DECLARE |
2211 | node RECORD; |
2212 | BEGIN |
2213 | - SELECT system_id, installable INTO node |
2214 | + SELECT system_id, node_type INTO node |
2215 | FROM maasserver_node, |
2216 | maasserver_blockdevice, |
2217 | maasserver_partition, |
2218 | @@ -388,7 +389,7 @@ |
2219 | AND maasserver_partition.id = maasserver_filesystem.partition_id |
2220 | AND maasserver_filesystem.cache_set_id = %s; |
2221 | |
2222 | - IF node.installable THEN |
2223 | + IF node.node_type = %d THEN |
2224 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2225 | END IF; |
2226 | RETURN NEW; |
2227 | @@ -405,7 +406,7 @@ |
2228 | BEGIN |
2229 | FOR node IN ( |
2230 | SELECT DISTINCT ON (maasserver_node.id) |
2231 | - system_id, installable, parent_id |
2232 | + system_id, node_type, parent_id |
2233 | FROM |
2234 | maasserver_node, |
2235 | maasserver_subnet, |
2236 | @@ -418,7 +419,7 @@ |
2237 | AND ip_link.interface_id = maasserver_interface.id |
2238 | AND maasserver_node.id = maasserver_interface.node_id) |
2239 | LOOP |
2240 | - IF node.installable THEN |
2241 | + IF node.node_type = %d THEN |
2242 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2243 | ELSIF node.parent_id IS NOT NULL THEN |
2244 | SELECT system_id INTO pnode |
2245 | @@ -444,7 +445,7 @@ |
2246 | BEGIN |
2247 | FOR node IN ( |
2248 | SELECT DISTINCT ON (maasserver_node.id) |
2249 | - system_id, installable, parent_id |
2250 | + system_id, node_type, parent_id |
2251 | FROM |
2252 | maasserver_node, |
2253 | maasserver_fabric, |
2254 | @@ -455,7 +456,7 @@ |
2255 | AND maasserver_node.id = maasserver_interface.node_id |
2256 | AND maasserver_vlan.id = maasserver_interface.vlan_id) |
2257 | LOOP |
2258 | - IF node.installable THEN |
2259 | + IF node.node_type = %d THEN |
2260 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2261 | ELSIF node.parent_id IS NOT NULL THEN |
2262 | SELECT system_id INTO pnode |
2263 | @@ -481,7 +482,7 @@ |
2264 | BEGIN |
2265 | FOR node IN ( |
2266 | SELECT DISTINCT ON (maasserver_node.id) |
2267 | - system_id, installable, parent_id |
2268 | + system_id, node_type, parent_id |
2269 | FROM |
2270 | maasserver_node, |
2271 | maasserver_space, |
2272 | @@ -496,7 +497,7 @@ |
2273 | AND ip_link.interface_id = maasserver_interface.id |
2274 | AND maasserver_node.id = maasserver_interface.node_id) |
2275 | LOOP |
2276 | - IF node.installable THEN |
2277 | + IF node.node_type = %d THEN |
2278 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2279 | ELSIF node.parent_id IS NOT NULL THEN |
2280 | SELECT system_id INTO pnode |
2281 | @@ -522,13 +523,13 @@ |
2282 | BEGIN |
2283 | FOR node IN ( |
2284 | SELECT DISTINCT ON (maasserver_node.id) |
2285 | - system_id, installable, parent_id |
2286 | + system_id, node_type, parent_id |
2287 | FROM maasserver_node, maasserver_interface, maasserver_vlan |
2288 | WHERE maasserver_vlan.id = %s |
2289 | AND maasserver_node.id = maasserver_interface.node_id |
2290 | AND maasserver_vlan.id = maasserver_interface.vlan_id) |
2291 | LOOP |
2292 | - IF node.installable THEN |
2293 | + IF node.node_type = %d THEN |
2294 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2295 | ELSIF node.parent_id IS NOT NULL THEN |
2296 | SELECT system_id INTO pnode |
2297 | @@ -555,7 +556,7 @@ |
2298 | BEGIN |
2299 | FOR node IN ( |
2300 | SELECT DISTINCT ON (maasserver_node.id) |
2301 | - system_id, installable, parent_id |
2302 | + system_id, node_type, parent_id |
2303 | FROM |
2304 | maasserver_node, |
2305 | maasserver_interface, |
2306 | @@ -564,7 +565,7 @@ |
2307 | AND ip_link.interface_id = maasserver_interface.id |
2308 | AND maasserver_node.id = maasserver_interface.node_id) |
2309 | LOOP |
2310 | - IF node.installable THEN |
2311 | + IF node.node_type = %d THEN |
2312 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2313 | ELSIF node.parent_id IS NOT NULL THEN |
2314 | SELECT system_id INTO pnode |
2315 | @@ -638,11 +639,11 @@ |
2316 | node RECORD; |
2317 | pnode RECORD; |
2318 | BEGIN |
2319 | - SELECT system_id, installable, parent_id INTO node |
2320 | + SELECT system_id, node_type, parent_id INTO node |
2321 | FROM maasserver_node |
2322 | WHERE id = %s; |
2323 | |
2324 | - IF node.installable THEN |
2325 | + IF node.node_type = %d THEN |
2326 | PERFORM pg_notify('node_update',CAST(node.system_id AS text)); |
2327 | ELSIF node.parent_id IS NOT NULL THEN |
2328 | SELECT system_id INTO pnode |
2329 | @@ -655,7 +656,7 @@ |
2330 | RETURN NEW; |
2331 | END; |
2332 | $$ LANGUAGE plpgsql; |
2333 | - """ % (proc_name, node_id_relation)) |
2334 | + """ % (proc_name, node_id_relation, NODE_TYPE.MACHINE)) |
2335 | |
2336 | |
2337 | def register_trigger(table, procedure, event, params=None, when="after"): |
2338 | @@ -699,7 +700,7 @@ |
2339 | @transactional |
2340 | def register_all_triggers(): |
2341 | """Register all triggers into the database.""" |
2342 | - # Node(installable) table |
2343 | + # Node where type is node table |
2344 | register_procedure( |
2345 | render_notification_procedure( |
2346 | 'node_create_notify', 'node_create', 'NEW.system_id')) |
2347 | @@ -711,13 +712,13 @@ |
2348 | 'node_delete_notify', 'node_delete', 'OLD.system_id')) |
2349 | register_trigger( |
2350 | "maasserver_node", "node_create_notify", "insert", |
2351 | - {'NEW.installable': True}) |
2352 | + {'NEW.node_type': NODE_TYPE.MACHINE}) |
2353 | register_trigger( |
2354 | "maasserver_node", "node_update_notify", "update", |
2355 | - {'NEW.installable': True}) |
2356 | + {'NEW.node_type': NODE_TYPE.MACHINE}) |
2357 | register_trigger( |
2358 | "maasserver_node", "node_delete_notify", "delete", |
2359 | - {'OLD.installable': True}) |
2360 | + {'OLD.node_type': NODE_TYPE.MACHINE}) |
2361 | |
2362 | # Node(device) table |
2363 | register_procedure( |
2364 | @@ -731,13 +732,13 @@ |
2365 | 'device_delete_notify', 'device_delete', 'OLD')) |
2366 | register_trigger( |
2367 | "maasserver_node", "device_create_notify", "insert", |
2368 | - {'NEW.installable': False}) |
2369 | + {'NEW.node_type': NODE_TYPE.DEVICE}) |
2370 | register_trigger( |
2371 | "maasserver_node", "device_update_notify", "update", |
2372 | - {'NEW.installable': False}) |
2373 | + {'NEW.node_type': NODE_TYPE.DEVICE}) |
2374 | register_trigger( |
2375 | "maasserver_node", "device_delete_notify", "delete", |
2376 | - {'OLD.installable': False}) |
2377 | + {'OLD.node_type': NODE_TYPE.DEVICE}) |
2378 | |
2379 | # VLAN table |
2380 | register_procedure( |
2381 | @@ -856,28 +857,32 @@ |
2382 | |
2383 | # Subnet node notifications |
2384 | register_procedure( |
2385 | - SUBNET_NODE_NOTIFY % ('subnet_node_update_notify', 'NEW.id',)) |
2386 | + SUBNET_NODE_NOTIFY % ('subnet_node_update_notify', 'NEW.id', |
2387 | + NODE_TYPE.MACHINE)) |
2388 | register_trigger( |
2389 | "maasserver_subnet", |
2390 | "subnet_node_update_notify", "update") |
2391 | |
2392 | # Fabric node notifications |
2393 | register_procedure( |
2394 | - FABRIC_NODE_NOTIFY % ('fabric_node_update_notify', 'NEW.id',)) |
2395 | + FABRIC_NODE_NOTIFY % ('fabric_node_update_notify', 'NEW.id', |
2396 | + NODE_TYPE.MACHINE)) |
2397 | register_trigger( |
2398 | "maasserver_fabric", |
2399 | "fabric_node_update_notify", "update") |
2400 | |
2401 | # Space node notifications |
2402 | register_procedure( |
2403 | - SPACE_NODE_NOTIFY % ('space_node_update_notify', 'NEW.id',)) |
2404 | + SPACE_NODE_NOTIFY % ('space_node_update_notify', 'NEW.id', |
2405 | + NODE_TYPE.MACHINE)) |
2406 | register_trigger( |
2407 | "maasserver_space", |
2408 | "space_node_update_notify", "update") |
2409 | |
2410 | # VLAN node notifications |
2411 | register_procedure( |
2412 | - VLAN_NODE_NOTIFY % ('vlan_node_update_notify', 'NEW.id',)) |
2413 | + VLAN_NODE_NOTIFY % ('vlan_node_update_notify', 'NEW.id', |
2414 | + NODE_TYPE.MACHINE)) |
2415 | register_trigger( |
2416 | "maasserver_vlan", |
2417 | "vlan_node_update_notify", "update") |
2418 | @@ -885,7 +890,7 @@ |
2419 | # IP address node notifications |
2420 | register_procedure( |
2421 | STATIC_IP_ADDRESS_NODE_NOTIFY % ( |
2422 | - 'ipaddress_node_update_notify', 'NEW.id',)) |
2423 | + 'ipaddress_node_update_notify', 'NEW.id', NODE_TYPE.MACHINE)) |
2424 | register_trigger( |
2425 | "maasserver_staticipaddress", |
2426 | "ipaddress_node_update_notify", "update") |
2427 | @@ -934,21 +939,17 @@ |
2428 | # Node tag link table |
2429 | register_procedure( |
2430 | NODE_TAG_NOTIFY % ( |
2431 | - 'node_device_tag_link_notify', |
2432 | - 'NEW.node_id', |
2433 | - )) |
2434 | + 'node_device_tag_link_notify', 'NEW.node_id', NODE_TYPE.MACHINE)) |
2435 | register_procedure( |
2436 | NODE_TAG_NOTIFY % ( |
2437 | - 'node_device_tag_unlink_notify', |
2438 | - 'OLD.node_id', |
2439 | - )) |
2440 | + 'node_device_tag_unlink_notify', 'OLD.node_id', NODE_TYPE.MACHINE)) |
2441 | register_trigger( |
2442 | "maasserver_node_tags", "node_device_tag_link_notify", "insert") |
2443 | register_trigger( |
2444 | "maasserver_node_tags", "node_device_tag_unlink_notify", "delete") |
2445 | |
2446 | # Tag table, update to linked nodes. |
2447 | - register_procedure(TAG_NODES_NOTIFY) |
2448 | + register_procedure(TAG_NODES_NOTIFY % NODE_TYPE.MACHINE) |
2449 | register_trigger( |
2450 | "maasserver_tag", "tag_update_node_device_notify", "update") |
2451 | |
2452 | @@ -987,21 +988,19 @@ |
2453 | "maasserver_event", "event_delete_notify", "delete") |
2454 | |
2455 | # Events table, update to linked node. |
2456 | - register_procedure(EVENT_NODE_NOTIFY) |
2457 | + register_procedure(EVENT_NODE_NOTIFY % NODE_TYPE.MACHINE) |
2458 | register_trigger( |
2459 | "maasserver_event", "event_create_node_device_notify", "insert") |
2460 | |
2461 | # MAC static ip address table, update to linked node. |
2462 | register_procedure( |
2463 | INTERFACE_IP_ADDRESS_NODE_NOTIFY % ( |
2464 | - 'nd_sipaddress_link_notify', |
2465 | - 'NEW.interface_id', |
2466 | - )) |
2467 | + 'nd_sipaddress_link_notify', 'NEW.interface_id', |
2468 | + NODE_TYPE.MACHINE)) |
2469 | register_procedure( |
2470 | INTERFACE_IP_ADDRESS_NODE_NOTIFY % ( |
2471 | - 'nd_sipaddress_unlink_notify', |
2472 | - 'OLD.interface_id', |
2473 | - )) |
2474 | + 'nd_sipaddress_unlink_notify', 'OLD.interface_id', |
2475 | + NODE_TYPE.MACHINE)) |
2476 | register_trigger( |
2477 | "maasserver_interface_ip_addresses", |
2478 | "nd_sipaddress_link_notify", "insert") |
2479 | @@ -1030,7 +1029,8 @@ |
2480 | register_procedure( |
2481 | render_node_related_notification_procedure( |
2482 | 'nd_interface_unlink_notify', 'OLD.node_id')) |
2483 | - register_procedure(INTERFACE_UPDATE_NODE_NOTIFY) |
2484 | + register_procedure( |
2485 | + INTERFACE_UPDATE_NODE_NOTIFY % (NODE_TYPE.MACHINE, NODE_TYPE.MACHINE)) |
2486 | register_trigger( |
2487 | "maasserver_interface", |
2488 | "nd_interface_link_notify", "insert") |
2489 | @@ -1053,10 +1053,12 @@ |
2490 | 'nd_blockdevice_unlink_notify', 'OLD.node_id')) |
2491 | register_procedure( |
2492 | PHYSICAL_OR_VIRTUAL_BLOCK_DEVICE_NODE_NOTIFY % ( |
2493 | - 'nd_physblockdevice_update_notify', 'NEW.blockdevice_ptr_id')) |
2494 | + 'nd_physblockdevice_update_notify', 'NEW.blockdevice_ptr_id', |
2495 | + NODE_TYPE.MACHINE)) |
2496 | register_procedure( |
2497 | PHYSICAL_OR_VIRTUAL_BLOCK_DEVICE_NODE_NOTIFY % ( |
2498 | - 'nd_virtblockdevice_update_notify', 'NEW.blockdevice_ptr_id')) |
2499 | + 'nd_virtblockdevice_update_notify', 'NEW.blockdevice_ptr_id', |
2500 | + NODE_TYPE.MACHINE)) |
2501 | register_trigger( |
2502 | "maasserver_blockdevice", |
2503 | "nd_blockdevice_link_notify", "insert") |
2504 | @@ -1076,13 +1078,17 @@ |
2505 | # Partition table, update to linked user. |
2506 | register_procedure( |
2507 | PARTITIONTABLE_NODE_NOTIFY % ( |
2508 | - 'nd_partitiontable_link_notify', 'NEW.block_device_id')) |
2509 | - register_procedure( |
2510 | - PARTITIONTABLE_NODE_NOTIFY % ( |
2511 | - 'nd_partitiontable_update_notify', 'NEW.block_device_id')) |
2512 | - register_procedure( |
2513 | - PARTITIONTABLE_NODE_NOTIFY % ( |
2514 | - 'nd_partitiontable_unlink_notify', 'OLD.block_device_id')) |
2515 | + 'nd_partitiontable_link_notify', 'NEW.block_device_id', |
2516 | + NODE_TYPE.MACHINE)) |
2517 | + register_procedure( |
2518 | + PARTITIONTABLE_NODE_NOTIFY % ( |
2519 | + 'nd_partitiontable_update_notify', |
2520 | + 'NEW.block_device_id', |
2521 | + NODE_TYPE.MACHINE)) |
2522 | + register_procedure( |
2523 | + PARTITIONTABLE_NODE_NOTIFY % ( |
2524 | + 'nd_partitiontable_unlink_notify', 'OLD.block_device_id', |
2525 | + NODE_TYPE.MACHINE)) |
2526 | register_trigger( |
2527 | "maasserver_partitiontable", |
2528 | "nd_partitiontable_link_notify", "insert") |
2529 | @@ -1096,13 +1102,16 @@ |
2530 | # Partition, update to linked user. |
2531 | register_procedure( |
2532 | PARTITION_NODE_NOTIFY % ( |
2533 | - 'nd_partition_link_notify', 'NEW.partition_table_id')) |
2534 | - register_procedure( |
2535 | - PARTITION_NODE_NOTIFY % ( |
2536 | - 'nd_partition_update_notify', 'NEW.partition_table_id')) |
2537 | - register_procedure( |
2538 | - PARTITION_NODE_NOTIFY % ( |
2539 | - 'nd_partition_unlink_notify', 'OLD.partition_table_id')) |
2540 | + 'nd_partition_link_notify', 'NEW.partition_table_id', |
2541 | + NODE_TYPE.MACHINE)) |
2542 | + register_procedure( |
2543 | + PARTITION_NODE_NOTIFY % ( |
2544 | + 'nd_partition_update_notify', 'NEW.partition_table_id', |
2545 | + NODE_TYPE.MACHINE)) |
2546 | + register_procedure( |
2547 | + PARTITION_NODE_NOTIFY % ( |
2548 | + 'nd_partition_unlink_notify', 'OLD.partition_table_id', |
2549 | + NODE_TYPE.MACHINE)) |
2550 | register_trigger( |
2551 | "maasserver_partition", |
2552 | "nd_partition_link_notify", "insert") |
2553 | @@ -1117,15 +1126,15 @@ |
2554 | register_procedure( |
2555 | FILESYSTEM_NODE_NOTIFY % ( |
2556 | 'nd_filesystem_link_notify', 'NEW.block_device_id', |
2557 | - 'NEW.partition_id')) |
2558 | + 'NEW.partition_id', NODE_TYPE.MACHINE)) |
2559 | register_procedure( |
2560 | FILESYSTEM_NODE_NOTIFY % ( |
2561 | 'nd_filesystem_update_notify', 'NEW.block_device_id', |
2562 | - 'NEW.partition_id')) |
2563 | + 'NEW.partition_id', NODE_TYPE.MACHINE)) |
2564 | register_procedure( |
2565 | FILESYSTEM_NODE_NOTIFY % ( |
2566 | 'nd_filesystem_unlink_notify', 'OLD.block_device_id', |
2567 | - 'OLD.partition_id')) |
2568 | + 'OLD.partition_id', NODE_TYPE.MACHINE)) |
2569 | register_trigger( |
2570 | "maasserver_filesystem", |
2571 | "nd_filesystem_link_notify", "insert") |
2572 | @@ -1139,13 +1148,16 @@ |
2573 | # Filesystemgroup, update to linked user. |
2574 | register_procedure( |
2575 | FILESYSTEMGROUP_NODE_NOTIFY % ( |
2576 | - 'nd_filesystemgroup_link_notify', 'NEW.id', 'NEW.cache_set_id')) |
2577 | - register_procedure( |
2578 | - FILESYSTEMGROUP_NODE_NOTIFY % ( |
2579 | - 'nd_filesystemgroup_update_notify', 'NEW.id', 'NEW.cache_set_id')) |
2580 | - register_procedure( |
2581 | - FILESYSTEMGROUP_NODE_NOTIFY % ( |
2582 | - 'nd_filesystemgroup_unlink_notify', 'OLD.id', 'OLD.cache_set_id')) |
2583 | + 'nd_filesystemgroup_link_notify', 'NEW.id', 'NEW.cache_set_id', |
2584 | + NODE_TYPE.MACHINE)) |
2585 | + register_procedure( |
2586 | + FILESYSTEMGROUP_NODE_NOTIFY % ( |
2587 | + 'nd_filesystemgroup_update_notify', 'NEW.id', 'NEW.cache_set_id', |
2588 | + NODE_TYPE.MACHINE)) |
2589 | + register_procedure( |
2590 | + FILESYSTEMGROUP_NODE_NOTIFY % ( |
2591 | + 'nd_filesystemgroup_unlink_notify', 'OLD.id', 'OLD.cache_set_id', |
2592 | + NODE_TYPE.MACHINE)) |
2593 | register_trigger( |
2594 | "maasserver_filesystemgroup", |
2595 | "nd_filesystemgroup_link_notify", "insert") |
2596 | @@ -1159,13 +1171,13 @@ |
2597 | # Cacheset, update to linked user. |
2598 | register_procedure( |
2599 | CACHESET_NODE_NOTIFY % ( |
2600 | - 'nd_cacheset_link_notify', 'NEW.id')) |
2601 | - register_procedure( |
2602 | - CACHESET_NODE_NOTIFY % ( |
2603 | - 'nd_cacheset_update_notify', 'NEW.id')) |
2604 | - register_procedure( |
2605 | - CACHESET_NODE_NOTIFY % ( |
2606 | - 'nd_cacheset_unlink_notify', 'OLD.id')) |
2607 | + 'nd_cacheset_link_notify', 'NEW.id', NODE_TYPE.MACHINE)) |
2608 | + register_procedure( |
2609 | + CACHESET_NODE_NOTIFY % ( |
2610 | + 'nd_cacheset_update_notify', 'NEW.id', NODE_TYPE.MACHINE)) |
2611 | + register_procedure( |
2612 | + CACHESET_NODE_NOTIFY % ( |
2613 | + 'nd_cacheset_unlink_notify', 'OLD.id', NODE_TYPE.MACHINE)) |
2614 | register_trigger( |
2615 | "maasserver_cacheset", |
2616 | "nd_cacheset_link_notify", "insert") |
2617 | |
2618 | === modified file 'src/maasserver/websockets/handlers/device.py' |
2619 | --- src/maasserver/websockets/handlers/device.py 2015-12-01 18:12:59 +0000 |
2620 | +++ src/maasserver/websockets/handlers/device.py 2015-12-18 15:12:10 +0000 |
2621 | @@ -11,6 +11,7 @@ |
2622 | from maasserver.enum import ( |
2623 | IPADDRESS_TYPE, |
2624 | NODE_PERMISSION, |
2625 | + NODE_TYPE, |
2626 | ) |
2627 | from maasserver.exceptions import NodeActionError |
2628 | from maasserver.forms import ( |
2629 | @@ -87,7 +88,7 @@ |
2630 | |
2631 | class Meta: |
2632 | queryset = ( |
2633 | - Device.devices.filter(installable=False, parent=None) |
2634 | + Device.devices.filter(node_type=NODE_TYPE.DEVICE, parent=None) |
2635 | .select_related('nodegroup', 'owner') |
2636 | .prefetch_related('interface_set__ip_addresses__subnet') |
2637 | .prefetch_related('nodegroup__nodegroupinterface_set') |
2638 | @@ -98,7 +99,7 @@ |
2639 | allowed_methods = ['list', 'get', 'set_active', 'create', 'action'] |
2640 | exclude = [ |
2641 | "id", |
2642 | - "installable", |
2643 | + "type", |
2644 | "boot_interface", |
2645 | "boot_cluster_ip", |
2646 | "boot_disk", |
2647 | |
2648 | === modified file 'src/maasserver/websockets/handlers/general.py' |
2649 | --- src/maasserver/websockets/handlers/general.py 2015-12-01 18:12:59 +0000 |
2650 | +++ src/maasserver/websockets/handlers/general.py 2015-12-18 15:12:10 +0000 |
2651 | @@ -94,19 +94,19 @@ |
2652 | actions = dict() |
2653 | for name, action in ACTIONS_DICT.items(): |
2654 | permission = action.permission |
2655 | - if action.installable_permission is not None: |
2656 | - permission = action.installable_permission |
2657 | + if action.node_permission is not None: |
2658 | + permission = action.node_permission |
2659 | if permission != NODE_PERMISSION.ADMIN: |
2660 | actions[name] = action |
2661 | return self.dehydrate_actions(actions) |
2662 | |
2663 | def device_actions(self, params): |
2664 | """Return all possible device actions.""" |
2665 | - # Remove the actions that can only be performed on installable nodes. |
2666 | + # Remove the actions that can only be performed on nodes. |
2667 | actions = { |
2668 | name: action |
2669 | for name, action in ACTIONS_DICT.items() |
2670 | - if not action.installable_only |
2671 | + if not action.node_only |
2672 | } |
2673 | return self.dehydrate_actions(actions) |
2674 | |
2675 | |
2676 | === modified file 'src/maasserver/websockets/handlers/node.py' |
2677 | --- src/maasserver/websockets/handlers/node.py 2015-12-01 18:12:59 +0000 |
2678 | +++ src/maasserver/websockets/handlers/node.py 2015-12-18 15:12:10 +0000 |
2679 | @@ -19,6 +19,7 @@ |
2680 | IPADDRESS_TYPE, |
2681 | NODE_PERMISSION, |
2682 | NODE_STATUS, |
2683 | + NODE_TYPE, |
2684 | ) |
2685 | from maasserver.exceptions import NodeActionError |
2686 | from maasserver.forms import ( |
2687 | @@ -106,7 +107,7 @@ |
2688 | |
2689 | class Meta: |
2690 | queryset = ( |
2691 | - Node.nodes.filter(installable=True) |
2692 | + Node.nodes.filter(node_type=NODE_TYPE.MACHINE) |
2693 | .select_related('nodegroup', 'boot_interface', 'owner') |
2694 | .prefetch_related( |
2695 | 'interface_set__ip_addresses__subnet__vlan__fabric') |
2696 | @@ -151,7 +152,6 @@ |
2697 | ] |
2698 | form = AdminNodeWithMACAddressesForm |
2699 | exclude = [ |
2700 | - "installable", |
2701 | "parent", |
2702 | "boot_interface", |
2703 | "boot_cluster_ip", |
2704 | @@ -1188,7 +1188,7 @@ |
2705 | @transactional |
2706 | def get_node_cluster_and_power_info(): |
2707 | obj = self.get_object(params) |
2708 | - if obj.installable: |
2709 | + if obj.power_type is not None: |
2710 | node_info = obj.system_id, obj.hostname |
2711 | nodegroup_info = obj.nodegroup.cluster_name, obj.nodegroup.uuid |
2712 | try: |
2713 | @@ -1199,8 +1199,8 @@ |
2714 | return node_info, nodegroup_info, power_info |
2715 | else: |
2716 | raise HandlerError( |
2717 | - "%s: Unable to query power state; not an " |
2718 | - "installable node" % obj.hostname) |
2719 | + "%s: Unable to query power state; no power state defined" |
2720 | + % obj.hostname) |
2721 | |
2722 | @transactional |
2723 | def update_power_state(state): |
2724 | |
2725 | === modified file 'src/maasserver/websockets/handlers/tests/test_device.py' |
2726 | --- src/maasserver/websockets/handlers/tests/test_device.py 2015-12-02 20:43:30 +0000 |
2727 | +++ src/maasserver/websockets/handlers/tests/test_device.py 2015-12-18 15:12:10 +0000 |
2728 | @@ -7,6 +7,7 @@ |
2729 | |
2730 | from maasserver.enum import ( |
2731 | IPADDRESS_TYPE, |
2732 | + NODE_TYPE, |
2733 | NODEGROUP_STATUS, |
2734 | NODEGROUPINTERFACE_MANAGEMENT, |
2735 | ) |
2736 | @@ -107,6 +108,7 @@ |
2737 | tag.name |
2738 | for tag in node.tags.all() |
2739 | ], |
2740 | + "node_type": node.node_type, |
2741 | "updated": dehydrate_datetime(node.updated), |
2742 | "zone": { |
2743 | "id": node.zone.id, |
2744 | @@ -140,7 +142,7 @@ |
2745 | if owner is None: |
2746 | owner = factory.make_User() |
2747 | device = factory.make_Node( |
2748 | - nodegroup=nodegroup, installable=False, |
2749 | + nodegroup=nodegroup, node_type=NODE_TYPE.DEVICE, |
2750 | interface=True, owner=owner) |
2751 | interface = device.get_boot_interface() |
2752 | if ip_assignment == DEVICE_IP_ASSIGNMENT.EXTERNAL: |
2753 | @@ -483,7 +485,7 @@ |
2754 | |
2755 | def test_action_performs_action(self): |
2756 | user = factory.make_User() |
2757 | - device = factory.make_Node(owner=user, installable=False) |
2758 | + device = factory.make_Node(owner=user, node_type=NODE_TYPE.DEVICE) |
2759 | handler = DeviceHandler(user, {}) |
2760 | handler.action({"system_id": device.system_id, "action": "delete"}) |
2761 | self.assertIsNone(reload_object(device)) |
2762 | |
2763 | === modified file 'src/maasserver/websockets/handlers/tests/test_general.py' |
2764 | --- src/maasserver/websockets/handlers/tests/test_general.py 2015-12-01 18:12:59 +0000 |
2765 | +++ src/maasserver/websockets/handlers/tests/test_general.py 2015-12-18 15:12:10 +0000 |
2766 | @@ -115,8 +115,8 @@ |
2767 | actions_expected = dict() |
2768 | for name, action in ACTIONS_DICT.items(): |
2769 | permission = action.permission |
2770 | - if action.installable_permission is not None: |
2771 | - permission = action.installable_permission |
2772 | + if action.node_permission is not None: |
2773 | + permission = action.node_permission |
2774 | if permission != NODE_PERMISSION.ADMIN: |
2775 | actions_expected[name] = action |
2776 | actions_expected = self.dehydrate_actions(actions_expected) |
2777 | @@ -127,7 +127,7 @@ |
2778 | actions_expected = self.dehydrate_actions({ |
2779 | name: action |
2780 | for name, action in ACTIONS_DICT.items() |
2781 | - if not action.installable_only |
2782 | + if not action.node_only |
2783 | }) |
2784 | self.assertItemsEqual(actions_expected, handler.device_actions({})) |
2785 | |
2786 | |
2787 | === modified file 'src/maasserver/websockets/handlers/tests/test_node.py' |
2788 | --- src/maasserver/websockets/handlers/tests/test_node.py 2015-12-02 20:43:30 +0000 |
2789 | +++ src/maasserver/websockets/handlers/tests/test_node.py 2015-12-18 15:12:10 +0000 |
2790 | @@ -23,6 +23,7 @@ |
2791 | INTERFACE_TYPE, |
2792 | IPADDRESS_TYPE, |
2793 | NODE_STATUS, |
2794 | + NODE_TYPE, |
2795 | ) |
2796 | from maasserver.exceptions import NodeActionError |
2797 | from maasserver.forms import AdminNodeWithMACAddressesForm |
2798 | @@ -213,6 +214,7 @@ |
2799 | "module": driver["module"] if "module" in driver else "", |
2800 | "comment": driver["comment"] if "comment" in driver else "", |
2801 | }, |
2802 | + "node_type": node.node_type, |
2803 | "updated": dehydrate_datetime(node.updated), |
2804 | "zone": handler.dehydrate_zone(node.zone), |
2805 | } |
2806 | @@ -248,7 +250,7 @@ |
2807 | # Make some devices. |
2808 | for _ in range(3): |
2809 | factory.make_Node( |
2810 | - installable=False, parent=node, interface=True) |
2811 | + node_type=NODE_TYPE.DEVICE, parent=node, interface=True) |
2812 | |
2813 | def test_dehydrate_owner_empty_when_None(self): |
2814 | owner = factory.make_User() |
2815 | @@ -333,7 +335,7 @@ |
2816 | owner = factory.make_User() |
2817 | node = factory.make_Node(owner=owner) |
2818 | handler = NodeHandler(owner, {}) |
2819 | - device = factory.make_Node(installable=False, parent=node) |
2820 | + device = factory.make_Node(node_type=NODE_TYPE.DEVICE, parent=node) |
2821 | interface = factory.make_Interface( |
2822 | INTERFACE_TYPE.PHYSICAL, node=device) |
2823 | self.assertEqual({ |
2824 | @@ -831,7 +833,7 @@ |
2825 | # Make some devices. |
2826 | for _ in range(3): |
2827 | factory.make_Node( |
2828 | - installable=False, parent=node, interface=True) |
2829 | + node_type=NODE_TYPE.DEVICE, parent=node, interface=True) |
2830 | |
2831 | self.patch_autospec(interface_module, "update_host_maps") |
2832 | boot_interface = node.get_boot_interface() |
2833 | @@ -856,7 +858,7 @@ |
2834 | owner = factory.make_User() |
2835 | handler = NodeHandler(owner, {}) |
2836 | # Create a device. |
2837 | - factory.make_Node(owner=owner, installable=False) |
2838 | + factory.make_Node(owner=owner, node_type=NODE_TYPE.DEVICE) |
2839 | node = factory.make_Node(owner=owner) |
2840 | self.assertItemsEqual( |
2841 | [self.dehydrate_node(node, handler, for_list=True)], |
All branches merged in maas-ha have already been reviewed and approved.