Merge "Not permitted to delete pools which are used by flavor"

This commit is contained in:
Jenkins 2014-09-16 09:25:26 +00:00 committed by Gerrit Code Review
commit f218b60475
5 changed files with 61 additions and 2 deletions

View File

@ -395,10 +395,19 @@ class MongodbPoolsTests(base.PoolsControllerTest):
def setUp(self):
super(MongodbPoolsTests, self).setUp()
self.load_conf('wsgi_mongodb.conf')
self.flavors_controller = self.driver.flavors_controller
def tearDown(self):
super(MongodbPoolsTests, self).tearDown()
def test_delete_pool_used_by_flavor(self):
self.flavors_controller.create('durable', self.pool,
project=self.project,
capabilities={})
with testing.expect(errors.PoolInUseByFlavor):
self.pools_controller.delete(self.pool)
@testing.requires_mongodb
class MongodbCatalogueTests(base.CatalogueControllerTest):

View File

@ -163,3 +163,16 @@ class NoPoolFound(ExceptionBase):
def __init__(self):
super(NoPoolFound, self).__init__()
class PoolInUseByFlavor(NotPermitted):
msg_format = u'Pool {pid} is in use by flavor {fid}'
def __init__(self, pid, fid):
super(PoolInUseByFlavor, self).__init__(pid=pid, fid=fid)
self._flavor = fid
@property
def flavor(self):
return self._flavor

View File

@ -31,6 +31,10 @@ FLAVORS_INDEX = [
('n', 1),
]
FLAVORS_STORAGE_POOL_INDEX = [
('s', 1)
]
# NOTE(cpp-cabrera): used for get/list operations. There's no need to
# show the marker or the _id - they're implementation details.
OMIT_FIELDS = (('_id', False),)
@ -50,9 +54,21 @@ class FlavorsController(base.FlavorsBase):
background=True,
name='flavors_name',
unique=True)
self._col.ensure_index(FLAVORS_STORAGE_POOL_INDEX,
background=True,
name='flavors_storage_pool_name')
self._pools_ctrl = self.driver.pools_controller
@utils.raises_conn_error
def _list_by_pool(self, pool, limit=10, detailed=False):
query = {'s': pool}
cursor = self._col.find(query, fields=_field_spec(detailed),
limit=limit).sort('n', 1)
normalizer = functools.partial(_normalize, detailed=detailed)
return utils.HookedCursor(cursor, normalizer)
@utils.raises_conn_error
def list(self, project=None, marker=None, limit=10, detailed=False):
query = {'p': project}

View File

@ -100,6 +100,16 @@ class PoolsController(base.PoolsBase):
@utils.raises_conn_error
def delete(self, name):
# NOTE(wpf): Initializing the Flavors controller here instead of
# doing so in __init__ is required to avoid falling in a maximum
# recursion error.
flavor_ctl = self.driver.flavors_controller
res = list(flavor_ctl._list_by_pool(name))
if res:
flavors = ', '.join([x['name'] for x in res])
raise errors.PoolInUseByFlavor(name, flavors)
self._col.remove({'n': name}, w=0)
@utils.raises_conn_error

View File

@ -41,6 +41,7 @@ import jsonschema
from zaqar.common.schemas import pools as schema
from zaqar.common import utils as common_utils
from zaqar.i18n import _
from zaqar.openstack.common import log
from zaqar.queues.storage import errors
from zaqar.queues.storage import utils as storage_utils
@ -165,11 +166,21 @@ class Resource(object):
def on_delete(self, request, response, project_id, pool):
"""Deregisters a pool.
:returns: HTTP | 204
:returns: HTTP | [204, 403]
"""
LOG.debug(u'DELETE pool - name: %s', pool)
self._ctrl.delete(pool)
try:
self._ctrl.delete(pool)
except errors.PoolInUseByFlavor as ex:
LOG.exception(ex)
title = _(u'Unable to delete')
description = _(u'This pool is used by flavors {flavor}; '
u'It cannot be deleted.')
description = description.format(flavor=ex.flavor)
raise falcon.HTTPForbidden(title, description)
response.status = falcon.HTTP_204
def on_patch(self, request, response, project_id, pool):