Merge ~ltrager/maas:lp1650396 into maas:master
- Git
- lp:~ltrager/maas
- lp1650396
- Merge into master
Status: | Merged |
---|---|
Approved by: | Lee Trager |
Approved revision: | fa3a3006598c6fedb68ac6e7fcf957a5e9fd36da |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~ltrager/maas:lp1650396 |
Merge into: | maas:master |
Diff against target: |
441 lines (+61/-79) 5 files modified
src/maasserver/api/interfaces.py (+6/-14) src/maasserver/api/tests/test_interfaces.py (+29/-16) src/maasserver/static/js/angular/controllers/node_details_networking.js (+7/-30) src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js (+8/-8) src/maasserver/static/partials/node-details.html (+11/-11) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Needs Information | ||
Данило Шеган (community) | Approve | ||
Review via email: mp+326332@code.launchpad.net |
Commit message
Allow editing of network settings while a machine is in an allocated state.
This fixes LP:1650396
Description of the change
- a75bb01... by Lee Trager
-
Merge branch 'master' into lp1650396
- bcf2525... by Lee Trager
-
Squashed commit of the following:
commit a4f9627af7727bb
96f4aad276c7f4a 8d88b06d6a
Author: Lee Trager <email address hidden>
Date: Tue Jun 27 19:31:06 2017 +0000Remove link-junk from Makefile
make lint ran link-junk which checks for bzr files accidentally committed.
MAAS is no longer in bzr so this check is no longer needed and keeping it
causes bzr to complain its not being run from a bzr branch. - 0e05b6c... by Lee Trager
-
danilo fixes
- d5b995b... by Lee Trager
-
danilo fixes
Lee Trager (ltrager) wrote : | # |
Thanks for the review. I missed that MAAS allows editing of an interface name and MAC while deployed. I've brought back isLimitedEditin
Данило Шеган (danilo) wrote : | # |
Looks good, thanks. It seems there's one change from isLimited... to isAllNetworking... that you missed to revert. Not blocking on it, though.
Andres Rodriguez (andreserl) wrote : | # |
this needs a backport to 2.2
Andres Rodriguez (andreserl) wrote : | # |
I have a comment inline
- 2cece51... by Lee Trager
-
Danillo fixes
- fa3a300... by Lee Trager
-
Merge branch 'lp1650396' of git+ssh:
//git.launchpad .net/~ltrager/ maas into lp1650396
Preview Diff
1 | diff --git a/src/maasserver/api/interfaces.py b/src/maasserver/api/interfaces.py |
2 | index bd55ef6..5e96ff4 100644 |
3 | --- a/src/maasserver/api/interfaces.py |
4 | +++ b/src/maasserver/api/interfaces.py |
5 | @@ -1,4 +1,4 @@ |
6 | -# Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
7 | +# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
8 | # GNU Affero General Public License version 3 (see the file LICENSE). |
9 | |
10 | """API handlers: `Interface`.""" |
11 | @@ -92,7 +92,7 @@ INTERFACES_PREFETCH = [ |
12 | 'children_relationships__child__vlan'), |
13 | ] |
14 | |
15 | -ALLOWED_STATES = (NODE_STATUS.READY, NODE_STATUS.BROKEN) |
16 | +ALLOWED_STATES = (NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN) |
17 | |
18 | |
19 | def raise_error_for_invalid_state_on_allocated_operations( |
20 | @@ -112,8 +112,8 @@ def raise_error_for_invalid_state_on_allocated_operations( |
21 | allowed.extend(extra_states) |
22 | if node.status not in allowed: |
23 | raise NodeStateViolation( |
24 | - "Cannot %s interface because the machine is not Ready or " |
25 | - "Broken." % operation) |
26 | + "Cannot %s interface because the machine is not Ready, Allocated, " |
27 | + "or Broken." % operation) |
28 | |
29 | |
30 | def raise_error_if_controller(node, operation): |
31 | @@ -327,16 +327,8 @@ class InterfacesHandler(OperationsHandler): |
32 | """ |
33 | machine = Machine.objects.get_node_or_404( |
34 | system_id, request.user, NODE_PERMISSION.EDIT) |
35 | - if machine.status not in ( |
36 | - NODE_STATUS.READY, NODE_STATUS.BROKEN, NODE_STATUS.ALLOCATED): |
37 | - raise NodeStateViolation( |
38 | - "Cannot create bridge interface because the machine is not " |
39 | - "Ready, Broken, or Allocated.") |
40 | - if (not request.user.is_superuser and |
41 | - machine.status in ALLOWED_STATES): |
42 | - raise NodeStateViolation( |
43 | - "Machine must be alloacted to '%s' to allow bridge " |
44 | - "creation." % request.user.username) |
45 | + raise_error_for_invalid_state_on_allocated_operations( |
46 | + machine, request.user, "create bridge") |
47 | # Cast parent to parents to make it easier on the user and to make it |
48 | # work with the form. |
49 | request.data = request.data.copy() |
50 | diff --git a/src/maasserver/api/tests/test_interfaces.py b/src/maasserver/api/tests/test_interfaces.py |
51 | index 6fb1b9f..e6c91a1 100644 |
52 | --- a/src/maasserver/api/tests/test_interfaces.py |
53 | +++ b/src/maasserver/api/tests/test_interfaces.py |
54 | @@ -1,4 +1,4 @@ |
55 | -# Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
56 | +# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
57 | # GNU Affero General Public License version 3 (see the file LICENSE). |
58 | |
59 | """Tests for NodeInterfaces API.""" |
60 | @@ -43,7 +43,6 @@ STATUSES = ( |
61 | NODE_STATUS.FAILED_COMMISSIONING, |
62 | NODE_STATUS.MISSING, |
63 | NODE_STATUS.RESERVED, |
64 | - NODE_STATUS.ALLOCATED, |
65 | NODE_STATUS.DEPLOYING, |
66 | NODE_STATUS.DEPLOYED, |
67 | NODE_STATUS.RETIRED, |
68 | @@ -241,7 +240,8 @@ class TestInterfacesAPI(APITestCase.ForUser): |
69 | |
70 | def test_create_physical_disabled(self): |
71 | self.become_admin() |
72 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
73 | + for status in ( |
74 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
75 | node = factory.make_Node(status=status) |
76 | mac = factory.make_mac_address() |
77 | name = factory.make_name("eth") |
78 | @@ -342,7 +342,8 @@ class TestInterfacesAPI(APITestCase.ForUser): |
79 | |
80 | def test_create_bond(self): |
81 | self.become_admin() |
82 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
83 | + for status in ( |
84 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
85 | node = factory.make_Node(status=status) |
86 | vlan = factory.make_VLAN() |
87 | parent_1_iface = factory.make_Interface( |
88 | @@ -931,7 +932,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
89 | |
90 | def test_update_physical_interface(self): |
91 | self.become_admin() |
92 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
93 | + for status in ( |
94 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
95 | node = factory.make_Node(status=status) |
96 | interface = factory.make_Interface( |
97 | INTERFACE_TYPE.PHYSICAL, node=node) |
98 | @@ -969,7 +971,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
99 | |
100 | def test_update_bond_interface(self): |
101 | self.become_admin() |
102 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
103 | + for status in ( |
104 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
105 | node = factory.make_Node(status=status) |
106 | bond, [nic_0, nic_1], [vlan_10, vlan_11] = make_complex_interface( |
107 | node) |
108 | @@ -984,7 +987,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
109 | |
110 | def test_update_vlan_interface(self): |
111 | self.become_admin() |
112 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
113 | + for status in ( |
114 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
115 | node = factory.make_Node(status=status) |
116 | bond, [nic_0, nic_1], [vlan_10, vlan_11] = make_complex_interface( |
117 | node) |
118 | @@ -1031,7 +1035,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
119 | |
120 | def test_delete_deletes_interface(self): |
121 | self.become_admin() |
122 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
123 | + for status in ( |
124 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
125 | node = factory.make_Node(interface=True, status=status) |
126 | interface = node.get_boot_interface() |
127 | uri = get_interface_uri(interface) |
128 | @@ -1086,7 +1091,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
129 | # This just tests that the form is saved and the updated interface |
130 | # is returned. |
131 | self.become_admin() |
132 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
133 | + for status in ( |
134 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
135 | node = factory.make_Node(interface=True, status=status) |
136 | interface = node.get_boot_interface() |
137 | uri = get_interface_uri(interface) |
138 | @@ -1324,7 +1330,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
139 | |
140 | def test_link_subnet_raises_error(self): |
141 | self.become_admin() |
142 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
143 | + for status in ( |
144 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
145 | node = factory.make_Node(interface=True, status=status) |
146 | interface = node.get_boot_interface() |
147 | uri = get_interface_uri(interface) |
148 | @@ -1366,7 +1373,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
149 | # This just tests that the form is saved and the updated interface |
150 | # is returned. |
151 | self.become_admin() |
152 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
153 | + for status in ( |
154 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
155 | node = factory.make_Node(interface=True, status=status) |
156 | interface = node.get_boot_interface() |
157 | subnet = factory.make_Subnet() |
158 | @@ -1403,7 +1411,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
159 | |
160 | def test_unlink_subnet_raises_error(self): |
161 | self.become_admin() |
162 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
163 | + for status in ( |
164 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
165 | node = factory.make_Node(interface=True, status=status) |
166 | interface = node.get_boot_interface() |
167 | uri = get_interface_uri(interface) |
168 | @@ -1444,7 +1453,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
169 | # This just tests that the form is saved and the updated interface |
170 | # is returned. |
171 | self.become_admin() |
172 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
173 | + for status in ( |
174 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
175 | node = factory.make_Node(interface=True, status=status) |
176 | interface = node.get_boot_interface() |
177 | subnet = factory.make_Subnet() |
178 | @@ -1486,7 +1496,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
179 | # The form that is used is fully tested in test_forms_interface_link. |
180 | # This just tests that the form is saved and the node link is created. |
181 | self.become_admin() |
182 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
183 | + for status in ( |
184 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
185 | node = factory.make_Node(interface=True, status=status) |
186 | interface = node.get_boot_interface() |
187 | network = factory.make_ipv4_network() |
188 | @@ -1508,7 +1519,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
189 | # The form that is used is fully tested in test_forms_interface_link. |
190 | # This just tests that the form is saved and the node link is created. |
191 | self.become_admin() |
192 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
193 | + for status in ( |
194 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
195 | node = factory.make_Node(interface=True, status=status) |
196 | interface = node.get_boot_interface() |
197 | network = factory.make_ipv6_network() |
198 | @@ -1528,7 +1540,8 @@ class TestNodeInterfaceAPI(APITransactionTestCase.ForUser): |
199 | |
200 | def test_set_default_gateway_raises_error(self): |
201 | self.become_admin() |
202 | - for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
203 | + for status in ( |
204 | + NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.BROKEN): |
205 | node = factory.make_Node(interface=True, status=status) |
206 | interface = node.get_boot_interface() |
207 | uri = get_interface_uri(interface) |
208 | diff --git a/src/maasserver/static/js/angular/controllers/node_details_networking.js b/src/maasserver/static/js/angular/controllers/node_details_networking.js |
209 | index 84b7739..4067dab 100644 |
210 | --- a/src/maasserver/static/js/angular/controllers/node_details_networking.js |
211 | +++ b/src/maasserver/static/js/angular/controllers/node_details_networking.js |
212 | @@ -1,4 +1,4 @@ |
213 | -/* Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
214 | +/* Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
215 | * GNU Affero General Public License version 3 (see the file LICENSE). |
216 | * |
217 | * MAAS Node Networking Controller |
218 | @@ -568,30 +568,6 @@ angular.module('MAAS').controller('NodeNetworkingController', [ |
219 | updateLoaded(); |
220 | }; |
221 | |
222 | - // Return true if the Node is Ready (or Broken) |
223 | - $scope.isNodeEditingAllowed = function() { |
224 | - if (!$scope.isSuperUser()) { |
225 | - // If the user is not the superuser, pretend it's not Ready. |
226 | - return false; |
227 | - } |
228 | - if ($scope.$parent.isDevice) { |
229 | - // Devices are always Ready, for our purposes, for now. |
230 | - return true; |
231 | - } |
232 | - if ($scope.$parent.isController) { |
233 | - // Controllers are always Ready, for our purposes. |
234 | - return true; |
235 | - } |
236 | - if (angular.isObject($scope.node) && |
237 | - ["Ready", "Broken"].indexOf($scope.node.status) === -1) { |
238 | - // If a non-controller node is not Ready or Broken, then no |
239 | - // editing networking. |
240 | - return false; |
241 | - } |
242 | - // All is well, let them edit. |
243 | - return true; |
244 | - }; |
245 | - |
246 | // Return true if only the name or mac address of an interface can |
247 | // be edited. |
248 | $scope.isLimitedEditingAllowed = function(nic) { |
249 | @@ -623,9 +599,10 @@ angular.module('MAAS').controller('NodeNetworkingController', [ |
250 | return false; |
251 | } |
252 | if (angular.isObject($scope.node) && |
253 | - ["Ready", "Broken"].indexOf($scope.node.status) === -1) { |
254 | - // If a non-controller node is not ready or broken, disable |
255 | - // networking panel. |
256 | + ["Ready", "Allocated", "Broken"].indexOf( |
257 | + $scope.node.status) === -1) { |
258 | + // If a non-controller node is not ready allocated, or broken, |
259 | + // disable networking panel. |
260 | return true; |
261 | } |
262 | // User must be a superuser and the node must be |
263 | @@ -1090,7 +1067,7 @@ angular.module('MAAS').controller('NodeNetworkingController', [ |
264 | $scope.canAddAliasOrVLAN = function(nic) { |
265 | if($scope.$parent.isController) { |
266 | return false; |
267 | - } else if (!$scope.isNodeEditingAllowed()) { |
268 | + } else if ($scope.isAllNetworkingDisabled()) { |
269 | return false; |
270 | } else { |
271 | return $scope.canAddAlias(nic) || $scope.canAddVLAN(nic); |
272 | @@ -1148,7 +1125,7 @@ angular.module('MAAS').controller('NodeNetworkingController', [ |
273 | $scope.canBeRemoved = function() { |
274 | return ( |
275 | !$scope.$parent.isController && |
276 | - $scope.isNodeEditingAllowed()); |
277 | + !$scope.isAllNetworkingDisabled()); |
278 | }; |
279 | |
280 | // Enter remove mode. |
281 | diff --git a/src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js b/src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js |
282 | index a51834c..77967e7 100644 |
283 | --- a/src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js |
284 | +++ b/src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js |
285 | @@ -1,4 +1,4 @@ |
286 | -/* Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
287 | +/* Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
288 | * GNU Affero General Public License version 3 (see the file LICENSE). |
289 | * |
290 | * Unit tests for NodeNetworkingController. |
291 | @@ -2146,7 +2146,7 @@ describe("NodeNetworkingController", function() { |
292 | it("returns false if isController", function() { |
293 | var controller = makeController(); |
294 | $parentScope.isController = true; |
295 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(true); |
296 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(false); |
297 | spyOn($scope, "canAddAlias").and.returnValue(true); |
298 | spyOn($scope, "canAddVLAN").and.returnValue(true); |
299 | expect($scope.canAddAliasOrVLAN({})).toBe(false); |
300 | @@ -2155,7 +2155,7 @@ describe("NodeNetworkingController", function() { |
301 | it("returns false if no node editing", function() { |
302 | var controller = makeController(); |
303 | $parentScope.isController = false; |
304 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(false); |
305 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(true); |
306 | spyOn($scope, "canAddAlias").and.returnValue(true); |
307 | spyOn($scope, "canAddVLAN").and.returnValue(true); |
308 | expect($scope.canAddAliasOrVLAN({})).toBe(false); |
309 | @@ -2164,7 +2164,7 @@ describe("NodeNetworkingController", function() { |
310 | it("returns true if can edit alias", function() { |
311 | var controller = makeController(); |
312 | $parentScope.isController = false; |
313 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(true); |
314 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(false); |
315 | spyOn($scope, "canAddAlias").and.returnValue(true); |
316 | spyOn($scope, "canAddVLAN").and.returnValue(false); |
317 | expect($scope.canAddAliasOrVLAN({})).toBe(true); |
318 | @@ -2173,7 +2173,7 @@ describe("NodeNetworkingController", function() { |
319 | it("returns true if can edit VLAN", function() { |
320 | var controller = makeController(); |
321 | $parentScope.isController = false; |
322 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(true); |
323 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(false); |
324 | spyOn($scope, "canAddAlias").and.returnValue(false); |
325 | spyOn($scope, "canAddVLAN").and.returnValue(true); |
326 | expect($scope.canAddAliasOrVLAN({})).toBe(true); |
327 | @@ -2523,21 +2523,21 @@ describe("NodeNetworkingController", function() { |
328 | it("false if isController", function() { |
329 | var controller = makeController(); |
330 | $parentScope.isController = true; |
331 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(true); |
332 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(false); |
333 | expect($scope.canBeRemoved()).toBe(false); |
334 | }); |
335 | |
336 | it("false if no node editing", function() { |
337 | var controller = makeController(); |
338 | $parentScope.isController = false; |
339 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(false); |
340 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(true); |
341 | expect($scope.canBeRemoved()).toBe(false); |
342 | }); |
343 | |
344 | it("true if node can be edited", function() { |
345 | var controller = makeController(); |
346 | $parentScope.isController = false; |
347 | - spyOn($scope, "isNodeEditingAllowed").and.returnValue(true); |
348 | + spyOn($scope, "isAllNetworkingDisabled").and.returnValue(false); |
349 | expect($scope.canBeRemoved()).toBe(true); |
350 | }); |
351 | }); |
352 | diff --git a/src/maasserver/static/partials/node-details.html b/src/maasserver/static/partials/node-details.html |
353 | index 0066e2b..62d379a 100755 |
354 | --- a/src/maasserver/static/partials/node-details.html |
355 | +++ b/src/maasserver/static/partials/node-details.html |
356 | @@ -656,7 +656,7 @@ |
357 | <div class="p-notification" data-ng-if="!isController && isAllNetworkingDisabled() && isSuperUser()"> |
358 | <p class="p-notification__response">Interface |
359 | configuration cannot be modified unless the |
360 | - node is Ready or Broken.</p> |
361 | + node is Ready, Allocated, or Broken.</p> |
362 | </div> |
363 | <div class="p-notification--warning" data-ng-if="!isController && isCustomOS()"> |
364 | <p class="p-notification__response"> |
365 | @@ -698,15 +698,15 @@ |
366 | </header> |
367 | <div class="table__body" data-selected-rows> |
368 | <div class="table__row" |
369 | - data-ng-class="{ disabled: isDisabled(), 'is-active': isInterfaceSelected(interface) && (isNodeEditingAllowed() || isLimitedEditingAllowed(interface)), noEdit: cannotEditInterface(interface) }" |
370 | - data-ng-repeat="interface in interfaces | removeInterfaceParents:newBondInterface:!isNodeEditingAllowed() | removeInterfaceParents:newBridgeInterface:!isNodeEditingAllowed()"> |
371 | + data-ng-class="{ disabled: isDisabled(), 'is-active': isInterfaceSelected(interface) && (!isAllNetworkingDisabled() || isLimitedEditingAllowed(interface)), noEdit: cannotEditInterface(interface) }" |
372 | + data-ng-repeat="interface in interfaces | removeInterfaceParents:newBondInterface:isAllNetworkingDisabled() | removeInterfaceParents:newBridgeInterface:isAllNetworkingDisabled()"> |
373 | <div class="table__data table-col--3" data-ng-if="!isDevice" aria-label="Select"> |
374 | <input type="checkbox" class="checkbox" id="{$ getUniqueKey(interface) $}" |
375 | data-ng-hide="isAllNetworkingDisabled()" |
376 | data-ng-checked="isInterfaceSelected(interface)" |
377 | data-ng-click="toggleInterfaceSelect(interface)" |
378 | data-ng-disabled="isDisabled()" |
379 | - data-ng-if="!isController && isNodeEditingAllowed()"> |
380 | + data-ng-if="!isController && !isAllNetworkingDisabled()"> |
381 | <label for="{$ getUniqueKey(interface) $}"></label> |
382 | </div> |
383 | <div class="table__data table-col--12" aria-label="Name" data-ng-if="!isDevice" data-ng-show="tableInfo.column == 'name'"> |
384 | @@ -755,7 +755,7 @@ |
385 | </span> |
386 | </div> |
387 | <div class="table__data table--mobile-controls table-col--8"> |
388 | - <div class="table__controls" toggle-ctrl data-ng-if="isNodeEditingAllowed() || isLimitedEditingAllowed(interface)"> |
389 | + <div class="table__controls" toggle-ctrl data-ng-if="!isAllNetworkingDisabled() || isLimitedEditingAllowed(interface)"> |
390 | <button class="table__controls-toggle" data-ng-click="toggleMenu()">View actions</button> |
391 | <div class="table__controls-menu" role="menu" data-ng-show="isToggled"> |
392 | <button class="table__controls-action" |
393 | @@ -787,7 +787,7 @@ |
394 | </div> |
395 | </div> |
396 | </div> |
397 | - <div data-ng-if="isNodeEditingAllowed() || isLimitedEditingAllowed(interface)"> |
398 | + <div data-ng-if="!isAllNetworkingDisabled() || isLimitedEditingAllowed(interface)"> |
399 | <div class="table__dropdown" tabindex="0" data-ng-if="isShowingAdd() || isEditing(interface) || isShowingDeleteConfirm() || isShowingAdd() && !newInterface.saving"> |
400 | <div class="table__dropdown-title"> |
401 | <h2 data-ng-click="cancel()" class="u-float--left"> |
402 | @@ -888,10 +888,10 @@ |
403 | input-class="table__input u-margin--none" placeholder="00:00:00:00:00:00"></maas-obj-field> |
404 | <maas-obj-field type="tags" key="tags" label="Tags" label-width="two" input-width="three" |
405 | placeholder="Add a tag" |
406 | - data-ng-if="!isLimitedEditingAllowed(interface) && interface.type !== 'alias'" |
407 | + data-ng-if="!isAllNetworkingDisabled(interface) && interface.type !== 'alias'" |
408 | disable-label="false" input-class="table__input u-margin--none"></maas-obj-field> |
409 | </fieldset> |
410 | - <fieldset class="form__fieldset six-col last-col" data-ng-if="!isLimitedEditingAllowed(interface)"> |
411 | + <fieldset class="form__fieldset six-col last-col" data-ng-if="!isAllNetworkingDisabled(interface)"> |
412 | <maas-obj-field type="options" key="fabric" label="Fabric" label-width="two" input-width="three" |
413 | disable-label="false" input-class="table__input u-margin--none" |
414 | data-ng-if="!isDevice" |
415 | @@ -976,7 +976,7 @@ |
416 | </div> |
417 | </div> |
418 | </div> |
419 | - <div class="table__row is-active" tabindex="0" data-ng-if="isShowingCreateBond() && isNodeEditingAllowed()"> |
420 | + <div class="table__row is-active" tabindex="0" data-ng-if="isShowingCreateBond() && !isAllNetworkingDisabled()"> |
421 | <div class="table__data table-col--3"> |
422 | <input type="checkbox" class="checkbox" name="bond-create" disabled="disabled" checked /> |
423 | <label for="bond-create"></label> |
424 | @@ -1077,7 +1077,7 @@ |
425 | </div> |
426 | </div> |
427 | </div> |
428 | - <div class="table__row is-active" tabindex="0" data-ng-if="isShowingCreateBridge() && isNodeEditingAllowed()"> |
429 | + <div class="table__row is-active" tabindex="0" data-ng-if="isShowingCreateBridge() && !isAllNetworkingDisabled()"> |
430 | <div class="table__data table-col--3"> |
431 | <input type="checkbox" class="checkbox" id="bond-create" disabled="disabled" checked /> |
432 | <label for="bridge-create"></label> |
433 | @@ -1262,7 +1262,7 @@ |
434 | data-ng-class="{ 'has-error': isMACAddressInvalid(newInterface.mac_address, true) }"> |
435 | </div> |
436 | </fieldset> |
437 | - <fieldset class="form__fieldset six-col last-col" data-ng-if="!isLimitedEditingAllowed(interface)"> |
438 | + <fieldset class="form__fieldset six-col last-col" data-ng-if="!isAllNetworkingDisabled(interface)"> |
439 | <div class="form__group"> |
440 | <label for="ip-assignment" class="two-col">IP Assignment</label> |
441 | <select name="ip-assignment" class="three-col" |
Looks good, but I do have a question about dropping isLimitedEditin gAllowed removal: it seems to be about "Deployed" status, so I think we still want to keep that. Did I miss something there (the bug only talks about allowing editing in allocated state)?
I also ain't too happy about how we create multiple test scenarios with a for loop over 3 different node statuses, but you didn't introduce this originally, so no need to fix it either, though I have to rant a bit about it :-)