Permalink
Browse files

Delete from store after registry delete.

Because we rely on the registry to determine authorization in the glance
v1 api, we must attempt a registry delete before deleting an image from
the image store.

This patch includes the test for the bug, which was posted separately
on the bug.

Fixes bug 1065187.

Change-Id: I1a06b7c7421524066c684539e2f3516c4ed2c475
  • Loading branch information...
1 parent 6b2300f commit 6ab0992e5472ae3f9bef0d2ced41030655d9d2bc Mark Washenberger committed with russellb Nov 7, 2012
Showing with 39 additions and 6 deletions.
  1. +11 −5 glance/api/v1/images.py
  2. +7 −1 glance/tests/stubs.py
  3. +20 −0 glance/tests/unit/v1/test_api.py
  4. +1 −0 glance/tests/utils.py
View
@@ -827,22 +827,28 @@ def delete(self, req, id):
raise HTTPForbidden(explanation=msg, request=req,
content_type="text/plain")
- status = 'deleted'
+ if image['location'] and CONF.delayed_delete:
+ status = 'pending_delete'
+ else:
+ status = 'deleted'
+
try:
+ # Delete the image from the registry first, since we rely on it
+ # for authorization checks.
+ # See https://bugs.launchpad.net/glance/+bug/1065187
+ registry.update_image_metadata(req.context, id, {'status': status})
+ registry.delete_image_metadata(req.context, id)
+
# The image's location field may be None in the case
# of a saving or queued image, therefore don't ask a backend
# to delete the image if the backend doesn't yet store it.
# See https://bugs.launchpad.net/glance/+bug/747799
if image['location']:
if CONF.delayed_delete:
- status = 'pending_delete'
schedule_delayed_delete_from_backend(image['location'], id)
else:
safe_delete_from_backend(image['location'],
req.context, id)
-
- registry.update_image_metadata(req.context, id, {'status': status})
- registry.delete_image_metadata(req.context, id)
except exception.NotFound, e:
msg = ("Failed to find image to delete: %(e)s" % locals())
for line in msg.split('\n'):
View
@@ -60,7 +60,13 @@ def request(self, method, url, body=None, headers=None):
def getresponse(self):
mapper = routes.Mapper()
- api = context.UnauthenticatedContextMiddleware(rserver.API(mapper))
+ server = rserver.API(mapper)
+ # NOTE(markwash): we need to pass through context auth information if
+ # we have it.
+ if 'X-Auth-Token' in self.req.headers:
+ api = utils.FakeAuthMiddleware(server)
+ else:
+ api = context.UnauthenticatedContextMiddleware(server)
webob_res = self.req.get_response(api)
return utils.FakeHTTPResponse(status=webob_res.status_int,
@@ -3015,6 +3015,26 @@ def test_delete_non_exists_image(self):
res = req.get_response(self.api)
self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code)
+ def test_delete_not_allowed(self):
+ # Verify we can get the image data
+ req = webob.Request.blank("/images/%s" % UUID2)
+ req.method = 'GET'
+ req.headers['X-Auth-Token'] = 'user:tenant:'
+ res = req.get_response(self.api)
+ self.assertEqual(res.status_int, 200)
+ self.assertEqual(len(res.body), 19)
+
+ # Verify we cannot delete the image
+ req.method = 'DELETE'
+ res = req.get_response(self.api)
+ self.assertEqual(res.status_int, 403)
+
+ # Verify the image data is still there
+ req.method = 'GET'
+ res = req.get_response(self.api)
+ self.assertEqual(res.status_int, 200)
+ self.assertEqual(len(res.body), 19)
+
def test_delete_queued_image(self):
"""Delete an image in a queued state
View
@@ -372,6 +372,7 @@ def process_request(self, req):
'tenant': tenant,
'roles': roles,
'is_admin': self.is_admin,
+ 'auth_tok': auth_tok,
}
req.context = context.RequestContext(**kwargs)

0 comments on commit 6ab0992

Please sign in to comment.