Merge ~mpontillo/maas:add-deploy-kvm-ui--bug-1795013 into maas:master

Proposed by Mike Pontillo
Status: Merged
Approved by: Mike Pontillo
Approved revision: e1f1fdc1cba18a0905bc13b71e018e26aeb56b69
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~mpontillo/maas:add-deploy-kvm-ui--bug-1795013
Merge into: maas:master
Diff against target: 419 lines (+183/-22)
8 files modified
src/maasserver/node_action.py (+24/-4)
src/maasserver/static/js/angular/controllers/node_details.js (+19/-13)
src/maasserver/static/js/angular/controllers/nodes_list.js (+15/-1)
src/maasserver/static/js/angular/controllers/tests/test_node_details.js (+27/-3)
src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js (+26/-1)
src/maasserver/static/partials/node-details.html (+8/-0)
src/maasserver/static/partials/nodes-list.html (+8/-0)
src/maasserver/tests/test_node_action.py (+56/-0)
Reviewer Review Type Date Requested Status
Martin Storey (community) Approve
Andres Rodriguez (community) Approve
MAAS Lander Approve
Lee Trager (community) Approve
Anthony Dillon Approve
Kit Randel (community) Approve
Review via email: mp+356376@code.launchpad.net

Commit message

LP: #1795013 - Add KVM deployment option to the UI

Description of the change

I'm not sure if the tickbox text (or the fact that there should be a tickbox at all) are finalized, but this is a first pass at KVM pod deployment.

I noticed an alignment issue with the tickboxes; it can be seen by comparing the "Allow SSH..." tick with the green tick in the node listing in the following screenshot (it seems to be a pre-existing issue):

https://usercontent.irccloud-cdn.com/file/atu4Zcy1/tickbox-alignment.png

With that in mind, here are a couple of screenshots of this change, from the machine listing and machine details pages, respectively:

https://usercontent.irccloud-cdn.com/file/VOM7JyXn/install-kvm-checkbox.png
https://usercontent.irccloud-cdn.com/file/qrKlNUgB/checkbox-install-kvm-from-details.png

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4118/console
COMMIT: a44f2c82b8f6df3d445e97099eccc7bb508f70c4

review: Needs Fixing
Revision history for this message
Kit Randel (blr) wrote :

code lgtm, just a few comments inline.

review: Approve
Revision history for this message
Andres Rodriguez (andreserl) wrote :

We should send this over to UX team for a quick view.

On Tue, Oct 9, 2018 at 9:37 PM Kit Randel <email address hidden> wrote:

> Review: Approve
>
> code lgtm, just a few comments inline.
>
> Diff comments:
>
> > diff --git
> a/src/maasserver/static/js/angular/controllers/node_details.js
> b/src/maasserver/static/js/angular/controllers/node_details.js
> > index 55d1c16..f4083b5 100644
> > --- a/src/maasserver/static/js/angular/controllers/node_details.js
> > +++ b/src/maasserver/static/js/angular/controllers/node_details.js
> > @@ -139,9 +142,9 @@
> angular.module('MAAS').controller('NodeDetailsController', [
> > // id matching the node id. Otherwise we end up setting our
> > // selected field to an option not from DomainsManager which
> > // doesn't work.
> > - var i;
> > + let i;
> > for(i=0;i<$scope.header.domain.options.length;i++) {
>
> Can `i` be initialised inside the `for` like the other cases?
>
> > - var option = $scope.header.domain.options[i];
> > + let option = $scope.header.domain.options[i];
> > if(option.id === $scope.node.domain.id) {
> > $scope.header.domain.selected = option;
> > break;
> > @@ -592,13 +592,14 @@
> angular.module('MAAS').controller('NodeDetailsController', [
> > $scope.osSelection.hwe_kernel.indexOf('ga-') >= 0))
> {
> > extra.hwe_kernel = $scope.osSelection.hwe_kernel;
> > }
> > + extra.install_kvm = $scope.deployOptions.installKVM;
> > } else if($scope.action.option.name === "commission") {
> > extra.enable_ssh = $scope.commissionOptions.enableSSH;
> > extra.skip_networking = (
> > $scope.commissionOptions.skipNetworking);
> > extra.skip_storage =
> $scope.commissionOptions.skipStorage;
> > extra.commissioning_scripts = [];
> > - for(i=0;i<$scope.commissioningSelection.length;i++) {
> > + for(let i=0;i<$scope.commissioningSelection.length;i++)
> {
>
> A minor point, but this is a bit more readable with spaces around the
> operators and after the semi-colons (like l93).
>
> > extra.commissioning_scripts.push(
> > $scope.commissioningSelection[i].id);
> > }
>
>
> --
> https://code.launchpad.net/~mpontillo/maas/+git/maas/+merge/356376
> You are reviewing the proposed merge of
> ~mpontillo/maas:add-deploy-kvm-ui--bug-1795013 into maas:master.
>
--
Andres Rodriguez
Engineering Manager, MAAS
Canonical USA, Inc.

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4119/console
COMMIT: 00f7b9d9a648d91a5c6e46da92c1dae369dea4f6

review: Needs Fixing
Revision history for this message
Lilyana Videnova (lilyanavidenova) wrote :

We suggest adding a label (Additional installs) as well as an information icon + a link to the appropriate docs (https://docs.maas.io/2.5/en/nodes-comp-hw). The text of the checkbox then loses the word "install".

A rough wireframe: https://usercontent.irccloud-cdn.com/file/goCKhGSm/deploy%20KVM%20ui.png

Revision history for this message
Anthony Dillon (ya-bo-ng) wrote :

Looks good +1. I am having a little trouble reproducing the wireframe for it to be a quick patch for this branch. This should land as is and I'll fix up the UI and alignment of checkboxes in a follow up branch.

review: Approve
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Thanks for taking a look, all.

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4132/console
COMMIT: 36867d99144ed602d0dd5c27d4c8e09178769e97

review: Needs Fixing
Revision history for this message
Andres Rodriguez (andreserl) wrote :

couple comments inline and a question here.

Does this option only show when you select Ubuntu as the default OS?

review: Needs Information
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Andres, your review brings up some good points, many of which are still undecided, I think.

== Interactions Between KVM Pod Installation and OS Selection ==

I didn't implement any special functionality in the UI for causing the "Install KVM" option to modify the OS selection. I think it should probably gray out the OS selection (and possibly select Bionic automatically) to make it clear that the user doesn't get a choice.

Instead, what happens in this branch is, if you select "Install KVM", on the back-end it forces the OS selection to become "ubuntu/bionic".

This needs to be revisited in a future branch to provide a complete solution, because when you specify install_kvm from the API, no such forced-OS-selection occurs. For supportability purposes, we should always deploy KVM with the latest LTS we've tested it on (in this case, bionic).

In summary, this branch is more of an initial cut than a polished version of this UI action. It just gets the basics done.

== KVM Pod Labels and Terminology ==

I kind of disagree with putting (pod) in parentheses. It's not a (pod), it's a Pod, according to our current UI. I proposed this branch without mentioning "pod" in anticipation of the idea that the "Pod" terminology might be going away in the near future. I feel that if it's not going away, we might as well say "KVM Pod".

The API/model terminology of "install_kvm" is similarly vague. To many people, including data center engineers, KVM might mean "Keyboard/Video/Mouse".

More generally, this needs to be more consistent in other places in the UI. In other branches I've seen proposed (and in the actual UI itself), we often say "Virsh pod", which is also weird. (Likely because the power type for a KVM pod is literally "virsh", but we can correct that in the UI, to some degree).

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 4561bbf26c02cc5bee9a04664e2fe5eeb0cdeab5

review: Approve
Revision history for this message
Lee Trager (ltrager) wrote :

Thanks for adding the admin check :)

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 4febb6fcb1182672ef45e64444d621a4f8a635fc

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4139/console
COMMIT: cfcee8dbd98ebe17142790cac8e57bcf3152a5ee

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4141/console
COMMIT: 83f6c086d1f38484043f5fcbc4a4c06158297f2c

review: Needs Fixing
Revision history for this message
Martin Storey (cassiocassio) wrote :

Revised proposal from UX:

1. OS selection updates automagically when checking "install KVM"

Menus that jump around automatically when you check checkboxes don't help the user understand the OS requirement - they have to notice that it changed, and they have to intuit why.

If we do this, we should
  - put an "[i] 18.04 Bionic required for a KVM host" under the OS selector.
  - disable the pulldown so they have to uncheck KVM to pick a different OS.

that said, Bionic is the default, and a user will have to switch away from the default to encounter this.

so,

2. selecting away from Bionic should disable the KVM checkbox and text, so you can't click it.
  - put an "[i] KVM requires 18.04 Bionic" under the KVM checkbox.

if it was already checked, bionic will already be selected.

NB

- in the future we'll need to cope with 19.04, 20.04 etc which will be viable options for KVM.

Revision history for this message
Andres Rodriguez (andreserl) :
review: Needs Fixing
Revision history for this message
Mike Pontillo (mpontillo) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 68a594c06452790907ab78428e80502b82c3369b

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4159/console
COMMIT: ebb00aeec73c3b05556e344c25bbc6b22b92ff93

review: Needs Fixing
Revision history for this message
Andres Rodriguez (andreserl) :
review: Needs Information
Revision history for this message
Mike Pontillo (mpontillo) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-deploy-kvm-ui--bug-1795013 lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: e1f1fdc1cba18a0905bc13b71e018e26aeb56b69

review: Approve
Revision history for this message
Andres Rodriguez (andreserl) :
Revision history for this message
Andres Rodriguez (andreserl) wrote :

I've chatted with Mike about this and I agree with him that it would be good to land this, so that it unblocks further development on this.

We will target the UX improvements of this for next week.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Revision history for this message
Martin Storey (cassiocassio) wrote :

this is merged, but for completeness: the proposed UX improvements to this feature are here:

https://zpl.io/boZoEgE

Revision history for this message
Martin Storey (cassiocassio) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/node_action.py b/src/maasserver/node_action.py
2index e30ab66..f299700 100644
3--- a/src/maasserver/node_action.py
4+++ b/src/maasserver/node_action.py
5@@ -456,23 +456,43 @@ class Deploy(NodeAction):
6 """Retrieve the node action audit description."""
7 return self.audit_description % action.node.hostname
8
9- def _execute(self, osystem=None, distro_series=None, hwe_kernel=None):
10+ def _execute(
11+ self, osystem=None, distro_series=None, hwe_kernel=None,
12+ install_kvm=False):
13 """See `NodeAction.execute`."""
14+ if install_kvm:
15+ if not self.user.is_superuser:
16+ raise NodeActionError(
17+ "You must be a MAAS administrator to deploy a machine "
18+ "as a MAAS-managed KVM Pod.")
19 if self.node.owner is None:
20 with locks.node_acquire:
21 try:
22 self.node.acquire(self.user, token=None)
23 except ValidationError as e:
24 raise NodeActionError(e)
25-
26- if osystem and distro_series:
27+ if install_kvm:
28+ try:
29+ # KVM Pod installation should default to ubuntu/bionic, since
30+ # that was the release it was tested on.
31+ if osystem is None:
32+ osystem = 'ubuntu'
33+ if distro_series is None:
34+ distro_series = 'bionic'
35+ self.node.osystem, self.node.distro_series = (
36+ validate_osystem_and_distro_series(osystem, distro_series)
37+ )
38+ self.node.install_kvm = True
39+ self.node.save()
40+ except ValidationError as e:
41+ raise NodeActionError(e)
42+ elif osystem and distro_series:
43 try:
44 self.node.osystem, self.node.distro_series = (
45 validate_osystem_and_distro_series(osystem, distro_series))
46 self.node.save()
47 except ValidationError as e:
48 raise NodeActionError(e)
49-
50 try:
51 self.node.hwe_kernel = validate_hwe_kernel(
52 hwe_kernel, self.node.min_hwe_kernel,
53diff --git a/src/maasserver/static/js/angular/controllers/node_details.js b/src/maasserver/static/js/angular/controllers/node_details.js
54index ce6f2f9..7924054 100644
55--- a/src/maasserver/static/js/angular/controllers/node_details.js
56+++ b/src/maasserver/static/js/angular/controllers/node_details.js
57@@ -56,6 +56,9 @@ angular.module('MAAS').controller('NodeDetailsController', [
58 updateFirmware: false,
59 configureHBA: false
60 };
61+ $scope.deployOptions = {
62+ installKVM: false,
63+ };
64 $scope.commissioningSelection = [];
65 $scope.testSelection = [];
66 $scope.releaseOptions = {};
67@@ -140,9 +143,8 @@ angular.module('MAAS').controller('NodeDetailsController', [
68 // id matching the node id. Otherwise we end up setting our
69 // selected field to an option not from DomainsManager which
70 // doesn't work.
71- var i;
72- for(i=0;i<$scope.header.domain.options.length;i++) {
73- var option = $scope.header.domain.options[i];
74+ for(let i = 0 ; i < $scope.header.domain.options.length ; i++) {
75+ let option = $scope.header.domain.options[i];
76 if(option.id === $scope.node.domain.id) {
77 $scope.header.domain.selected = option;
78 break;
79@@ -155,7 +157,7 @@ angular.module('MAAS').controller('NodeDetailsController', [
80 if(!angular.isObject($scope.node)) {
81 return;
82 }
83- var actionTypeForNodeType = {
84+ const actionTypeForNodeType = {
85 0: "machine_actions",
86 1: "device_actions",
87 2: "rack_controller_actions",
88@@ -183,7 +185,6 @@ angular.module('MAAS').controller('NodeDetailsController', [
89 // isn't called until after load as its triggered on the loaded
90 // node's actions. If the node's action list isn't loaded load
91 // it then update the available options.
92- var self = updateAvailableActionOptions;
93 GeneralManager.loadItems(
94 [actionTypeForNodeType[$scope.node.node_type]]).then(
95 updateAvailableActionOptions);
96@@ -198,9 +199,8 @@ angular.module('MAAS').controller('NodeDetailsController', [
97 return;
98 }
99
100- var i;
101 $scope.power.type = null;
102- for(i = 0; i < $scope.power_types.length; i++) {
103+ for(let i = 0; i < $scope.power_types.length; i++) {
104 if($scope.node.power_type === $scope.power_types[i].name) {
105 $scope.power.type = $scope.power_types[i];
106 break;
107@@ -572,8 +572,7 @@ angular.module('MAAS').controller('NodeDetailsController', [
108
109 // Perform the action.
110 $scope.actionGo = function() {
111- var extra = {};
112- var i;
113+ let extra = {};
114 // Set deploy parameters if a deploy.
115 if($scope.action.option.name === "deploy" &&
116 angular.isString($scope.osSelection.osystem) &&
117@@ -593,6 +592,13 @@ angular.module('MAAS').controller('NodeDetailsController', [
118 $scope.osSelection.hwe_kernel.indexOf('ga-') >= 0)) {
119 extra.hwe_kernel = $scope.osSelection.hwe_kernel;
120 }
121+ let installKVM = $scope.deployOptions.installKVM;
122+ // KVM pod deployment required bionic.
123+ if(installKVM) {
124+ extra.osystem = "ubuntu";
125+ extra.distro_series = "bionic";
126+ }
127+ extra.install_kvm = installKVM;
128 } else if($scope.action.option.name === "commission") {
129 extra.enable_ssh = $scope.commissionOptions.enableSSH;
130 extra.skip_bmc_config = $scope.commissionOptions.skipBMCConfig;
131@@ -600,7 +606,7 @@ angular.module('MAAS').controller('NodeDetailsController', [
132 $scope.commissionOptions.skipNetworking);
133 extra.skip_storage = $scope.commissionOptions.skipStorage;
134 extra.commissioning_scripts = [];
135- for(i=0;i<$scope.commissioningSelection.length;i++) {
136+ for(let i = 0 ; i < $scope.commissioningSelection.length ; i++){
137 extra.commissioning_scripts.push(
138 $scope.commissioningSelection[i].id);
139 }
140@@ -616,7 +622,7 @@ angular.module('MAAS').controller('NodeDetailsController', [
141 extra.commissioning_scripts.push('none');
142 }
143 extra.testing_scripts = [];
144- for(i=0;i<$scope.testSelection.length;i++) {
145+ for(let i=0 ; i < $scope.testSelection.length ; i++) {
146 extra.testing_scripts.push($scope.testSelection[i].id);
147 }
148 if(extra.testing_scripts.length === 0) {
149@@ -632,7 +638,7 @@ angular.module('MAAS').controller('NodeDetailsController', [
150 // Set the test options.
151 extra.enable_ssh = $scope.commissionOptions.enableSSH;
152 extra.testing_scripts = [];
153- for(i=0;i<$scope.testSelection.length;i++) {
154+ for(let i = 0 ; i < $scope.testSelection.length ; i++) {
155 extra.testing_scripts.push($scope.testSelection[i].id);
156 }
157 if(extra.testing_scripts.length === 0) {
158@@ -1097,7 +1103,7 @@ angular.module('MAAS').controller('NodeDetailsController', [
159 } else {
160 return label + " @ " + ($scope.node.cpu_speed / 1000) + " Ghz";
161 }
162- }
163+ };
164
165 // Reload osinfo when the page reloads
166 $scope.$on("$routeUpdate", function () {
167diff --git a/src/maasserver/static/js/angular/controllers/nodes_list.js b/src/maasserver/static/js/angular/controllers/nodes_list.js
168index 8a71a0a..dea2857 100644
169--- a/src/maasserver/static/js/angular/controllers/nodes_list.js
170+++ b/src/maasserver/static/js/angular/controllers/nodes_list.js
171@@ -93,6 +93,9 @@ angular.module('MAAS').controller('NodesListController', [
172 updateFirmware: false,
173 configureHBA: false
174 };
175+ $scope.tabs.machines.deployOptions = {
176+ installKVM: false
177+ };
178 $scope.tabs.machines.releaseOptions = {};
179 $scope.tabs.machines.commissioningSelection = [];
180 $scope.tabs.machines.testSelection = [];
181@@ -153,7 +156,7 @@ angular.module('MAAS').controller('NodesListController', [
182 $scope.toggleTab('machines');
183 // update the location URL otherwise to match the tab
184 $location.path('/machines');
185- }
186+ };
187 $scope.tabs.pools.isDefaultPool = function(pool) {
188 return pool.id === 0;
189 };
190@@ -266,6 +269,9 @@ angular.module('MAAS').controller('NodesListController', [
191 updateFirmware: false,
192 configureHBA: false
193 };
194+ $scope.tabs.switches.deployOptions = {
195+ installKVM: false
196+ };
197 $scope.tabs.switches.releaseOptions = {};
198
199
200@@ -359,6 +365,7 @@ angular.module('MAAS').controller('NodesListController', [
201 $scope.tabs[tab].commissionOptions.skipStorage = false;
202 $scope.tabs[tab].commissionOptions.updateFirmware = false;
203 $scope.tabs[tab].commissionOptions.configureHBA = false;
204+ $scope.tabs[tab].deployOptions.installKVM = false;
205 }
206 $scope.tabs[tab].commissioningSelection = [];
207 $scope.tabs[tab].testSelection = [];
208@@ -721,6 +728,13 @@ angular.module('MAAS').controller('NodesListController', [
209 tab.osSelection.hwe_kernel.indexOf('ga-') >= 0)) {
210 extra.hwe_kernel = tab.osSelection.hwe_kernel;
211 }
212+ let installKVM = tab.deployOptions.installKVM;
213+ // KVM pod deployment requires bionic.
214+ if(installKVM) {
215+ extra.osystem = "ubuntu";
216+ extra.distro_series = "bionic";
217+ }
218+ extra.install_kvm = installKVM;
219 } else if(tab.actionOption.name === "set-zone" &&
220 angular.isNumber(tab.zoneSelection.id)) {
221 // Set the zone parameter.
222diff --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
223index 135045a..5757c4c 100644
224--- a/src/maasserver/static/js/angular/controllers/tests/test_node_details.js
225+++ b/src/maasserver/static/js/angular/controllers/tests/test_node_details.js
226@@ -1057,7 +1057,29 @@ describe("NodeDetailsController", function() {
227 expect(MachinesManager.performAction).toHaveBeenCalledWith(
228 node, "deploy", {
229 osystem: "ubuntu",
230- distro_series: "trusty"
231+ distro_series: "trusty",
232+ install_kvm: false
233+ });
234+ });
235+
236+ it("calls performAction with install_kvm", function() {
237+ var controller = makeController();
238+ spyOn(MachinesManager, "performAction").and.returnValue(
239+ $q.defer().promise);
240+ $scope.node = node;
241+ $scope.action.option = {
242+ name: "deploy"
243+ };
244+ $scope.osSelection.osystem = "debian";
245+ $scope.osSelection.release = "etch";
246+ $scope.deployOptions.installKVM = true;
247+ $scope.actionGo();
248+ // When deploying KVM, coerce the distro to ubuntu/bionic.
249+ expect(MachinesManager.performAction).toHaveBeenCalledWith(
250+ node, "deploy", {
251+ osystem: "ubuntu",
252+ distro_series: "bionic",
253+ install_kvm: true
254 });
255 });
256
257@@ -1077,7 +1099,8 @@ describe("NodeDetailsController", function() {
258 node, "deploy", {
259 osystem: "ubuntu",
260 distro_series: "xenial",
261- hwe_kernel: "hwe-16.04-edge"
262+ hwe_kernel: "hwe-16.04-edge",
263+ install_kvm: false
264 });
265 });
266
267@@ -1097,7 +1120,8 @@ describe("NodeDetailsController", function() {
268 node, "deploy", {
269 osystem: "ubuntu",
270 distro_series: "xenial",
271- hwe_kernel: "ga-16.04"
272+ hwe_kernel: "ga-16.04",
273+ install_kvm: false
274 });
275 });
276
277diff --git a/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js b/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js
278index df95ba7..92e467b 100644
279--- a/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js
280+++ b/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js
281@@ -1576,7 +1576,32 @@ describe("NodesListController", function() {
282 expect(spy).toHaveBeenCalledWith(
283 object, "deploy", {
284 osystem: "ubuntu",
285- distro_series: "trusty"
286+ distro_series: "trusty",
287+ install_kvm: false
288+ });
289+ });
290+
291+ it("calls performAction with install_kvm",
292+ function() {
293+ var controller = makeController();
294+ var object = makeObject("machines");
295+ var spy = spyOn(
296+ $scope.tabs.machines.manager,
297+ "performAction").and.returnValue(
298+ $q.defer().promise);
299+ $scope.tabs.machines.actionOption = {name: "deploy"};
300+ $scope.tabs.machines.selectedItems = [object];
301+ $scope.tabs.machines.osSelection.osystem = "debian";
302+ $scope.tabs.machines.osSelection.release = "etch";
303+ $scope.tabs.machines.deployOptions.installKVM = true;
304+ $scope.actionGo("machines");
305+ $scope.$digest();
306+ // When deploying KVM, coerce the distro to ubuntu/bionic.
307+ expect(spy).toHaveBeenCalledWith(
308+ object, "deploy", {
309+ osystem: "ubuntu",
310+ distro_series: "bionic",
311+ install_kvm: true
312 });
313 });
314
315diff --git a/src/maasserver/static/partials/node-details.html b/src/maasserver/static/partials/node-details.html
316index b74ab09..00c81b4 100755
317--- a/src/maasserver/static/partials/node-details.html
318+++ b/src/maasserver/static/partials/node-details.html
319@@ -104,6 +104,14 @@
320 <div class="col-12 u-no-margin--left" data-ng-show="action.option.name === 'deploy' || action.option.name === 'release'">
321 <div class="ng-hide" data-ng-show="action.option.name === 'deploy'">
322 <div data-maas-os-select="osinfo" data-ng-model="osSelection"></div>
323+ <div class="row" data-ng-if="isSuperUser()">
324+ <ul class="p-inline-list--settings u-no-margin--left u-no-padding--left">
325+ <li class="p-inline-list__item">
326+ <input id="installKVM" type="checkbox" data-ng-model="deployOptions.installKVM"></input>
327+ <label for="installKVM">Install MAAS-managed KVM Pod</label>
328+ </li>
329+ </ul>
330+ </div>
331 </div>
332 <div data-ng-if="action.option.name === 'release'" class="u-no-margin--top">
333 <div data-maas-release-options="releaseOptions"></div>
334diff --git a/src/maasserver/static/partials/nodes-list.html b/src/maasserver/static/partials/nodes-list.html
335index 4364061..db4abeb 100644
336--- a/src/maasserver/static/partials/nodes-list.html
337+++ b/src/maasserver/static/partials/nodes-list.html
338@@ -209,6 +209,14 @@
339 <div class="p-form__group ng-hide" data-ng-show="tabs[tab].actionOption.name === 'deploy'">
340 <div class="p-form__control u-clearfix">
341 <div data-maas-os-select="osinfo" data-ng-model="tabs[tab].osSelection"></div>
342+ <div class="row" data-ng-if="isSuperUser()">
343+ <ul class="p-inline-list--settings u-no-margin--left u-no-padding--left">
344+ <li class="p-inline-list__item">
345+ <input id="{$ tab $}-installKVM" type="checkbox" data-ng-model="tabs[tab].deployOptions.installKVM"></input>
346+ <label for="{$ tab $}-installKVM">Install MAAS-managed KVM Pod</label>
347+ </li>
348+ </ul>
349+ </div>
350 </div>
351 <div data-ng-if="tabs[tab].actionOption.name === 'release'">
352 <div data-maas-release-options="tabs[tab].releaseOptions"></div>
353diff --git a/src/maasserver/tests/test_node_action.py b/src/maasserver/tests/test_node_action.py
354index 67b422f..4cf029e 100644
355--- a/src/maasserver/tests/test_node_action.py
356+++ b/src/maasserver/tests/test_node_action.py
357@@ -694,6 +694,62 @@ class TestDeployAction(MAASServerTestCase):
358 self.expectThat(
359 node.distro_series, Equals(release_name))
360
361+ def test_Deploy_sets_install_kvm_and_osystem_series_if_specified(self):
362+ user = factory.make_admin()
363+ request = factory.make_fake_request('/')
364+ request.user = user
365+ node = factory.make_Node(
366+ interface=True, status=NODE_STATUS.ALLOCATED,
367+ power_type='manual', owner=user)
368+ mock_get_curtin_config = self.patch(
369+ node_action_module, 'get_curtin_config')
370+ mock_node_start = self.patch(node, 'start')
371+ mock_validate_os = self.patch(
372+ node_action_module, 'validate_osystem_and_distro_series')
373+ mock_validate_os.side_effect = lambda os, release: (os, release)
374+ mock_validate_hwe = self.patch(
375+ node_action_module, 'validate_hwe_kernel')
376+ mock_validate_hwe.side_effect = lambda *args, **kwargs: args[0]
377+ extra = {
378+ "install_kvm": True
379+ }
380+ Deploy(node, user, request).execute(**extra)
381+ self.expectThat(mock_get_curtin_config, MockCalledOnceWith(ANY, node))
382+ self.expectThat(mock_node_start, MockCalledOnceWith(user))
383+ # Make sure ubuntu/bionic is selected if KVM pod deployment has been
384+ # selected.
385+ self.expectThat(node.osystem, Equals("ubuntu"))
386+ self.expectThat(node.distro_series, Equals("bionic"))
387+ self.expectThat(node.install_kvm, Equals(True))
388+
389+ def test_Deploy_raises_NodeActionError_on_install_kvm_if_os_missing(self):
390+ user = factory.make_admin()
391+ request = factory.make_fake_request('/')
392+ request.user = user
393+ node = factory.make_Node(
394+ interface=True, status=NODE_STATUS.ALLOCATED,
395+ power_type='manual', owner=user)
396+ self.patch(node, 'start')
397+ extra = {
398+ "install_kvm": True
399+ }
400+ self.assertRaises(
401+ NodeActionError, Deploy(node, user, request).execute, **extra)
402+
403+ def test_Deploy_raises_NodeActionError_if_non_admin_install_kvm(self):
404+ user = factory.make_User()
405+ request = factory.make_fake_request('/')
406+ request.user = user
407+ node = factory.make_Node(
408+ interface=True, status=NODE_STATUS.ALLOCATED,
409+ power_type='manual', owner=user)
410+ self.patch(node, 'start')
411+ extra = {
412+ "install_kvm": True
413+ }
414+ self.assertRaises(
415+ NodeActionError, Deploy(node, user, request).execute, **extra)
416+
417 def test_Deploy_sets_osystem_and_series_strips_license_key_token(self):
418 user = factory.make_User()
419 request = factory.make_fake_request('/')

Subscribers

People subscribed via source and target branches