Forbidden exception being incorrectly instantiated by filesystem driver

Bug #1444663 reported by Taylor Peoples
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
glance_store
Fix Released
High
Taylor Peoples
Kilo
Fix Released
Undecided
Unassigned
Liberty
Fix Released
High
Taylor Peoples

Bug Description

Stack trace:

  File "/usr/lib/python2.7/site-packages/eventlet/wsgi.py", line 442, in handle_one_response
    result = self.application(self.environ, start_response)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/glance/common/wsgi.py", line 486, in __call__
    response = req.get_response(self.application)
  File "/usr/lib/python2.7/site-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/lib/python2.7/site-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/osprofiler/web.py", line 99, in __call__
    return request.get_response(self.application)
  File "/usr/lib/python2.7/site-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/lib/python2.7/site-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/usr/lib/python2.7/site-packages/keystonemiddleware/auth_token/__init__.py", line 634, in __call__
    return self._call_app(env, start_response)
  File "/usr/lib/python2.7/site-packages/keystonemiddleware/auth_token/__init__.py", line 554, in _call_app
    return self._app(env, _fake_start_response)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/glance/common/wsgi.py", line 486, in __call__
    response = req.get_response(self.application)
  File "/usr/lib/python2.7/site-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/lib/python2.7/site-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/usr/lib/python2.7/site-packages/paste/urlmap.py", line 203, in __call__
    return app(environ, start_response)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 144, in __call__
    return resp(environ, start_response)
  File "/usr/lib/python2.7/site-packages/routes/middleware.py", line 131, in __call__
    response = self.app(environ, start_response)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 144, in __call__
    return resp(environ, start_response)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/glance/common/wsgi.py", line 777, in __call__
    request, **action_args)
  File "/usr/lib/python2.7/site-packages/glance/common/wsgi.py", line 801, in dispatch
    return method(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/glance/common/utils.py", line 509, in wrapped
    return func(self, req, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/glance/api/v1/images.py", line 1089, in delete
    {'status': ori_status})
  File "/usr/lib/python2.7/site-packages/oslo_utils/excutils.py", line 85, in __exit__
    six.reraise(self.type_, self.value, self.tb)
  File "/usr/lib/python2.7/site-packages/glance/api/v1/images.py", line 1085, in delete
    upload_utils.initiate_deletion(req, loc_data, id)
  File "/usr/lib/python2.7/site-packages/glance/api/v1/upload_utils.py", line 46, in initiate_deletion
    id, location_data)
  File "/usr/lib/python2.7/site-packages/glance/common/store_utils.py", line 124, in delete_image_location_from_backend
    safe_delete_from_backend(context, image_id, location)
  File "/usr/lib/python2.7/site-packages/glance/common/store_utils.py", line 58, in safe_delete_from_backend
    ret = store_api.delete_from_backend(location['url'], context=context)
  File "/usr/lib/python2.7/site-packages/glance_store/backend.py", line 290, in delete_from_backend
    return store.delete(loc, context=context)
  File "/usr/lib/python2.7/site-packages/glance_store/capabilities.py", line 226, in op_checker
    return store_op_fun(store, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/glance_store/_drivers/filesystem.py", line 492, in delete
    raise exceptions.Forbidden(_("You cannot delete file %s") % fn)
TypeError: __init__() takes exactly 1 argument (2 given)

glance_store/_drivers/filesystem.py's delete method raises an exception if deletion of an image fails:

     def delete(self, location, context=None):
        """
        Takes a `glance_store.location.Location` object that indicates
        where to find the image file to delete

        :location `glance_store.location.Location` object, supplied
                  from glance_store.location.get_location_from_uri()

        :raises NotFound if image does not exist
        :raises Forbidden if cannot delete because of permissions
        """
        loc = location.store_location
        fn = loc.path
        if os.path.exists(fn):
            try:
                LOG.debug(_("Deleting image at %(fn)s"), {'fn': fn})
                os.unlink(fn)
            except OSError:
                raise exceptions.Forbidden(_("You cannot delete file %s") % fn)
        else:
            raise exceptions.NotFound(image=fn)

The problem is that the instantiation of exceptions.Forbidden is passing an argument when it shouldn't be:

class Forbidden(GlanceStoreException):
    message = _("You are not authorized to complete this action.")

class GlanceStoreException(Exception):
    """
    Base Glance Store Exception

    To correctly use this class, inherit from it and define
    a 'message' property. That message will get printf'd
    with the keyword arguments provided to the constructor.
    """
    message = ''

    def __init__(self, **kwargs):
        self.msg = kwargs.pop('message', None) or self.message % kwargs
        super(Exception, self).__init__(self.msg)

If the instantiation within filesystem.py is changed to:

raise exceptions.Forbidden(message=(_("You cannot delete file %s") % fn))

then the exception is thrown as expected:

  ...
  File "/usr/lib/python2.7/site-packages/glance_store/_drivers/filesystem.py", line 492, in delete
    raise exceptions.Forbidden(message=(_("You cannot delete file %s") % fn))
Forbidden: You cannot delete file /var/lib/glance/images/47dfa80f-cc9e-4f18-ab1b-96f4204d228a

Changed in glance-store:
assignee: nobody → Taylor Peoples (tpeoples)
status: New → In Progress
Revision history for this message
Taylor Peoples (tpeoples) wrote :
Revision history for this message
Ian Cordasco (icordasc) wrote :

Someone should backport https://review.openstack.org/#/c/176819/ for Kilo. It's a backwards compatible fix and is certainly desirable, if not necessary

Revision history for this message
Cyril Roelandt (cyril-roelandt) wrote :

This was indeed backported to kilo a while ago.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.