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

View File

@ -528,6 +528,13 @@ class MongodbPoolsTests(base.PoolsControllerTest):
group=self.pool_group,
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
class MongodbCatalogueTests(base.CatalogueControllerTest):

View File

@ -38,9 +38,11 @@ registered, there is an optional field::
import falcon
import jsonschema
from oslo_log import log
import six
from zaqar.common.api.schemas import pools as schema
from zaqar.common import utils as common_utils
from zaqar.i18n import _
from zaqar.storage import errors
from zaqar.storage import utils as storage_utils
from zaqar.transport import utils as transport_utils
@ -171,11 +173,16 @@ class Resource(object):
raise wsgi_errors.HTTPBadRequestBody(
'cannot connect to %s' % data['uri']
)
self._ctrl.create(pool, weight=data['weight'],
uri=data['uri'],
options=data.get('options', {}))
response.status = falcon.HTTP_201
response.location = request.path
try:
self._ctrl.create(pool, weight=data['weight'],
uri=data['uri'],
options=data.get('options', {}))
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):
"""Deregisters a pool.

View File

@ -186,6 +186,10 @@ class Resource(object):
LOG.exception(e)
title = _(u'Unable to create pool')
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):
"""Deregisters a pool.

View File

@ -190,6 +190,10 @@ class Resource(object):
LOG.exception(e)
title = _(u'Unable to create pool')
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")
def on_delete(self, request, response, project_id, pool):