From: Luis A. Garcia Date: Mon, 19 Aug 2013 20:19:57 +0000 (+0000) Subject: Avoid serializing CinderExceptions before they are translated X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=2bec15e185e844dff757e09fa72a3b61d91e5f96;p=openstack-build%2Fcinder-build.git Avoid serializing CinderExceptions before they are translated CinderExceptions were being unicode()'d when being wrapped in an HTTPException, and this was causing the delayed translation to fail for those errors. Also, CinderExceptions have a 'message' class attribute that holds the generic error message template, e.g. "Backup %(backup_id)s is not found", unfortunately, because the names are the same, it was overshadowing the actual exception instance 'message', e.g. "Backup 1 is not found", when translating. This patch puts the exception's actual message in a new field called 'msg'. Fixes Bug: #1214102 Change-Id: Ied9abcc3d05454852c0a5891432eb181220a744e --- diff --git a/cinder/api/contrib/backups.py b/cinder/api/contrib/backups.py index 6c67b2db7..e284baa29 100644 --- a/cinder/api/contrib/backups.py +++ b/cinder/api/contrib/backups.py @@ -131,7 +131,7 @@ class BackupsController(wsgi.Controller): try: backup = self.backup_api.get(context, backup_id=id) except exception.BackupNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) return self._view_builder.detail(req, backup) @@ -145,9 +145,9 @@ class BackupsController(wsgi.Controller): try: self.backup_api.delete(context, id) except exception.BackupNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) except exception.InvalidBackup as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) return webob.Response(status_int=202) @@ -207,11 +207,11 @@ class BackupsController(wsgi.Controller): new_backup = self.backup_api.create(context, name, description, volume_id, container) except exception.InvalidVolume as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.VolumeNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) except exception.ServiceNotFound as error: - raise exc.HTTPInternalServerError(explanation=unicode(error)) + raise exc.HTTPInternalServerError(explanation=error.msg) retval = self._view_builder.summary(req, dict(new_backup.iteritems())) return retval @@ -244,21 +244,21 @@ class BackupsController(wsgi.Controller): backup_id=id, volume_id=volume_id) except exception.InvalidInput as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolume as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidBackup as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.BackupNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge( - explanation=error.message, headers={'Retry-After': 0}) + explanation=error.msg, headers={'Retry-After': 0}) except exception.VolumeLimitExceeded as error: raise exc.HTTPRequestEntityTooLarge( - explanation=error.message, headers={'Retry-After': 0}) + explanation=error.msg, headers={'Retry-After': 0}) retval = self._view_builder.restore_summary( req, dict(new_restore.iteritems())) diff --git a/cinder/api/contrib/types_extra_specs.py b/cinder/api/contrib/types_extra_specs.py index 0887c912f..95314db4f 100644 --- a/cinder/api/contrib/types_extra_specs.py +++ b/cinder/api/contrib/types_extra_specs.py @@ -64,7 +64,7 @@ class VolumeTypeExtraSpecsController(wsgi.Controller): try: volume_types.get_volume_type(context, type_id) except exception.NotFound as ex: - raise webob.exc.HTTPNotFound(explanation=unicode(ex)) + raise webob.exc.HTTPNotFound(explanation=ex.msg) @wsgi.serializers(xml=VolumeTypeExtraSpecsTemplate) def index(self, req, type_id): @@ -138,7 +138,7 @@ class VolumeTypeExtraSpecsController(wsgi.Controller): try: db.volume_type_extra_specs_delete(context, type_id, id) except exception.VolumeTypeExtraSpecsNotFound as error: - raise webob.exc.HTTPNotFound(explanation=unicode(error)) + raise webob.exc.HTTPNotFound(explanation=error.msg) notifier_info = dict(type_id=type_id, id=id) notifier_api.notify(context, 'volumeTypeExtraSpecs', diff --git a/cinder/api/contrib/volume_actions.py b/cinder/api/contrib/volume_actions.py index 63d45246b..7bec44930 100644 --- a/cinder/api/contrib/volume_actions.py +++ b/cinder/api/contrib/volume_actions.py @@ -183,7 +183,7 @@ class VolumeActionsController(wsgi.Controller): try: volume = self.volume_api.get(context, id) except exception.VolumeNotFound as error: - raise webob.exc.HTTPNotFound(explanation=unicode(error)) + raise webob.exc.HTTPNotFound(explanation=error.msg) authorize(context, "upload_image") image_metadata = {"container_format": params.get("container_format", "bare"), @@ -195,7 +195,7 @@ class VolumeActionsController(wsgi.Controller): image_metadata, force) except exception.InvalidVolume as error: - raise webob.exc.HTTPBadRequest(explanation=unicode(error)) + raise webob.exc.HTTPBadRequest(explanation=error.msg) except ValueError as error: raise webob.exc.HTTPBadRequest(explanation=unicode(error)) except rpc_common.RemoteError as error: diff --git a/cinder/api/contrib/volume_transfer.py b/cinder/api/contrib/volume_transfer.py index e21cd05f2..a400f05ef 100644 --- a/cinder/api/contrib/volume_transfer.py +++ b/cinder/api/contrib/volume_transfer.py @@ -113,7 +113,7 @@ class VolumeTransferController(wsgi.Controller): try: transfer = self.transfer_api.get(context, transfer_id=id) except exception.TransferNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) return self._view_builder.detail(req, transfer) @@ -168,9 +168,9 @@ class VolumeTransferController(wsgi.Controller): try: new_transfer = self.transfer_api.create(context, volume_id, name) except exception.InvalidVolume as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.VolumeNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) transfer = self._view_builder.create(req, dict(new_transfer.iteritems())) @@ -203,9 +203,9 @@ class VolumeTransferController(wsgi.Controller): auth_key) except exception.VolumeSizeExceedsAvailableQuota as error: raise exc.HTTPRequestEntityTooLarge( - explanation=error.message, headers={'Retry-After': 0}) + explanation=error.msg, headers={'Retry-After': 0}) except exception.InvalidVolume as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) transfer = \ self._view_builder.summary(req, @@ -221,7 +221,7 @@ class VolumeTransferController(wsgi.Controller): try: self.transfer_api.delete(context, transfer_id=id) except exception.TransferNotFound as error: - raise exc.HTTPNotFound(explanation=unicode(error)) + raise exc.HTTPNotFound(explanation=error.msg) return webob.Response(status_int=202) diff --git a/cinder/api/contrib/volume_type_encryption.py b/cinder/api/contrib/volume_type_encryption.py index aede70f9f..d8aed1575 100644 --- a/cinder/api/contrib/volume_type_encryption.py +++ b/cinder/api/contrib/volume_type_encryption.py @@ -55,7 +55,7 @@ class VolumeTypeEncryptionController(wsgi.Controller): try: volume_types.get_volume_type(context, type_id) except exception.NotFound as ex: - raise webob.exc.HTTPNotFound(explanation=unicode(ex)) + raise webob.exc.HTTPNotFound(explanation=ex.msg) def _check_encryption_input(self, encryption, create=True): if 'key_size' in encryption.keys(): diff --git a/cinder/api/openstack/wsgi.py b/cinder/api/openstack/wsgi.py index 89a4356ae..5ce6f76f3 100644 --- a/cinder/api/openstack/wsgi.py +++ b/cinder/api/openstack/wsgi.py @@ -588,11 +588,10 @@ class ResourceExceptionHandler(object): return True if isinstance(ex_value, exception.NotAuthorized): - msg = unicode(ex_value) - raise Fault(webob.exc.HTTPForbidden(explanation=msg)) + raise Fault(webob.exc.HTTPForbidden(explanation=ex_value.msg)) elif isinstance(ex_value, exception.Invalid): raise Fault(exception.ConvertedException( - code=ex_value.code, explanation=unicode(ex_value))) + code=ex_value.code, explanation=ex_value.msg)) elif isinstance(ex_value, TypeError): exc_info = (ex_type, ex_value, ex_traceback) LOG.error(_( diff --git a/cinder/api/v1/snapshot_metadata.py b/cinder/api/v1/snapshot_metadata.py index 32922c4b2..9328d138b 100644 --- a/cinder/api/v1/snapshot_metadata.py +++ b/cinder/api/v1/snapshot_metadata.py @@ -124,10 +124,10 @@ class Controller(object): raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidVolumeMetadata as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolumeMetadataSize as error: - raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error)) + raise exc.HTTPRequestEntityTooLarge(explanation=error.msg) @wsgi.serializers(xml=common.MetaItemTemplate) def show(self, req, snapshot_id, id): diff --git a/cinder/api/v1/volume_metadata.py b/cinder/api/v1/volume_metadata.py index 7065dfa3f..645897745 100644 --- a/cinder/api/v1/volume_metadata.py +++ b/cinder/api/v1/volume_metadata.py @@ -124,10 +124,10 @@ class Controller(object): raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidVolumeMetadata as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolumeMetadataSize as error: - raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error)) + raise exc.HTTPRequestEntityTooLarge(explanation=error.msg) @wsgi.serializers(xml=common.MetaItemTemplate) def show(self, req, volume_id, id): diff --git a/cinder/api/v2/snapshot_metadata.py b/cinder/api/v2/snapshot_metadata.py index 32922c4b2..9328d138b 100644 --- a/cinder/api/v2/snapshot_metadata.py +++ b/cinder/api/v2/snapshot_metadata.py @@ -124,10 +124,10 @@ class Controller(object): raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidVolumeMetadata as error: - raise exc.HTTPBadRequest(explanation=unicode(error)) + raise exc.HTTPBadRequest(explanation=error.msg) except exception.InvalidVolumeMetadataSize as error: - raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error)) + raise exc.HTTPRequestEntityTooLarge(explanation=error.msg) @wsgi.serializers(xml=common.MetaItemTemplate) def show(self, req, snapshot_id, id): diff --git a/cinder/exception.py b/cinder/exception.py index 6af8a2d87..1d6141345 100644 --- a/cinder/exception.py +++ b/cinder/exception.py @@ -119,8 +119,15 @@ class CinderException(Exception): # at least get the core message out if something happened message = self.message + # NOTE(luisg): We put the actual message in 'msg' so that we can access + # it, because if we try to access the message via 'message' it will be + # overshadowed by the class' message attribute + self.msg = message super(CinderException, self).__init__(message) + def __unicode__(self): + return unicode(self.msg) + class GlanceConnectionFailed(CinderException): message = _("Connection to glance failed") + ": %(reason)s" diff --git a/cinder/tests/api/contrib/test_backups.py b/cinder/tests/api/contrib/test_backups.py index a7c5c73fd..fdc57aabc 100644 --- a/cinder/tests/api/contrib/test_backups.py +++ b/cinder/tests/api/contrib/test_backups.py @@ -914,8 +914,7 @@ class BackupsAPITestCase(test.TestCase): self.assertEqual(res.status_int, 413) self.assertEqual(res_dict['overLimit']['code'], 413) self.assertEqual(res_dict['overLimit']['message'], - 'Maximum number of volumes allowed ' - '(%(allowed)d) exceeded') + 'Maximum number of volumes allowed (1) exceeded') def test_restore_backup_to_undersized_volume(self): backup_size = 10