Fix 500 error when create pools in wsgi v2.

When create a pool with a url which is already exist in db,
pymongo will raise a DuplicateKeyError error. Zaqar-wsgi
don't catch it.

APIImpact

Change-Id: I487a372533c5e8de9edd5796e0039320d2d55b6a
Closes-bug: #1540246
This commit is contained in:
wangxiyuan 2016-02-01 15:45:33 +08:00
parent 9b77a5bd78
commit ad47f1bcfc
6 changed files with 43 additions and 12 deletions

View File

@ -191,3 +191,8 @@ class PoolCapabilitiesMismatch(ExceptionBase):
msg_format = (u'The pool being added does not ' msg_format = (u'The pool being added does not '
u'support the minimum set of capabilities') u'support the minimum set of capabilities')
class PoolAlreadyExists(Conflict):
msg_format = u'The database URI is in use by another pool.'

View File

@ -23,6 +23,7 @@ Schema:
""" """
import functools import functools
from pymongo import errors as mongo_error
from zaqar.common import utils as common_utils from zaqar.common import utils as common_utils
from zaqar.storage import base from zaqar.storage import base
@ -97,13 +98,16 @@ class PoolsController(base.PoolsBase):
@utils.raises_conn_error @utils.raises_conn_error
def _create(self, name, weight, uri, group=None, options=None): def _create(self, name, weight, uri, group=None, options=None):
options = {} if options is None else options options = {} if options is None else options
self._col.update({'n': name}, try:
{'$set': {'n': name, self._col.update({'n': name},
'w': weight, {'$set': {'n': name,
'u': uri, 'w': weight,
'g': group, 'u': uri,
'o': options}}, 'g': group,
upsert=True) 'o': options}},
upsert=True)
except mongo_error.DuplicateKeyError:
raise errors.PoolAlreadyExists()
@utils.raises_conn_error @utils.raises_conn_error
def _exists(self, name): def _exists(self, name):

View File

@ -528,6 +528,13 @@ class MongodbPoolsTests(base.PoolsControllerTest):
group=self.pool_group, group=self.pool_group,
options={}) options={})
def test_duplicate_uri(self):
with testing.expect(errors.PoolAlreadyExists):
# The url 'localhost' is used in setUp(). So reusing the uri
# 'localhost' here will raise PoolAlreadyExists.
self.pools_controller.create(str(uuid.uuid1()), 100, 'localhost',
group=str(uuid.uuid1()), options={})
@testing.requires_mongodb @testing.requires_mongodb
class MongodbCatalogueTests(base.CatalogueControllerTest): class MongodbCatalogueTests(base.CatalogueControllerTest):

View File

@ -38,9 +38,11 @@ registered, there is an optional field::
import falcon import falcon
import jsonschema import jsonschema
from oslo_log import log from oslo_log import log
import six
from zaqar.common.api.schemas import pools as schema from zaqar.common.api.schemas import pools as schema
from zaqar.common import utils as common_utils from zaqar.common import utils as common_utils
from zaqar.i18n import _
from zaqar.storage import errors from zaqar.storage import errors
from zaqar.storage import utils as storage_utils from zaqar.storage import utils as storage_utils
from zaqar.transport import utils as transport_utils from zaqar.transport import utils as transport_utils
@ -171,11 +173,16 @@ class Resource(object):
raise wsgi_errors.HTTPBadRequestBody( raise wsgi_errors.HTTPBadRequestBody(
'cannot connect to %s' % data['uri'] 'cannot connect to %s' % data['uri']
) )
self._ctrl.create(pool, weight=data['weight'], try:
uri=data['uri'], self._ctrl.create(pool, weight=data['weight'],
options=data.get('options', {})) uri=data['uri'],
response.status = falcon.HTTP_201 options=data.get('options', {}))
response.location = request.path response.status = falcon.HTTP_201
response.location = request.path
except errors.PoolAlreadyExists as e:
LOG.exception(e)
title = _(u'Unable to create pool')
raise falcon.HTTPConflict(title, six.text_type(e))
def on_delete(self, request, response, project_id, pool): def on_delete(self, request, response, project_id, pool):
"""Deregisters a pool. """Deregisters a pool.

View File

@ -186,6 +186,10 @@ class Resource(object):
LOG.exception(e) LOG.exception(e)
title = _(u'Unable to create pool') title = _(u'Unable to create pool')
raise falcon.HTTPBadRequest(title, six.text_type(e)) raise falcon.HTTPBadRequest(title, six.text_type(e))
except errors.PoolAlreadyExists as e:
LOG.exception(e)
title = _(u'Unable to create pool')
raise falcon.HTTPConflict(title, six.text_type(e))
def on_delete(self, request, response, project_id, pool): def on_delete(self, request, response, project_id, pool):
"""Deregisters a pool. """Deregisters a pool.

View File

@ -190,6 +190,10 @@ class Resource(object):
LOG.exception(e) LOG.exception(e)
title = _(u'Unable to create pool') title = _(u'Unable to create pool')
raise falcon.HTTPBadRequest(title, six.text_type(e)) raise falcon.HTTPBadRequest(title, six.text_type(e))
except errors.PoolAlreadyExists as e:
LOG.exception(e)
title = _(u'Unable to create pool')
raise falcon.HTTPConflict(title, six.text_type(e))
@acl.enforce("pools:delete") @acl.enforce("pools:delete")
def on_delete(self, request, response, project_id, pool): def on_delete(self, request, response, project_id, pool):