Commit 45b56769 authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

Delete Image without deleting file from Pithos

Until now, deleting an image resulted in deletion of the corresponding
file from Pithos. Plankton Images are files in Pithos with special
metadata on the 'plankton' metadata domain. Adding an Image to plankton
is equivalent with adding some special metadata in this domain. In the
same way, this commit implements Image deletion by deleting these
metadata, and retaining the original file in Pithos.

Refs #3522
parent 584f7d9a
......@@ -206,7 +206,7 @@ def delete_image(request, image_id):
log.info('delete_image %s', image_id)
with image_backend(request.user_uniq) as backend:
backend.delete(image_id)
backend.unregister(image_id)
log.info('User %s deleted image %s', request.user_uniq, image_id)
return HttpResponse(status=204)
......
......@@ -187,7 +187,8 @@ class ImageAPITest(BaseAPITest):
def test_delete_image(self, mimage):
response = self.delete("/api/v1.1/images/42", "user")
self.assertEqual(response.status_code, 204)
mimage.return_value.delete.assert_called_once_with('42')
mimage.return_value.unregister.assert_called_once_with('42')
mimage.return_value._delete.assert_not_called('42')
@patch('synnefo.api.util.ImageBackend')
......
......@@ -297,7 +297,12 @@ class ImageBackend(object):
self.backend.close()
@handle_backend_exceptions
def delete(self, image_id):
def _delete(self, image_id):
"""Delete an Image.
This method will delete the Image from the Storage backend.
"""
image = self.get_image(image_id)
account, container, object = split_location(image['location'])
self.backend.delete_object(self.user, account, container, object)
......@@ -511,3 +516,17 @@ class ImageBackend(object):
self._update_meta(location, meta)
return self.get_image(image_id)
@handle_backend_exceptions
def unregister(self, image_id):
"""Unregister an image."""
image = self.get_image(image_id)
assert image, "Image not found"
location = image["location"]
# Unregister the image by removing all metadata from domain
# 'PLANKTON_DOMAIN'
meta = self._get_meta(location)
for k in meta.keys():
meta[k] = ""
self._update_meta(location, meta, False)
......@@ -291,3 +291,10 @@ class PlanktonTest(BaseAPITest):
def test_get_image(self, backend):
response = self.get("/plankton/images/123")
self.assertEqual(response.status_code, 501)
@assert_backend_closed
def test_delete_image(self, backend):
response = self.delete("/plankton/images/123")
self.assertEqual(response.status_code, 204)
backend.return_value.unregister.assert_called_once_with('123')
backend.return_value._delete.assert_not_called()
......@@ -47,14 +47,16 @@ def demux(request):
def demux_image(request, image_id):
if request.method == 'GET':
if request.method == "GET":
return views.get_image(request, image_id)
elif request.method == 'HEAD':
elif request.method == "HEAD":
return views.get_image_meta(request, image_id)
elif request.method == 'PUT':
elif request.method == "PUT":
return views.update_image(request, image_id)
elif request.method == "DELETE":
return views.delete_image(request, image_id)
else:
return HttpResponseNotAllowed(['GET', 'HEAD', 'PUT'])
return HttpResponseNotAllowed(["GET", "HEAD", "PUT", "DELETE"])
def demux_image_members(request, image_id):
......
......@@ -155,6 +155,25 @@ def add_image(request):
return _create_image_response(image)
@plankton_method("DELETE")
def delete_image(request, image_id):
"""Delete an Image.
This API call is not described in the Openstack Glance API.
Implementation notes:
* The implementation does not delete the Image from the storage
backend. Instead it unregisters the image by removing all the
metadata from the plankton metadata domain.
"""
log.info("delete_image '%s'" % image_id)
userid = request.user_uniq
request.backend.unregister(image_id)
log.info("User '%s' deleted image '%s'" % (userid, image_id))
return HttpResponse(status=204)
@plankton_method('PUT')
def add_image_member(request, image_id, member):
"""Add a member to an image
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment