Add parameters for container

This patch adds following parameters for container creation.

* cpu
* hostname
* workdir
* ports
* labels

Also, classify all params for creation dialog and details view.

And 'task_state' is added for views.

Change-Id: I647c8d6b06b9b573b45f804f55d4e2154e8c1f4a
Depends-On: Ief55b52317c0a97dd7175556755e460522959789
This commit is contained in:
Shu Muto 2016-10-06 20:06:27 +09:00
parent c16e7a4b3d
commit 78620bef27
22 changed files with 408 additions and 76 deletions

View File

@ -20,7 +20,9 @@ from zunclient.v1 import client as zun_client
LOG = logging.getLogger(__name__)
CONTAINER_CREATE_ATTRS = ['name', 'image', 'command', 'memory', 'environment']
CONTAINER_CREATE_ATTRS = ['name', 'image', 'command', 'cpu', 'memory',
'environment', 'workdir', 'ports', 'hostname',
'labels']
@memoized
@ -56,6 +58,15 @@ def container_create(request, **kwargs):
kv = v.split("=", 1)
envs[kv[0]] = kv[1]
args["environment"] = envs
elif key == "labels":
labels = {}
vals = value.split(",")
for v in vals:
kv = v.split("=", 1)
labels[kv[0]] = kv[1]
args["labels"] = labels
elif key == "ports":
args["ports"] = [v for v in value.split(",")]
return zunclient(request).containers.create(**args)

View File

@ -56,7 +56,7 @@
function run(registry, zun, basePath, resourceType) {
registry.getResourceType(resourceType)
.setNames(gettext('Container'), gettext('Containers'))
// for detail summary view on table row
// for detail summary view on table row.
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
// for table row items and detail summary view.
.setProperty('name', {
@ -71,6 +71,9 @@
.setProperty('status', {
label: gettext('Status')
})
.setProperty('task_state', {
label: gettext('Task State')
})
.setListFunction(listFunction)
.tableColumns
.append({
@ -82,7 +85,7 @@
})
.append({
id: 'id',
priority: 2
priority: 3
})
.append({
id: 'image',
@ -91,6 +94,10 @@
.append({
id: 'status',
priority: 2
})
.append({
id: 'task_state',
priority: 2
});
// for magic-search
registry.getResourceType(resourceType).filterFacets
@ -113,6 +120,11 @@
'label': gettext('Status'),
'name': 'status',
'singleton': true
})
.append({
'label': gettext('Task State'),
'name': 'task_state',
'singleton': true
});
function listFunction(params) {

View File

@ -38,10 +38,15 @@
name: null,
image: null,
command: null,
cpu: null,
memory: null,
memory_size: null,
memory_unit: "m",
environment: null
environment: null,
hostname: null,
workdir: null,
ports: null,
labels: null
};
}

View File

@ -35,7 +35,31 @@
templateUrl: basePath + 'containers/create/info/info.html',
helpUrl: basePath + 'containers/create/info/info.help.html',
formName: 'containerInfoForm'
}
},
{
title: gettext('Spec'),
templateUrl: basePath + 'containers/create/spec/spec.html',
helpUrl: basePath + 'containers/create/spec/spec.help.html',
formName: 'containerSpecForm'
},
{
title: gettext('Miscellaneous'),
templateUrl: basePath + 'containers/create/misc/misc.html',
helpUrl: basePath + 'containers/create/misc/misc.help.html',
formName: 'containerMiscForm'
},
{
title: gettext('Environments'),
templateUrl: basePath + 'containers/create/envs/envs.html',
helpUrl: basePath + 'containers/create/envs/envs.help.html',
formName: 'containerEnvsForm'
},
{
title: gettext('Labels'),
templateUrl: basePath + 'containers/create/labels/labels.html',
helpUrl: basePath + 'containers/create/labels/labels.help.html',
formName: 'containerLabelsForm'
},
],
btnText: {

View File

@ -0,0 +1,34 @@
/**
* 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 createContainerEnvsController
* @ngController
* @description
* Controller for the container environments step in create workflow
*/
angular
.module('horizon.dashboard.container.containers')
.controller('createContainerEnvsController', createContainerEnvsController);
createContainerEnvsController.$inject = [
];
function createContainerEnvsController() {
}
})();

View File

@ -0,0 +1,4 @@
<dl>
<dt translate>Environment Variables</dt>
<dd translate>The environment variables in comma separated KEY=VALUE pairs</dd>
</dl>

View File

@ -0,0 +1,12 @@
<div ng-controller="createContainerEnvsController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-environment" translate>Environment Variables</label>
<input name="container-environment" type="text" class="form-control" id="container-environment"
ng-model="model.newContainerSpec.environment"
placeholder="{$ 'KEY1=VALUE1,KEY2=VALUE2...'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -27,32 +27,8 @@
.controller('createContainerInfoController', createContainerInfoController);
createContainerInfoController.$inject = [
'$q',
'$scope',
'horizon.dashboard.container.basePath',
'horizon.app.core.openstack-service-api.zun',
'horizon.framework.util.i18n.gettext'
];
function createContainerInfoController($q, $scope, basePath, zun, gettext) {
var ctrl = this;
ctrl.memory_units = [{unit: "b", label: gettext("bytes")},
{unit: "k", label: gettext("KB")},
{unit: "m", label: gettext("MB")},
{unit: "g", label: gettext("GB")}];
$scope.changeMemory = function(){
if($scope.model.newContainerSpec.memory_size > 0){
$scope.model.newContainerSpec.memory = $scope.model.newContainerSpec.memory_size + $scope.model.newContainerSpec.memory_unit;
}else{
$scope.model.newContainerSpec.memory = null;
}
};
$scope.changeMemoryUnit = function(){
$scope.changeMemory();
};
$scope.changeMemorySize = function(){
$scope.changeMemory();
};
function createContainerInfoController() {
}
})();

View File

@ -1,13 +1,8 @@
<dl>
<!-- TODO(shu-mutou): descript more! -->
<dt translate>Container Name</dt>
<dd translate>An arbitrary human-readable name</dd>
<dd translate>An arbitrary human-readable name.</dd>
<dt translate>Image</dt>
<dd translate>Name or ID of container image</dd>
<dd translate>Name or ID of container image.</dd>
<dt translate>Command</dt>
<dd translate>Command sent to the container</dd>
<dt translate>Memory</dt>
<dd translate>The container memory size</dd>
<dt translate>Environment Variables</dt>
<dd translate>The environment variables in comma separated KEY=VALUE pairs</dd>
<dd translate>Command sent to the container.</dd>
</dl>

View File

@ -1,6 +1,6 @@
<div ng-controller="createContainerInfoController as ctrl">
<div class="row">
<div class="col-xs-6">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-name" translate>Container Name</label>
<input name="container-name" type="text" class="form-control" id="container-name"
@ -8,7 +8,7 @@
placeholder="{$ 'Name of the container to create.'|translate $}">
</div>
</div>
<div class="col-xs-6">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-image">
<translate>Image</translate>
@ -28,31 +28,5 @@
placeholder="{$ 'A command that will be sent to the container.'|translate $}">
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="control-label" for="container-memory-size" translate>Memory Size</label>
<input name="container-memory-size" type="number" min="1"
class="form-control" ng-model="model.newContainerSpec.memory_size"
placeholder="{$ 'The container memory size.'|translate $}"
ng-change="changeMemorySize()" id="container-memory-size">
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="control-label" for="container-memory-unit" translate>Memory Unit</label>
<select name="container-memory-unit" id="container-memory-unit"
class="form-control" ng-options="mu.unit as mu.label for mu in ctrl.memory_units"
ng-model="model.newContainerSpec.memory_unit" ng-change="changeMemoryUnit()">
</select>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-environment" translate>Environment Variables</label>
<input name="container-environment" type="text" class="form-control" id="container-environment"
ng-model="model.newContainerSpec.environment"
placeholder="{$ 'KEY1=VALUE1,KEY2=VALUE2...'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,34 @@
/**
* 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 createContainerLabelsController
* @ngController
* @description
* Controller for the container labels step in create workflow
*/
angular
.module('horizon.dashboard.container.containers')
.controller('createContainerLabelsController', createContainerLabelsController);
createContainerLabelsController.$inject = [
];
function createContainerLabelsController() {
}
})();

View File

@ -0,0 +1,4 @@
<dl>
<dt translate>Labels</dt>
<dd translate>Adds a map of labels to a container in comma separated KEY=VALUE pairs.</dd>
</dl>

View File

@ -0,0 +1,12 @@
<div ng-controller="createContainerInfoController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-labels" translate>Labels</label>
<input name="container-labels" type="text" class="form-control" id="container-labels"
ng-model="model.newContainerSpec.labels"
placeholder="{$ 'KEY1=VALUE1,KEY2=VALUE2...'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,34 @@
/**
* 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 createContainerMiscController
* @ngController
* @description
* Controller for the container miscellanious step in create workflow
*/
angular
.module('horizon.dashboard.container.containers')
.controller('createContainerMiscController', createContainerMiscController);
createContainerMiscController.$inject = [
];
function createContainerMiscController() {
}
})();

View File

@ -0,0 +1,8 @@
<dl>
<dt translate>Hostname</dt>
<dd translate>The hostname to use for the container.</dd>
<dt translate>Working Directory</dt>
<dd translate>The working directory needs to be an absolute path.</dd>
<dt translate>Ports</dt>
<dd translate>The ports to expose in comma separated values.</dd>
</dl>

View File

@ -0,0 +1,28 @@
<div ng-controller="createContainerMiscController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-hostname" translate>Hostname</label>
<input name="container-hostname" type="text" class="form-control" id="container-hostname"
ng-model="model.newContainerSpec.hostname"
placeholder="{$ 'The hostname to use for the container'|translate $}">
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-workdir" translate>Working Directory</label>
<input name="container-workdir" type="text" class="form-control" id="container-workdir"
ng-model="model.newContainerSpec.workdir"
placeholder="{$ 'The working directory for commands to run in.'|translate $}">
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-ports" translate>Ports</label>
<input name="container-ports" type="text" class="form-control" id="container-ports"
ng-model="model.newContainerSpec.ports"
placeholder="{$ 'PORT1,PORT2,PORT3...'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,55 @@
/**
* 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 createContainerSpecController
* @ngController
* @description
* Controller for the container spec step in create workflow
*/
angular
.module('horizon.dashboard.container.containers')
.controller('createContainerSpecController', createContainerSpecController);
createContainerSpecController.$inject = [
'$scope',
'horizon.framework.util.i18n.gettext'
];
function createContainerSpecController($scope, gettext) {
var ctrl = this;
ctrl.memory_units = [{unit: "b", label: gettext("bytes")},
{unit: "k", label: gettext("KB")},
{unit: "m", label: gettext("MB")},
{unit: "g", label: gettext("GB")}];
$scope.changeMemory = function(){
if($scope.model.newContainerSpec.memory_size > 0){
$scope.model.newContainerSpec.memory = $scope.model.newContainerSpec.memory_size + $scope.model.newContainerSpec.memory_unit;
}else{
$scope.model.newContainerSpec.memory = null;
}
};
$scope.changeMemoryUnit = function(){
$scope.changeMemory();
};
$scope.changeMemorySize = function(){
$scope.changeMemory();
};
}
})();

View File

@ -0,0 +1,6 @@
<dl>
<dt translate>CPU</dt>
<dd translate>The number of virtual cpus.</dd>
<dt translate>Memory</dt>
<dd translate>The container memory size.</dd>
</dl>

View File

@ -0,0 +1,32 @@
<div ng-controller="createContainerSpecController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-cpu" translate>CPU</label>
<input name="container-cpu" type="number" id="container-cpu" min="0" step="0.1"
class="form-control" ng-model="model.newContainerSpec.cpu"
placeholder="{$ 'The number of virtual cpu for this container.'|translate $}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-8">
<div class="form-group">
<label class="control-label" for="container-memory-size" translate>Memory Size</label>
<input name="container-memory-size" type="number" min="1"
class="form-control" ng-model="model.newContainerSpec.memory_size"
placeholder="{$ 'The container memory size.'|translate $}"
ng-change="changeMemorySize()" id="container-memory-size">
</div>
</div>
<div class="col-xs-4">
<div class="form-group">
<label class="control-label" for="container-memory-unit" translate>Memory Unit</label>
<select name="container-memory-unit" id="container-memory-unit"
class="form-control" ng-options="mu.unit as mu.label for mu in ctrl.memory_units"
ng-model="model.newContainerSpec.memory_unit" ng-change="changeMemoryUnit()">
</select>
</div>
</div>
</div>
</div>

View File

@ -1,28 +1,36 @@
<div ng-controller="horizon.dashboard.container.containers.DrawerController as drawerCtrl">
<div class="row">
<span class="rsp-alt-p2">
<dl class="col-md-5">
<span class="rsp-alt-p3">
<dl class="col-md-4">
<dt translate>ID</dt>
<dd>{$ item.id $}</dd>
</dl>
</span>
<span class="rsp-alt-p2">
<dl class="col-md-4">
<dt translate>Image</dt>
<dd>{$ item.image $}</dd>
</dl>
<dl class="col-md-3">
<dl class="col-md-2">
<dt translate>Status</dt>
<dd>{$ item.status $}</dd>
</dl>
<dl class="col-md-2">
<dt translate>Task State</dt>
<dd>{$ item.task_state $}</dd>
</dl>
</span>
</div>
<div class="row">
<dl class="col-md-9">
<dl class="col-md-8">
<dt translate>Command</dt>
<dd>{$ item.command $}</dd>
</dl>
<dl class="col-md-3">
<dt translate>Memory</dt>
<dd>{$ item.memory $}</dd>
<dl class="col-md-4">
<dt translate>Ports</dt>
<div ng-repeat="value in item.ports">
<dd>{$ value $}</dd>
</div>
</dl>
</div>
</div>

View File

@ -12,12 +12,38 @@
<dd>{$ ctrl.container.image $}</dd>
<dt translate>Command</dt>
<dd>{$ ctrl.container.command $}</dd>
<dt translate>Memory</dt>
<dd>{$ ctrl.container.memory $}</dd>
<dt translate>Task State</dt>
<dd>{$ ctrl.container.task_state $}</dd>
</dl>
</div>
<div class="col-md-6 detail">
<h3 translate>Environment</h3>
<h3 translate>Spec</h3>
<hr>
<dl class="dl-horizontal">
<dt translate>CPU</dt>
<dd>{$ ctrl.container.cpu $}</dd>
<dt translate>Memory</dt>
<dd>{$ ctrl.container.memorysize $} {$ ctrl.container.memoryunit $}</dd>
</dl>
</div>
</div>
<div class="row">
<div class="col-md-6 detail">
<h3 translate>Miscellaneous</h3>
<hr>
<dl class="dl-horizontal">
<dt translate>Hostname</dt>
<dd>{$ ctrl.container.hostname $}</dd>
<dt translate>Working Directory</dt>
<dd>{$ ctrl.container.workdir $}</dd>
<dt translate>Ports</dt>
<div ng-repeat="value in ctrl.container.ports">
<dd>{$ value $}</dd>
</div>
</dl>
</div>
<div class="col-md-6 detail">
<h3 translate>Environment Variables</h3>
<hr>
<dl class="dl-horizontal">
<div ng-repeat="(key, value) in ctrl.container.environment">
@ -28,6 +54,16 @@
</div>
</div>
<div class="row">
<div class="col-md-6 detail">
<h3 translate>Labels</h3>
<hr>
<dl class="dl-horizontal">
<div ng-repeat="(key, value) in ctrl.container.labels">
<dt>{$ key $}</dt>
<dd>{$ value $}</dd>
</div>
</dl>
</div>
<div class="col-md-6 detail">
<h3 translate>Record Properties</h3>
<hr>

View File

@ -51,6 +51,10 @@
function getContainer(id) {
return apiService.get('/api/zun/containers/' + id)
.success(function(data, status, headers, config) {
convertMemorySize(data);
return data;
})
.error(function() {
toastService.add('error', gettext('Unable to retrieve the Container.'));
});
@ -58,6 +62,12 @@
function getContainers() {
return apiService.get('/api/zun/containers/')
.success(function(data, status, headers, config) {
angular.forEach(data.items, function(container, idx){
convertMemorySize(container);
});
return data;
})
.error(function() {
toastService.add('error', gettext('Unable to retrieve the Containers.'));
});
@ -100,5 +110,23 @@
});
}
function convertMemorySize(container){
var memoryUnits = { "b": gettext("bytes"),
"k": gettext("KB"),
"m": gettext("MB"),
"g": gettext("GB") };
container.memorysize = "";
container.memoryunit = "";
if(container.memory !== null && container.memory !== ""){
// separate number and unit.
var regex = /(\d+)([bkmg]?)/;
var match = regex.exec(container.memory);
container.memorysize = match[1];
if(match[2]){
container.memoryunit = memoryUnits[match[2]];
}
}
}
}
}());