diff --git a/zaqar_ui/__init__.py b/zaqar_ui/__init__.py index e69de29..a819e7b 100644 --- a/zaqar_ui/__init__.py +++ b/zaqar_ui/__init__.py @@ -0,0 +1,22 @@ +# Copyright 2015 IBM Corp. +# +# 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. + +import pbr.version + +# Register the REST API URLs so they can be called from the JavaScript files +import zaqar_ui.api.rest # noqa + + +__version__ = pbr.version.VersionInfo( + 'neutron_lbaas_dashboard').version_string() diff --git a/zaqar_ui/api/__init__.py b/zaqar_ui/api/__init__.py new file mode 100644 index 0000000..1613ce2 --- /dev/null +++ b/zaqar_ui/api/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015 IBM Corp. +# +# 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. + +""" +Methods and interface objects used to interact with external APIs. + +API method calls return objects that are in many cases objects with +attributes that are direct maps to the data returned from the API http call. +Unfortunately, these objects are also often constructed dynamically, making +it difficult to know what data is available from the API object. Because of +this, all API calls should wrap their returned object in one defined here, +using only explicitly defined attributes and/or methods. + +In other words, Horizon developers not working on openstack_dashboard.api +shouldn't need to understand the finer details of APIs for +Keystone/Nova/Glance/Swift et. al. +""" + +from zaqar_ui.api import zaqar # noqa diff --git a/zaqar_ui/api/rest/__init__.py b/zaqar_ui/api/rest/__init__.py new file mode 100644 index 0000000..1313cb9 --- /dev/null +++ b/zaqar_ui/api/rest/__init__.py @@ -0,0 +1,24 @@ +# Copyright 2015 IBM Corp. +# +# 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. + +"""This package holds the REST API that supports the LBaaS v2 dashboard +Javascript code. +It is not intended to be used outside of Horizon, and makes no promises of +stability or fitness for purpose outside of that scope. +It does not promise to adhere to the general OpenStack API Guidelines set out +in https://wiki.openstack.org/wiki/APIChangeGuidelines. +""" + +# import REST API modules here +from zaqar_ui.api.rest import zaqar # noqa diff --git a/zaqar_ui/api/rest/zaqar.py b/zaqar_ui/api/rest/zaqar.py new file mode 100644 index 0000000..1ac2708 --- /dev/null +++ b/zaqar_ui/api/rest/zaqar.py @@ -0,0 +1,78 @@ +# 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.views import generic + +from zaqar_ui.api import zaqar + +from openstack_dashboard.api.rest import urls +from openstack_dashboard.api.rest import utils as rest_utils + + +@urls.register +class Queue(generic.View): + """API for retrieving a single queue + """ + url_regex = r'zaqar/queues/(?P[^/]+)$' + + @rest_utils.ajax() + def get(self, request, queue_name): + """Get a specific queue + """ + return zaqar.queue_show(request, queue_name).to_dict() + + +@urls.register +class Queues(generic.View): + """API for queues + """ + url_regex = r'zaqar/queues/$' + + @rest_utils.ajax() + def get(self, request): + """Get a list of the Queues for a project. + + The returned result is an object with property 'items' and each + item under this is a queue. + """ + result = zaqar.queue_list(request) + queues = [] + for q in result: + stats = q.stats['messages'] + queues.append({'name': q.name, + 'claimed': stats['claimed'], + 'free': stats['free'], + 'total': stats['total'], + 'metadata': q.metadata()}) + return queues + + @rest_utils.ajax(data_required=True) + def delete(self, request): + """Delete one or more queue by name. + + Returns HTTP 204 (no content) on successful deletion. + """ + for queue_name in request.DATA: + zaqar.queue_delete(request, queue_name) + + @rest_utils.ajax(data_required=True) + def create(self, request): + """Create a new queue. + + Returns the new queue object on success. + """ + new_queue = zaqar.queue_create(request, **request.DATA) + return rest_utils.CreatedResponse( + '/api/messaging/queues/%s' % new_queue.name, + new_queue.to_dict()) diff --git a/zaqar_ui/api/zaqar.py b/zaqar_ui/api/zaqar.py new file mode 100644 index 0000000..dc8d308 --- /dev/null +++ b/zaqar_ui/api/zaqar.py @@ -0,0 +1,93 @@ +# Copyright 2015 Catalyst IT Ltd. +# +# 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 __future__ import absolute_import +import logging +from zaqarclient.queues import client as zaqar_client + +from horizon import exceptions +from horizon.utils.memoized import memoized +from openstack_dashboard.api import base + +LOG = logging.getLogger(__name__) + + +@memoized +def zaqarclient(request): + zaqar_url = "" + service_type = 'messaging' + try: + zaqar_url = base.url_for(request, service_type) + except exceptions.ServiceCatalogException: + LOG.debug('No messaging service is configured.') + return None + + LOG.debug('zaqarclient connection created using the token "%s" and url' + '"%s"' % (request.user.token.id, zaqar_url)) + + opts = {'os_auth_token': request.user.token.id, + 'os_auth_url': base.url_for(request, 'identity'), + 'os_project_id': request.user.tenant_id, + 'os_service_type': service_type} + + auth_opts = {'backend': 'keystone', + 'options': opts} + + conf = {'auth_opts': auth_opts} + + return zaqar_client.Client(url=zaqar_url, version=2, conf=conf) + + +def queue_list(request, limit=None, marker=None): + return zaqarclient(request).queues(limit=limit, marker=marker) + + +def queue_create(request, queue_name, metadata): + """Pop up a modal form, which contains several inputbox: + 1. queue_name + 2. ttl + 3. max message size + 4. Metadata + """ + + queue = zaqarclient(request).queue(queue_name, force_create=True) + queue.metadata(new_meta=metadata) + + +def queue_delete(request, queue_name): + queue = zaqarclient(request).queue(queue_name, auto_create=False) + queue.delete() + + +def queue_update(request, queue_name, metadata): + """Popup a modal form, the queue name is a realonly label or inputbox. + user can change ttl, max message size and metadata + """ + + queue = zaqarclient(request).queue(queue_name, auto_create=False) + queue.metadata(new_meta=metadata) + + +def queue_get(request, queue_name): + return zaqarclient(request).queue(queue_name, auto_create=False) + + +def queue_subscribe(request, subscriber, ttl=None, options={}): + """Popup a modal form, user can input subscriber, ttl and options to + subscribe the queue. + + subscriber could be an URL or email address. + """ + pass diff --git a/zaqar_ui/content/queues/templates/queues/index.html b/zaqar_ui/content/queues/templates/queues/index.html index 6a63a77..17e679b 100644 --- a/zaqar_ui/content/queues/templates/queues/index.html +++ b/zaqar_ui/content/queues/templates/queues/index.html @@ -3,8 +3,9 @@ {% block title %}{% trans "Queues" %}{% endblock %} {% block page_header %} - + {% endblock page_header %} {% block main %} + {% endblock %} diff --git a/zaqar_ui/content/queues/urls.py b/zaqar_ui/content/queues/urls.py index a18ad90..5e989b2 100644 --- a/zaqar_ui/content/queues/urls.py +++ b/zaqar_ui/content/queues/urls.py @@ -16,7 +16,8 @@ from django.conf import urls from zaqar_ui.content.queues import views + urlpatterns = urls.patterns( - '', + 'zaqar_ui.content.queues', urls.url(r'^$', views.IndexView.as_view(), name='index'), ) diff --git a/zaqar_ui/enabled/_1520_project_queues.py b/zaqar_ui/enabled/_1520_project_queues.py index c7e8a34..23c4044 100644 --- a/zaqar_ui/enabled/_1520_project_queues.py +++ b/zaqar_ui/enabled/_1520_project_queues.py @@ -25,8 +25,19 @@ ADD_ANGULAR_MODULES = [ 'horizon.dashboard.project.queues' ] +ADD_JS_FILES = [ + 'app/core/openstack-service-api/zaqar.service.js', + 'dashboard/project/queues/queues.module.js', + 'dashboard/project/queues/table/table.controller.js', +] + +ADD_JS_SPEC_FILES = [ + 'dashboard/project/queues/queues.module.spec.js', + 'dashboard/project/queues/table/table.controller.spec.js', +] + ADD_SCSS_FILES = [ 'dashboard/project/queues/queues.scss' ] -AUTO_DISCOVER_STATIC_FILES = True +# AUTO_DISCOVER_STATIC_FILES = True diff --git a/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js b/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js new file mode 100644 index 0000000..ebeb617 --- /dev/null +++ b/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js @@ -0,0 +1,47 @@ +/** + * Copyright 2015 Catalyst IT Ltd. + * + * 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.app.core.openstack-service-api') + .factory('horizon.app.core.openstack-service-api.zaqar', ZaqarAPI); + + ZaqarAPI.$inject = [ + 'horizon.framework.util.http.service', + 'horizon.framework.widgets.toast.service' + ]; + + function ZaqarAPI(apiService, toastService) { + var service = { + getQueues: getQueues + }; + + return service; + + ////////// + + function getQueues() { + return apiService.get('/api/zaqar/queues/') + .error(function() { + toastService.add('error', gettext('Unable to retrieve the Queues.')); + }); + } + + } + +}()); diff --git a/zaqar_ui/static/dashboard/project/queues/table/table.controller.js b/zaqar_ui/static/dashboard/project/queues/table/table.controller.js new file mode 100644 index 0000000..54273bd --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/table/table.controller.js @@ -0,0 +1,60 @@ +/** + * 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 queuesTableController + * @ngController + * + * @description + * Controller for the queues table + */ + angular + .module('horizon.dashboard.project.queues') + .controller('horizon.dashboard.project.queues.tableController', queuesTableController); + + queuesTableController.$inject = [ + '$scope', + 'horizon.app.core.openstack-service-api.zaqar' + ]; + + function queuesTableController($scope, zaqar) { + + var ctrl = this; + + ctrl.iqueues = []; + ctrl.queues = []; + + init(); + + ////////// + + function init() { + zaqar.getQueues().success(getQueuesSuccess); + } + + function getQueuesSuccess(response) { + + // TODO: If the response does not contain the id field + // then you must manually add them on the client-side + // the horizon table's checkboxes requires that the id field be present + console.log(response); + ctrl.queues = response; + } + } + +})(); diff --git a/zaqar_ui/static/dashboard/project/queues/table/table.controller.spec.js b/zaqar_ui/static/dashboard/project/queues/table/table.controller.spec.js new file mode 100644 index 0000000..e69de29 diff --git a/zaqar_ui/static/dashboard/project/queues/table/table.html b/zaqar_ui/static/dashboard/project/queues/table/table.html new file mode 100644 index 0000000..22dfe9a --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/table/table.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + NameClaimed MessagesFree MessagesTotal Messages
+ + + + {$ q.name $}{$ q.claimed $}{$ q.free $}{$ q.total $}
+ +
+ + + +
+
Flavor
+
{$ q.metadata.flavor $}
+
+ +
+
Max Message Size
+
{$ q.metadata.max_message_size $}
+
+ +
+
Time To Live
+
{$ q.metadata.ttl $}
+
+
+ + +
+
Metadata
+
{$ q.metadata $}
+
+ +
+
+ {$ table.iqueues.length|itemCount $} +
+