Skip to content

Commit

Permalink
Delete from store after registry delete.
Browse files Browse the repository at this point in the history
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
Mark Washenberger authored and russellb committed Nov 7, 2012
1 parent 6b2300f commit 6ab0992
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
16 changes: 11 additions & 5 deletions glance/api/v1/images.py
Expand Up @@ -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'):
Expand Down
8 changes: 7 additions & 1 deletion glance/tests/stubs.py
Expand Up @@ -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,
Expand Down
20 changes: 20 additions & 0 deletions glance/tests/unit/v1/test_api.py
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions glance/tests/utils.py
Expand Up @@ -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)
Expand Down

0 comments on commit 6ab0992

Please sign in to comment.