Add REST APIs for pools and flavors

This patch adds REST APIs for storage pools and pool flavors.
And this includes AngularJS services for these REST APIs.

Change-Id: Ideb3847f6192afb9c99891f8bf4d68da11988214
Partial-Implements: blueprint support-pool
Partial-Implements: blueprint support-pool-flavor
This commit is contained in:
Shu Muto 2016-12-14 15:58:36 +09:00
parent e524400286
commit 61b638e722
3 changed files with 306 additions and 4 deletions

View File

@ -12,12 +12,34 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
import yaml
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
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.load(data)
except Exception as ex:
raise Exception(_('The specified input is not a valid '
'YAML format: %s') % six.text_type(ex))
return loaded_data
@urls.register
@ -128,3 +150,167 @@ class Subscription(generic.View):
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<pool_name>[^/]+)$'
@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<flavor_name>[^/]+)$'
@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)

View File

@ -108,3 +108,55 @@ def subscription_update(request, queue_name, old_data, new_data):
subscription = zaqarclient(request).subscription(queue_name, **old_data)
subscription.update(new_data)
return subscription
def pool_list(request, limit=None, marker=None):
return zaqarclient(request).pools(limit=limit,
marker=marker,
detailed=True)
def pool_create(request, pool_name, params):
pool = zaqarclient(request).pool(pool_name, **params)
return pool
def pool_delete(request, pool_name):
pool = zaqarclient(request).pool(pool_name, auto_create=False)
pool.delete()
def pool_update(request, pool_name, params):
pool = zaqarclient(request).pool(pool_name, auto_create=False)
pool.update(params)
return pool
def pool_get(request, pool_name):
return zaqarclient(request).pool(pool_name, auto_create=False).get()
def flavor_list(request, limit=None, marker=None):
return zaqarclient(request).flavors(limit=limit,
marker=marker,
detailed=True)
def flavor_create(request, flavor_name, params):
flavor = zaqarclient(request).flavor(flavor_name, **params)
return flavor
def flavor_delete(request, flavor_name):
flavor = zaqarclient(request).flavor(flavor_name, auto_create=False)
flavor.delete()
def flavor_update(request, flavor_name, params):
flavor = zaqarclient(request).flavor(flavor_name, auto_create=False)
flavor.update(params)
return flavor
def flavor_get(request, flavor_name):
return zaqarclient(request).flavor(flavor_name, auto_create=False).get()

View File

@ -30,6 +30,8 @@
var queuePath = '/api/zaqar/queues/';
var subPath = '/api/zaqar/queues/%s/subscriptions/';
var poolPath = '/api/zaqar/pools/';
var flavorPath = '/api/zaqar/flavors/';
var service = {
getQueues: getQueues,
@ -38,7 +40,17 @@
updateQueue: updateQueue,
getSubscriptions: getSubscriptions,
addSubscription: addSubscription,
deleteSubscription: deleteSubscription
deleteSubscription: deleteSubscription,
getPools: getPools,
getPool: getPool,
createPool: createPool,
deletePool: deletePool,
updatePool: updatePool,
getFlavors: getFlavors,
getFlavor: getFlavor,
createFlavor: createFlavor,
deleteFlavor: deleteFlavor,
updateFlavor: updateFlavor
};
return service;
@ -83,6 +95,58 @@
return apiService.delete(url, subscription).error(error(msg));
}
function getPools() {
var msg = gettext('Unable to retrieve the pools.');
return apiService.get(poolPath).error(error(msg));
}
function getPool(poolName) {
var msg = gettext('Unable to retrieve the pool.');
var url = poolPath + poolName;
return apiService.get(url).error(error(msg));
}
function createPool(newPool) {
var msg = gettext('Unable to create the pool.');
return apiService.put(poolPath, newPool).error(error(msg));
}
function deletePool(poolName) {
return apiService.delete(poolPath, [poolName]);
}
function updatePool(pool) {
var msg = gettext('Unable to update the pool.');
var url = poolPath + pool.name;
return apiService.post(url, pool).error(error(msg));
}
function getFlavors() {
var msg = gettext('Unable to retrieve the flavors.');
return apiService.get(flavorPath).error(error(msg));
}
function getFlavor(flavorName) {
var msg = gettext('Unable to retrieve the flavor.');
var url = flavorPath + flavorName;
return apiService.get(url).error(error(msg));
}
function createFlavor(newFlavor) {
var msg = gettext('Unable to create the flavor.');
return apiService.put(flavorPath, newFlavor).error(error(msg));
}
function deleteFlavor(flavorName) {
return apiService.delete(flavorPath, [flavorName]);
}
function updateFlavor(flavor) {
var msg = gettext('Unable to update the flavor.');
var url = flavorPath + flavor.name;
return apiService.post(url, flavor).error(error(msg));
}
function error(message) {
return function() {
toast.add('error', message);