Merge "Remove Container panel and action"

This commit is contained in:
Jenkins 2016-05-12 23:16:59 +00:00 committed by Gerrit Code Review
commit 5b8f93deb3
39 changed files with 19 additions and 1680 deletions

View File

@ -51,7 +51,6 @@ And enable it in Horizon::
cp ../magnum-ui/enabled/_50_project_containers_panelgroup.py openstack_dashboard/local/enabled cp ../magnum-ui/enabled/_50_project_containers_panelgroup.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_51_project_containers_bays_panel.py openstack_dashboard/local/enabled cp ../magnum-ui/enabled/_51_project_containers_bays_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_52_project_containers_baymodels_panel.py openstack_dashboard/local/enabled cp ../magnum-ui/enabled/_52_project_containers_baymodels_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_53_project_containers_containers_panel.py openstack_dashboard/local/enabled
To run horizon with the newly enabled Magnum UI plugin run:: To run horizon with the newly enabled Magnum UI plugin run::

View File

@ -8,8 +8,16 @@ Magnum Dashboard
* Source: http://git.openstack.org/cgit/openstack/magnum-ui * Source: http://git.openstack.org/cgit/openstack/magnum-ui
* Bugs: http://bugs.launchpad.net/magnum-ui * Bugs: http://bugs.launchpad.net/magnum-ui
Installation instructions Enabling in DevStack
========================= ====================
Add this repo as an external repository into your ``local.conf`` file::
[[local|localrc]]
enable_plugin magnum-ui https://github.com/openstack/magnum-ui
Manual Installation
===================
Begin by cloning the Horizon and Magnum UI repositories:: Begin by cloning the Horizon and Magnum UI repositories::
@ -34,7 +42,6 @@ editor. You will want to customize several settings:
environment. (They should be correct unless you modified your environment. (They should be correct unless you modified your
OpenStack server to change them.) OpenStack server to change them.)
Install Magnum UI with all dependencies in your virtual environment:: Install Magnum UI with all dependencies in your virtual environment::
tools/with_venv.sh pip install -e ../magnum-ui/ tools/with_venv.sh pip install -e ../magnum-ui/
@ -44,7 +51,13 @@ And enable it in Horizon::
cp ../magnum-ui/enabled/_50_project_containers_panelgroup.py openstack_dashboard/local/enabled cp ../magnum-ui/enabled/_50_project_containers_panelgroup.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_51_project_containers_bays_panel.py openstack_dashboard/local/enabled cp ../magnum-ui/enabled/_51_project_containers_bays_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_52_project_containers_baymodels_panel.py openstack_dashboard/local/enabled cp ../magnum-ui/enabled/_52_project_containers_baymodels_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_53_project_containers_containers_panel.py openstack_dashboard/local/enabled
To run horizon with the newly enabled Magnum UI plugin run::
./run_tests.sh --runserver 0.0.0.0:8080
to have the application start on port 8080 and the horizon dashboard will be
available in your browser at http://localhost:8080/
Release Notes Release Notes
============= =============

View File

@ -1,23 +0,0 @@
# Copyright 2015 NEC Corporation, 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.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'bays.containers'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'containers'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# Python panel class of the PANEL to be added.
ADD_PANEL = 'magnum_ui.content.bays.containers.panel.Containers'

View File

@ -112,49 +112,3 @@ def bay_list(request, limit=None, marker=None, sort_key=None,
def bay_show(request, id): def bay_show(request, id):
return magnumclient(request).bays.get(id) return magnumclient(request).bays.get(id)
def container_create(request, bay_uuid, **kwargs):
"""Creates a container object
:param request: Request context
:param bay_uuid: ID of a bay (Required)
:param kwargs: Image ID, Name, Command, Memory
:returns: Container object
"""
return magnumclient(request).containers.create(bay_uuid=bay_uuid, **kwargs)
def container_delete(request, id):
"""Deletes a container
:param request: Request context
:param id: The ID of the container to delete
"""
magnumclient(request).containers.delete(id)
def container_list(request, marker=None, limit=None, sort_key=None,
sort_dir=None, detail=False):
"""Lists all containers
:param request: Request context
:param marker: Optional, ID of last container in previous results
:param limit: '==0' return all, '> 0' specifies max, None respects max
imposed by Magnum API
:param sort_key: Optional, key to sort by
:param sort_dir: Optional, direction of sorting ('asc' or 'desc')
:param detail: Optional, boolean, return detailed info about containers
"""
return magnumclient(request).containers.list(
marker=marker, limit=limit, sort_key=sort_key, sort_dir=sort_dir,
detail=detail)
def container_show(request, id):
"""Get an individual container
:param request: Request context
:param id: ID of the container to get
"""
return magnumclient(request).containers.get(id)

View File

@ -122,50 +122,3 @@ class Bays(generic.View):
return rest_utils.CreatedResponse( return rest_utils.CreatedResponse(
'/api/containers/bay/%s' % new_bay.uuid, '/api/containers/bay/%s' % new_bay.uuid,
new_bay.to_dict()) new_bay.to_dict())
@urls.register
class Container(generic.View):
"""API for retrieving a single container"""
url_regex = r'containers/containers/(?P<container_id>[^/]+)$'
@rest_utils.ajax()
def get(self, request, container_id):
"""Get a specific container"""
return magnum.container_show(request, container_id).to_dict()
@urls.register
class Containers(generic.View):
"""API for Magnum Containers"""
url_regex = r'containers/containers/$'
@rest_utils.ajax()
def get(self, request):
"""Get a list of the Containers for a project.
The returned result is an object with property 'items' and each
item under this is a Container.
"""
result = magnum.container_list(request)
return {'items': [change_to_id(n.to_dict()) for n in result]}
@rest_utils.ajax(data_required=True)
def delete(self, request):
"""Delete one or more Containers by ID.
Returns HTTP 204 (no content) on successful deletion.
"""
for container_id in request.DATA:
magnum.container_delete(request, container_id)
@rest_utils.ajax(data_required=True)
def post(self, request):
"""Create a new Container.
Returns the new Container object on success.
"""
container = magnum.container_create(request, **request.DATA)
return rest_utils.CreatedResponse(
'/api/containers/container/%s' % container.uuid,
container.to_dict())

View File

@ -1,21 +0,0 @@
# Copyright 2015 Cisco Systems
#
# 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.
from django.utils.translation import ugettext_lazy as _
import horizon
class Containers(horizon.Panel):
name = _("Containers")
slug = "bays.containers"

View File

@ -1,36 +0,0 @@
# Copyright 2015 Cisco Systems, 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.
# from django.core.urlresolvers import reverse
# import horizon
# from magnum_ui.containers.containers.panel import Containers
from openstack_dashboard.test import helpers as test
class ContainerTests(test.TestCase):
def test_me(self):
self.assertTrue(1 + 1 == 2)
# FIXME(shu-mutou): this tests seems not to work in new Horizon's plugin
# registration system
# def test_registration(self):
# dashboard = horizon.get_dashboard('project')
# registered_panel = dashboard.get_panel('containers.containers')
# self.assertEqual(registered_panel.slug, Containers.slug)
# def test_index(self):
# index = reverse('horizon:bays:containers:index')
# res = self.client.get(index)
# self.assertTemplateUsed(
# res, 'project/bays/containers/index.html')

View File

@ -1,22 +0,0 @@
# Copyright 2015 Cisco Systems, 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.
from django.conf.urls import url
from magnum_ui.content.bays.containers import views
urlpatterns = [
url(r'^[0-9a-f\-]{36}$', views.IndexView.as_view(), name='detail'),
url(r'^$', views.IndexView.as_view(), name='index'),
]

View File

@ -1,19 +0,0 @@
# Copyright 2015 Cisco Systems
#
# 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.
from horizon import views
class IndexView(views.APIView):
template_name = 'bays.containers/index.html'

View File

@ -12,14 +12,11 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from django.conf.urls import include
from django.conf.urls import url from django.conf.urls import url
from magnum_ui.content.bays.containers import urls as containers_urls
from magnum_ui.content.bays.views import IndexView from magnum_ui.content.bays.views import IndexView
urlpatterns = [ urlpatterns = [
url(r'^containers/', include(containers_urls, namespace='containers')),
url(r'^[0-9a-f\-]{36}$', IndexView.as_view(), name='detail'), url(r'^[0-9a-f\-]{36}$', IndexView.as_view(), name='detail'),
url(r'^$', IndexView.as_view(), name='index'), url(r'^$', IndexView.as_view(), name='index'),
] ]

View File

@ -30,7 +30,6 @@
'horizon.framework.util.i18n.gettext', 'horizon.framework.util.i18n.gettext',
'horizon.dashboard.containers.bays.create.service', 'horizon.dashboard.containers.bays.create.service',
'horizon.dashboard.containers.bays.delete.service', 'horizon.dashboard.containers.bays.delete.service',
'horizon.dashboard.containers.containers.create.service',
'horizon.dashboard.containers.bays.resourceType', 'horizon.dashboard.containers.bays.resourceType',
]; ];
@ -39,18 +38,10 @@
gettext, gettext,
createBayService, createBayService,
deleteBayService, deleteBayService,
createContainerService,
resourceType) resourceType)
{ {
var bayResourceType = registry.getResourceType(resourceType); var bayResourceType = registry.getResourceType(resourceType);
bayResourceType.itemActions bayResourceType.itemActions
.append({
id: 'createContainerAction',
service: createContainerService,
template: {
text: gettext('Create Container')
}
})
.append({ .append({
id: 'deleteBayAction', id: 'deleteBayAction',
service: deleteBayService, service: deleteBayService,

View File

@ -27,13 +27,12 @@
'$routeParams', '$routeParams',
'horizon.app.core.openstack-service-api.magnum', 'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.bays.events', 'horizon.dashboard.containers.bays.events',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service', 'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.bays.resourceType' 'horizon.dashboard.containers.bays.resourceType'
]; ];
function BayDetailController( function BayDetailController(
$scope, $window, $location, $routeParams, magnum, events, containerEvents, registry, bayResourceType $scope, $window, $location, $routeParams, magnum, events, registry, bayResourceType
) { ) {
var ctrl = this; var ctrl = this;
ctrl.bay = {}; ctrl.bay = {};
@ -43,7 +42,6 @@
var bayId = $routeParams.bayId; var bayId = $routeParams.bayId;
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess); var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
var createContainerWatcher = $scope.$on(containerEvents.CREATE_SUCCESS, onCreateContainerSuccess);
$scope.$on('$destroy', destroy); $scope.$on('$destroy', destroy);
@ -70,14 +68,8 @@
$location.path("/project/bays"); $location.path("/project/bays");
} }
function onCreateContainerSuccess(e, createdItem) {
e.stopPropagation();
$location.path("/project/bays/containers");
}
function destroy() { function destroy() {
deleteWatcher(); deleteWatcher();
createContainerWatcher();
} }
} }
})(); })();

View File

@ -34,12 +34,11 @@
'$location', '$location',
'horizon.app.core.openstack-service-api.magnum', 'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.bays.events', 'horizon.dashboard.containers.bays.events',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service', 'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.bays.resourceType' 'horizon.dashboard.containers.bays.resourceType'
]; ];
function containersBaysTableController($scope, $location, magnum, events, containerEvents, registry, bayResourceType) { function containersBaysTableController($scope, $location, magnum, events, registry, bayResourceType) {
var ctrl = this; var ctrl = this;
ctrl.bays = []; ctrl.bays = [];
ctrl.baysSrc = []; ctrl.baysSrc = [];
@ -78,7 +77,6 @@
]; ];
var createWatcher = $scope.$on(events.CREATE_SUCCESS, onCreateSuccess); var createWatcher = $scope.$on(events.CREATE_SUCCESS, onCreateSuccess);
var createContainerWatcher = $scope.$on(containerEvents.CREATE_SUCCESS, onCreateContainerSuccess);
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess); var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
$scope.$on('$destroy', destroy); $scope.$on('$destroy', destroy);
@ -99,11 +97,6 @@
e.stopPropagation(); e.stopPropagation();
} }
function onCreateContainerSuccess(e, createdItem) {
e.stopPropagation();
$location.path("/project/bays/containers");
}
function onDeleteSuccess(e, removedIds) { function onDeleteSuccess(e, removedIds) {
ctrl.baysSrc = difference(ctrl.baysSrc, removedIds, 'id'); ctrl.baysSrc = difference(ctrl.baysSrc, removedIds, 'id');
e.stopPropagation(); e.stopPropagation();
@ -125,7 +118,6 @@
function destroy() { function destroy() {
createWatcher(); createWatcher();
createContainerWatcher();
deleteWatcher(); deleteWatcher();
} }
} }

View File

@ -28,7 +28,6 @@
.module('horizon.dashboard.containers', [ .module('horizon.dashboard.containers', [
'horizon.dashboard.containers.bays', 'horizon.dashboard.containers.bays',
'horizon.dashboard.containers.baymodels', 'horizon.dashboard.containers.baymodels',
'horizon.dashboard.containers.containers',
'ngRoute' 'ngRoute'
]) ])
.config(config) .config(config)
@ -41,12 +40,6 @@
$provide.constant('horizon.dashboard.containers.basePath', path); $provide.constant('horizon.dashboard.containers.basePath', path);
$routeProvider $routeProvider
.when('/project/bays/containers', {
templateUrl: path + 'containers/table/table.html'
})
.when('/project/bays/containers/:containerId', {
templateUrl: path + 'containers/detail/detail.html'
})
.when('/project/baymodels', { .when('/project/baymodels', {
templateUrl: path + 'baymodels/table/table.html' templateUrl: path + 'baymodels/table/table.html'
}) })

View File

@ -1,6 +1,5 @@
@import "baymodels/baymodels"; @import "baymodels/baymodels";
@import "bays/bays"; @import "bays/bays";
@import "containers/containers";
.table > thead > .action-row > th > actions { .table > thead > .action-row > th > actions {
float: right; float: right;

View File

@ -1,73 +0,0 @@
/**
* 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 overview
* @ngname horizon.dashboard.containers.containers.actions
*
* @description
* Provides all of the actions for containers.
*/
angular.module('horizon.dashboard.containers.containers.actions', ['horizon.framework', 'horizon.dashboard.containers'])
.run(registerContainerActions);
registerContainerActions.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.containers.containers.create.service',
'horizon.dashboard.containers.containers.delete.service',
'horizon.dashboard.containers.containers.resourceType',
];
function registerContainerActions(
registry,
gettext,
createContainerService,
deleteContainerService,
resourceType)
{
var containerResourceType = registry.getResourceType(resourceType);
containerResourceType.itemActions
.append({
id: 'deleteContainerAction',
service: deleteContainerService,
template: {
type: 'delete',
text: gettext('Delete Container')
}
});
containerResourceType.batchActions
.append({
id: 'createContainerAction',
service: createContainerService,
template: {
type: 'create',
text: gettext('Create Container')
}
})
.append({
id: 'batchDeleteContainerAction',
service: deleteContainerService,
template: {
type: 'delete-selected',
text: gettext('Delete Containers')
}
});
}
})();

View File

@ -1,46 +0,0 @@
/**
* Copyright 2015 Cisco Systems, 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';
/**
* @ngdoc overview
* @name horizon.dashboard.containers.containers
* @ngModule
*
* @description
* Provides all the services and widgets require to display the containers
* panel
*/
angular
.module('horizon.dashboard.containers.containers', ['horizon.dashboard.containers.containers.actions'])
.constant('horizon.dashboard.containers.containers.events', events())
.constant('horizon.dashboard.containers.containers.resourceType', 'OS::Magnum::Container');
/**
* @ngdoc constant
* @name horizon.dashboard.containers.containers.events
* @description A list of events used by Containers
*/
function events() {
return {
CREATE_SUCCESS: 'horizon.dashboard.containers.containers.CREATE_SUCCESS',
DELETE_SUCCESS: 'horizon.dashboard.containers.containers.DELETE_SUCCESS'
};
}
})();

View File

@ -1,25 +0,0 @@
/**
* Copyright 2015 Cisco Systems, 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.containers.containers', function() {
it('should exist', function() {
expect(angular.module('horizon.dashboard.containers.containers')).toBeDefined();
});
});
})();

View File

@ -1,74 +0,0 @@
/**
* Copyright 2015 Cisco Systems, 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.containers.containers')
.factory('horizon.dashboard.containers.containers.containerModel', containerModel);
containerModel.$inject = [
'horizon.app.core.openstack-service-api.magnum'
];
function containerModel(magnum) {
var model = {
newContainerSpec: {},
// API methods
init: init,
createContainer: createContainer
};
function initNewContainerSpec() {
model.newContainerSpec = {
name: null,
bay_uuid: null,
image: null,
memory: null,
memory_size: null,
memory_unit: "m",
command: null
};
}
function init() {
// Reset the new Bay spec
initNewContainerSpec();
}
function createContainer() {
var finalSpec = angular.copy(model.newContainerSpec);
cleanNullProperties(finalSpec);
return magnum.createContainer(finalSpec);
}
function cleanNullProperties(finalSpec) {
// Initially clean fields that don't have any value.
for (var key in finalSpec) {
if (finalSpec.hasOwnProperty(key) && finalSpec[key] === null
|| key === "memory_size" || key === "memory_unit") {
delete finalSpec[key];
}
}
}
return model;
}
})();

View File

@ -1,58 +0,0 @@
/**
* Copyright 2015 Cisco Systems, 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.containers.containers')
.factory('horizon.dashboard.containers.containers.workflow', containerWorkflow);
containerWorkflow.$inject = [
'horizon.dashboard.containers.basePath',
'horizon.app.core.workflow.factory',
'horizon.framework.util.i18n.gettext'
];
function containerWorkflow(basePath, dashboardWorkflow, gettext) {
return dashboardWorkflow({
title: gettext('Create Container'),
steps: [
{
title: gettext('Info'),
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'
}
],
btnText: {
finish: gettext('Create')
},
btnIcon: {
finish: 'fa fa-check'
}
});
}
})();

View File

@ -1,90 +0,0 @@
/**
* 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 overview
* @name horizon.dashboard.containers.containers.create.service
* @description Service for the container create modal
*/
angular
.module('horizon.dashboard.containers.containers')
.factory('horizon.dashboard.containers.containers.create.service', createService);
createService.$inject = [
'horizon.dashboard.containers.containers.containerModel',
'horizon.framework.widgets.modal.wizard-modal.service',
'horizon.framework.widgets.toast.service',
'horizon.dashboard.containers.containers.workflow',
'horizon.dashboard.containers.containers.events',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions'
];
function createService(
model, wizardModalService, toast, createWorkflow, events, policy, gettext, $qExtensions
) {
var scope;
var message = {
success: gettext('Container %s was successfully created.')
};
var service = {
initScope: initScope,
perform: perform,
allowed: allowed
};
return service;
//////////////
function initScope($scope) {
scope = $scope;
scope.workflow = createWorkflow;
scope.model = model;
scope.$on('$destroy', function() {
});
}
function perform(selected) {
scope.model.init();
scope.selected = selected;
wizardModalService.modal({
scope: scope,
workflow: createWorkflow,
submit: submit
});
}
function allowed(selected) {
return $qExtensions.booleanAsPromise(true);
}
function submit(){
return model.createContainer().then(success);
}
function success(response) {
response.data.id = response.data.uuid;
toast.add('success', interpolate(message.success, [response.data.id]));
scope.$emit(events.CREATE_SUCCESS, response.data);
}
}
})();

View File

@ -1,83 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* 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 createContainerInfoController
* @ngController
*
* @description
* Controller for the container info step in create workflow
*/
angular
.module('horizon.dashboard.containers.containers')
.controller('createContainerInfoController', createContainerInfoController);
createContainerInfoController.$inject = [
'$q',
'$scope',
'horizon.dashboard.containers.basePath',
'horizon.app.core.openstack-service-api.magnum'
];
function createContainerInfoController($q, $scope, basePath, magnum) {
var ctrl = this;
ctrl.bays = [{id:"", name: gettext("Choose a Bay")}];
$scope.model.newContainerSpec.bay_uuid = "";
$scope.baydetail = {
name: "",
id: "",
baymodel: "",
master_count: "",
node_count: "",
discovery_url: "",
timeout: ""
};
$scope.changeBay = function(){
angular.forEach(ctrl.bays, function(bay, idx){
if($scope.model.newContainerSpec.bay_uuid === bay.id){
$("#bay_detail").show();
$("#bay_detail_none").hide();
$scope.baydetail.name = bay.name;
$scope.baydetail.id = bay.id;
$scope.baydetail.baymodel_id = bay.baymodel_id;
$scope.baydetail.master_count = bay.master_count;
$scope.baydetail.node_count = bay.node_count;
$scope.baydetail.discovery_url = bay.discovery_url;
$scope.baydetail.timeout = bay.timeout;
}
});
};
init();
function init() {
magnum.getBays({paginate: false}).success(onGetBays);
}
function onGetBays(response) {
Array.prototype.push.apply(ctrl.bays, response.items);
if($scope.selected instanceof Object){
$scope.model.newContainerSpec.bay_uuid = $scope.selected.id;
$scope.changeBay();
}
}
}
})();

View File

@ -1 +0,0 @@
<p translate>Specify container name and choose bay.</p>

View File

@ -1,46 +0,0 @@
<div ng-controller="createContainerInfoController as ctrl">
<div class="row">
<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"
ng-model="model.newContainerSpec.name"
placeholder="{$ 'Name of the container to create.'|translate $}">
</div>
<div class="form-group">
<label class="control-label" for="container-bay">
<translate>Bay</translate>
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<select class="form-control" name="container-bay" id="container-bay"
ng-model="model.newContainerSpec.bay_uuid"
ng-required="true"
ng-options="bay.id as bay.name|noName for bay in ctrl.bays"
ng-change="changeBay()">
</select>
</div>
<div class="detail" ng-show="model.newContainerSpec.bay_uuid">
<span translate class="h4">Bay Detail</span>
<dl class="dl-horizontal">
<dt translate>Name</dt>
<dd><a ng-href="project/bays/{$ baydetail.id $}" ng-click="cancel()">
{$ baydetail.name|noName $}
</a></dd>
<dt translate>ID</dt>
<dd>{$ baydetail.id $}</dd>
<dt translate>Baymodel ID</dt>
<dd>{$ baydetail.baymodel_id $}</dd>
<dt translate>Master Count</dt>
<dd>{$ baydetail.master_count $}</dd>
<dt translate>Node Count</dt>
<dd>{$ baydetail.node_count $}</dd>
<dt translate>Timeout</dt>
<dd>{$ baydetail.timeout $}</dd>
</dl>
</div>
</div>
</div>
</div>

View File

@ -1,61 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* 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.containers.containers')
.controller('createContainerSpecController', createContainerSpecController);
createContainerSpecController.$inject = [
'$q',
'$scope',
'horizon.dashboard.containers.basePath',
'horizon.app.core.openstack-service-api.magnum'
];
function createContainerSpecController($q, $scope, basePath, magnum) {
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

@ -1 +0,0 @@
<p translate>Specify the specs for the container.</p>

View File

@ -1,48 +0,0 @@
<div ng-controller="createContainerSpecController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-image" translate>
<translate>Image</translate>
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<input name="container-image" type="text" class="form-control" id="container-image"
ng-required="true" ng-model="model.newContainerSpec.image"
placeholder="{$ 'Name of the container image.'|translate $}">
</div>
</div>
</div>
<div class="row">
<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>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-command" translate>Command</label>
<input name="container-command" type="text" class="form-control" id="container-command"
ng-model="model.newContainerSpec.command"
placeholder="{$ 'Send command to the contaier in a line.'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -1,125 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self 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.containers.containers')
.factory('horizon.dashboard.containers.containers.delete.service', deleteService);
deleteService.$inject = [
'horizon.app.core.openstack-service-api.magnum',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.widgets.modal.deleteModalService',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions',
'horizon.dashboard.containers.containers.events'
];
/**
* @ngDoc factory
* @name horizon.dashboard.containers.containers.delete.service
*
* @Description
* Brings up the delete containers confirmation modal dialog.
* On submit, delete selected resources.
* On cancel, do nothing.
*/
function deleteService(
magnum, policy, deleteModalService, gettext, $qExtensions, events
) {
var scope;
var context = {
labels: null,
deleteEntity: deleteEntity,
successEvent: events.DELETE_SUCCESS
};
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
//////////////
// include this function in your service
// if you plan to emit events to the parent controller
function initScope($scope) {
scope = $scope;
}
function allowed() {
return $qExtensions.booleanAsPromise(true);
}
// delete selected resource objects
function perform(selected) {
if(!selected.hasOwnProperty('id')){
// batch (multi)
context.labels = labelize(selected.length);
$qExtensions.allSettled(selected.map(checkPermission)).then(afterCheck);
}else{
// row (single)
context.labels = labelize(1);
deleteModalService.open(scope, [selected], context);
}
}
function labelize(count){
return {
title: ngettext('Confirm Delete Container',
'Confirm Delete Containers', count),
/* eslint-disable max-len */
message: ngettext('You have selected "%s". Please confirm your selection. Deleted container is not recoverable.',
'You have selected "%s". Please confirm your selection. Deleted containers are not recoverable.', count),
/* eslint-enable max-len */
submit: ngettext('Delete Container',
'Delete Containers', count),
success: ngettext('Deleted Container: %s.',
'Deleted Containers: %s.', count),
error: ngettext('Unable to delete Container: %s.',
'Unable to delete Containers: %s.', count)
};
}
// for batch delete
function checkPermission(selected) {
return {promise: allowed(selected), context: selected};
}
// for batch delete
function afterCheck(result){
if (result.fail.length > 0) {
toast.add('error', getMessage(notAllowedMessage, result.fail));
}
if (result.pass.length > 0) {
deleteModalService.open(scope, result.pass.map(getEntity), context);
}
}
// for batch delete
function getEntity(result) {
return result.context;
}
// call delete REST API
function deleteEntity(id){
return magnum.deleteContainer(id, true);
}
}
})();

View File

@ -1,79 +0,0 @@
/*
* Copyright 2015 NEC Corporation
*
* 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.containers.containers')
.controller('ContainerDetailController', ContainerDetailController);
ContainerDetailController.$inject = [
'$scope',
'$window',
'$location',
'$routeParams',
'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.containers.resourceType'
];
function ContainerDetailController($scope, $window, $location, $routeParams, magnum, events, registry, containerResourceType) {
var ctrl = this;
ctrl.container = {};
ctrl.bay = {};
ctrl.baymodel = {};
ctrl.containerResource = registry.getResourceType(containerResourceType);
var containerId = $routeParams.containerId;
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
$scope.$on('$destroy', destroy);
init();
function init() {
registry.initActions(containerResourceType, $scope);
// Load the elements that are used in the overview.
magnum.getContainer(containerId).success(onGetContainer);
}
function onGetContainer(container) {
ctrl.container = container;
ctrl.container.id = container.uuid;
magnum.getBay(ctrl.container.bay_uuid).success(onGetBay);
}
function onGetBay(bay) {
ctrl.bay = bay;
magnum.getBaymodel(ctrl.bay.baymodel_id).success(onGetBaymodel);
}
function onGetBaymodel(baymodel) {
ctrl.baymodel = baymodel;
}
function onDeleteSuccess(e, removedIds) {
e.stopPropagation();
$location.path("/project/bays/containers");
}
function destroy() {
deleteWatcher();
}
}
})();

View File

@ -1,107 +0,0 @@
<div class="content" ng-controller="ContainerDetailController as ctrl">
<div class="page-header">
<ol class="breadcrumb">
<li><a ng-href="project/bays/containers" translate>Containers</a></li>
<li class="active">{$ ctrl.container.name|noName $}</li>
<div class="pull-right">
<actions allowed="ctrl.containerResource.itemActions" type="row" item="ctrl.container"></actions>
</div>
</ol>
</div>
<tabset>
<tab heading="{$ 'Overview' | translate $}">
<div class="row">
<div class="col-md-6">
<h3 translate>Spec</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Image</dt>
<dd>{$ ctrl.container.image $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Memory</dt>
<dd>{$ ctrl.container.memorysize $} {$ ctrl.container.memoryunit $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Command</dt>
<dd>{$ ctrl.container.command $}</dd>
</div>
</dl>
</div>
<div class="col-md-6">
<h3 translate>Bay</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Name</dt>
<dd><a ng-href="project/bays/{$ ctrl.bay.uuid $}">{$ ctrl.bay.name|noName $}</a></dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>ID</dt>
<dd>{$ ctrl.bay.uuid $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Status</dt>
<dd>{$ ctrl.bay.status $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Master Count</dt>
<dd>{$ ctrl.bay.master_count $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Node Count</dt>
<dd>{$ ctrl.bay.node_count $}</dd>
</div>
</dl>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h3 translate>Baymodel</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Name</dt>
<dd><a ng-href="project/baymodels/{$ ctrl.baymodel.uuid $}">{$ ctrl.baymodel.name|noName $}</a></dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>ID</dt>
<dd>{$ ctrl.baymodel.uuid $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>COE</dt>
<dd>{$ ctrl.baymodel.coe $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Image ID</dt>
<dd>{$ ctrl.baymodel.image_id $}</dd>
</div>
</dl>
</div>
<div class="col-md-6">
<h3 translate>Record Properties</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Created</dt>
<dd>{$ ctrl.container.created_at | date:'short' $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Updated</dt>
<dd>{$ ctrl.container.updated_at | date:'short' $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>ID</dt>
<dd>{$ ctrl.container.uuid $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Status</dt>
<dd>{$ ctrl.container.status $}</dd>
</div>
</dl>
</div>
</div>
</tab>
</tabset>
</div>

View File

@ -1,136 +0,0 @@
/**
* Copyright 2015 Cisco Systems, 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';
/**
* @ngdoc overview
* @name containersContainersTableController
* @ngController
*
* @description
* Controller for the Magnum containers table
*/
angular
.module('horizon.dashboard.containers.containers')
.controller('containersContainersTableController', containersContainersTableController);
containersContainersTableController.$inject = [
'$scope',
'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.containers.resourceType'
];
function containersContainersTableController($scope, magnum, events, registry, containerResourceType) {
var ctrl = this;
ctrl.containers = [];
ctrl.containersSrc = [];
ctrl.containerResource = registry.getResourceType(containerResourceType);
/**
* Filtering - client-side MagicSearch
* all facets for container table
*/
ctrl.containerFacets = [
{
'label': gettext('Name'),
'name': 'name',
'singleton': true
},
{
'label': gettext('UUID'),
'name': 'id',
'singleton': true
},
{
'label': gettext('Status'),
'name': 'status',
'singleton': true
},
{
'label': gettext('Bay'),
'name': 'bay-uuid',
'singleton': true
},
{
'label': gettext('Image'),
'name': 'image',
'singleton': true
},
{
'label': gettext('Memory'),
'name': 'memory',
'singleton': true
},
{
'label': gettext('Command'),
'name': 'command',
'singleton': true
}
];
var createWatcher = $scope.$on(events.CREATE_SUCCESS, onCreateSuccess);
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
$scope.$on('$destroy', destroy);
init();
function init() {
registry.initActions(containerResourceType, $scope);
magnum.getContainers().success(getContainersSuccess);
}
function getContainersSuccess(response) {
ctrl.containersSrc = response.items;
}
function onCreateSuccess(e, createdItem) {
ctrl.containersSrc.push(createdItem);
e.stopPropagation();
}
function onDeleteSuccess(e, removedIds) {
ctrl.containersSrc = difference(ctrl.containersSrc, removedIds, 'id');
e.stopPropagation();
// after deleting the items
// we need to clear selected items from table controller
$scope.$emit('hzTable:clearSelected');
}
function difference(currentList, otherList, key) {
return currentList.filter(filter);
function filter(elem) {
return otherList.filter(function filterDeletedItem(deletedItem) {
return deletedItem === elem[key];
}).length === 0;
}
}
function destroy() {
createWatcher();
deleteWatcher();
}
}
})();

View File

@ -1,156 +0,0 @@
<table ng-controller="containersContainersTableController as table"
hz-table ng-cloak
st-table="table.containers"
st-safe-src="table.containersSrc"
default-sort="name"
default-sort-reverse="false"
class="table table-striped table-rsp table-detail">
<thead>
<!--
Table-batch-actions:
This is where batch actions like searching, creating, and deleting.
-->
<tr>
<th colspan="100" class="search-header">
<hz-magic-search-bar group-classes="input-group-sm" icon-classes="fa-search"
filter-facets="table.containerFacets">
</hz-magic-search-bar>
</th>
</tr>
<tr class="action-row">
<th colspan="100">
<actions allowed="table.containerResource.batchActions" type="batch"></actions>
</th>
</tr>
<!--
Table-column-headers:
The headers for the table columns
-->
<tr>
<th class="multi_select_column">
<input type="checkbox" hz-select-all="table.containers">
</th>
<th class="expander"></th>
<th class="rsp-p1" st-sort="name" st-sort-default translate>
Name
</th>
<th class="rsp-p2" st-sort="id" translate>
ID
</th>
<th class="rsp-p1" st-sort="status" translate>
Status
</th>
<th class="rsp-p3" st-sort="bay" translate>
Bay ID
</th>
<th class="rsp-p2" st-sort="image" translate>
Image
</th>
<th class="rsp-p3" st-sort="memory" translate>
Memory
</th>
<th class="actions_column" translate>
Actions
</th>
</tr>
</thead>
<tbody>
<!--
Table-rows:
This is where we declaratively define the table columns.
Include multi_select_column if you want to select all.
Include expander if you want to inline details.
Include actions_column if you want to perform actions.
rsp-p1 rsp-p2 are responsive priority as user resizes window.
-->
<tr ng-repeat-start="c in table.containers track by c.id">
<td class="multi_select_column">
<input type="checkbox"
ng-model="tCtrl.selections[c.id].checked"
hz-select="c">
</td>
<td class="expander">
<i class="fa fa-chevron-right"
hz-expand-detail
duration="200">
</i>
</td>
<td class="rsp-p1"><a ng-href="project/bays/containers/{$ c.id $}">{$ c.name|noName $}</a></td>
<td class="rsp-p2">{$ c.id $}</td>
<td class="rsp-p1">{$ c.status $}</td>
<td class="rsp-p3"><a ng-href="project/bays/{$ c.bay_uuid $}">{$ c.bay_uuid $}</a></td>
<td class="rsp-p2">{$ c.image $}</td>
<td class="rsp-p3">{$ c.memorysize $} {$ c.memoryunit $}</td>
<td class="actions_column">
<!--
Table-row-action-column:
Actions taken here applies to a single item/row.
-->
<actions allowed="table.containerResource.itemActions" type="row" item="c"></actions>
</td>
</tr>
<tr ng-repeat-end class="detail-row">
<!--
Detail-row:
Contains detailed information on this item.
Can be toggled using the chevron button.
Ensure colspan is greater or equal to number of column-headers.
-->
<td class="detail" colspan="100">
<!--
The responsive columns that disappear typically should reappear here
with the same responsive priority that they disappear.
E.g. table header with rsp-p2 should be here with rsp-alt-p2
-->
<div class="row">
<span class="rsp-alt-p2">
<dl class="col-xs-5">
<dt translate>ID</dt>
<dd>{$ c.id $}</dd>
</dl>
<dl class="col-xs-5">
<dt translate>Image</dt>
<dd>{$ c.image $}</dd>
</dl>
</span>
<span class="rsp-alt-p3">
<dl class="col-xs-5">
<dt translate>Bay ID</dt>
<dd><a ng-href="project/bays/{$ c.bay_uuid $}">{$ c.bay_uuid $}</a></dd>
</dl>
<dl class="col-xs-2">
<dt translate>Memory</dt>
<dd>{$ c.memorysize $} {$ c.memoryunit $}</dd>
</dl>
</span>
</div>
<div class="row">
<dl class="col-xs-12">
<dt translate>Command</dt>
<dd>{$ c.command $}</dd>
</dl>
</div>
</td>
</tr>
<tr hz-no-items items="table.containers"></tr>
</tbody>
<!--
Table-footer:
This is where we display number of items and pagination controls.
-->
<tfoot hz-table-footer items="table.containers"></tfoot>
</table>

View File

@ -38,13 +38,6 @@
getBaymodels: getBaymodels, getBaymodels: getBaymodels,
deleteBaymodel: deleteBaymodel, deleteBaymodel: deleteBaymodel,
deleteBaymodels: deleteBaymodels, deleteBaymodels: deleteBaymodels,
createContainer: createContainer,
getContainer: getContainer,
getContainers: getContainers,
deleteContainer: deleteContainer,
deleteContainers: deleteContainers,
memoryUnits: memoryUnits,
convertMemorySize: convertMemorySize,
}; };
return service; return service;
@ -130,76 +123,5 @@
toastService.add('error', gettext('Unable to delete the Baymodels.')); toastService.add('error', gettext('Unable to delete the Baymodels.'));
}) })
} }
////////////////
// Containers //
////////////////
function createContainer(params) {
return apiService.post('/api/containers/containers/', params)
.error(function() {
toastService.add('error', gettext('Unable to create Container.'));
});
}
function getContainer(id) {
return apiService.get('/api/containers/containers/' + id)
.success(function(data, status, headers, config) {
convertMemorySize(data);
return data;
})
.error(function() {
toastService.add('error', gettext('Unable to retrieve the Container.'));
});
}
function getContainers() {
return apiService.get('/api/containers/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.'));
});
}
function deleteContainer(id, suppressError) {
var promise = apiService.delete('/api/containers/containers/', [id]);
return suppressError ? promise : promise.error(function() {
var msg = gettext('Unable to delete the Container with id: %(id)s');
toastService.add('error', interpolate(msg, { id: id }, true));
});
}
// FIXME(shu-mutou): Unused for batch-delete in Horizon framework in Feb, 2016.
function deleteContainers(ids) {
return apiService.delete('/api/containers/containers/', ids)
.error(function() {
toastService.add('error', gettext('Unable to delete the Containers.'));
});
}
} }
var memoryUnits = { "b": gettext("bytes"),
"k": gettext("KB"),
"m": gettext("MB"),
"g": gettext("GB")};
function convertMemorySize(container){
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]];
}
}
};
}()); }());

View File

@ -1,18 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Containers" %}
{% endblock %}
{% block page_header %}
<hz-page-header header="{$ 'Containers' | translate $}"/>
{% endblock page_header %}
{% block ng_route_base %}
<base href="{{ WEBROOT }}"></base>
{% endblock %}
{% block main %}
<div ng-view></div>
{% endblock %}

View File

@ -1,66 +0,0 @@
# Copyright 2015 Cisco Systems, 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.
from magnum_ui import api
from magnum_ui.test import helpers as test
class MagnumApiTests(test.APITestCase):
def test_container_list(self):
containers = self.magnum_containers.list()
form_data = {'marker': None,
'limit': None,
'sort_key': None,
'sort_dir': None,
'detail': False}
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.list(**form_data).AndReturn(containers)
self.mox.ReplayAll()
api.magnum.container_list(self.request)
def test_container_get(self):
container = self.magnum_containers.first()
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.get(container['uuid']).AndReturn(container)
self.mox.ReplayAll()
api.magnum.container_show(self.request, container['uuid'])
def test_container_delete(self):
container = self.magnum_containers.first()
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.delete(container['uuid'])
self.mox.ReplayAll()
api.magnum.container_delete(self.request, container['uuid'])
def test_container_create(self):
container = self.magnum_containers.first()
form_data = {'bay_uuid': container['bay'],
'name': container['name']}
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.create(**form_data)\
.AndReturn(container)
self.mox.ReplayAll()
api.magnum.container_create(self.request, **form_data)

View File

@ -103,46 +103,6 @@ class MagnumRestTestCase(test.TestCase):
request, request,
u'bay_id') u'bay_id')
# Containers
@mock.patch.object(magnum, 'magnum')
def test_container_get(self, client):
request = self.mock_rest_request()
client.container_list.return_value = \
mock_resource(TEST.magnum_containers.list())
response = magnum.Containers().get(request)
self.assertStatusCode(response, 200)
self.assertItemsCollectionEqual(response,
TEST.magnum_containers.list())
client.container_list.assert_called_once_with(request)
@mock.patch.object(magnum, 'magnum')
def test_container_create(self, client):
test_conts = mock_resource(TEST.magnum_containers.list())
test_cont = test_conts[0]
test_body = json.dumps(test_cont.to_dict())
request = self.mock_rest_request(body=test_body)
client.container_create.return_value = test_cont
response = magnum.Containers().post(request)
self.assertStatusCode(response, 201)
self.assertEqual(response['location'],
'/api/containers/container/%s' % test_cont.uuid)
client.container_create.assert_called_once_with(request,
**test_cont.to_dict())
@mock.patch.object(magnum, 'magnum')
def test_container_delete(self, client):
test_container = TEST.magnum_containers.first()
request = self.mock_rest_request(
body='{"container_id":' + str(test_container['uuid']) + '}')
response = magnum.Containers().delete(request)
self.assertStatusCode(response, 204)
client.container_delete.assert_called_once_with(
request,
u'container_id')
def mock_resource(resource): def mock_resource(resource):
"""Utility function to make mocking more DRY""" """Utility function to make mocking more DRY"""

View File

@ -19,8 +19,6 @@ def data(TEST):
# Test Data Containers # Test Data Containers
TEST.baymodels = utils.TestDataContainer() TEST.baymodels = utils.TestDataContainer()
TEST.bays = utils.TestDataContainer() TEST.bays = utils.TestDataContainer()
# 'magnum_containers' to avoid Swift naming confusion
TEST.magnum_containers = utils.TestDataContainer()
# Bay Models # Bay Models
baymodel_dict_1 = {"uuid": 1, baymodel_dict_1 = {"uuid": 1,
@ -53,13 +51,3 @@ def data(TEST):
"timeout": 0} "timeout": 0}
TEST.bays.add(bay_dict_1) TEST.bays.add(bay_dict_1)
# Containers
container_dict_1 = {"uuid": 1,
"name": "myapartmentsmellsofrichmahogany",
"image": "",
"bay": bay_dict_1["uuid"],
"command": "",
"memory": ""}
TEST.magnum_containers.add(container_dict_1)