Merge ~newell-jensen/maas:fix-1827149 into maas:master

Proposed by Newell Jensen
Status: Merged
Approved by: Newell Jensen
Approved revision: 35994df102d8ff382d6d7ceb77cba61aae209412
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~newell-jensen/maas:fix-1827149
Merge into: maas:master
Diff against target: 253 lines (+68/-34)
9 files modified
src/maasserver/api/machines.py (+15/-17)
src/maasserver/api/nodes.py (+19/-1)
src/maasserver/api/tests/test_machine.py (+4/-2)
src/maasserver/forms/__init__.py (+0/-6)
src/maasserver/forms/tests/test_machine.py (+0/-2)
src/maasserver/models/node.py (+10/-1)
src/maasserver/models/tests/test_node.py (+17/-0)
src/maasserver/node_action.py (+1/-3)
src/maasserver/tests/test_node_action.py (+2/-2)
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Björn Tillenius Pending
Review via email: mp+367324@code.launchpad.net

Commit message

LP: #1827149 -- Create bridges by default when deploying a machine and install_kvm is set to True.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) :
review: Needs Information
~newell-jensen/maas:fix-1827149 updated
8bd7f96... by Newell Jensen

Review updates.

35994df... by Newell Jensen

Update node.start unit test to check if install_kvm is being set.

Revision history for this message
Newell Jensen (newell-jensen) wrote :

Changed node.start to take install_kvm. Yes, the call to node._create_acquired_bridges is a noop if it has already been called and nothing has changed with regards to the interfaces since the last call was made.

Revision history for this message
Blake Rouse (blake-rouse) wrote :

Thanks for the fixes, looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/machines.py b/src/maasserver/api/machines.py
2index be156d0..ab5ab67 100644
3--- a/src/maasserver/api/machines.py
4+++ b/src/maasserver/api/machines.py
5@@ -684,6 +684,21 @@ class MachineHandler(NodeHandler, OwnerDataMixin, PowerMixin):
6 system_id=system_id, user=request.user,
7 perm=NodePermission.edit)
8 options = get_allocation_options(request)
9+ # Deploying a node requires re-checking for EDIT permissions.
10+ if not request.user.has_perm(NodePermission.edit, machine):
11+ raise PermissionDenied()
12+ # Deploying with 'install_rackd' requires ADMIN permissions.
13+ if (options.install_rackd and not
14+ request.user.has_perm(NodePermission.admin, machine)):
15+ raise PermissionDenied()
16+ # Deploying with 'install_kvm' requires ADMIN permissions.
17+ if (options.install_kvm and not
18+ request.user.has_perm(NodePermission.admin, machine)):
19+ raise PermissionDenied()
20+ if options.install_kvm and (
21+ machine.ephemeral_deployment or options.ephemeral_deploy):
22+ raise MAASAPIBadRequest(
23+ "Cannot install KVM host for ephemeral deployments.")
24 if machine.status == NODE_STATUS.READY:
25 with locks.node_acquire:
26 if machine.owner is not None and machine.owner != request.user:
27@@ -701,21 +716,6 @@ class MachineHandler(NodeHandler, OwnerDataMixin, PowerMixin):
28 raise NodeStateViolation(
29 "Can't deploy a machine that is in the '{}' state".format(
30 NODE_STATUS_CHOICES_DICT[machine.status]))
31- # Deploying a node requires re-checking for EDIT permissions.
32- if not request.user.has_perm(NodePermission.edit, machine):
33- raise PermissionDenied()
34- # Deploying with 'install_rackd' requires ADMIN permissions.
35- if (options.install_rackd and not
36- request.user.has_perm(NodePermission.admin, machine)):
37- raise PermissionDenied()
38- # Deploying with 'install_kvm' requires ADMIN permissions.
39- if (options.install_kvm and not
40- request.user.has_perm(NodePermission.admin, machine)):
41- raise PermissionDenied()
42- if options.install_kvm and (
43- machine.ephemeral_deployment or options.ephemeral_deploy):
44- raise MAASAPIBadRequest(
45- "Cannot install KVM host for ephemeral deployments.")
46 if not machine.distro_series and not series:
47 series = Config.objects.get_config('default_distro_series')
48 Form = get_machine_edit_form(request.user)
49@@ -728,8 +728,6 @@ class MachineHandler(NodeHandler, OwnerDataMixin, PowerMixin):
50 form.set_hwe_kernel(hwe_kernel=hwe_kernel)
51 if options.install_rackd:
52 form.set_install_rackd(install_rackd=options.install_rackd)
53- if options.install_kvm:
54- form.set_install_kvm(install_kvm=options.install_kvm)
55 if options.ephemeral_deploy:
56 form.set_ephemeral_deploy(
57 ephemeral_deploy=options.ephemeral_deploy)
58diff --git a/src/maasserver/api/nodes.py b/src/maasserver/api/nodes.py
59index e0229db..ae33551 100644
60--- a/src/maasserver/api/nodes.py
61+++ b/src/maasserver/api/nodes.py
62@@ -16,6 +16,10 @@ import bson
63 from django.db.models import Prefetch
64 from django.http import HttpResponse
65 from django.shortcuts import get_object_or_404
66+from formencode.validators import (
67+ Int,
68+ StringBool,
69+)
70 from maasserver.api.support import (
71 admin_method,
72 AnonymousOperationsHandler,
73@@ -905,7 +909,21 @@ class PowerMixin:
74 if user_data is not None:
75 user_data = b64decode(user_data)
76 try:
77- node.start(request.user, user_data=user_data, comment=comment)
78+ # These parameters are passed in the request from
79+ # maasserver.api.machines.deploy when powering on
80+ # the node for deployment.
81+ install_kvm = get_optional_param(
82+ request.POST, 'install_kvm',
83+ default=False, validator=StringBool)
84+ bridge_stp = get_optional_param(
85+ request.POST, 'bridge_stp', default=None,
86+ validator=StringBool)
87+ bridge_fd = get_optional_param(
88+ request.POST, 'bridge_fd', default=None, validator=Int)
89+ node.start(
90+ request.user, user_data=user_data, comment=comment,
91+ install_kvm=install_kvm, bridge_stp=bridge_stp,
92+ bridge_fd=bridge_fd)
93 except StaticIPAddressExhaustion:
94 # The API response should contain error text with the
95 # system_id in it, as that is the primary API key to a node.
96diff --git a/src/maasserver/api/tests/test_machine.py b/src/maasserver/api/tests/test_machine.py
97index d4a218e..6eb2cd6 100644
98--- a/src/maasserver/api/tests/test_machine.py
99+++ b/src/maasserver/api/tests/test_machine.py
100@@ -678,7 +678,8 @@ class TestMachineAPI(APITestCase.ForUser):
101 'comment': comment,
102 })
103 self.assertThat(machine_start, MockCalledOnceWith(
104- self.user, user_data=ANY, comment=comment))
105+ self.user, user_data=ANY, comment=comment,
106+ install_kvm=ANY, bridge_stp=ANY, bridge_fd=ANY))
107
108 def test_POST_deploy_handles_missing_comment(self):
109 machine = factory.make_Node(
110@@ -698,7 +699,8 @@ class TestMachineAPI(APITestCase.ForUser):
111 'distro_series': distro_series,
112 })
113 self.assertThat(machine_start, MockCalledOnceWith(
114- self.user, user_data=ANY, comment=None))
115+ self.user, user_data=ANY, comment=None,
116+ install_kvm=ANY, bridge_stp=ANY, bridge_fd=ANY))
117
118 def test_POST_deploy_doesnt_reset_power_options_bug_1569102(self):
119 self.become_admin()
120diff --git a/src/maasserver/forms/__init__.py b/src/maasserver/forms/__init__.py
121index 021acdd..2341511 100644
122--- a/src/maasserver/forms/__init__.py
123+++ b/src/maasserver/forms/__init__.py
124@@ -874,11 +874,6 @@ class MachineForm(NodeForm):
125 self.is_bound = True
126 self.data['install_rackd'] = install_rackd
127
128- def set_install_kvm(self, install_kvm=False):
129- """Sets whether to deploy the rack alongside this machine."""
130- self.is_bound = True
131- self.data['install_kvm'] = install_kvm
132-
133 def set_ephemeral_deploy(self, ephemeral_deploy=False):
134 """Sets whether to deploy this machine ephemerally."""
135 self.is_bound = True
136@@ -916,7 +911,6 @@ class MachineForm(NodeForm):
137 'min_hwe_kernel',
138 'hwe_kernel',
139 'install_rackd',
140- 'install_kvm',
141 'ephemeral_deploy',
142 'commission'
143 )
144diff --git a/src/maasserver/forms/tests/test_machine.py b/src/maasserver/forms/tests/test_machine.py
145index 9a79406..84be9bf 100644
146--- a/src/maasserver/forms/tests/test_machine.py
147+++ b/src/maasserver/forms/tests/test_machine.py
148@@ -50,7 +50,6 @@ class TestMachineForm(MAASServerTestCase):
149 'min_hwe_kernel',
150 'hwe_kernel',
151 'install_rackd',
152- 'install_kvm',
153 'ephemeral_deploy',
154 'commission',
155 ], list(form.fields))
156@@ -370,7 +369,6 @@ class TestAdminMachineForm(MAASServerTestCase):
157 'min_hwe_kernel',
158 'hwe_kernel',
159 'install_rackd',
160- 'install_kvm',
161 'ephemeral_deploy',
162 'cpu_count',
163 'memory',
164diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
165index 10af042..40af61c 100644
166--- a/src/maasserver/models/node.py
167+++ b/src/maasserver/models/node.py
168@@ -4388,10 +4388,16 @@ class Node(CleanSave, TimestampedModel):
169 return NODE_STATUS_CHOICES_DICT[self.status]
170
171 @transactional
172- def start(self, user, user_data=None, comment=None):
173+ def start(
174+ self, user, user_data=None, comment=None, install_kvm=None,
175+ bridge_stp=None, bridge_fd=None):
176 if not user.has_perm(NodePermission.edit, self):
177 # You can't start a node you don't own unless you're an admin.
178 raise PermissionDenied()
179+ # Set install_kvm if not already set.
180+ if not self.install_kvm and install_kvm:
181+ self.install_kvm = True
182+ self.save()
183 event = EVENT_TYPES.REQUEST_NODE_START
184 allow_power_cycle = False
185 # If status is ALLOCATED, this start is actually for a deployment.
186@@ -4401,6 +4407,9 @@ class Node(CleanSave, TimestampedModel):
187 if self.status == NODE_STATUS.ALLOCATED:
188 event = EVENT_TYPES.REQUEST_NODE_START_DEPLOYMENT
189 allow_power_cycle = True
190+ if self.install_kvm:
191+ self._create_acquired_bridges(
192+ bridge_stp=bridge_stp, bridge_fd=bridge_fd)
193 # Bug #1630361: Make sure that there is a maas_facing_server_address in
194 # the same address family as our configured interfaces.
195 # Every node in a real system has a rack controller, but many tests do
196diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py
197index 2a721ae..cc7b45e 100644
198--- a/src/maasserver/models/tests/test_node.py
199+++ b/src/maasserver/models/tests/test_node.py
200@@ -7108,6 +7108,23 @@ class TestNode_Start(MAASTransactionServerTestCase):
201 node.start(user)
202 self.assertEquals(NODE_STATUS.DEPLOYING, node.status)
203
204+ def test__creates_acquired_bridges_for_install_kvm(self):
205+ user = factory.make_User()
206+ node = self.make_acquired_node_with_interface(
207+ user, power_type="manual")
208+ bridge_stp = factory.pick_bool()
209+ bridge_fd = random.randint(0, 500)
210+ node.start(
211+ user, install_kvm=True, bridge_stp=bridge_stp, bridge_fd=bridge_fd)
212+ node = reload_object(node)
213+ bridge = BridgeInterface.objects.get(node=node)
214+ interface = node.interface_set.first()
215+ self.assertEquals(NODE_STATUS.DEPLOYING, node.status)
216+ self.assertEquals(bridge.mac_address, interface.mac_address)
217+ self.assertEquals(bridge.params['bridge_stp'], bridge_stp)
218+ self.assertEquals(bridge.params['bridge_fd'], bridge_fd)
219+ self.assertTrue(node.install_kvm)
220+
221 def test__doesnt_change_broken(self):
222 user = factory.make_User()
223 node = self.make_acquired_node_with_interface(
224diff --git a/src/maasserver/node_action.py b/src/maasserver/node_action.py
225index e969138..32239ec 100644
226--- a/src/maasserver/node_action.py
227+++ b/src/maasserver/node_action.py
228@@ -450,9 +450,7 @@ class Deploy(NodeAction):
229 if self.node.owner is None:
230 with locks.node_acquire:
231 try:
232- bridge_all = True if install_kvm else False
233- self.node.acquire(
234- self.user, token=None, bridge_all=bridge_all)
235+ self.node.acquire(self.user, token=None)
236 except ValidationError as e:
237 raise NodeActionError(e)
238 if install_kvm:
239diff --git a/src/maasserver/tests/test_node_action.py b/src/maasserver/tests/test_node_action.py
240index 8365260..7b3e256 100644
241--- a/src/maasserver/tests/test_node_action.py
242+++ b/src/maasserver/tests/test_node_action.py
243@@ -724,8 +724,8 @@ class TestDeployAction(MAASServerTestCase):
244 Deploy(node, user, request).execute(**extra)
245 self.expectThat(mock_get_curtin_config, MockCalledOnceWith(ANY, node))
246 # Make sure we set bridge_all when we acquire the Node.
247- self.expectThat(mock_node_acquire, MockCalledOnceWith(
248- user, token=None, bridge_all=True))
249+ self.expectThat(
250+ mock_node_acquire, MockCalledOnceWith(user, token=None))
251 self.expectThat(mock_node_start, MockCalledOnceWith(user))
252 # Make sure ubuntu/bionic is selected if KVM pod deployment has been
253 # selected.

Subscribers

People subscribed via source and target branches