Glance to handle exceptions from glance_store
After the split glance_store raises its own exceptions, that have the same names as in glance. Several times those exceptions aren't caught in glance and it leads to incorrect behaviour. This code fixed it. Change-Id: I8600e0813ecbc599b5411e1fc0d0c9b470f68f6b Closes-Bug: #1469817
This commit is contained in:
parent
d4cf5a015b
commit
3fc57a4e0a
|
@ -93,3 +93,8 @@ class BaseController(object):
|
|||
raise webob.exc.HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type='text/plain')
|
||||
except store.NotFound:
|
||||
msg = _("Data for image_id not found: %s") % image_id
|
||||
raise webob.exc.HTTPNotFound(explanation=msg,
|
||||
request=req,
|
||||
content_type='text/plain')
|
||||
|
|
|
@ -679,7 +679,7 @@ class Controller(controller.BaseController):
|
|||
return image_meta_data
|
||||
except exception.Duplicate:
|
||||
with excutils.save_and_reraise_exception():
|
||||
# Delete image data since it has been supersceded by another
|
||||
# Delete image data since it has been superseded by another
|
||||
# upload and re-raise.
|
||||
LOG.debug("duplicate operation - deleting image data for "
|
||||
" %(id)s (location:%(location)s)" %
|
||||
|
@ -715,18 +715,19 @@ class Controller(controller.BaseController):
|
|||
image_id,
|
||||
location_data,
|
||||
from_state='saving')
|
||||
except Exception as e:
|
||||
except exception.Duplicate:
|
||||
raise
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
if not isinstance(e, exception.Duplicate):
|
||||
# NOTE(zhiyan): Delete image data since it has already
|
||||
# been added to store by above _upload() call.
|
||||
LOG.warn(_LW("Failed to activate image %s in "
|
||||
"registry. About to delete image "
|
||||
"bits from store and update status "
|
||||
"to 'killed'.") % image_id)
|
||||
upload_utils.initiate_deletion(req, location_data,
|
||||
image_id)
|
||||
upload_utils.safe_kill(req, image_id, 'saving')
|
||||
# NOTE(zhiyan): Delete image data since it has already
|
||||
# been added to store by above _upload() call.
|
||||
LOG.warn(_LW("Failed to activate image %s in "
|
||||
"registry. About to delete image "
|
||||
"bits from store and update status "
|
||||
"to 'killed'.") % image_id)
|
||||
upload_utils.initiate_deletion(req, location_data,
|
||||
image_id)
|
||||
upload_utils.safe_kill(req, image_id, 'saving')
|
||||
else:
|
||||
image_meta = None
|
||||
|
||||
|
@ -1130,7 +1131,7 @@ class Controller(controller.BaseController):
|
|||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
except store.InUseByStore as e:
|
||||
msg = (_("Image %(id)s could not be deleted because it is in use: "
|
||||
"%(exc)s")
|
||||
% {"id": id, "exc": encodeutils.exception_to_unicode(e)})
|
||||
|
|
|
@ -196,7 +196,7 @@ def upload_data_to_store(req, image_meta, image_data, store, notifier):
|
|||
raise webob.exc.HTTPGone(explanation=msg, request=req,
|
||||
content_type='text/plain')
|
||||
|
||||
except exception.Duplicate as e:
|
||||
except (store_api.Duplicate, exception.Duplicate) as e:
|
||||
msg = (_("Attempt to upload duplicate image: %s") %
|
||||
encodeutils.exception_to_unicode(e))
|
||||
LOG.warn(msg)
|
||||
|
|
|
@ -155,7 +155,7 @@ class ImagesController(object):
|
|||
image_repo.save(image)
|
||||
except exception.NotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
except exception.Invalid as e:
|
||||
except (exception.Invalid, exception.BadStoreUri) as e:
|
||||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
except exception.Forbidden as e:
|
||||
LOG.debug("User not permitted to update image '%s'", image_id)
|
||||
|
@ -232,15 +232,15 @@ class ImagesController(object):
|
|||
image = image_repo.get(image_id)
|
||||
image.delete()
|
||||
image_repo.remove(image)
|
||||
except exception.Forbidden as e:
|
||||
except (glance_store.Forbidden, exception.Forbidden) as e:
|
||||
LOG.debug("User not permitted to delete image '%s'", image_id)
|
||||
raise webob.exc.HTTPForbidden(explanation=e.msg)
|
||||
except exception.NotFound as e:
|
||||
except (glance_store.NotFound, exception.NotFound) as e:
|
||||
msg = (_("Failed to find image %(image_id)s to delete") %
|
||||
{'image_id': image_id})
|
||||
LOG.warn(msg)
|
||||
raise webob.exc.HTTPNotFound(explanation=msg)
|
||||
except exception.InUseByStore as e:
|
||||
except glance_store.exceptions.InUseByStore as e:
|
||||
msg = (_("Image %(id)s could not be deleted "
|
||||
"because it is in use: %(exc)s") %
|
||||
{"id": image_id,
|
||||
|
|
|
@ -163,6 +163,8 @@ class ArtifactsController(object):
|
|||
raise webob.exc.HTTPConflict(explanation=dupex.msg)
|
||||
except exception.Invalid as e:
|
||||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
except exception.NotAuthenticated as e:
|
||||
raise webob.exc.HTTPUnauthorized(explanation=e.msg)
|
||||
|
||||
@utils.mutating
|
||||
def update_property(self, req, id, type_name, type_version, path, data,
|
||||
|
@ -191,6 +193,8 @@ class ArtifactsController(object):
|
|||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
except exception.NotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
except exception.NotAuthenticated as e:
|
||||
raise webob.exc.HTTPUnauthorized(explanation=e.msg)
|
||||
|
||||
@utils.mutating
|
||||
def update(self, req, id, type_name, type_version, changes, **kwargs):
|
||||
|
@ -223,6 +227,8 @@ class ArtifactsController(object):
|
|||
except exception.LimitExceeded as e:
|
||||
raise webob.exc.HTTPRequestEntityTooLarge(
|
||||
explanation=e.msg, request=req, content_type='text/plain')
|
||||
except exception.NotAuthenticated as e:
|
||||
raise webob.exc.HTTPUnauthorized(explanation=e.msg)
|
||||
|
||||
@utils.mutating
|
||||
def delete(self, req, id, type_name, type_version, **kwargs):
|
||||
|
@ -234,16 +240,18 @@ class ArtifactsController(object):
|
|||
artifact_repo.remove(artifact)
|
||||
except exception.Invalid as e:
|
||||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
except exception.Forbidden as e:
|
||||
except (glance_store.Forbidden, exception.Forbidden) as e:
|
||||
raise webob.exc.HTTPForbidden(explanation=e.msg)
|
||||
except exception.NotFound as e:
|
||||
except (glance_store.NotFound, exception.NotFound) as e:
|
||||
msg = (_("Failed to find artifact %(artifact_id)s to delete") %
|
||||
{'artifact_id': id})
|
||||
raise webob.exc.HTTPNotFound(explanation=msg)
|
||||
except exception.InUseByStore as e:
|
||||
except glance_store.exceptions.InUseByStore as e:
|
||||
msg = (_("Artifact %s could not be deleted "
|
||||
"because it is in use: %s") % (id, e.msg)) # noqa
|
||||
raise webob.exc.HTTPConflict(explanation=msg)
|
||||
except exception.NotAuthenticated as e:
|
||||
raise webob.exc.HTTPUnauthorized(explanation=e.msg)
|
||||
|
||||
@utils.mutating
|
||||
def publish(self, req, id, type_name, type_version, **kwargs):
|
||||
|
@ -259,6 +267,8 @@ class ArtifactsController(object):
|
|||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
except exception.Invalid as e:
|
||||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
except exception.NotAuthenticated as e:
|
||||
raise webob.exc.HTTPUnauthorized(explanation=e.msg)
|
||||
|
||||
def _upload_list_property(self, method, blob_list, index, data, size):
|
||||
if method == 'PUT' and not index and len(blob_list) > 0:
|
||||
|
@ -281,6 +291,7 @@ class ArtifactsController(object):
|
|||
def upload(self, req, id, type_name, type_version, attr, size, data,
|
||||
index, **kwargs):
|
||||
artifact_repo = self.gateway.get_artifact_repo(req.context)
|
||||
artifact = None
|
||||
try:
|
||||
artifact = self._get_artifact_with_dependencies(artifact_repo,
|
||||
id,
|
||||
|
@ -302,16 +313,82 @@ class ArtifactsController(object):
|
|||
artifact_repo.save(artifact)
|
||||
return artifact
|
||||
|
||||
except ValueError as e:
|
||||
LOG.debug("Cannot save data for artifact %(id)s: %(e)s",
|
||||
{'id': id, 'e': utils.exception_to_str(e)})
|
||||
self._restore(artifact_repo, artifact)
|
||||
raise webob.exc.HTTPBadRequest(
|
||||
explanation=utils.exception_to_str(e))
|
||||
|
||||
except glance_store.StoreAddDisabled:
|
||||
msg = _("Error in store configuration. Adding artifacts to store "
|
||||
"is disabled.")
|
||||
LOG.exception(msg)
|
||||
self._restore(artifact_repo, artifact)
|
||||
raise webob.exc.HTTPGone(explanation=msg, request=req,
|
||||
content_type='text/plain')
|
||||
|
||||
except (glance_store.Duplicate,
|
||||
exception.InvalidImageStatusTransition) as e:
|
||||
msg = utils.exception_to_str(e)
|
||||
LOG.exception(msg)
|
||||
raise webob.exc.HTTPConflict(explanation=e.msg, request=req)
|
||||
|
||||
except exception.Forbidden as e:
|
||||
raise webob.exc.HTTPForbidden(explanation=e.msg)
|
||||
msg = ("Not allowed to upload data for artifact %s" %
|
||||
id)
|
||||
LOG.debug(msg)
|
||||
raise webob.exc.HTTPForbidden(explanation=msg, request=req)
|
||||
|
||||
except exception.NotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
except exception.Invalid as e:
|
||||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
except Exception as e:
|
||||
# TODO(mfedosin): add more exception handlers here
|
||||
|
||||
except glance_store.StorageFull as e:
|
||||
msg = _("Artifact storage media "
|
||||
"is full: %s") % utils.exception_to_str(e)
|
||||
LOG.error(msg)
|
||||
self._restore(artifact_repo, artifact)
|
||||
raise webob.exc.HTTPRequestEntityTooLarge(explanation=msg,
|
||||
request=req)
|
||||
|
||||
except exception.StorageQuotaFull as e:
|
||||
msg = _("Artifact exceeds the storage "
|
||||
"quota: %s") % utils.exception_to_str(e)
|
||||
LOG.error(msg)
|
||||
self._restore(artifact_repo, artifact)
|
||||
raise webob.exc.HTTPRequestEntityTooLarge(explanation=msg,
|
||||
request=req)
|
||||
|
||||
except exception.ImageSizeLimitExceeded as e:
|
||||
msg = _("The incoming artifact blob is "
|
||||
"too large: %s") % utils.exception_to_str(e)
|
||||
LOG.error(msg)
|
||||
self._restore(artifact_repo, artifact)
|
||||
raise webob.exc.HTTPRequestEntityTooLarge(explanation=msg,
|
||||
request=req)
|
||||
|
||||
except glance_store.StorageWriteDenied as e:
|
||||
msg = _("Insufficient permissions on artifact "
|
||||
"storage media: %s") % utils.exception_to_str(e)
|
||||
LOG.error(msg)
|
||||
self._restore(artifact_repo, artifact)
|
||||
raise webob.exc.HTTPServiceUnavailable(explanation=msg,
|
||||
request=req)
|
||||
|
||||
except webob.exc.HTTPGone as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE("Failed to upload image data due to "
|
||||
LOG.error(_LE("Failed to upload artifact blob data due to"
|
||||
" HTTP error"))
|
||||
|
||||
except webob.exc.HTTPError as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Failed to upload artifact blob data due to HTTP"
|
||||
" error"))
|
||||
self._restore(artifact_repo, artifact)
|
||||
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE("Failed to upload artifact blob data due to "
|
||||
"internal error"))
|
||||
self._restore(artifact_repo, artifact)
|
||||
|
||||
|
@ -340,9 +417,9 @@ class ArtifactsController(object):
|
|||
raise webob.exc.HTTPBadRequest(explanation=message)
|
||||
except exception.Forbidden as e:
|
||||
raise webob.exc.HTTPForbidden(explanation=e.msg)
|
||||
except exception.NotFound as e:
|
||||
except (glance_store.NotFound, exception.NotFound) as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
except exception.Invalid as e:
|
||||
except (glance_store.Invalid, exception.Invalid) as e:
|
||||
raise webob.exc.HTTPBadRequest(explanation=e.msg)
|
||||
|
||||
def _restore(self, artifact_repo, artifact):
|
||||
|
|
|
@ -290,11 +290,6 @@ class UnsupportedHeaderFeature(GlanceException):
|
|||
message = _("Provided header feature is unsupported: %(feature)s")
|
||||
|
||||
|
||||
class InUseByStore(GlanceException):
|
||||
message = _("The image cannot be deleted because it is in use through "
|
||||
"the backend store outside of Glance.")
|
||||
|
||||
|
||||
class ImageSizeLimitExceeded(GlanceException):
|
||||
message = _("The provided image is too large.")
|
||||
|
||||
|
|
|
@ -77,12 +77,11 @@ def _check_location_uri(context, store_api, store_utils, uri):
|
|||
:param uri: location's uri string
|
||||
"""
|
||||
|
||||
is_ok = True
|
||||
try:
|
||||
# NOTE(zhiyan): Some stores return zero when it catch exception
|
||||
is_ok = (store_utils.validate_external_location(uri) and
|
||||
store_api.get_size_from_backend(uri, context=context) > 0)
|
||||
except (store.UnknownScheme, store.NotFound):
|
||||
except (store.UnknownScheme, store.NotFound, store.BadStoreUri):
|
||||
is_ok = False
|
||||
if not is_ok:
|
||||
reason = _('Invalid location')
|
||||
|
|
|
@ -2000,7 +2000,7 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||
|
||||
def test_delete_in_use(self):
|
||||
def fake_safe_delete_from_backend(self, *args, **kwargs):
|
||||
raise exception.InUseByStore()
|
||||
raise store.exceptions.InUseByStore()
|
||||
self.stubs.Set(self.store_utils, 'safe_delete_from_backend',
|
||||
fake_safe_delete_from_backend)
|
||||
request = unit_test_utils.get_fake_request()
|
||||
|
|
Loading…
Reference in New Issue