Added support for creating portgroups
The existing functionality for portgroups in the node-details/configuration tab has been augmented with the capability to create portgroups. Clicking on the menu button above the portgroup table will launch a modal dialog that guides the user in entering the parameters required to create a portgroup. Change-Id: Ieef7fff4f29318ae74e11559dc69e6317c3c25d6
This commit is contained in:
parent
35ad02697e
commit
7dc721fd79
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used to support operations on an Ironic portgroup
|
||||
*/
|
||||
angular
|
||||
.module('horizon.dashboard.admin.ironic')
|
||||
.controller('BasePortgroupController', BasePortgroupController);
|
||||
|
||||
BasePortgroupController.$inject = [
|
||||
'$uibModalInstance',
|
||||
'horizon.dashboard.admin.ironic.validMacAddressPattern',
|
||||
'horizon.dashboard.admin.ironic.validDatapathIdPattern',
|
||||
'horizon.dashboard.admin.ironic.form-field.service',
|
||||
'horizon.dashboard.admin.ironic.property-collection.service',
|
||||
'ctrl'
|
||||
];
|
||||
|
||||
function BasePortgroupController($uibModalInstance,
|
||||
validMacAddressPattern,
|
||||
validDatapathIdPattern,
|
||||
formFieldService,
|
||||
propertyCollectionService,
|
||||
ctrl) {
|
||||
|
||||
ctrl.address = new formFieldService.FormField({
|
||||
id: "macAddress",
|
||||
title: gettext("MAC address"),
|
||||
desc: gettext("MAC address for this portgroup."),
|
||||
pattern: new RegExp(validMacAddressPattern),
|
||||
value: null,
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ctrl.name = new formFieldService.FormField({
|
||||
id: "portgroupName",
|
||||
title: gettext("Name"),
|
||||
desc: gettext("Name for the portgroup.")
|
||||
});
|
||||
|
||||
ctrl.standalone_ports_supported = new formFieldService.FormField({
|
||||
type: "radio",
|
||||
id: "standalonePorts",
|
||||
title: gettext("Standalone Ports Supported"),
|
||||
desc: gettext(
|
||||
"Specifies whether ports in this portgroup can be used as standalone ports."),
|
||||
options: ['True', 'False'],
|
||||
value: 'True'});
|
||||
|
||||
ctrl.mode = new formFieldService.FormField({
|
||||
type: "radio",
|
||||
id: "mode",
|
||||
title: gettext("Mode"),
|
||||
desc: gettext("Linux portgroup mode. For possible values refer to https://www.kernel.org/doc/Documentation/networking/bonding.txt"), // eslint-disable-line max-len
|
||||
options: ['balance-rr',
|
||||
'active-backup',
|
||||
'balance-xor',
|
||||
'broadcast',
|
||||
'802.3ad',
|
||||
'balance-tlb',
|
||||
'balance-alb'],
|
||||
value: 'active-backup'});
|
||||
|
||||
ctrl.properties = new propertyCollectionService.PropertyCollection({
|
||||
id: 'properties',
|
||||
title: gettext('Properties'),
|
||||
addPropertyLabel: gettext('Add Property'),
|
||||
placeholder: gettext('Property Name')
|
||||
});
|
||||
|
||||
ctrl.extra = new propertyCollectionService.PropertyCollection({
|
||||
id: 'extra',
|
||||
title: gettext('Extras'),
|
||||
addPropertyLabel: gettext('Add Extra'),
|
||||
placeholder: gettext('Property Name')
|
||||
});
|
||||
|
||||
/**
|
||||
* Cancel the modal
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
ctrl.cancel = function() {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
describe('horizon.dashboard.admin.ironic.base-portgroup', function () {
|
||||
var uibModalInstance;
|
||||
var ctrl = {};
|
||||
|
||||
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
uibModalInstance = {
|
||||
dismiss: jasmine.createSpy()
|
||||
};
|
||||
$provide.value('$uibModalInstance', uibModalInstance);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
var controller = $injector.get('$controller');
|
||||
controller('BasePortgroupController', {ctrl: ctrl});
|
||||
}));
|
||||
|
||||
it('controller should be defined', function () {
|
||||
expect(ctrl).toBeDefined();
|
||||
});
|
||||
|
||||
it('base construction', function () {
|
||||
expect(Object.getOwnPropertyNames(ctrl).sort()).toEqual(
|
||||
BASE_PORTGROUP_CONTROLLER_PROPERTIES.sort());
|
||||
|
||||
angular.forEach(
|
||||
['address', 'name', 'standalone_ports_supported', 'mode'],
|
||||
function(propertyName) {
|
||||
expect(Object.keys(ctrl[propertyName])).toContain('value');
|
||||
});
|
||||
});
|
||||
|
||||
it('cancel', function () {
|
||||
ctrl.cancel();
|
||||
expect(uibModalInstance.dismiss).toHaveBeenCalledWith('cancel');
|
||||
});
|
||||
});
|
||||
})();
|
@ -0,0 +1,37 @@
|
||||
<div class="modal-header" modal-draggable>
|
||||
<button type="button"
|
||||
class="close"
|
||||
ng-click="$dismiss()"
|
||||
aria-hidden="true"
|
||||
aria-label="Close">
|
||||
<span aria-hidden="true" class="fa fa-times"></span>
|
||||
</button>
|
||||
<h3 class="modal-title">{$ ::ctrl.modalTitle $}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="CreatePortgroupForm" name="CreatePortgroupForm">
|
||||
<form-field field="ctrl.address" form="CreatePortgroupForm"></form-field>
|
||||
<form-field field="ctrl.name" form="CreatePortgroupForm"></form-field>
|
||||
<form-field field="ctrl.standalone_ports_supported"
|
||||
form="CreatePortgroupForm"></form-field>
|
||||
<form-field field="ctrl.mode" form="CreatePortgroupForm"></form-field>
|
||||
</form>
|
||||
|
||||
<property-collection-editor collection="ctrl.properties"></property-collection-editor>
|
||||
<property-collection-editor collection="ctrl.extra"></property-collection-editor>
|
||||
</div>
|
||||
<!--modal footer-->
|
||||
<div class="modal-footer ng-scope">
|
||||
<button class="btn btn-default" ng-click="ctrl.cancel()">
|
||||
<span class="fa fa-close"></span>
|
||||
<span class="ng-scope" translate>Cancel</span>
|
||||
</button>
|
||||
<button type="submit"
|
||||
ng-disabled="CreatePortgroupForm.$invalid ||
|
||||
!ctrl.properties.complete() ||
|
||||
!ctrl.extra.complete()"
|
||||
ng-click="ctrl.submit()"
|
||||
class="btn btn-primary">
|
||||
{$ ::ctrl.submitButtonTitle $}
|
||||
</button>
|
||||
</div>
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used to create a portgroup on a specified node
|
||||
*/
|
||||
angular
|
||||
.module('horizon.dashboard.admin.ironic')
|
||||
.controller('CreatePortgroupController', CreatePortgroupController);
|
||||
|
||||
CreatePortgroupController.$inject = [
|
||||
'$controller',
|
||||
'$uibModalInstance',
|
||||
'horizon.app.core.openstack-service-api.ironic',
|
||||
'node'
|
||||
];
|
||||
|
||||
function CreatePortgroupController($controller,
|
||||
$uibModalInstance,
|
||||
ironic,
|
||||
node) {
|
||||
var ctrl = this;
|
||||
|
||||
$controller('BasePortgroupController',
|
||||
{ctrl: ctrl,
|
||||
$uibModalInstance: $uibModalInstance});
|
||||
|
||||
ctrl.modalTitle = gettext("Create Portgroup");
|
||||
ctrl.submitButtonTitle = ctrl.modalTitle;
|
||||
|
||||
/**
|
||||
* Create the defined portgroup
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
ctrl.createPortgroup = function() {
|
||||
var portgroup = {
|
||||
extra: ctrl.extra.properties,
|
||||
properties: ctrl.properties.properties
|
||||
};
|
||||
|
||||
portgroup.node_uuid = node.uuid;
|
||||
angular.forEach(['address', 'name', 'standalone_ports_supported', 'mode'],
|
||||
function(propertyName) {
|
||||
if (ctrl[propertyName].hasValue()) {
|
||||
portgroup[propertyName] = ctrl[propertyName].value;
|
||||
}
|
||||
});
|
||||
ironic.createPortgroup(portgroup).then(
|
||||
function(createdPortgroup) {
|
||||
$uibModalInstance.close(createdPortgroup);
|
||||
});
|
||||
};
|
||||
|
||||
ctrl.submit = function() {
|
||||
ctrl.createPortgroup();
|
||||
};
|
||||
}
|
||||
})();
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
describe('horizon.dashboard.admin.ironic.create-portgroup', function () {
|
||||
var ironicBackendMockService, uibModalInstance, ironicAPI, controller;
|
||||
|
||||
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
uibModalInstance = {};
|
||||
$provide.value('$uibModalInstance', uibModalInstance);
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.framework.widgets.toast.service', {
|
||||
add: function() {}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
ironicBackendMockService =
|
||||
$injector.get('horizon.dashboard.admin.ironic.backend-mock.service');
|
||||
ironicBackendMockService.init();
|
||||
|
||||
ironicAPI =
|
||||
$injector.get('horizon.app.core.openstack-service-api.ironic');
|
||||
|
||||
controller = $injector.get('$controller');
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
ironicBackendMockService.postTest();
|
||||
});
|
||||
|
||||
function createController() {
|
||||
return ironicAPI.createNode({
|
||||
driver: ironicBackendMockService.params.defaultDriver})
|
||||
.then(function(response) {
|
||||
var node = response.data;
|
||||
return {node: response.data,
|
||||
ctrl: controller('CreatePortgroupController',
|
||||
{node: node})};
|
||||
});
|
||||
}
|
||||
|
||||
it('controller should be defined', function () {
|
||||
createController()
|
||||
.then(function(data) {
|
||||
expect(data.ctrl).toBeDefined();
|
||||
})
|
||||
.catch(function() {
|
||||
fail();
|
||||
});
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('base construction', function () {
|
||||
createController()
|
||||
.then(function(data) {
|
||||
var ctrl = data.ctrl;
|
||||
var properties = angular.copy(BASE_PORTGROUP_CONTROLLER_PROPERTIES);
|
||||
properties.push('modalTitle');
|
||||
properties.push('submitButtonTitle');
|
||||
properties.push('createPortgroup');
|
||||
properties.push('submit');
|
||||
expect(Object.getOwnPropertyNames(ctrl).sort()).toEqual(
|
||||
properties.sort());
|
||||
})
|
||||
.catch(function() {
|
||||
fail();
|
||||
});
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('submit - success', function () {
|
||||
var portgroupParams = {
|
||||
address: '00:00:00:00:00:00',
|
||||
name: 'my-portgroup',
|
||||
standalone_ports_supported: 'False',
|
||||
mode: '802.3ad',
|
||||
properties: {
|
||||
prop_1: 'prop-1-value'
|
||||
},
|
||||
extra: {
|
||||
extra_1: 'extra-1-value'
|
||||
}
|
||||
};
|
||||
|
||||
spyOn(ironicAPI, 'createPortgroup').and.callThrough();
|
||||
|
||||
uibModalInstance.close = function(portgroup) {
|
||||
expect(portgroup).toEqual(
|
||||
ironicBackendMockService.getPortgroup(portgroupParams.name));
|
||||
};
|
||||
|
||||
createController()
|
||||
.then(function(data) {
|
||||
var ctrl = data.ctrl;
|
||||
angular.forEach(
|
||||
portgroupParams,
|
||||
function(value, param) {
|
||||
if (param === 'properties' ||
|
||||
param === 'extra') {
|
||||
ctrl[param].properties = value;
|
||||
} else {
|
||||
ctrl[param].value = value;
|
||||
}
|
||||
});
|
||||
portgroupParams.node_uuid = data.node.uuid;
|
||||
|
||||
ctrl.submit();
|
||||
|
||||
expect(ironicAPI.createPortgroup)
|
||||
.toHaveBeenCalledWith(portgroupParams);
|
||||
})
|
||||
.catch(function() {
|
||||
fail();
|
||||
});
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
});
|
||||
})();
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.admin.ironic')
|
||||
.factory('horizon.dashboard.admin.ironic.create-portgroup.service',
|
||||
createPortgroupService);
|
||||
|
||||
createPortgroupService.$inject = [
|
||||
'$uibModal',
|
||||
'horizon.dashboard.admin.ironic.basePath'
|
||||
];
|
||||
|
||||
function createPortgroupService($uibModal, basePath) {
|
||||
var service = {
|
||||
createPortgroup: createPortgroup
|
||||
};
|
||||
return service;
|
||||
|
||||
/**
|
||||
* @description Launch a modal dialog that will guide the user
|
||||
* in creating a new portgroup
|
||||
*
|
||||
* @param {object} node - Node to which the portgroup will be associated
|
||||
* @return {promise} Object describing the created portgroup
|
||||
*/
|
||||
function createPortgroup(node) {
|
||||
var options = {
|
||||
controller: 'CreatePortgroupController as ctrl',
|
||||
backdrop: 'static',
|
||||
resolve: {
|
||||
node: function() {
|
||||
return node;
|
||||
}
|
||||
},
|
||||
templateUrl: basePath + '/base-portgroup/base-portgroup.html'
|
||||
};
|
||||
return $uibModal.open(options).result;
|
||||
}
|
||||
}
|
||||
})();
|
@ -31,6 +31,7 @@
|
||||
'horizon.dashboard.admin.ironic.basePath',
|
||||
'horizon.dashboard.admin.ironic.edit-node.service',
|
||||
'horizon.dashboard.admin.ironic.create-port.service',
|
||||
'horizon.dashboard.admin.ironic.create-portgroup.service',
|
||||
'horizon.dashboard.admin.ironic.edit-port.service',
|
||||
'horizon.dashboard.admin.ironic.maintenance.service',
|
||||
'horizon.dashboard.admin.ironic.bootdevice.service',
|
||||
@ -46,6 +47,7 @@
|
||||
basePath,
|
||||
editNodeService,
|
||||
createPortService,
|
||||
createPortgroupService,
|
||||
editPortService,
|
||||
maintenanceService,
|
||||
bootDeviceService,
|
||||
@ -90,6 +92,7 @@
|
||||
ctrl.getVifPortId = getVifPortId;
|
||||
ctrl.editNode = editNode;
|
||||
ctrl.createPort = createPort;
|
||||
ctrl.createPortgroup = createPortgroup;
|
||||
ctrl.deletePort = deletePort;
|
||||
ctrl.editPort = editPort;
|
||||
ctrl.refresh = refresh;
|
||||
@ -318,5 +321,18 @@
|
||||
function toggleConsoleMode() {
|
||||
ironic.nodeSetConsoleMode(ctrl.node.uuid, !ctrl.node.console_enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.dashboard.admin.ironic.NodeDetailsController.createPortgroup
|
||||
* @description Initiate creation of a portgroup for the current
|
||||
* node
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function createPortgroup() {
|
||||
createPortgroupService.createPortgroup(ctrl.node).then(function() {
|
||||
ctrl.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -138,7 +138,7 @@
|
||||
<action-list uib-dropdown class="pull-right">
|
||||
<action button-type="split-button"
|
||||
action-classes="'btn btn-default btn-sm'"
|
||||
callback="">
|
||||
callback="ctrl.createPortgroup">
|
||||
{$ ::'Create portgroup' | translate $}
|
||||
</action>
|
||||
<menu>
|
||||
|
@ -41,6 +41,16 @@ var BASE_NODE_CONTROLLER_PROPERTIES = [
|
||||
'submitButtonTitle',
|
||||
'validHostNameRegex'];
|
||||
|
||||
/* exported BASE_PORTGROUP_CONTROLLER_PROPERTIES */
|
||||
var BASE_PORTGROUP_CONTROLLER_PROPERTIES = [
|
||||
'address',
|
||||
'cancel',
|
||||
'extra',
|
||||
'mode',
|
||||
'name',
|
||||
'properties',
|
||||
'standalone_ports_supported'];
|
||||
|
||||
/* exported PROPERTY_COLLECTION_PROPERTIES */
|
||||
|
||||
var PROPERTY_COLLECTION_PROPERTIES = [
|
||||
|
Loading…
Reference in New Issue
Block a user