Merge ~ack/maas:lock-unlock-machine-ui into maas:master
- Git
- lp:~ack/maas
- lock-unlock-machine-ui
- Merge into master
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Alberto Donato | ||||
Approved revision: | 52d5ce6cbf464368ee0fc6992d985d81072cba1d | ||||
Merge reported by: | MAAS Lander | ||||
Merged at revision: | not available | ||||
Proposed branch: | ~ack/maas:lock-unlock-machine-ui | ||||
Merge into: | maas:master | ||||
Prerequisite: | ~ack/maas:lock-unlock-machine-api | ||||
Diff against target: |
1112 lines (+518/-112) 9 files modified
src/maasserver/node_action.py (+43/-0) src/maasserver/static/js/angular/controllers/node_details.js (+11/-1) src/maasserver/static/js/angular/controllers/tests/test_node_details.js (+12/-0) src/maasserver/static/partials/node-details.html (+2/-0) src/maasserver/static/partials/nodes-list.html (+6/-0) src/maasserver/tests/test_node_action.py (+71/-0) src/maasserver/websockets/handlers/machine.py (+35/-108) src/maasserver/websockets/handlers/tests/test_general.py (+2/-1) src/maasserver/websockets/handlers/tests/test_machine.py (+336/-2) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Approve | ||
MAAS Lander | Approve | ||
Review via email: mp+333793@code.launchpad.net |
Commit message
LP: #1453878 - add lock/unlock actions in the UI
Description of the change
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: FAILED
LOG: http://
COMMIT: c92eae16a19f384
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: FAILED
LOG: http://
COMMIT: fbf1bf948bcda4e
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: FAILED
LOG: http://
COMMIT: 557739c6ee76f11
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: SUCCESS
COMMIT: 6d70369582f2dc9
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: FAILED
LOG: http://
COMMIT: aae7b4c0a64671f
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: SUCCESS
COMMIT: 71c00214bc5cc8b
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lock-unlock-
STATUS: SUCCESS
COMMIT: 52d5ce6cbf46436
MAAS Lander (maas-lander) wrote : | # |
LANDING
-b lock-unlock-
STATUS: FAILED BUILD
LOG: http://
MAAS Lander (maas-lander) wrote : | # |
LANDING
-b lock-unlock-
STATUS: FAILED BUILD
LOG: http://
MAAS Lander (maas-lander) wrote : | # |
LANDING
-b lock-unlock-
STATUS: FAILED BUILD
LOG: http://
There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.
Preview Diff
1 | diff --git a/src/maasserver/node_action.py b/src/maasserver/node_action.py | |||
2 | index 74c8df7..5b7435c 100644 | |||
3 | --- a/src/maasserver/node_action.py | |||
4 | +++ b/src/maasserver/node_action.py | |||
5 | @@ -108,6 +108,9 @@ class NodeAction(metaclass=ABCMeta): | |||
6 | 108 | # is being applied to a node_type which is node | 108 | # is being applied to a node_type which is node |
7 | 109 | node_permission = None | 109 | node_permission = None |
8 | 110 | 110 | ||
9 | 111 | # Whether the action is allowed when the node is locked | ||
10 | 112 | allowed_when_locked = False | ||
11 | 113 | |||
12 | 111 | def __init__(self, node, user, request=None): | 114 | def __init__(self, node, user, request=None): |
13 | 112 | """Initialize a node action. | 115 | """Initialize a node action. |
14 | 113 | 116 | ||
15 | @@ -129,8 +132,11 @@ class NodeAction(metaclass=ABCMeta): | |||
16 | 129 | elif (self.node_permission == NODE_PERMISSION.ADMIN and | 132 | elif (self.node_permission == NODE_PERMISSION.ADMIN and |
17 | 130 | not self.user.is_superuser): | 133 | not self.user.is_superuser): |
18 | 131 | return False | 134 | return False |
19 | 135 | elif self.node.locked and not self.allowed_when_locked: | ||
20 | 136 | return False | ||
21 | 132 | elif self.node.node_type == NODE_TYPE.MACHINE: | 137 | elif self.node.node_type == NODE_TYPE.MACHINE: |
22 | 133 | return self.node.status in self.actionable_statuses | 138 | return self.node.status in self.actionable_statuses |
23 | 139 | |||
24 | 134 | return True | 140 | return True |
25 | 135 | 141 | ||
26 | 136 | def inhibit(self): | 142 | def inhibit(self): |
27 | @@ -498,6 +504,41 @@ class MarkFixed(NodeAction): | |||
28 | 498 | return not script_failures.exists() | 504 | return not script_failures.exists() |
29 | 499 | 505 | ||
30 | 500 | 506 | ||
31 | 507 | class Lock(NodeAction): | ||
32 | 508 | """Lock a node.""" | ||
33 | 509 | |||
34 | 510 | name = "lock" | ||
35 | 511 | display = "Lock" | ||
36 | 512 | display_sentence = "Lock" | ||
37 | 513 | actionable_statuses = (NODE_STATUS.DEPLOYED,) | ||
38 | 514 | permission = NODE_PERMISSION.LOCK | ||
39 | 515 | for_type = {NODE_TYPE.MACHINE} | ||
40 | 516 | |||
41 | 517 | def execute(self): | ||
42 | 518 | self.node.lock(self.user, "via web interface") | ||
43 | 519 | |||
44 | 520 | |||
45 | 521 | class Unlock(NodeAction): | ||
46 | 522 | """Unlock a node.""" | ||
47 | 523 | |||
48 | 524 | name = "unlock" | ||
49 | 525 | display = "Unlock" | ||
50 | 526 | display_sentence = "Unlock" | ||
51 | 527 | actionable_statuses = ALL_STATUSES | ||
52 | 528 | permission = NODE_PERMISSION.LOCK | ||
53 | 529 | for_type = {NODE_TYPE.MACHINE} | ||
54 | 530 | allowed_when_locked = True | ||
55 | 531 | |||
56 | 532 | def is_actionable(self): | ||
57 | 533 | if not super().is_actionable(): | ||
58 | 534 | return False | ||
59 | 535 | # don't show action if not locked | ||
60 | 536 | return self.node.locked | ||
61 | 537 | |||
62 | 538 | def execute(self): | ||
63 | 539 | self.node.unlock(self.user, "via web interface") | ||
64 | 540 | |||
65 | 541 | |||
66 | 501 | class OverrideFailedTesting(NodeAction): | 542 | class OverrideFailedTesting(NodeAction): |
67 | 502 | """Override failed tests and reset node into a usable state.""" | 543 | """Override failed tests and reset node into a usable state.""" |
68 | 503 | name = "override-failed-testing" | 544 | name = "override-failed-testing" |
69 | @@ -601,6 +642,8 @@ ACTION_CLASSES = ( | |||
70 | 601 | MarkBroken, | 642 | MarkBroken, |
71 | 602 | MarkFixed, | 643 | MarkFixed, |
72 | 603 | OverrideFailedTesting, | 644 | OverrideFailedTesting, |
73 | 645 | Lock, | ||
74 | 646 | Unlock, | ||
75 | 604 | SetZone, | 647 | SetZone, |
76 | 605 | ImportImages, | 648 | ImportImages, |
77 | 606 | Delete, | 649 | Delete, |
78 | diff --git a/src/maasserver/static/js/angular/controllers/node_details.js b/src/maasserver/static/js/angular/controllers/node_details.js | |||
79 | index 1633a61..565dced 100644 | |||
80 | --- a/src/maasserver/static/js/angular/controllers/node_details.js | |||
81 | +++ b/src/maasserver/static/js/angular/controllers/node_details.js | |||
82 | @@ -739,11 +739,21 @@ angular.module('MAAS').controller('NodeDetailsController', [ | |||
83 | 739 | return $scope.power_types.length > 0; | 739 | return $scope.power_types.length > 0; |
84 | 740 | }; | 740 | }; |
85 | 741 | 741 | ||
86 | 742 | // Return true if the node is locked | ||
87 | 743 | $scope.isLocked = function() { | ||
88 | 744 | if ($scope.node === null) { | ||
89 | 745 | return false; | ||
90 | 746 | } | ||
91 | 747 | |||
92 | 748 | return $scope.node.locked; | ||
93 | 749 | }; | ||
94 | 750 | |||
95 | 742 | // Return true when the edit buttons can be clicked. | 751 | // Return true when the edit buttons can be clicked. |
96 | 743 | $scope.canEdit = function() { | 752 | $scope.canEdit = function() { |
97 | 744 | return ( | 753 | return ( |
98 | 745 | $scope.isRackControllerConnected() && | 754 | $scope.isRackControllerConnected() && |
100 | 746 | $scope.isSuperUser()); | 755 | $scope.isSuperUser() && |
101 | 756 | ! $scope.isLocked()); | ||
102 | 747 | }; | 757 | }; |
103 | 748 | 758 | ||
104 | 749 | // Called to edit the domain name. | 759 | // Called to edit the domain name. |
105 | diff --git a/src/maasserver/static/js/angular/controllers/tests/test_node_details.js b/src/maasserver/static/js/angular/controllers/tests/test_node_details.js | |||
106 | index 28f4b9b..cc583d4 100644 | |||
107 | --- a/src/maasserver/static/js/angular/controllers/tests/test_node_details.js | |||
108 | +++ b/src/maasserver/static/js/angular/controllers/tests/test_node_details.js | |||
109 | @@ -1439,6 +1439,18 @@ describe("NodeDetailsController", function() { | |||
110 | 1439 | "isRackControllerConnected").and.returnValue(true); | 1439 | "isRackControllerConnected").and.returnValue(true); |
111 | 1440 | expect($scope.canEdit()).toBe(true); | 1440 | expect($scope.canEdit()).toBe(true); |
112 | 1441 | }); | 1441 | }); |
113 | 1442 | |||
114 | 1443 | it("returns false if machine is locked", | ||
115 | 1444 | function() { | ||
116 | 1445 | var controller = makeController(); | ||
117 | 1446 | $scope.isController = false; | ||
118 | 1447 | spyOn( | ||
119 | 1448 | $scope, | ||
120 | 1449 | "isRackControllerConnected").and.returnValue(true); | ||
121 | 1450 | $scope.node = makeNode(); | ||
122 | 1451 | $scope.node.locked = true; | ||
123 | 1452 | expect($scope.canEdit()).toBe(false); | ||
124 | 1453 | }); | ||
125 | 1442 | }); | 1454 | }); |
126 | 1443 | 1455 | ||
127 | 1444 | describe("editHeaderDomain", function() { | 1456 | describe("editHeaderDomain", function() { |
128 | diff --git a/src/maasserver/static/partials/node-details.html b/src/maasserver/static/partials/node-details.html | |||
129 | index bcbf37e..3741be9 100755 | |||
130 | --- a/src/maasserver/static/partials/node-details.html | |||
131 | +++ b/src/maasserver/static/partials/node-details.html | |||
132 | @@ -100,6 +100,8 @@ | |||
133 | 100 | <span data-ng-if="action.option.name === 'mark-broken'">Mark {$ type_name $}</span> | 100 | <span data-ng-if="action.option.name === 'mark-broken'">Mark {$ type_name $}</span> |
134 | 101 | <span data-ng-if="action.option.name === 'mark-fixed'">Mark {$ type_name $}</span> | 101 | <span data-ng-if="action.option.name === 'mark-fixed'">Mark {$ type_name $}</span> |
135 | 102 | <span data-ng-if="action.option.name === 'override-failed-testing'">Override failed testing</span> | 102 | <span data-ng-if="action.option.name === 'override-failed-testing'">Override failed testing</span> |
136 | 103 | <span data-ng-if="action.option.name === 'lock'">Lock {$ type_name $}</span> | ||
137 | 104 | <span data-ng-if="action.option.name === 'unlock'">Unlock {$ type_name $}</span> | ||
138 | 103 | <span data-ng-if="action.option.name === 'delete'">Delete {$ type_name $}</span> | 105 | <span data-ng-if="action.option.name === 'delete'">Delete {$ type_name $}</span> |
139 | 104 | <span data-ng-if="action.option.name === 'import-images'">Import images</span> | 106 | <span data-ng-if="action.option.name === 'import-images'">Import images</span> |
140 | 105 | </button> | 107 | </button> |
141 | diff --git a/src/maasserver/static/partials/nodes-list.html b/src/maasserver/static/partials/nodes-list.html | |||
142 | index 05cce9b..a817cf3 100644 | |||
143 | --- a/src/maasserver/static/partials/nodes-list.html | |||
144 | +++ b/src/maasserver/static/partials/nodes-list.html | |||
145 | @@ -159,6 +159,12 @@ | |||
146 | 159 | <span data-ng-if="tabs[tab].actionOption.name === 'override-failed-testing'">Override failed testing on {$ tabs[tab].selectedItems.length $} | 159 | <span data-ng-if="tabs[tab].actionOption.name === 'override-failed-testing'">Override failed testing on {$ tabs[tab].selectedItems.length $} |
147 | 160 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | 160 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> |
148 | 161 | </span> | 161 | </span> |
149 | 162 | <span data-ng-if="tabs[tab].actionOption.name === 'lock'">Lock {$ tabs[tab].selectedItems.length $} | ||
150 | 163 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
151 | 164 | </span> | ||
152 | 165 | <span data-ng-if="tabs[tab].actionOption.name === 'unlock'">Unlock {$ tabs[tab].selectedItems.length $} | ||
153 | 166 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
154 | 167 | </span> | ||
155 | 162 | <span data-ng-if="tabs[tab].actionOption.name === 'delete'">Delete {$ tabs[tab].selectedItems.length $} | 168 | <span data-ng-if="tabs[tab].actionOption.name === 'delete'">Delete {$ tabs[tab].selectedItems.length $} |
156 | 163 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | 169 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> |
157 | 164 | </span> | 170 | </span> |
158 | diff --git a/src/maasserver/tests/test_node_action.py b/src/maasserver/tests/test_node_action.py | |||
159 | index a9368e0..9e0a3de 100644 | |||
160 | --- a/src/maasserver/tests/test_node_action.py | |||
161 | +++ b/src/maasserver/tests/test_node_action.py | |||
162 | @@ -39,6 +39,7 @@ from maasserver.node_action import ( | |||
163 | 39 | Deploy, | 39 | Deploy, |
164 | 40 | ExitRescueMode, | 40 | ExitRescueMode, |
165 | 41 | ImportImages, | 41 | ImportImages, |
166 | 42 | Lock, | ||
167 | 42 | MarkBroken, | 43 | MarkBroken, |
168 | 43 | MarkFixed, | 44 | MarkFixed, |
169 | 44 | NodeAction, | 45 | NodeAction, |
170 | @@ -50,6 +51,7 @@ from maasserver.node_action import ( | |||
171 | 50 | RPC_EXCEPTIONS, | 51 | RPC_EXCEPTIONS, |
172 | 51 | SetZone, | 52 | SetZone, |
173 | 52 | Test, | 53 | Test, |
174 | 54 | Unlock, | ||
175 | 53 | ) | 55 | ) |
176 | 54 | import maasserver.node_action as node_action_module | 56 | import maasserver.node_action as node_action_module |
177 | 55 | from maasserver.node_status import ( | 57 | from maasserver.node_status import ( |
178 | @@ -270,6 +272,22 @@ class TestNodeAction(MAASServerTestCase): | |||
179 | 270 | node = factory.make_Node() | 272 | node = factory.make_Node() |
180 | 271 | self.assertFalse(MyAction(node, factory.make_User()).is_actionable()) | 273 | self.assertFalse(MyAction(node, factory.make_User()).is_actionable()) |
181 | 272 | 274 | ||
182 | 275 | def test_is_actionable_false_if_locked(self): | ||
183 | 276 | |||
184 | 277 | class MyAction(FakeNodeAction): | ||
185 | 278 | pass | ||
186 | 279 | |||
187 | 280 | node = factory.make_Node(status=NODE_STATUS.DEPLOYED, locked=True) | ||
188 | 281 | self.assertFalse(MyAction(node, factory.make_User()).is_actionable()) | ||
189 | 282 | |||
190 | 283 | def test_is_actionable_true_if_allow_ed_when_locked(self): | ||
191 | 284 | |||
192 | 285 | class MyAction(FakeNodeAction): | ||
193 | 286 | allowed_when_locked = True | ||
194 | 287 | |||
195 | 288 | node = factory.make_Node(status=NODE_STATUS.DEPLOYED, locked=True) | ||
196 | 289 | self.assertTrue(MyAction(node, factory.make_User()).is_actionable()) | ||
197 | 290 | |||
198 | 273 | def test_delete_action_last_for_node(self): | 291 | def test_delete_action_last_for_node(self): |
199 | 274 | node = factory.make_Node() | 292 | node = factory.make_Node() |
200 | 275 | actions = compile_node_actions( | 293 | actions = compile_node_actions( |
201 | @@ -821,6 +839,59 @@ class TestPowerOffAction(MAASServerTestCase): | |||
202 | 821 | "Nodes already powered off can be powered off.") | 839 | "Nodes already powered off can be powered off.") |
203 | 822 | 840 | ||
204 | 823 | 841 | ||
205 | 842 | class TestLockAction(MAASServerTestCase): | ||
206 | 843 | |||
207 | 844 | def test_changes_locked_status(self): | ||
208 | 845 | user = factory.make_User() | ||
209 | 846 | node = factory.make_Node(status=NODE_STATUS.DEPLOYED, owner=user) | ||
210 | 847 | action = Lock(node, user) | ||
211 | 848 | self.assertTrue(action.is_permitted()) | ||
212 | 849 | action.execute() | ||
213 | 850 | self.assertTrue(reload_object(node).locked) | ||
214 | 851 | |||
215 | 852 | def test_not_actionable_if_not_deployed(self): | ||
216 | 853 | user = factory.make_User() | ||
217 | 854 | node = factory.make_Node(status=NODE_STATUS.READY, owner=user) | ||
218 | 855 | action = Lock(node, user) | ||
219 | 856 | self.assertFalse(action.is_actionable()) | ||
220 | 857 | |||
221 | 858 | def test_not_actionable_if_locked(self): | ||
222 | 859 | user = factory.make_User() | ||
223 | 860 | node = factory.make_Node( | ||
224 | 861 | status=NODE_STATUS.DEPLOYED, owner=user, locked=True) | ||
225 | 862 | action = Lock(node, user) | ||
226 | 863 | self.assertFalse(action.is_actionable()) | ||
227 | 864 | |||
228 | 865 | def test_not_actionable_if_not_machine(self): | ||
229 | 866 | user = factory.make_User() | ||
230 | 867 | controller = factory.make_RackController() | ||
231 | 868 | action = Lock(controller, user) | ||
232 | 869 | self.assertFalse(action.is_actionable()) | ||
233 | 870 | |||
234 | 871 | |||
235 | 872 | class TestUnlockAction(MAASServerTestCase): | ||
236 | 873 | |||
237 | 874 | def test_changes_locked_status(self): | ||
238 | 875 | user = factory.make_User() | ||
239 | 876 | node = factory.make_Node(locked=True, owner=user) | ||
240 | 877 | action = Unlock(node, user) | ||
241 | 878 | self.assertTrue(action.is_permitted()) | ||
242 | 879 | action.execute() | ||
243 | 880 | self.assertFalse(reload_object(node).locked) | ||
244 | 881 | |||
245 | 882 | def test_not_actionable_if_not_locked(self): | ||
246 | 883 | user = factory.make_User() | ||
247 | 884 | node = factory.make_Node(owner=user) | ||
248 | 885 | action = Unlock(node, user) | ||
249 | 886 | self.assertFalse(action.is_actionable()) | ||
250 | 887 | |||
251 | 888 | def test_not_actionable_if_not_machine(self): | ||
252 | 889 | user = factory.make_User() | ||
253 | 890 | controller = factory.make_RackController() | ||
254 | 891 | action = Unlock(controller, user) | ||
255 | 892 | self.assertFalse(action.is_actionable()) | ||
256 | 893 | |||
257 | 894 | |||
258 | 824 | ACTIONABLE_STATUSES = [ | 895 | ACTIONABLE_STATUSES = [ |
259 | 825 | NODE_STATUS.DEPLOYING, | 896 | NODE_STATUS.DEPLOYING, |
260 | 826 | NODE_STATUS.FAILED_DEPLOYMENT, | 897 | NODE_STATUS.FAILED_DEPLOYMENT, |
261 | diff --git a/src/maasserver/websockets/handlers/machine.py b/src/maasserver/websockets/handlers/machine.py | |||
262 | index b3126d3..67fe666 100644 | |||
263 | --- a/src/maasserver/websockets/handlers/machine.py | |||
264 | +++ b/src/maasserver/websockets/handlers/machine.py | |||
265 | @@ -350,10 +350,8 @@ class MachineHandler(NodeHandler): | |||
266 | 350 | 350 | ||
267 | 351 | def update(self, params): | 351 | def update(self, params): |
268 | 352 | """Update the object from params.""" | 352 | """Update the object from params.""" |
273 | 353 | # Only admin users can perform update. | 353 | # check that the operation is allowed |
274 | 354 | if not reload_object(self.user).is_superuser: | 354 | self._get_node_or_permission_error(params) |
271 | 355 | raise HandlerPermissionError() | ||
272 | 356 | |||
275 | 357 | data = super(NodeHandler, self).update(params) | 355 | data = super(NodeHandler, self).update(params) |
276 | 358 | node_obj = Node.objects.get(system_id=data['system_id']) | 356 | node_obj = Node.objects.get(system_id=data['system_id']) |
277 | 359 | 357 | ||
278 | @@ -375,6 +373,8 @@ class MachineHandler(NodeHandler): | |||
279 | 375 | `m.api.machines`. | 373 | `m.api.machines`. |
280 | 376 | """ | 374 | """ |
281 | 377 | machine = self.get_object(params) | 375 | machine = self.get_object(params) |
282 | 376 | if machine.locked: | ||
283 | 377 | raise HandlerPermissionError() | ||
284 | 378 | self._preflight_special_filesystem_modifications("mount", machine) | 378 | self._preflight_special_filesystem_modifications("mount", machine) |
285 | 379 | form = MountNonStorageFilesystemForm(machine, data=params) | 379 | form = MountNonStorageFilesystemForm(machine, data=params) |
286 | 380 | if form.is_valid(): | 380 | if form.is_valid(): |
287 | @@ -391,6 +391,8 @@ class MachineHandler(NodeHandler): | |||
288 | 391 | `m.api.machines`. | 391 | `m.api.machines`. |
289 | 392 | """ | 392 | """ |
290 | 393 | machine = self.get_object(params) | 393 | machine = self.get_object(params) |
291 | 394 | if machine.locked: | ||
292 | 395 | raise HandlerPermissionError() | ||
293 | 394 | self._preflight_special_filesystem_modifications("unmount", machine) | 396 | self._preflight_special_filesystem_modifications("unmount", machine) |
294 | 395 | form = UnmountNonStorageFilesystemForm(machine, data=params) | 397 | form = UnmountNonStorageFilesystemForm(machine, data=params) |
295 | 396 | if form.is_valid(): | 398 | if form.is_valid(): |
296 | @@ -414,6 +416,8 @@ class MachineHandler(NodeHandler): | |||
297 | 414 | 416 | ||
298 | 415 | def update_filesystem(self, params): | 417 | def update_filesystem(self, params): |
299 | 416 | node = self.get_object(params) | 418 | node = self.get_object(params) |
300 | 419 | if node.locked: | ||
301 | 420 | raise HandlerPermissionError() | ||
302 | 417 | block_id = params.get('block_id') | 421 | block_id = params.get('block_id') |
303 | 418 | partition_id = params.get('partition_id') | 422 | partition_id = params.get('partition_id') |
304 | 419 | fstype = params.get('fstype') | 423 | fstype = params.get('fstype') |
305 | @@ -523,11 +527,7 @@ class MachineHandler(NodeHandler): | |||
306 | 523 | 527 | ||
307 | 524 | def update_disk(self, params): | 528 | def update_disk(self, params): |
308 | 525 | """Update disk information.""" | 529 | """Update disk information.""" |
314 | 526 | # Only admin users can perform delete. | 530 | node = self._get_node_or_permission_error(params) |
310 | 527 | if not reload_object(self.user).is_superuser: | ||
311 | 528 | raise HandlerPermissionError() | ||
312 | 529 | |||
313 | 530 | node = self.get_object(params) | ||
315 | 531 | device = BlockDevice.objects.get( | 531 | device = BlockDevice.objects.get( |
316 | 532 | id=params['block_id'], node=node).actual_instance | 532 | id=params['block_id'], node=node).actual_instance |
317 | 533 | if device.type == 'physical': | 533 | if device.type == 'physical': |
318 | @@ -551,22 +551,14 @@ class MachineHandler(NodeHandler): | |||
319 | 551 | params.get('mount_options', '')) | 551 | params.get('mount_options', '')) |
320 | 552 | 552 | ||
321 | 553 | def delete_disk(self, params): | 553 | def delete_disk(self, params): |
327 | 554 | # Only admin users can perform delete. | 554 | node = self._get_node_or_permission_error(params) |
323 | 555 | if not reload_object(self.user).is_superuser: | ||
324 | 556 | raise HandlerPermissionError() | ||
325 | 557 | |||
326 | 558 | node = self.get_object(params) | ||
328 | 559 | block_id = params.get('block_id') | 555 | block_id = params.get('block_id') |
329 | 560 | if block_id is not None: | 556 | if block_id is not None: |
330 | 561 | block_device = BlockDevice.objects.get(id=block_id, node=node) | 557 | block_device = BlockDevice.objects.get(id=block_id, node=node) |
331 | 562 | block_device.delete() | 558 | block_device.delete() |
332 | 563 | 559 | ||
333 | 564 | def delete_partition(self, params): | 560 | def delete_partition(self, params): |
339 | 565 | # Only admin users can perform delete. | 561 | node = self._get_node_or_permission_error(params) |
335 | 566 | if not reload_object(self.user).is_superuser: | ||
336 | 567 | raise HandlerPermissionError() | ||
337 | 568 | |||
338 | 569 | node = self.get_object(params) | ||
340 | 570 | partition_id = params.get('partition_id') | 562 | partition_id = params.get('partition_id') |
341 | 571 | if partition_id is not None: | 563 | if partition_id is not None: |
342 | 572 | partition = Partition.objects.get( | 564 | partition = Partition.objects.get( |
343 | @@ -574,11 +566,7 @@ class MachineHandler(NodeHandler): | |||
344 | 574 | partition.delete() | 566 | partition.delete() |
345 | 575 | 567 | ||
346 | 576 | def delete_volume_group(self, params): | 568 | def delete_volume_group(self, params): |
352 | 577 | # Only admin users can perform delete. | 569 | node = self._get_node_or_permission_error(params) |
348 | 578 | if not reload_object(self.user).is_superuser: | ||
349 | 579 | raise HandlerPermissionError() | ||
350 | 580 | |||
351 | 581 | node = self.get_object(params) | ||
353 | 582 | volume_group_id = params.get('volume_group_id') | 570 | volume_group_id = params.get('volume_group_id') |
354 | 583 | if volume_group_id is not None: | 571 | if volume_group_id is not None: |
355 | 584 | volume_group = VolumeGroup.objects.get(id=volume_group_id) | 572 | volume_group = VolumeGroup.objects.get(id=volume_group_id) |
356 | @@ -587,11 +575,7 @@ class MachineHandler(NodeHandler): | |||
357 | 587 | volume_group.delete() | 575 | volume_group.delete() |
358 | 588 | 576 | ||
359 | 589 | def delete_cache_set(self, params): | 577 | def delete_cache_set(self, params): |
365 | 590 | # Only admin users can perform delete. | 578 | node = self._get_node_or_permission_error(params) |
361 | 591 | if not reload_object(self.user).is_superuser: | ||
362 | 592 | raise HandlerPermissionError() | ||
363 | 593 | |||
364 | 594 | node = self.get_object(params) | ||
366 | 595 | cache_set_id = params.get('cache_set_id') | 579 | cache_set_id = params.get('cache_set_id') |
367 | 596 | if cache_set_id is not None: | 580 | if cache_set_id is not None: |
368 | 597 | cache_set = CacheSet.objects.get(id=cache_set_id) | 581 | cache_set = CacheSet.objects.get(id=cache_set_id) |
369 | @@ -600,10 +584,7 @@ class MachineHandler(NodeHandler): | |||
370 | 600 | cache_set.delete() | 584 | cache_set.delete() |
371 | 601 | 585 | ||
372 | 602 | def delete_filesystem(self, params): | 586 | def delete_filesystem(self, params): |
377 | 603 | # Only admin users can perform delete. | 587 | node = self._get_node_or_permission_error(params) |
374 | 604 | if not reload_object(self.user).is_superuser: | ||
375 | 605 | raise HandlerPermissionError() | ||
376 | 606 | node = self.get_object(params) | ||
378 | 607 | blockdevice_id = params.get('blockdevice_id') | 588 | blockdevice_id = params.get('blockdevice_id') |
379 | 608 | partition_id = params.get('partition_id') | 589 | partition_id = params.get('partition_id') |
380 | 609 | filesystem_id = params.get('filesystem_id') | 590 | filesystem_id = params.get('filesystem_id') |
381 | @@ -618,11 +599,7 @@ class MachineHandler(NodeHandler): | |||
382 | 618 | 599 | ||
383 | 619 | def create_partition(self, params): | 600 | def create_partition(self, params): |
384 | 620 | """Create a partition.""" | 601 | """Create a partition.""" |
390 | 621 | # Only admin users can perform delete. | 602 | node = self._get_node_or_permission_error(params) |
386 | 622 | if not reload_object(self.user).is_superuser: | ||
387 | 623 | raise HandlerPermissionError() | ||
388 | 624 | |||
389 | 625 | node = self.get_object(params) | ||
391 | 626 | disk_obj = BlockDevice.objects.get(id=params['block_id'], node=node) | 603 | disk_obj = BlockDevice.objects.get(id=params['block_id'], node=node) |
392 | 627 | form = AddPartitionForm( | 604 | form = AddPartitionForm( |
393 | 628 | disk_obj, { | 605 | disk_obj, { |
394 | @@ -640,11 +617,7 @@ class MachineHandler(NodeHandler): | |||
395 | 640 | 617 | ||
396 | 641 | def create_cache_set(self, params): | 618 | def create_cache_set(self, params): |
397 | 642 | """Create a cache set.""" | 619 | """Create a cache set.""" |
403 | 643 | # Only admin users can perform delete. | 620 | node = self._get_node_or_permission_error(params) |
399 | 644 | if not reload_object(self.user).is_superuser: | ||
400 | 645 | raise HandlerPermissionError() | ||
401 | 646 | |||
402 | 647 | node = self.get_object(params) | ||
404 | 648 | block_id = params.get('block_id') | 621 | block_id = params.get('block_id') |
405 | 649 | partition_id = params.get('partition_id') | 622 | partition_id = params.get('partition_id') |
406 | 650 | 623 | ||
407 | @@ -665,11 +638,7 @@ class MachineHandler(NodeHandler): | |||
408 | 665 | 638 | ||
409 | 666 | def create_bcache(self, params): | 639 | def create_bcache(self, params): |
410 | 667 | """Create a bcache.""" | 640 | """Create a bcache.""" |
416 | 668 | # Only admin users can perform delete. | 641 | node = self._get_node_or_permission_error(params) |
412 | 669 | if not reload_object(self.user).is_superuser: | ||
413 | 670 | raise HandlerPermissionError() | ||
414 | 671 | |||
415 | 672 | node = self.get_object(params) | ||
417 | 673 | block_id = params.get('block_id') | 642 | block_id = params.get('block_id') |
418 | 674 | partition_id = params.get('partition_id') | 643 | partition_id = params.get('partition_id') |
419 | 675 | 644 | ||
420 | @@ -701,11 +670,7 @@ class MachineHandler(NodeHandler): | |||
421 | 701 | 670 | ||
422 | 702 | def create_raid(self, params): | 671 | def create_raid(self, params): |
423 | 703 | """Create a RAID.""" | 672 | """Create a RAID.""" |
429 | 704 | # Only admin users can perform delete. | 673 | node = self._get_node_or_permission_error(params) |
425 | 705 | if not reload_object(self.user).is_superuser: | ||
426 | 706 | raise HandlerPermissionError() | ||
427 | 707 | |||
428 | 708 | node = self.get_object(params) | ||
430 | 709 | form = CreateRaidForm(node=node, data=params) | 674 | form = CreateRaidForm(node=node, data=params) |
431 | 710 | if not form.is_valid(): | 675 | if not form.is_valid(): |
432 | 711 | raise HandlerError(form.errors) | 676 | raise HandlerError(form.errors) |
433 | @@ -720,11 +685,7 @@ class MachineHandler(NodeHandler): | |||
434 | 720 | 685 | ||
435 | 721 | def create_volume_group(self, params): | 686 | def create_volume_group(self, params): |
436 | 722 | """Create a volume group.""" | 687 | """Create a volume group.""" |
442 | 723 | # Only admin users can perform delete. | 688 | node = self._get_node_or_permission_error(params) |
438 | 724 | if not reload_object(self.user).is_superuser: | ||
439 | 725 | raise HandlerPermissionError() | ||
440 | 726 | |||
441 | 727 | node = self.get_object(params) | ||
443 | 728 | form = CreateVolumeGroupForm(node=node, data=params) | 689 | form = CreateVolumeGroupForm(node=node, data=params) |
444 | 729 | if not form.is_valid(): | 690 | if not form.is_valid(): |
445 | 730 | raise HandlerError(form.errors) | 691 | raise HandlerError(form.errors) |
446 | @@ -733,11 +694,7 @@ class MachineHandler(NodeHandler): | |||
447 | 733 | 694 | ||
448 | 734 | def create_logical_volume(self, params): | 695 | def create_logical_volume(self, params): |
449 | 735 | """Create a logical volume.""" | 696 | """Create a logical volume.""" |
455 | 736 | # Only admin users can perform delete. | 697 | node = self._get_node_or_permission_error(params) |
451 | 737 | if not reload_object(self.user).is_superuser: | ||
452 | 738 | raise HandlerPermissionError() | ||
453 | 739 | |||
454 | 740 | node = self.get_object(params) | ||
456 | 741 | volume_group = VolumeGroup.objects.get(id=params['volume_group_id']) | 698 | volume_group = VolumeGroup.objects.get(id=params['volume_group_id']) |
457 | 742 | if volume_group.get_node() != node: | 699 | if volume_group.get_node() != node: |
458 | 743 | raise VolumeGroup.DoesNotExist() | 700 | raise VolumeGroup.DoesNotExist() |
459 | @@ -759,11 +716,7 @@ class MachineHandler(NodeHandler): | |||
460 | 759 | 716 | ||
461 | 760 | def set_boot_disk(self, params): | 717 | def set_boot_disk(self, params): |
462 | 761 | """Set the disk as the boot disk.""" | 718 | """Set the disk as the boot disk.""" |
468 | 762 | # Only admin users can perform delete. | 719 | node = self._get_node_or_permission_error(params) |
464 | 763 | if not reload_object(self.user).is_superuser: | ||
465 | 764 | raise HandlerPermissionError() | ||
466 | 765 | |||
467 | 766 | node = self.get_object(params) | ||
469 | 767 | device = BlockDevice.objects.get( | 720 | device = BlockDevice.objects.get( |
470 | 768 | id=params['block_id'], node=node).actual_instance | 721 | id=params['block_id'], node=node).actual_instance |
471 | 769 | if device.type != 'physical': | 722 | if device.type != 'physical': |
472 | @@ -803,11 +756,7 @@ class MachineHandler(NodeHandler): | |||
473 | 803 | 756 | ||
474 | 804 | def create_physical(self, params): | 757 | def create_physical(self, params): |
475 | 805 | """Create physical interface.""" | 758 | """Create physical interface.""" |
481 | 806 | # Only admin users can perform create. | 759 | node = self._get_node_or_permission_error(params) |
477 | 807 | if not reload_object(self.user).is_superuser: | ||
478 | 808 | raise HandlerPermissionError() | ||
479 | 809 | |||
480 | 810 | node = self.get_object(params) | ||
482 | 811 | form = PhysicalInterfaceForm(node=node, data=params) | 760 | form = PhysicalInterfaceForm(node=node, data=params) |
483 | 812 | if form.is_valid(): | 761 | if form.is_valid(): |
484 | 813 | interface = form.save() | 762 | interface = form.save() |
485 | @@ -818,11 +767,7 @@ class MachineHandler(NodeHandler): | |||
486 | 818 | 767 | ||
487 | 819 | def create_vlan(self, params): | 768 | def create_vlan(self, params): |
488 | 820 | """Create VLAN interface.""" | 769 | """Create VLAN interface.""" |
494 | 821 | # Only admin users can perform create. | 770 | node = self._get_node_or_permission_error(params) |
490 | 822 | if not reload_object(self.user).is_superuser: | ||
491 | 823 | raise HandlerPermissionError() | ||
492 | 824 | |||
493 | 825 | node = self.get_object(params) | ||
495 | 826 | params['parents'] = [params.pop('parent')] | 771 | params['parents'] = [params.pop('parent')] |
496 | 827 | form = VLANInterfaceForm(node=node, data=params) | 772 | form = VLANInterfaceForm(node=node, data=params) |
497 | 828 | if form.is_valid(): | 773 | if form.is_valid(): |
498 | @@ -834,11 +779,7 @@ class MachineHandler(NodeHandler): | |||
499 | 834 | 779 | ||
500 | 835 | def create_bond(self, params): | 780 | def create_bond(self, params): |
501 | 836 | """Create bond interface.""" | 781 | """Create bond interface.""" |
507 | 837 | # Only admin users can perform create. | 782 | node = self._get_node_or_permission_error(params) |
503 | 838 | if not reload_object(self.user).is_superuser: | ||
504 | 839 | raise HandlerPermissionError() | ||
505 | 840 | |||
506 | 841 | node = self.get_object(params) | ||
508 | 842 | form = BondInterfaceForm(node=node, data=params) | 783 | form = BondInterfaceForm(node=node, data=params) |
509 | 843 | if form.is_valid(): | 784 | if form.is_valid(): |
510 | 844 | interface = form.save() | 785 | interface = form.save() |
511 | @@ -849,11 +790,7 @@ class MachineHandler(NodeHandler): | |||
512 | 849 | 790 | ||
513 | 850 | def create_bridge(self, params): | 791 | def create_bridge(self, params): |
514 | 851 | """Create bridge interface.""" | 792 | """Create bridge interface.""" |
520 | 852 | # Only admin users can perform create. | 793 | node = self._get_node_or_permission_error(params) |
516 | 853 | if not reload_object(self.user).is_superuser: | ||
517 | 854 | raise HandlerPermissionError() | ||
518 | 855 | |||
519 | 856 | node = self.get_object(params) | ||
521 | 857 | if node.status == NODE_STATUS.ALLOCATED: | 794 | if node.status == NODE_STATUS.ALLOCATED: |
522 | 858 | form = AcquiredBridgeInterfaceForm(node=node, data=params) | 795 | form = AcquiredBridgeInterfaceForm(node=node, data=params) |
523 | 859 | else: | 796 | else: |
524 | @@ -867,11 +804,7 @@ class MachineHandler(NodeHandler): | |||
525 | 867 | 804 | ||
526 | 868 | def update_interface(self, params): | 805 | def update_interface(self, params): |
527 | 869 | """Update the interface.""" | 806 | """Update the interface.""" |
533 | 870 | # Only admin users can perform update. | 807 | node = self._get_node_or_permission_error(params) |
529 | 871 | if not reload_object(self.user).is_superuser: | ||
530 | 872 | raise HandlerPermissionError() | ||
531 | 873 | |||
532 | 874 | node = self.get_object(params) | ||
534 | 875 | interface = Interface.objects.get(node=node, id=params["interface_id"]) | 808 | interface = Interface.objects.get(node=node, id=params["interface_id"]) |
535 | 876 | if node.status == NODE_STATUS.DEPLOYED: | 809 | if node.status == NODE_STATUS.DEPLOYED: |
536 | 877 | interface_form = DeployedInterfaceForm | 810 | interface_form = DeployedInterfaceForm |
537 | @@ -889,21 +822,13 @@ class MachineHandler(NodeHandler): | |||
538 | 889 | 822 | ||
539 | 890 | def delete_interface(self, params): | 823 | def delete_interface(self, params): |
540 | 891 | """Delete the interface.""" | 824 | """Delete the interface.""" |
546 | 892 | # Only admin users can perform delete. | 825 | node = self._get_node_or_permission_error(params) |
542 | 893 | if not reload_object(self.user).is_superuser: | ||
543 | 894 | raise HandlerPermissionError() | ||
544 | 895 | |||
545 | 896 | node = self.get_object(params) | ||
547 | 897 | interface = Interface.objects.get(node=node, id=params["interface_id"]) | 826 | interface = Interface.objects.get(node=node, id=params["interface_id"]) |
548 | 898 | interface.delete() | 827 | interface.delete() |
549 | 899 | 828 | ||
550 | 900 | def link_subnet(self, params): | 829 | def link_subnet(self, params): |
551 | 901 | """Create or update the link.""" | 830 | """Create or update the link.""" |
557 | 902 | # Only admin users can perform update. | 831 | node = self._get_node_or_permission_error(params) |
553 | 903 | if not reload_object(self.user).is_superuser: | ||
554 | 904 | raise HandlerPermissionError() | ||
555 | 905 | |||
556 | 906 | node = self.get_object(params) | ||
558 | 907 | interface = Interface.objects.get(node=node, id=params["interface_id"]) | 832 | interface = Interface.objects.get(node=node, id=params["interface_id"]) |
559 | 908 | subnet = None | 833 | subnet = None |
560 | 909 | if "subnet" in params: | 834 | if "subnet" in params: |
561 | @@ -923,11 +848,7 @@ class MachineHandler(NodeHandler): | |||
562 | 923 | 848 | ||
563 | 924 | def unlink_subnet(self, params): | 849 | def unlink_subnet(self, params): |
564 | 925 | """Delete the link.""" | 850 | """Delete the link.""" |
570 | 926 | # Only admin users can perform unlink. | 851 | node = self._get_node_or_permission_error(params) |
566 | 927 | if not reload_object(self.user).is_superuser: | ||
567 | 928 | raise HandlerPermissionError() | ||
568 | 929 | |||
569 | 930 | node = self.get_object(params) | ||
571 | 931 | interface = Interface.objects.get(node=node, id=params["interface_id"]) | 852 | interface = Interface.objects.get(node=node, id=params["interface_id"]) |
572 | 932 | interface.unlink_subnet_by_id(params["link_id"]) | 853 | interface.unlink_subnet_by_id(params["link_id"]) |
573 | 933 | 854 | ||
574 | @@ -958,3 +879,9 @@ class MachineHandler(NodeHandler): | |||
575 | 958 | d.addErrback(eb_error) | 879 | d.addErrback(eb_error) |
576 | 959 | d.addCallback(partial(deferToDatabase, update_state)) | 880 | d.addCallback(partial(deferToDatabase, update_state)) |
577 | 960 | return d | 881 | return d |
578 | 882 | |||
579 | 883 | def _get_node_or_permission_error(self, params): | ||
580 | 884 | node = self.get_object(params) | ||
581 | 885 | if not reload_object(self.user).is_superuser or node.locked: | ||
582 | 886 | raise HandlerPermissionError() | ||
583 | 887 | return node | ||
584 | diff --git a/src/maasserver/websockets/handlers/tests/test_general.py b/src/maasserver/websockets/handlers/tests/test_general.py | |||
585 | index 8e4139b..f530de8 100644 | |||
586 | --- a/src/maasserver/websockets/handlers/tests/test_general.py | |||
587 | +++ b/src/maasserver/websockets/handlers/tests/test_general.py | |||
588 | @@ -164,7 +164,8 @@ class TestGeneralHandler(MAASServerTestCase): | |||
589 | 164 | self.assertItemsEqual( | 164 | self.assertItemsEqual( |
590 | 165 | ['release', 'mark-broken', 'on', 'deploy', 'mark-fixed', | 165 | ['release', 'mark-broken', 'on', 'deploy', 'mark-fixed', |
591 | 166 | 'commission', 'abort', 'acquire', 'off', 'rescue-mode', | 166 | 'commission', 'abort', 'acquire', 'off', 'rescue-mode', |
593 | 167 | 'exit-rescue-mode', 'test', 'override-failed-testing'], | 167 | 'exit-rescue-mode', 'lock', 'test', 'override-failed-testing', |
594 | 168 | 'unlock'], | ||
595 | 168 | [action['name'] for action in handler.machine_actions({})]) | 169 | [action['name'] for action in handler.machine_actions({})]) |
596 | 169 | 170 | ||
597 | 170 | def test_device_actions_for_admin(self): | 171 | def test_device_actions_for_admin(self): |
598 | diff --git a/src/maasserver/websockets/handlers/tests/test_machine.py b/src/maasserver/websockets/handlers/tests/test_machine.py | |||
599 | index ea45b78..ceef773 100644 | |||
600 | --- a/src/maasserver/websockets/handlers/tests/test_machine.py | |||
601 | +++ b/src/maasserver/websockets/handlers/tests/test_machine.py | |||
602 | @@ -1799,10 +1799,19 @@ class TestMachineHandler(MAASServerTestCase): | |||
603 | 1799 | 1799 | ||
604 | 1800 | def test_update_raise_permissions_error_for_non_admin(self): | 1800 | def test_update_raise_permissions_error_for_non_admin(self): |
605 | 1801 | user = factory.make_User() | 1801 | user = factory.make_User() |
606 | 1802 | node = factory.make_Node() | ||
607 | 1803 | handler = MachineHandler(user, {}) | ||
608 | 1804 | self.assertRaises( | ||
609 | 1805 | HandlerPermissionError, | ||
610 | 1806 | handler.update, {'system_id': node.system_id}) | ||
611 | 1807 | |||
612 | 1808 | def test_update_raise_permissions_error_for_locked_node(self): | ||
613 | 1809 | user = factory.make_admin() | ||
614 | 1810 | node = factory.make_Node(locked=True) | ||
615 | 1802 | handler = MachineHandler(user, {}) | 1811 | handler = MachineHandler(user, {}) |
616 | 1803 | self.assertRaises( | 1812 | self.assertRaises( |
617 | 1804 | HandlerPermissionError, | 1813 | HandlerPermissionError, |
619 | 1805 | handler.update, {}) | 1814 | handler.update, {'system_id': node.system_id}) |
620 | 1806 | 1815 | ||
621 | 1807 | def test_update_raises_validation_error_for_invalid_architecture(self): | 1816 | def test_update_raises_validation_error_for_invalid_architecture(self): |
622 | 1808 | user = factory.make_admin() | 1817 | user = factory.make_admin() |
623 | @@ -1980,6 +1989,18 @@ class TestMachineHandler(MAASServerTestCase): | |||
624 | 1980 | self.assertEqual(new_name, block_device.name) | 1989 | self.assertEqual(new_name, block_device.name) |
625 | 1981 | self.assertItemsEqual(new_tags, block_device.tags) | 1990 | self.assertItemsEqual(new_tags, block_device.tags) |
626 | 1982 | 1991 | ||
627 | 1992 | def test_update_disk_locked_raises_permission_error(self): | ||
628 | 1993 | user = factory.make_admin() | ||
629 | 1994 | handler = MachineHandler(user, {}) | ||
630 | 1995 | node = factory.make_Node(locked=True) | ||
631 | 1996 | block_device = factory.make_PhysicalBlockDevice(node=node) | ||
632 | 1997 | new_name = factory.make_name("new") | ||
633 | 1998 | params = { | ||
634 | 1999 | 'system_id': node.system_id, | ||
635 | 2000 | 'block_id': block_device.id, | ||
636 | 2001 | 'name': new_name} | ||
637 | 2002 | self.assertRaises(HandlerPermissionError, handler.update_disk, params) | ||
638 | 2003 | |||
639 | 1983 | def test_delete_disk(self): | 2004 | def test_delete_disk(self): |
640 | 1984 | user = factory.make_admin() | 2005 | user = factory.make_admin() |
641 | 1985 | handler = MachineHandler(user, {}) | 2006 | handler = MachineHandler(user, {}) |
642 | @@ -1995,6 +2016,16 @@ class TestMachineHandler(MAASServerTestCase): | |||
643 | 1995 | }) | 2016 | }) |
644 | 1996 | self.assertIsNone(reload_object(block_device)) | 2017 | self.assertIsNone(reload_object(block_device)) |
645 | 1997 | 2018 | ||
646 | 2019 | def test_delete_disk_locked_raises_permission_error(self): | ||
647 | 2020 | user = factory.make_admin() | ||
648 | 2021 | handler = MachineHandler(user, {}) | ||
649 | 2022 | node = factory.make_Node(locked=True) | ||
650 | 2023 | block_device = factory.make_PhysicalBlockDevice(node=node) | ||
651 | 2024 | params = { | ||
652 | 2025 | 'system_id': node.system_id, | ||
653 | 2026 | 'block_id': block_device.id} | ||
654 | 2027 | self.assertRaises(HandlerPermissionError, handler.delete_disk, params) | ||
655 | 2028 | |||
656 | 1998 | def test_delete_partition(self): | 2029 | def test_delete_partition(self): |
657 | 1999 | user = factory.make_admin() | 2030 | user = factory.make_admin() |
658 | 2000 | handler = MachineHandler(user, {}) | 2031 | handler = MachineHandler(user, {}) |
659 | @@ -2010,6 +2041,17 @@ class TestMachineHandler(MAASServerTestCase): | |||
660 | 2010 | }) | 2041 | }) |
661 | 2011 | self.assertIsNone(reload_object(partition)) | 2042 | self.assertIsNone(reload_object(partition)) |
662 | 2012 | 2043 | ||
663 | 2044 | def test_delete_partition_locked_raises_permission_error(self): | ||
664 | 2045 | user = factory.make_admin() | ||
665 | 2046 | handler = MachineHandler(user, {}) | ||
666 | 2047 | node = factory.make_Node(locked=True) | ||
667 | 2048 | partition = factory.make_Partition(node=node) | ||
668 | 2049 | params = { | ||
669 | 2050 | 'system_id': node.system_id, | ||
670 | 2051 | 'partition_id': partition.id} | ||
671 | 2052 | self.assertRaises( | ||
672 | 2053 | HandlerPermissionError, handler.delete_partition, params) | ||
673 | 2054 | |||
674 | 2013 | def test_delete_volume_group(self): | 2055 | def test_delete_volume_group(self): |
675 | 2014 | user = factory.make_admin() | 2056 | user = factory.make_admin() |
676 | 2015 | handler = MachineHandler(user, {}) | 2057 | handler = MachineHandler(user, {}) |
677 | @@ -2026,6 +2068,18 @@ class TestMachineHandler(MAASServerTestCase): | |||
678 | 2026 | }) | 2068 | }) |
679 | 2027 | self.assertIsNone(reload_object(volume_group)) | 2069 | self.assertIsNone(reload_object(volume_group)) |
680 | 2028 | 2070 | ||
681 | 2071 | def test_delete_volume_group_locked_raises_permission_error(self): | ||
682 | 2072 | user = factory.make_admin() | ||
683 | 2073 | handler = MachineHandler(user, {}) | ||
684 | 2074 | node = factory.make_Node(locked=True) | ||
685 | 2075 | volume_group = factory.make_FilesystemGroup( | ||
686 | 2076 | node=node, group_type=FILESYSTEM_GROUP_TYPE.LVM_VG) | ||
687 | 2077 | params = { | ||
688 | 2078 | 'system_id': node.system_id, | ||
689 | 2079 | 'volume_group_id': volume_group.id} | ||
690 | 2080 | self.assertRaises( | ||
691 | 2081 | HandlerPermissionError, handler.delete_volume_group, params) | ||
692 | 2082 | |||
693 | 2029 | def test_delete_cache_set(self): | 2083 | def test_delete_cache_set(self): |
694 | 2030 | user = factory.make_admin() | 2084 | user = factory.make_admin() |
695 | 2031 | handler = MachineHandler(user, {}) | 2085 | handler = MachineHandler(user, {}) |
696 | @@ -2041,6 +2095,17 @@ class TestMachineHandler(MAASServerTestCase): | |||
697 | 2041 | }) | 2095 | }) |
698 | 2042 | self.assertIsNone(reload_object(cache_set)) | 2096 | self.assertIsNone(reload_object(cache_set)) |
699 | 2043 | 2097 | ||
700 | 2098 | def test_delete_cache_set_locked_raises_permission_error(self): | ||
701 | 2099 | user = factory.make_admin() | ||
702 | 2100 | handler = MachineHandler(user, {}) | ||
703 | 2101 | node = factory.make_Node(locked=True) | ||
704 | 2102 | cache_set = factory.make_CacheSet(node=node) | ||
705 | 2103 | params = { | ||
706 | 2104 | 'system_id': node.system_id, | ||
707 | 2105 | 'cache_set_id': cache_set.id} | ||
708 | 2106 | self.assertRaises( | ||
709 | 2107 | HandlerPermissionError, handler.delete_cache_set, params) | ||
710 | 2108 | |||
711 | 2044 | def test_delete_filesystem_deletes_blockdevice_filesystem(self): | 2109 | def test_delete_filesystem_deletes_blockdevice_filesystem(self): |
712 | 2045 | user = factory.make_admin() | 2110 | user = factory.make_admin() |
713 | 2046 | handler = MachineHandler(user, {}) | 2111 | handler = MachineHandler(user, {}) |
714 | @@ -2079,6 +2144,20 @@ class TestMachineHandler(MAASServerTestCase): | |||
715 | 2079 | self.assertIsNone(reload_object(filesystem)) | 2144 | self.assertIsNone(reload_object(filesystem)) |
716 | 2080 | self.assertIsNotNone(reload_object(partition)) | 2145 | self.assertIsNotNone(reload_object(partition)) |
717 | 2081 | 2146 | ||
718 | 2147 | def test_delete_filesystem_locked_raises_permission_error(self): | ||
719 | 2148 | user = factory.make_admin() | ||
720 | 2149 | handler = MachineHandler(user, {}) | ||
721 | 2150 | node = factory.make_Node(locked=True) | ||
722 | 2151 | partition = factory.make_Partition(node=node) | ||
723 | 2152 | filesystem = factory.make_Filesystem( | ||
724 | 2153 | partition=partition, fstype=FILESYSTEM_TYPE.EXT4) | ||
725 | 2154 | params = { | ||
726 | 2155 | 'system_id': node.system_id, | ||
727 | 2156 | 'partition_id': partition.id, | ||
728 | 2157 | 'filesystem_id': filesystem.id} | ||
729 | 2158 | self.assertRaises( | ||
730 | 2159 | HandlerPermissionError, handler.delete_filesystem, params) | ||
731 | 2160 | |||
732 | 2082 | def test_create_partition(self): | 2161 | def test_create_partition(self): |
733 | 2083 | user = factory.make_admin() | 2162 | user = factory.make_admin() |
734 | 2084 | handler = MachineHandler(user, {}) | 2163 | handler = MachineHandler(user, {}) |
735 | @@ -2142,6 +2221,29 @@ class TestMachineHandler(MAASServerTestCase): | |||
736 | 2142 | fstype=fstype, mount_point=mount_point, | 2221 | fstype=fstype, mount_point=mount_point, |
737 | 2143 | mount_options=mount_options)) | 2222 | mount_options=mount_options)) |
738 | 2144 | 2223 | ||
739 | 2224 | def test_create_partition_locked_raises_permission_error(self): | ||
740 | 2225 | user = factory.make_admin() | ||
741 | 2226 | handler = MachineHandler(user, {}) | ||
742 | 2227 | node = factory.make_Node(locked=True) | ||
743 | 2228 | block_device = factory.make_BlockDevice(node=node) | ||
744 | 2229 | partition_table = factory.make_PartitionTable( | ||
745 | 2230 | block_device=block_device, node=node) | ||
746 | 2231 | partition_table = factory.make_PartitionTable( | ||
747 | 2232 | block_device=block_device, node=node) | ||
748 | 2233 | size = partition_table.block_device.size // 2 | ||
749 | 2234 | fstype = factory.pick_filesystem_type() | ||
750 | 2235 | mount_point = factory.make_absolute_path() | ||
751 | 2236 | mount_options = factory.make_name("options") | ||
752 | 2237 | params = { | ||
753 | 2238 | 'system_id': node.system_id, | ||
754 | 2239 | 'block_id': partition_table.block_device_id, | ||
755 | 2240 | 'partition_size': size, | ||
756 | 2241 | 'fstype': fstype, | ||
757 | 2242 | 'mount_point': mount_point, | ||
758 | 2243 | 'mount_options': mount_options} | ||
759 | 2244 | self.assertRaises( | ||
760 | 2245 | HandlerPermissionError, handler.create_partition, params) | ||
761 | 2246 | |||
762 | 2145 | def test_create_cache_set_for_partition(self): | 2247 | def test_create_cache_set_for_partition(self): |
763 | 2146 | user = factory.make_admin() | 2248 | user = factory.make_admin() |
764 | 2147 | handler = MachineHandler(user, {}) | 2249 | handler = MachineHandler(user, {}) |
765 | @@ -2171,6 +2273,17 @@ class TestMachineHandler(MAASServerTestCase): | |||
766 | 2171 | self.assertEqual( | 2273 | self.assertEqual( |
767 | 2172 | block_device.id, cache_set.get_filesystem().block_device.id) | 2274 | block_device.id, cache_set.get_filesystem().block_device.id) |
768 | 2173 | 2275 | ||
769 | 2276 | def test_create_cache_set_locked_raises_permission_error(self): | ||
770 | 2277 | user = factory.make_admin() | ||
771 | 2278 | handler = MachineHandler(user, {}) | ||
772 | 2279 | node = factory.make_Node(locked=True) | ||
773 | 2280 | partition = factory.make_Partition(node=node) | ||
774 | 2281 | params = { | ||
775 | 2282 | 'system_id': node.system_id, | ||
776 | 2283 | 'partition_id': partition.id} | ||
777 | 2284 | self.assertRaises( | ||
778 | 2285 | HandlerPermissionError, handler.create_cache_set, params) | ||
779 | 2286 | |||
780 | 2174 | def test_create_bcache_for_partition(self): | 2287 | def test_create_bcache_for_partition(self): |
781 | 2175 | user = factory.make_admin() | 2288 | user = factory.make_admin() |
782 | 2176 | handler = MachineHandler(user, {}) | 2289 | handler = MachineHandler(user, {}) |
783 | @@ -2303,6 +2416,29 @@ class TestMachineHandler(MAASServerTestCase): | |||
784 | 2303 | fstype=fstype, mount_point=mount_point, | 2416 | fstype=fstype, mount_point=mount_point, |
785 | 2304 | mount_options=mount_options)) | 2417 | mount_options=mount_options)) |
786 | 2305 | 2418 | ||
787 | 2419 | def test_create_bcache_set_locked_raises_permission_error(self): | ||
788 | 2420 | user = factory.make_admin() | ||
789 | 2421 | handler = MachineHandler(user, {}) | ||
790 | 2422 | node = factory.make_Node(locked=True) | ||
791 | 2423 | block_device = factory.make_PhysicalBlockDevice(node=node) | ||
792 | 2424 | name = factory.make_name("bcache") | ||
793 | 2425 | cache_set = factory.make_CacheSet(node=node) | ||
794 | 2426 | cache_mode = factory.pick_enum(CACHE_MODE_TYPE) | ||
795 | 2427 | fstype = factory.pick_filesystem_type() | ||
796 | 2428 | mount_point = factory.make_absolute_path() | ||
797 | 2429 | mount_options = factory.make_name("options") | ||
798 | 2430 | params = { | ||
799 | 2431 | 'system_id': node.system_id, | ||
800 | 2432 | 'block_id': block_device.id, | ||
801 | 2433 | 'name': name, | ||
802 | 2434 | 'cache_set': cache_set.id, | ||
803 | 2435 | 'cache_mode': cache_mode, | ||
804 | 2436 | 'fstype': fstype, | ||
805 | 2437 | 'mount_point': mount_point, | ||
806 | 2438 | 'mount_options': mount_options} | ||
807 | 2439 | self.assertRaises( | ||
808 | 2440 | HandlerPermissionError, handler.create_bcache, params) | ||
809 | 2441 | |||
810 | 2306 | def test_create_raid(self): | 2442 | def test_create_raid(self): |
811 | 2307 | user = factory.make_admin() | 2443 | user = factory.make_admin() |
812 | 2308 | handler = MachineHandler(user, {}) | 2444 | handler = MachineHandler(user, {}) |
813 | @@ -2363,6 +2499,20 @@ class TestMachineHandler(MAASServerTestCase): | |||
814 | 2363 | fstype=fstype, mount_point=mount_point, | 2499 | fstype=fstype, mount_point=mount_point, |
815 | 2364 | mount_options=mount_options)) | 2500 | mount_options=mount_options)) |
816 | 2365 | 2501 | ||
817 | 2502 | def test_create_raid_locked_raises_permission_error(self): | ||
818 | 2503 | user = factory.make_admin() | ||
819 | 2504 | handler = MachineHandler(user, {}) | ||
820 | 2505 | node = factory.make_Node(locked=True) | ||
821 | 2506 | disk0 = factory.make_PhysicalBlockDevice(node=node) | ||
822 | 2507 | disk1 = factory.make_PhysicalBlockDevice(node=node) | ||
823 | 2508 | params = { | ||
824 | 2509 | 'system_id': node.system_id, | ||
825 | 2510 | 'name': factory.make_name('md'), | ||
826 | 2511 | 'level': 'raid-1', | ||
827 | 2512 | 'block_devices': [disk0.id, disk1.id]} | ||
828 | 2513 | self.assertRaises( | ||
829 | 2514 | HandlerPermissionError, handler.create_raid, params) | ||
830 | 2515 | |||
831 | 2366 | def test_create_volume_group(self): | 2516 | def test_create_volume_group(self): |
832 | 2367 | user = factory.make_admin() | 2517 | user = factory.make_admin() |
833 | 2368 | handler = MachineHandler(user, {}) | 2518 | handler = MachineHandler(user, {}) |
834 | @@ -2439,6 +2589,21 @@ class TestMachineHandler(MAASServerTestCase): | |||
835 | 2439 | fstype=fstype, mount_point=mount_point, | 2589 | fstype=fstype, mount_point=mount_point, |
836 | 2440 | mount_options=mount_options)) | 2590 | mount_options=mount_options)) |
837 | 2441 | 2591 | ||
838 | 2592 | def test_create_logical_volume_locked_raises_permission_error(self): | ||
839 | 2593 | user = factory.make_admin() | ||
840 | 2594 | handler = MachineHandler(user, {}) | ||
841 | 2595 | node = factory.make_Node(locked=True) | ||
842 | 2596 | volume_group = factory.make_FilesystemGroup( | ||
843 | 2597 | group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, node=node) | ||
844 | 2598 | size = volume_group.get_lvm_free_space() | ||
845 | 2599 | params = { | ||
846 | 2600 | 'system_id': node.system_id, | ||
847 | 2601 | 'name': factory.make_name("lv"), | ||
848 | 2602 | 'volume_group_id': volume_group.id, | ||
849 | 2603 | 'size': size} | ||
850 | 2604 | self.assertRaises( | ||
851 | 2605 | HandlerPermissionError, handler.create_logical_volume, params) | ||
852 | 2606 | |||
853 | 2442 | def test_set_boot_disk(self): | 2607 | def test_set_boot_disk(self): |
854 | 2443 | user = factory.make_admin() | 2608 | user = factory.make_admin() |
855 | 2444 | handler = MachineHandler(user, {}) | 2609 | handler = MachineHandler(user, {}) |
856 | @@ -2464,6 +2629,17 @@ class TestMachineHandler(MAASServerTestCase): | |||
857 | 2464 | self.assertEqual( | 2629 | self.assertEqual( |
858 | 2465 | str(error), "Only a physical disk can be set as the boot disk.") | 2630 | str(error), "Only a physical disk can be set as the boot disk.") |
859 | 2466 | 2631 | ||
860 | 2632 | def test_set_boot_disk_locked_raises_permission_error(self): | ||
861 | 2633 | user = factory.make_admin() | ||
862 | 2634 | handler = MachineHandler(user, {}) | ||
863 | 2635 | node = factory.make_Node(locked=True) | ||
864 | 2636 | boot_disk = factory.make_PhysicalBlockDevice(node=node) | ||
865 | 2637 | params = { | ||
866 | 2638 | 'system_id': node.system_id, | ||
867 | 2639 | 'block_id': boot_disk.id} | ||
868 | 2640 | self.assertRaises( | ||
869 | 2641 | HandlerPermissionError, handler.set_boot_disk, params) | ||
870 | 2642 | |||
871 | 2467 | def test_update_raise_HandlerError_if_tag_has_definition(self): | 2643 | def test_update_raise_HandlerError_if_tag_has_definition(self): |
872 | 2468 | user = factory.make_admin() | 2644 | user = factory.make_admin() |
873 | 2469 | handler = MachineHandler(user, {}) | 2645 | handler = MachineHandler(user, {}) |
874 | @@ -2625,6 +2801,19 @@ class TestMachineHandler(MAASServerTestCase): | |||
875 | 2625 | node=node, type=INTERFACE_TYPE.VLAN, parents=interface)) | 2801 | node=node, type=INTERFACE_TYPE.VLAN, parents=interface)) |
876 | 2626 | self.assertIsNotNone(vlan_interface) | 2802 | self.assertIsNotNone(vlan_interface) |
877 | 2627 | 2803 | ||
878 | 2804 | def test_create_physical_locked_raises_permission_error(self): | ||
879 | 2805 | user = factory.make_admin() | ||
880 | 2806 | node = factory.make_Node(locked=True) | ||
881 | 2807 | handler = MachineHandler(user, {}) | ||
882 | 2808 | vlan = factory.make_VLAN() | ||
883 | 2809 | params = { | ||
884 | 2810 | "system_id": node.system_id, | ||
885 | 2811 | "name": factory.make_name("eth"), | ||
886 | 2812 | "mac_address": factory.make_mac_address(), | ||
887 | 2813 | "vlan": vlan.id} | ||
888 | 2814 | self.assertRaises( | ||
889 | 2815 | HandlerPermissionError, handler.create_physical, params) | ||
890 | 2816 | |||
891 | 2628 | def test_create_vlan_creates_link_auto(self): | 2817 | def test_create_vlan_creates_link_auto(self): |
892 | 2629 | user = factory.make_admin() | 2818 | user = factory.make_admin() |
893 | 2630 | node = factory.make_Node() | 2819 | node = factory.make_Node() |
894 | @@ -2692,6 +2881,23 @@ class TestMachineHandler(MAASServerTestCase): | |||
895 | 2692 | alloc_type=IPADDRESS_TYPE.STICKY, ip=None, subnet=new_subnet) | 2881 | alloc_type=IPADDRESS_TYPE.STICKY, ip=None, subnet=new_subnet) |
896 | 2693 | self.assertIsNotNone(link_up_ip) | 2882 | self.assertIsNotNone(link_up_ip) |
897 | 2694 | 2883 | ||
898 | 2884 | def test_create_vlan_locked_raises_permission_error(self): | ||
899 | 2885 | user = factory.make_admin() | ||
900 | 2886 | node = factory.make_Node(locked=True) | ||
901 | 2887 | handler = MachineHandler(user, {}) | ||
902 | 2888 | vlan = factory.make_VLAN() | ||
903 | 2889 | interface = factory.make_Interface( | ||
904 | 2890 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) | ||
905 | 2891 | new_subnet = factory.make_Subnet(vlan=vlan) | ||
906 | 2892 | params = { | ||
907 | 2893 | "system_id": node.system_id, | ||
908 | 2894 | "parent": interface.id, | ||
909 | 2895 | "vlan": vlan.id, | ||
910 | 2896 | "mode": INTERFACE_LINK_TYPE.AUTO, | ||
911 | 2897 | "subnet": new_subnet.id} | ||
912 | 2898 | self.assertRaises( | ||
913 | 2899 | HandlerPermissionError, handler.create_vlan, params) | ||
914 | 2900 | |||
915 | 2695 | def test_create_bond_creates_bond(self): | 2901 | def test_create_bond_creates_bond(self): |
916 | 2696 | user = factory.make_admin() | 2902 | user = factory.make_admin() |
917 | 2697 | node = factory.make_Node() | 2903 | node = factory.make_Node() |
918 | @@ -2729,6 +2935,24 @@ class TestMachineHandler(MAASServerTestCase): | |||
919 | 2729 | "parents": [nic1.id, nic2.id], | 2935 | "parents": [nic1.id, nic2.id], |
920 | 2730 | }) | 2936 | }) |
921 | 2731 | 2937 | ||
922 | 2938 | def test_create_bond_locked_raises_permission_error(self): | ||
923 | 2939 | user = factory.make_admin() | ||
924 | 2940 | node = factory.make_Node(locked=True) | ||
925 | 2941 | handler = MachineHandler(user, {}) | ||
926 | 2942 | nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | ||
927 | 2943 | nic2 = factory.make_Interface( | ||
928 | 2944 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=nic1.vlan) | ||
929 | 2945 | bond_mode = factory.pick_enum(BOND_MODE) | ||
930 | 2946 | params = { | ||
931 | 2947 | "system_id": node.system_id, | ||
932 | 2948 | "name": factory.make_name("bond"), | ||
933 | 2949 | "parents": [nic1.id, nic2.id], | ||
934 | 2950 | "mac_address": "%s" % nic1.mac_address, | ||
935 | 2951 | "vlan": nic1.vlan.id, | ||
936 | 2952 | "bond_mode": bond_mode} | ||
937 | 2953 | self.assertRaises( | ||
938 | 2954 | HandlerPermissionError, handler.create_bond, params) | ||
939 | 2955 | |||
940 | 2732 | def test_create_bridge_creates_bridge(self): | 2956 | def test_create_bridge_creates_bridge(self): |
941 | 2733 | user = factory.make_admin() | 2957 | user = factory.make_admin() |
942 | 2734 | node = factory.make_Node() | 2958 | node = factory.make_Node() |
943 | @@ -2765,6 +2989,22 @@ class TestMachineHandler(MAASServerTestCase): | |||
944 | 2765 | "parents": [nic1.id], | 2989 | "parents": [nic1.id], |
945 | 2766 | }) | 2990 | }) |
946 | 2767 | 2991 | ||
947 | 2992 | def test_create_bridge_locked_raises_permission_error(self): | ||
948 | 2993 | user = factory.make_admin() | ||
949 | 2994 | node = factory.make_Node(locked=True) | ||
950 | 2995 | handler = MachineHandler(user, {}) | ||
951 | 2996 | nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | ||
952 | 2997 | params = { | ||
953 | 2998 | "system_id": node.system_id, | ||
954 | 2999 | "name": factory.make_name("br"), | ||
955 | 3000 | "parents": [nic1.id], | ||
956 | 3001 | "mac_address": "%s" % nic1.mac_address, | ||
957 | 3002 | "vlan": nic1.vlan.id, | ||
958 | 3003 | "bridge_stp": factory.pick_bool(), | ||
959 | 3004 | "bridge_fd": random.randint(0, 15)} | ||
960 | 3005 | self.assertRaises( | ||
961 | 3006 | HandlerPermissionError, handler.create_bridge, params) | ||
962 | 3007 | |||
963 | 2768 | def test_update_interface(self): | 3008 | def test_update_interface(self): |
964 | 2769 | user = factory.make_admin() | 3009 | user = factory.make_admin() |
965 | 2770 | node = factory.make_Node() | 3010 | node = factory.make_Node() |
966 | @@ -2814,6 +3054,20 @@ class TestMachineHandler(MAASServerTestCase): | |||
967 | 2814 | "vlan": random.randint(1000, 5000), | 3054 | "vlan": random.randint(1000, 5000), |
968 | 2815 | }) | 3055 | }) |
969 | 2816 | 3056 | ||
970 | 3057 | def test_update_interface_locked_raises_permission_error(self): | ||
971 | 3058 | user = factory.make_admin() | ||
972 | 3059 | node = factory.make_Node(locked=True) | ||
973 | 3060 | handler = MachineHandler(user, {}) | ||
974 | 3061 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | ||
975 | 3062 | handler._script_results = {} | ||
976 | 3063 | handler._refresh_script_result_cache(node.get_latest_script_results) | ||
977 | 3064 | params = { | ||
978 | 3065 | "system_id": node.system_id, | ||
979 | 3066 | "interface_id": interface.id, | ||
980 | 3067 | "name": factory.make_name("name")} | ||
981 | 3068 | self.assertRaises( | ||
982 | 3069 | HandlerPermissionError, handler.update_interface, params) | ||
983 | 3070 | |||
984 | 2817 | def test_delete_interface(self): | 3071 | def test_delete_interface(self): |
985 | 2818 | user = factory.make_admin() | 3072 | user = factory.make_admin() |
986 | 2819 | node = factory.make_Node() | 3073 | node = factory.make_Node() |
987 | @@ -2825,6 +3079,17 @@ class TestMachineHandler(MAASServerTestCase): | |||
988 | 2825 | }) | 3079 | }) |
989 | 2826 | self.assertIsNone(reload_object(interface)) | 3080 | self.assertIsNone(reload_object(interface)) |
990 | 2827 | 3081 | ||
991 | 3082 | def test_delete_interface_locked_raises_permission_error(self): | ||
992 | 3083 | user = factory.make_admin() | ||
993 | 3084 | node = factory.make_Node(locked=True) | ||
994 | 3085 | handler = MachineHandler(user, {}) | ||
995 | 3086 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | ||
996 | 3087 | params = { | ||
997 | 3088 | "system_id": node.system_id, | ||
998 | 3089 | "interface_id": interface.id} | ||
999 | 3090 | self.assertRaises( | ||
1000 | 3091 | HandlerPermissionError, handler.delete_interface, params) | ||
1001 | 3092 | |||
1002 | 2828 | def test_link_subnet_calls_update_link_by_id_if_link_id(self): | 3093 | def test_link_subnet_calls_update_link_by_id_if_link_id(self): |
1003 | 2829 | user = factory.make_admin() | 3094 | user = factory.make_admin() |
1004 | 2830 | node = factory.make_Node() | 3095 | node = factory.make_Node() |
1005 | @@ -2894,6 +3159,22 @@ class TestMachineHandler(MAASServerTestCase): | |||
1006 | 2894 | MockCalledOnceWith( | 3159 | MockCalledOnceWith( |
1007 | 2895 | ANY, mode, subnet, ip_address=ip_address)) | 3160 | ANY, mode, subnet, ip_address=ip_address)) |
1008 | 2896 | 3161 | ||
1009 | 3162 | def test_link_subnet_locked_raises_permission_error(self): | ||
1010 | 3163 | user = factory.make_admin() | ||
1011 | 3164 | node = factory.make_Node(locked=True) | ||
1012 | 3165 | handler = MachineHandler(user, {}) | ||
1013 | 3166 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | ||
1014 | 3167 | subnet = factory.make_Subnet() | ||
1015 | 3168 | params = { | ||
1016 | 3169 | "system_id": node.system_id, | ||
1017 | 3170 | "interface_id": interface.id, | ||
1018 | 3171 | "link_id": factory.make_StaticIPAddress(interface=interface).id, | ||
1019 | 3172 | "subnet": subnet.id, | ||
1020 | 3173 | "mode": factory.pick_enum(INTERFACE_LINK_TYPE), | ||
1021 | 3174 | "ip_address": factory.make_ip_address()} | ||
1022 | 3175 | self.assertRaises( | ||
1023 | 3176 | HandlerPermissionError, handler.link_subnet, params) | ||
1024 | 3177 | |||
1025 | 2897 | def test_unlink_subnet(self): | 3178 | def test_unlink_subnet(self): |
1026 | 2898 | user = factory.make_admin() | 3179 | user = factory.make_admin() |
1027 | 2899 | node = factory.make_Node() | 3180 | node = factory.make_Node() |
1028 | @@ -2901,13 +3182,27 @@ class TestMachineHandler(MAASServerTestCase): | |||
1029 | 2901 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | 3182 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
1030 | 2902 | link_ip = factory.make_StaticIPAddress( | 3183 | link_ip = factory.make_StaticIPAddress( |
1031 | 2903 | alloc_type=IPADDRESS_TYPE.AUTO, ip="", interface=interface) | 3184 | alloc_type=IPADDRESS_TYPE.AUTO, ip="", interface=interface) |
1033 | 2904 | handler.delete_interface({ | 3185 | handler.unlink_subnet({ |
1034 | 2905 | "system_id": node.system_id, | 3186 | "system_id": node.system_id, |
1035 | 2906 | "interface_id": interface.id, | 3187 | "interface_id": interface.id, |
1036 | 2907 | "link_id": link_ip.id, | 3188 | "link_id": link_ip.id, |
1037 | 2908 | }) | 3189 | }) |
1038 | 2909 | self.assertIsNone(reload_object(link_ip)) | 3190 | self.assertIsNone(reload_object(link_ip)) |
1039 | 2910 | 3191 | ||
1040 | 3192 | def test_unlink_subnet_locked_raises_permission_error(self): | ||
1041 | 3193 | user = factory.make_admin() | ||
1042 | 3194 | node = factory.make_Node(locked=True) | ||
1043 | 3195 | handler = MachineHandler(user, {}) | ||
1044 | 3196 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | ||
1045 | 3197 | link_ip = factory.make_StaticIPAddress( | ||
1046 | 3198 | alloc_type=IPADDRESS_TYPE.AUTO, ip="", interface=interface) | ||
1047 | 3199 | params = { | ||
1048 | 3200 | "system_id": node.system_id, | ||
1049 | 3201 | "interface_id": interface.id, | ||
1050 | 3202 | "link_id": link_ip.id} | ||
1051 | 3203 | self.assertRaises( | ||
1052 | 3204 | HandlerPermissionError, handler.unlink_subnet, params) | ||
1053 | 3205 | |||
1054 | 2911 | def test_get_grouped_storages_parses_blockdevices(self): | 3206 | def test_get_grouped_storages_parses_blockdevices(self): |
1055 | 2912 | user = factory.make_User() | 3207 | user = factory.make_User() |
1056 | 2913 | node = factory.make_Node(owner=user) | 3208 | node = factory.make_Node(owner=user) |
1057 | @@ -3045,6 +3340,17 @@ class TestMachineHandlerMountSpecial(MAASServerTestCase): | |||
1058 | 3045 | 'mount_point': Equals(["Enter a valid value."]), | 3340 | 'mount_point': Equals(["Enter a valid value."]), |
1059 | 3046 | })) | 3341 | })) |
1060 | 3047 | 3342 | ||
1061 | 3343 | def test_locked_raises_permission_error(self): | ||
1062 | 3344 | user = factory.make_admin() | ||
1063 | 3345 | handler = MachineHandler(user, {}) | ||
1064 | 3346 | machine = factory.make_Node(locked=True, owner=user) | ||
1065 | 3347 | params = { | ||
1066 | 3348 | 'system_id': machine.system_id, 'fstype': FILESYSTEM_TYPE.RAMFS, | ||
1067 | 3349 | 'mount_point': factory.make_absolute_path(), | ||
1068 | 3350 | } | ||
1069 | 3351 | self.assertRaises( | ||
1070 | 3352 | HandlerPermissionError, handler.mount_special, params) | ||
1071 | 3353 | |||
1072 | 3048 | 3354 | ||
1073 | 3049 | class TestMachineHandlerMountSpecialScenarios(MAASServerTestCase): | 3355 | class TestMachineHandlerMountSpecialScenarios(MAASServerTestCase): |
1074 | 3050 | """Scenario tests for MachineHandler.mount_special.""" | 3356 | """Scenario tests for MachineHandler.mount_special.""" |
1075 | @@ -3247,9 +3553,37 @@ class TestMachineHandlerUnmountSpecialScenarios(MAASServerTestCase): | |||
1076 | 3247 | raises_node_state_violation, | 3553 | raises_node_state_violation, |
1077 | 3248 | "using status %d on %s" % (status, self.fstype)) | 3554 | "using status %d on %s" % (status, self.fstype)) |
1078 | 3249 | 3555 | ||
1079 | 3556 | def test_locked_raises_permission_error(self): | ||
1080 | 3557 | admin = factory.make_admin() | ||
1081 | 3558 | node = factory.make_Node(locked=True, owner=admin) | ||
1082 | 3559 | filesystem = factory.make_Filesystem( | ||
1083 | 3560 | node=node, fstype=self.fstype, | ||
1084 | 3561 | mount_point=factory.make_absolute_path()) | ||
1085 | 3562 | handler = MachineHandler(admin, {}) | ||
1086 | 3563 | params = { | ||
1087 | 3564 | 'system_id': node.system_id, | ||
1088 | 3565 | 'mount_point': filesystem.mount_point} | ||
1089 | 3566 | self.assertRaises( | ||
1090 | 3567 | HandlerPermissionError, handler.unmount_special, params) | ||
1091 | 3568 | |||
1092 | 3250 | 3569 | ||
1093 | 3251 | class TestMachineHandlerUpdateFilesystem(MAASServerTestCase): | 3570 | class TestMachineHandlerUpdateFilesystem(MAASServerTestCase): |
1094 | 3252 | 3571 | ||
1095 | 3572 | def test_locked_raises_permission_error(self): | ||
1096 | 3573 | user = factory.make_admin() | ||
1097 | 3574 | handler = MachineHandler(user, {}) | ||
1098 | 3575 | node = factory.make_Node(locked=True) | ||
1099 | 3576 | block_device = factory.make_PhysicalBlockDevice(node=node) | ||
1100 | 3577 | fs = factory.make_Filesystem(block_device=block_device) | ||
1101 | 3578 | params = { | ||
1102 | 3579 | 'system_id': node.system_id, | ||
1103 | 3580 | 'block_id': block_device.id, | ||
1104 | 3581 | 'fstype': fs.fstype, | ||
1105 | 3582 | 'mount_point': None, | ||
1106 | 3583 | 'mount_options': None} | ||
1107 | 3584 | self.assertRaises( | ||
1108 | 3585 | HandlerPermissionError, handler.update_filesystem, params) | ||
1109 | 3586 | |||
1110 | 3253 | def test_unmount_blockdevice_filesystem(self): | 3587 | def test_unmount_blockdevice_filesystem(self): |
1111 | 3254 | user = factory.make_admin() | 3588 | user = factory.make_admin() |
1112 | 3255 | handler = MachineHandler(user, {}) | 3589 | handler = MachineHandler(user, {}) |
UNIT TESTS machine- ui lp:~ack/maas into -b master lp:~maas-committers/maas
-b lock-unlock-
STATUS: FAILED maas-ci- jenkins. internal: 8080/job/ maas/job/ branch- tester/ 748/console ed15826cfc8b3aa 22fa9de318
LOG: http://
COMMIT: 4de6a9a9df5cabc