Change inputs for networks of cluster template into pulldowns

To be convinient to input netwok settings, this patch changes
input forms for External Network, Fixed Network and Fixed Subnet
in Cluster Template create/update dialogs to pulldowns.

Change-Id: I7ba72ef432bd79e1eb074e9fdf29e2fcc8424377
Closes-Bug: #1570668
This commit is contained in:
Shu Muto 2017-05-31 16:40:03 +09:00
parent 915227a9d7
commit e1bcb3ceb7
6 changed files with 161 additions and 55 deletions

View File

@ -16,6 +16,7 @@ from django.views import generic
from magnum_ui.api import magnum
from openstack_dashboard.api import neutron
from openstack_dashboard.api.rest import urls
from openstack_dashboard.api.rest import utils as rest_utils
@ -181,3 +182,23 @@ class Certificates(generic.View):
return rest_utils.CreatedResponse(
'/api/container_infra/certificates/',
new_cert.to_dict())
@urls.register
class Networks(generic.View):
"""API for Neutron networks for Cluster Templates creation"""
url_regex = r'container_infra/networks/$'
@rest_utils.ajax()
def get(self, request):
"""Get a list of the Networks for a project.
Networks includes external and private. Also, each network
has subnets.
The returned result is an object with property 'items' and each
item under this is a Network.
"""
tenant_id = request.user.tenant_id
result = neutron.network_list_for_tenant(request, tenant_id,
include_external=True)
return {'items': [n.to_dict() for n in result]}

View File

@ -117,6 +117,9 @@
}
}
config.model.labels = labels; //
// update workflow
workflow.update(config);
}
return modal.open(config).then(submit);

View File

@ -41,6 +41,8 @@
init: function (action, title) {
action = title;
return {model: model};
},
update: function () {
}
};
@ -66,6 +68,7 @@
spyOn(magnum, 'getClusterTemplate').and.returnValue(deferred.promise);
spyOn(magnum, 'updateClusterTemplate').and.returnValue(deferred.promise);
spyOn(workflow, 'init').and.returnValue({model: model});
spyOn(workflow, 'update').and.callThrough();
spyOn(modal, 'open').and.callThrough();
}));

View File

@ -24,25 +24,27 @@
ClusterTemplateWorkflow);
ClusterTemplateWorkflow.$inject = [
'$q',
'horizon.dashboard.container-infra.basePath',
'horizon.app.core.workflow.factory',
'horizon.framework.util.i18n.gettext',
'horizon.app.core.openstack-service-api.magnum',
'horizon.app.core.openstack-service-api.nova',
'horizon.app.core.openstack-service-api.glance'
];
function ClusterTemplateWorkflow(basePath, workflowService, gettext, nova, glance) {
function ClusterTemplateWorkflow($q, basePath, workflowService, gettext, magnum, nova, glance) {
var workflow = {
init: init
init: init,
update: update
};
function init(action, title) {
var schema, form, model;
var images = [{value:"", name: gettext("Choose an Image")}];
var nflavors = [{value:"", name: gettext("Choose a Flavor for the Node")}];
var mflavors = [{value:"", name: gettext("Choose a Flavor for the Master Node")}];
var keypairs = [{value:"", name: gettext("Choose a Keypair")}];
var form, model, images, nflavors, mflavors, keypairs,
externalNetworks, fixedNetworks, fixedSubnets;
var fixedSubnetsInitial = gettext("Choose a Private Network at first");
function init(action, title) {
var schema;
var coes = [{value: '', name: gettext("Choose a Container Orchestration Engine")},
{value: "swarm", name: gettext("Docker Swarm")},
{value: "kubernetes", name: gettext("Kubernetes")},
@ -161,30 +163,15 @@
},
'external_network_id': {
title: gettext('External Network ID'),
type: 'string',
'x-schema-form': {
type: 'string',
placeholder: gettext(
'The external Neutron network ID to connect to this cluster template')
}
type: 'string'
},
'fixed_network': {
title: gettext('Fixed Network'),
type: 'string',
'x-schema-form': {
type: 'string',
placeholder: gettext(
'The private Neutron network name to connect to this cluster template')
}
type: 'string'
},
'fixed_subnet': {
title: gettext('Fixed Subnet'),
type: 'string',
'x-schema-form': {
type: 'string',
placeholder: gettext(
'The private Neutron subnet name to connect to this cluster template')
}
type: 'string'
},
'dns_nameserver': {
title: gettext('DNS'),
@ -393,13 +380,22 @@
},
{
key: 'external_network_id',
type: 'select',
titleMap: externalNetworks,
required: true
},
{
key: 'fixed_network'
key: 'fixed_network',
type: 'select',
titleMap: fixedNetworks,
onChange: function () {
changeFixedNetwork(model);
}
},
{
key: 'fixed_subnet'
key: 'fixed_subnet',
type: 'select',
titleMap: fixedSubnets
},
{
key: 'dns_nameserver'
@ -446,29 +442,6 @@
}
];
glance.getImages().then(onGetImages);
nova.getFlavors(false, false).then(onGetFlavors);
nova.getKeypairs().then(onGetKeypairs);
function onGetImages(response) {
angular.forEach(response.data.items, function(item) {
images.push({value: item.name, name: item.name});
});
}
function onGetFlavors(response) {
angular.forEach(response.data.items, function(item) {
nflavors.push({value: item.name, name: item.name});
mflavors.push({value: item.name, name: item.name});
});
}
function onGetKeypairs(response) {
angular.forEach(response.data.items, function(item) {
keypairs.push({value: item.keypair.name, name: item.keypair.name});
});
}
model = {
name: "",
coe: "",
@ -502,10 +475,95 @@
model: model
};
update(config);
return config;
}
// called by update.service
function update(config) {
$q.all({
images: glance.getImages().then(onGetImages),
flavors: nova.getFlavors(false, false).then(onGetFlavors),
keypairs: nova.getKeypairs().then(onGetKeypairs),
networks: magnum.getNetworks().then(onGetNetworks)
}).then(function() {
changeFixedNetwork(config.model, init);
});
}
function onGetImages(response) {
images = [{value:"", name: gettext("Choose an Image")}];
angular.forEach(response.data.items, function(item) {
images.push({value: item.name, name: item.name});
});
form[0].tabs[1].items[0].items[0].items[0].titleMap = images;
var deferred = $q.defer();
deferred.resolve(images);
return deferred.promise;
}
function onGetFlavors(response) {
nflavors = [{value:"", name: gettext("Choose a Flavor for the Node")}];
mflavors = [{value:"", name: gettext("Choose a Flavor for the Master Node")}];
angular.forEach(response.data.items, function(item) {
nflavors.push({value: item.name, name: item.name});
mflavors.push({value: item.name, name: item.name});
});
form[0].tabs[1].items[0].items[0].items[1].titleMap = nflavors;
form[0].tabs[1].items[0].items[1].items[1].titleMap = mflavors;
var deferred = $q.defer();
deferred.resolve(nflavors);
return deferred.promise;
}
function onGetKeypairs(response) {
keypairs = [{value:"", name: gettext("Choose a Keypair")}];
angular.forEach(response.data.items, function(item) {
keypairs.push({value: item.keypair.name, name: item.keypair.name});
});
form[0].tabs[1].items[0].items[1].items[0].titleMap = keypairs;
var deferred = $q.defer();
deferred.resolve(keypairs);
return deferred.promise;
}
function onGetNetworks(response) {
externalNetworks = [{value:"", name: gettext("Choose a External Network")}];
fixedNetworks = [{value:"", name: gettext("Choose a Private Network")}];
angular.forEach(response.data.items, function(item) {
if (item["router:external"]) {
externalNetworks.push({value: item.id, name: item.name});
} else {
fixedNetworks.push({value: item.id, name: item.name, subnets: item.subnets});
}
});
form[0].tabs[2].items[0].items[0].items[4].titleMap = externalNetworks;
form[0].tabs[2].items[0].items[0].items[5].titleMap = fixedNetworks;
var deferred = $q.defer();
deferred.resolve({
externalNetworks: externalNetworks,
fixedNetworks: fixedNetworks
});
return deferred.promise;
}
function changeFixedNetwork(model) {
if (model.fixed_network) {
fixedSubnets = [{value:"", name: gettext("Choose a Private Subnet")}];
angular.forEach(fixedNetworks, function(fixed) {
if (fixed.value === model.fixed_network) {
angular.forEach(fixed.subnets, function(subnet) {
fixedSubnets.push({value: subnet.id, name: subnet.name});
});
}
});
} else {
fixedSubnets = [{value:"", name: fixedSubnetsInitial}];
model.fixed_subnet = "";
}
form[0].tabs[2].items[0].items[0].items[6].titleMap = fixedSubnets;
}
return workflow;
}
})();

View File

@ -19,7 +19,7 @@
describe('horizon.dashboard.container-infra.cluster-templates.workflow', function() {
var workflow, nova, glance, $q, deferred, keyDeferred;
var workflow, magnum, nova, glance, $q, deferred, keyDeferred;
beforeEach(module('horizon.app.core'));
beforeEach(module('horizon.framework'));
@ -31,6 +31,7 @@
'horizon.dashboard.container-infra.cluster-templates.workflow');
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
glance = $injector.get('horizon.app.core.openstack-service-api.glance');
magnum = $injector.get('horizon.app.core.openstack-service-api.magnum');
deferred = $q.defer();
deferred.resolve({data:{items:{1:{name:1},2:{name:2}}}});
keyDeferred = $q.defer();
@ -38,7 +39,7 @@
spyOn(glance, 'getImages').and.returnValue(deferred.promise);
spyOn(nova, 'getFlavors').and.returnValue(deferred.promise);
spyOn(nova, 'getKeypairs').and.returnValue(keyDeferred.promise);
spyOn(magnum, 'getNetworks').and.returnValue(deferred.promise);
}));
it('should be init', inject(function($timeout) {

View File

@ -43,7 +43,8 @@
deleteClusterTemplates: deleteClusterTemplates,
showCertificate: showCertificate,
signCertificate: signCertificate,
downloadTextAsFile: downloadTextAsFile
downloadTextAsFile: downloadTextAsFile,
getNetworks: getNetworks
};
return service;
@ -180,5 +181,24 @@
a.remove();
}, 0);
}
//////////////////
// Networks //
//////////////////
/**
* @name getNetworks
* @description
* Get a list of networks for a tenant including external and private.
* Also, each network has subnets.
* @returns {Object} An object with property "items". Each item is a network.
*/
function getNetworks() {
return apiService.get('/api/container_infra/networks/')
.error(function () {
toastService.add('error', gettext('Unable to retrieve the networks.'));
});
}
}
}());