From 822dd7f3955183a9a37f64c96b7d620c175b2861 Mon Sep 17 00:00:00 2001 From: Naoto Nishizono Date: Thu, 12 Feb 2015 16:49:27 +0900 Subject: [PATCH] Fix Delete Multiple Objects process when multipart object is deleted When delete a object created by Complete Multipart Upload in Delete Multiple Objects operation, delete both manifest file and segments by adding "multipart-manifest=delete" to query string. Change-Id: I3759e6f43d8c531d7a7d961c2069af1e411d04ef --- swift3/acl_handlers.py | 5 +++++ swift3/controllers/multi_delete.py | 3 ++- swift3/test/unit/test_multi_delete.py | 20 ++++++++++++++++++-- test-requirements.txt | 1 + 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/swift3/acl_handlers.py b/swift3/acl_handlers.py index afbad9ab..32f804a7 100644 --- a/swift3/acl_handlers.py +++ b/swift3/acl_handlers.py @@ -242,6 +242,11 @@ class MultiObjectDeleteAclHandler(BaseAclHandler): """ MultiObjectDeleteAclHandler: Handler for MultiObjectDeleteController """ + def HEAD(self, app): + # Only bucket write acl is required + if not self.obj: + return self._handle_acl(app, 'HEAD') + def DELETE(self, app): # Only bucket write acl is required pass diff --git a/swift3/controllers/multi_delete.py b/swift3/controllers/multi_delete.py index e5b1a3a2..ea4a2540 100644 --- a/swift3/controllers/multi_delete.py +++ b/swift3/controllers/multi_delete.py @@ -99,7 +99,8 @@ class MultiObjectDeleteController(Controller): req.object_name = key try: - req.get_response(self.app, method='DELETE') + query = req.gen_multipart_manifest_delete_query(self.app) + req.get_response(self.app, method='DELETE', query=query) except NoSuchKey: pass except ErrorResponse as e: diff --git a/swift3/test/unit/test_multi_delete.py b/swift3/test/unit/test_multi_delete.py index e984f830..0ffcd2d3 100644 --- a/swift3/test/unit/test_multi_delete.py +++ b/swift3/test/unit/test_multi_delete.py @@ -17,6 +17,7 @@ import unittest from datetime import datetime from hashlib import md5 +from six.moves import urllib from swift.common import swob from swift.common.swob import Request @@ -30,6 +31,10 @@ class TestSwift3MultiDelete(Swift3TestCase): def setUp(self): super(TestSwift3MultiDelete, self).setUp() + self.swift.register('HEAD', '/v1/AUTH_test/bucket/Key1', + swob.HTTPOk, {}, None) + self.swift.register('HEAD', '/v1/AUTH_test/bucket/Key2', + swob.HTTPNotFound, {}, None) @s3acl def test_object_multi_DELETE_to_object(self): @@ -51,13 +56,19 @@ class TestSwift3MultiDelete(Swift3TestCase): @s3acl def test_object_multi_DELETE(self): + self.swift.register('HEAD', '/v1/AUTH_test/bucket/Key3', + swob.HTTPOk, + {'x-static-large-object': 'True'}, + None) self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1', swob.HTTPNoContent, {}, None) self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2', swob.HTTPNotFound, {}, None) + self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key3', + swob.HTTPOk, {}, None) elem = Element('Delete') - for key in ['Key1', 'Key2']: + for key in ['Key1', 'Key2', 'Key3']: obj = SubElement(elem, 'Object') SubElement(obj, 'Key').text = key body = tostring(elem, use_s3ns=False) @@ -75,7 +86,12 @@ class TestSwift3MultiDelete(Swift3TestCase): self.assertEquals(status.split()[0], '200') elem = fromstring(body) - self.assertEquals(len(elem.findall('Deleted')), 2) + self.assertEquals(len(elem.findall('Deleted')), 3) + _, path, _ = self.swift.calls_with_headers[-1] + path, query_string = path.split('?', 1) + self.assertEquals(path, '/v1/AUTH_test/bucket/Key3') + query = dict(urllib.parse.parse_qsl(query_string)) + self.assertEquals(query['multipart-manifest'], 'delete') @s3acl def test_object_multi_DELETE_quiet(self): diff --git a/test-requirements.txt b/test-requirements.txt index 6bbf82df..a33e2ddc 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -7,3 +7,4 @@ mock pylint python-openstackclient<=1.9.0 boto +six>=1.9.0