Add create action for capsule

This patch adds create action for capsule as global action.

Change-Id: I9ffcc9bcc3118850a174eae0f8afc1dc34b40c34
Partial-Implements: blueprint capsule
This commit is contained in:
Shu Muto 2018-06-14 17:57:22 +09:00
parent 12da76bd2d
commit 05e5bb1b99
8 changed files with 266 additions and 1 deletions

View File

@ -20,12 +20,14 @@ from openstack_dashboard.api import base
from neutronclient.v2_0 import client as neutron_client
from zunclient import api_versions
from zunclient.common import template_format
from zunclient.common import utils
from zunclient.v1 import client as zun_client
LOG = logging.getLogger(__name__)
CONTAINER_CREATE_ATTRS = zun_client.containers.CREATION_ATTRIBUTES
CAPSULE_CREATE_ATTRS = zun_client.capsules.CREATION_ATTRIBUTES
IMAGE_PULL_ATTRS = zun_client.images.PULL_ATTRIBUTES
API_VERSION = api_versions.APIVersion(api_versions.DEFAULT_API_VERSION)
@ -276,6 +278,12 @@ def capsule_show(request, id):
return zunclient(request).capsules.get(id)
def capsule_create(request, **kwargs):
args, run = _cleanup_params(CAPSULE_CREATE_ATTRS, True, **kwargs)
args["template"] = template_format.parse(args["template"])
return zunclient(request).capsules.create(**args)
def image_list(request, limit=None, marker=None, sort_key=None,
sort_dir=None, detail=False):
# FIXME(shu-mutou): change "detail" param to True, if it enabled.

View File

@ -178,6 +178,17 @@ class Capsules(generic.View):
result = client.capsule_list(request)
return {'items': [i.to_dict() for i in result]}
@rest_utils.ajax(data_required=True)
def post(self, request):
"""Create a new Capsule.
Returns the new Capsule object on success.
"""
new_capsule = client.capsule_create(request, **request.DATA)
return rest_utils.CreatedResponse(
'/api/zun/capsules/%s' % new_capsule.uuid,
new_capsule.to_dict())
@urls.register
class Capsule(generic.View):

View File

@ -32,6 +32,7 @@
registerCapsuleActions.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.container.capsules.actions.create.service',
'horizon.dashboard.container.capsules.actions.refresh.service',
'horizon.dashboard.container.capsules.resourceType'
];
@ -39,12 +40,22 @@
function registerCapsuleActions(
registry,
gettext,
createCapsuleService,
refreshCapsuleService,
resourceType
) {
var capsulesResourceType = registry.getResourceType(resourceType);
// FIXME(shu-mutow): refresh action is dummy. remove it when add other action.
capsulesResourceType.globalActions
.append({
id: 'createCapsuleAction',
service: createCapsuleService,
template: {
text: gettext('Create')
}
});
// FIXME(shu-mutow): refresh action is dummy. remove it when add other item action.
capsulesResourceType.itemActions
.append({
id: 'refreshCapsuleAction',

View File

@ -0,0 +1,84 @@
/**
* 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';
/**
* @ngdoc factory
* @name horizon.dashboard.container.capsules.actions.create.service
* @description
* Service for the create capsule modal
*/
angular
.module('horizon.dashboard.container.capsules.actions')
.factory('horizon.dashboard.container.capsules.actions.create.service', createCapsuleService);
createCapsuleService.$inject = [
'horizon.app.core.openstack-service-api.policy',
'horizon.app.core.openstack-service-api.zun',
'horizon.dashboard.container.capsules.actions.workflow',
'horizon.dashboard.container.capsules.resourceType',
'horizon.framework.util.actions.action-result.service',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions',
'horizon.framework.widgets.form.ModalFormService',
'horizon.framework.widgets.toast.service'
];
function createCapsuleService(
policy, zun, workflow, resourceType,
actionResult, gettext, $qExtensions, modal, toast
) {
var message = {
success: gettext('Request to create capsule %s has been accepted.')
};
var service = {
initAction: initAction,
perform: perform,
allowed: allowed
};
return service;
//////////////
function initAction() {
}
function perform() {
var title, submitText;
title = gettext('Create Capsule');
submitText = gettext('Create');
var config = workflow.init('create', title, submitText);
return modal.open(config).then(submit);
}
function allowed() {
return policy.ifAllowed({ rules: [['capsule', 'create_capsule']] });
}
function submit(context) {
return zun.createCapsule(context.model, true).then(success, true);
}
function success(response) {
toast.add('success', interpolate(message.success, [response.data.id]));
var result = actionResult.getActionResult().created(resourceType, response.data.name);
return result.result;
}
}
})();

View File

@ -0,0 +1,47 @@
/**
* 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';
/**
* @ngdoc controller
* @name horizon.dashboard.container.capsules.actions.workflow.loadTemplateController
* @ngController
*
* @description
* Controller for the loading template file
*/
angular
.module('horizon.dashboard.container.capsules.actions')
.controller('horizon.dashboard.container.capsules.actions.workflow.loadTemplateController',
loadTemplateController);
loadTemplateController.$inject = [
'$scope'
];
function loadTemplateController($scope) {
var ctrl = this;
ctrl.title = $scope.schema.properties.template.title;
ctrl.template = "";
ctrl.onTemplateChange = onTemplateChange;
////
function onTemplateChange(template) {
$scope.model.template = template;
}
}
})();

View File

@ -0,0 +1,9 @@
<div ng-controller="horizon.dashboard.container.capsules.actions.workflow.loadTemplateController as ctrl">
<load-edit title="{$ ctrl.title $}"
model="ctrl.template"
max-bytes="{$ 16 * 1024 $}"
key="template"
rows=20 required="true"
on-textarea-change="ctrl.onTemplateChange(textContent)">
</load-edit>
</div>

View File

@ -0,0 +1,89 @@
/**
* 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';
/**
* @ngdoc factory
* @name horizon.dashboard.container.capsules.actions.workflow
* @description
* Workflow for creating capsule
*/
angular
.module('horizon.dashboard.container.capsules.actions')
.factory('horizon.dashboard.container.capsules.actions.workflow', workflow);
workflow.$inject = [
'horizon.dashboard.container.capsules.basePath',
'horizon.framework.util.i18n.gettext'
];
function workflow(basePath, gettext) {
var workflow = {
init: init
};
function init(actionType, title, submitText) {
var schema, form, model;
// schema
schema = {
type: 'object',
properties: {
template: {
title: gettext('Template'),
type: 'string'
}
}
};
// form
form = [
{
type: 'section',
htmlClass: 'row',
items: [
{
type: 'section',
htmlClass: 'col-sm-12',
items: [
{
type: 'template',
templateUrl: basePath + 'actions/workflow/load-template.html',
}
]
}
]
}
]; // form
model = {
template: ''
};
var config = {
title: title,
submitText: submitText,
schema: schema,
form: form,
model: model
};
return config;
}
return workflow;
}
})();

View File

@ -55,6 +55,7 @@
getZunAvailabilityZones: getZunAvailabilityZones,
getCapsules: getCapsules,
getCapsule: getCapsule,
createCapsule: createCapsule,
pullImage: pullImage,
getImages: getImages,
deleteImage: deleteImage,
@ -214,6 +215,11 @@
return apiService.get(capsulesPath + id).error(error(msg));
}
function createCapsule(params) {
var msg = gettext('Unable to create Capsule.');
return apiService.post(capsulesPath, params).error(error(msg));
}
////////////
// Images //
////////////