# 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. import json import yaml from django.utils.translation import gettext_lazy as _ from django.views import generic from openstack_dashboard.api.rest import urls from openstack_dashboard.api.rest import utils as rest_utils from zaqar_ui.api import zaqar def _convert_to_yaml(data, default_flow_style=False): if not data: return '' try: return yaml.safe_dump(data, default_flow_style=default_flow_style) except Exception: return '' def _load_yaml(data): if not data: loaded_data = {} else: try: loaded_data = yaml.safe_load(data) except Exception as ex: raise Exception(_('The specified input is not a valid ' 'YAML format: %s') % str(ex)) return loaded_data @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""" queue = zaqar.queue_get(request, queue_name) stats = queue.stats['messages'] queue_info = {'name': queue_name, 'claimed': stats['claimed'], 'free': stats['free'], 'total': stats['total'], 'metadata': queue.metadata()} return queue_info @rest_utils.ajax(data_required=True) def post(self, request, queue_name): """Update a queue. Returns the updated queue object on success. """ queue = zaqar.queue_update(request, queue_name, **request.DATA) location = '/api/zaqars/queue/%s' % queue._name response = {'name': queue._name, 'metadata': queue._metadata} return rest_utils.CreatedResponse(location, response) @urls.register class QueueActions(generic.View): """API for actions on a single queue""" url_regex = r'zaqar/queues/(?P[^/]+)/(?P[^/]+)$' @rest_utils.ajax(data_required=True) def post(self, request, queue_name, action): """Actions for a queue""" if action == "purge": resource_types = request.DATA.get("resource_types") zaqar.queue_purge(request, queue_name, resource_types) elif action == "share": paths = request.DATA.get("paths") ttl_seconds = request.DATA.get("ttl_seconds") methods = request.DATA.get("methods") return zaqar.queue_signed_url(request, queue_name, paths, ttl_seconds, methods) @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 put(self, request): """Create a new queue. Returns the new queue object on success. """ new_queue = zaqar.queue_create(request, **request.DATA) location = '/api/zaqar/queues/%s' % new_queue.name response = {'name': new_queue.name, 'claimed': 0, 'free': 0, 'total': 0, 'metadata': new_queue._metadata} return rest_utils.CreatedResponse(location, response) @urls.register class Subscriptions(generic.View): """API for Subscriptions""" url_regex = r'zaqar/queues/(?P[^/]+)/subscriptions/$' @rest_utils.ajax() def get(self, request, queue_name): """Get a list of the Subscriptions for a queue.""" return zaqar.subscription_list(request, queue_name) @rest_utils.ajax(data_required=True) def delete(self, request, queue_name): """Delete one or more queue by name. Returns HTTP 204 (no content) on successful deletion. """ zaqar.subscription_delete(request, queue_name, request.DATA) @rest_utils.ajax(data_required=True) def put(self, request, queue_name): """Create a new subscription. Returns the new queue object on success. """ return zaqar.subscription_create(request, queue_name, request.DATA) @urls.register class Messages(generic.View): """API for messages""" url_regex = r'zaqar/queues/(?P[^/]+)/messages/$' @rest_utils.ajax() def get(self, request, queue_name): """Get a list of messages""" result = zaqar.message_list(request, queue_name) messages = [] for m in result: claim_id = None if m.claim_id: claim_id = m.claim_id() messages.append({'age': m.age, 'body': m.body, 'claim_id': claim_id, 'id': m.id, 'href': m.href, 'ttl': m.ttl}) return messages @rest_utils.ajax(data_required=True) def post(self, request, queue_name): """Create new messages""" messages = json.loads(request.DATA.get("messages")) return zaqar.message_post(request, queue_name, messages) @urls.register class Subscription(generic.View): """API for retrieving a single subscription""" url_regex = r'zaqar/queues/(?P[^/]+)/' \ r'subscription/(?P[^/]+)/$' @rest_utils.ajax(data_required=True) def post(self, request, queue_name, subscriber): zaqar.subscription_update(request, queue_name, {'id': subscriber}, request.DATA) @urls.register class Pool(generic.View): """API for retrieving a single pool""" url_regex = r'zaqar/pools/(?P[^/]+)$' @rest_utils.ajax() def get(self, request, pool_name): """Get a specific pool""" pool = zaqar.pool_get(request, pool_name) pool['id'] = pool.get('name') pool['options'] = _convert_to_yaml(pool.get('options')) return pool @rest_utils.ajax(data_required=True) def post(self, request, pool_name): """Update a pool. Returns the updated pool object on success. """ request.DATA["options"] = _load_yaml(request.DATA.get("options")) params = request.DATA pool_name = params.pop('name') new_pool = zaqar.pool_update(request, pool_name, params) location = '/api/zaqar/pools/%s' % new_pool.name response = {'name': new_pool.name, 'uri': new_pool.uri, 'weight': new_pool.weight, 'group': new_pool.group, 'options': new_pool.options} return rest_utils.CreatedResponse(location, response) @urls.register class Pools(generic.View): """API for pools""" url_regex = r'zaqar/pools/$' @rest_utils.ajax() def get(self, request): """Get a list of the Pools for admin. The returned result is an object with property 'items' and each item under this is a pool. """ result = zaqar.pool_list(request) pools = [] for p in result: options = _convert_to_yaml(p.options) pools.append({'id': p.name, 'name': p.name, 'uri': p.uri, 'weight': p.weight, 'group': p.group, 'options': options}) return {'items': pools} @rest_utils.ajax(data_required=True) def delete(self, request): """Delete one or more pool by name. Returns HTTP 204 (no content) on successful deletion. """ for pool_name in request.DATA: zaqar.pool_delete(request, pool_name) @rest_utils.ajax(data_required=True) def put(self, request): """Create a new pool. Returns the new pool object on success. """ request.DATA['options'] = _load_yaml(request.DATA.get('options')) params = request.DATA pool_name = params.pop('name') new_pool = zaqar.pool_create(request, pool_name, params) location = '/api/zaqar/pools/%s' % new_pool.name response = {'name': new_pool.name, 'uri': new_pool.uri, 'weight': new_pool.weight, 'group': new_pool.group, 'options': new_pool.options} return rest_utils.CreatedResponse(location, response) @urls.register class Flavor(generic.View): """API for retrieving a single flavor""" url_regex = r'zaqar/flavors/(?P[^/]+)$' @rest_utils.ajax() def get(self, request, flavor_name): """Get a specific flavor""" flavor = zaqar.flavor_get(request, flavor_name) flavor['id'] = flavor.get('name') flavor['capabilities'] = _convert_to_yaml(flavor.get('capabilities')) return flavor @rest_utils.ajax(data_required=True) def post(self, request, flavor_name): """Update a flavor. Returns the updated flavor object on success. """ capabilities = request.DATA.get('capabilities') request.DATA['capabilities'] = _load_yaml(capabilities) params = request.DATA flavor_name = params.pop('name') new_flavor = zaqar.flavor_update(request, flavor_name, params) location = '/api/zaqar/flavors/%s' % new_flavor.name response = {'name': new_flavor.name, 'pool_group': new_flavor.pool_group, 'capabilities': new_flavor.capabilities} return rest_utils.CreatedResponse(location, response) @urls.register class Flavors(generic.View): """API for flavors""" url_regex = r'zaqar/flavors/$' @rest_utils.ajax() def get(self, request): """Get a list of the Flavors for admin. The returned result is an object with property 'items' and each item under this is a flavor. """ result = zaqar.flavor_list(request) flavors = [] for f in result: capabilities = _convert_to_yaml(f.capabilities) flavors.append({'id': f.name, 'name': f.name, 'pool_group': f.pool_group, 'capabilities': capabilities}) return {'items': flavors} @rest_utils.ajax(data_required=True) def delete(self, request): """Delete one or more flavor by name. Returns HTTP 204 (no content) on successful deletion. """ for flavor_name in request.DATA: zaqar.flavor_delete(request, flavor_name) @rest_utils.ajax(data_required=True) def put(self, request): """Create a new flavor. Returns the new flavor object on success. """ capabilities = request.DATA.get('capabilities') request.DATA['capabilities'] = _load_yaml(capabilities) params = request.DATA flavor_name = params.pop('name') new_flavor = zaqar.flavor_create(request, flavor_name, params) location = '/api/zaqar/flavors/%s' % new_flavor.name response = {'name': new_flavor.name, 'pool_group': new_flavor.pool_group, 'capabilities': new_flavor.capabilities} return rest_utils.CreatedResponse(location, response)