Merge "Remove Container panel and action"
This commit is contained in:
commit
5b8f93deb3
@ -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::
|
||||||
|
|
||||||
|
@ -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
|
||||||
=============
|
=============
|
||||||
|
@ -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'
|
|
@ -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)
|
|
||||||
|
@ -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())
|
|
||||||
|
@ -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"
|
|
@ -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')
|
|
@ -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'),
|
|
||||||
]
|
|
@ -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'
|
|
@ -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'),
|
||||||
]
|
]
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
})
|
})
|
||||||
|
@ -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;
|
||||||
|
@ -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')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -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'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
})();
|
|
@ -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;
|
|
||||||
}
|
|
||||||
})();
|
|
@ -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'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
@ -1 +0,0 @@
|
|||||||
<p translate>Specify container name and choose bay.</p>
|
|
@ -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>
|
|
@ -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();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -1 +0,0 @@
|
|||||||
<p translate>Specify the specs for the container.</p>
|
|
@ -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>
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
@ -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>
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -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>
|
|
@ -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]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
@ -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 %}
|
|
@ -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)
|
|
@ -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"""
|
||||||
|
@ -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)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user