Merge "Support for deleting images stored as SLO in Swift"
This commit is contained in:
commit
c1e8697f12
@ -22,6 +22,7 @@ import math
|
||||
|
||||
from oslo.config import cfg
|
||||
from oslo.utils import excutils
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import swiftclient
|
||||
import urllib
|
||||
@ -373,6 +374,14 @@ def Store(conf):
|
||||
Store.OPTIONS = _SWIFT_OPTS + sutils.swift_opts
|
||||
|
||||
|
||||
def _is_slo(slo_header):
|
||||
if (slo_header is not None and isinstance(slo_header, six.string_types)
|
||||
and slo_header.lower() == 'true'):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class BaseStore(driver.Store):
|
||||
|
||||
_CAPABILITIES = capabilities.BitMasks.RW_ACCESS
|
||||
@ -612,17 +621,27 @@ class BaseStore(driver.Store):
|
||||
# that means the object was uploaded in chunks/segments,
|
||||
# and we need to delete all the chunks as well as the
|
||||
# manifest.
|
||||
manifest = None
|
||||
dlo_manifest = None
|
||||
slo_manifest = None
|
||||
try:
|
||||
headers = connection.head_object(
|
||||
location.container, location.obj)
|
||||
manifest = headers.get('x-object-manifest')
|
||||
dlo_manifest = headers.get('x-object-manifest')
|
||||
slo_manifest = headers.get('x-static-large-object')
|
||||
except swiftclient.ClientException as e:
|
||||
if e.http_status != httplib.NOT_FOUND:
|
||||
raise
|
||||
if manifest:
|
||||
|
||||
if _is_slo(slo_manifest):
|
||||
# Delete the manifest as well as the segments
|
||||
query_string = 'multipart-manifest=delete'
|
||||
connection.delete_object(location.container, location.obj,
|
||||
query_string=query_string)
|
||||
return
|
||||
|
||||
if dlo_manifest:
|
||||
# Delete all the chunks before the object manifest itself
|
||||
obj_container, obj_prefix = manifest.split('/', 1)
|
||||
obj_container, obj_prefix = dlo_manifest.split('/', 1)
|
||||
segments = connection.get_container(
|
||||
obj_container, prefix=obj_prefix)[1]
|
||||
for segment in segments:
|
||||
|
@ -49,6 +49,7 @@ from tests.unit import test_store_capabilities
|
||||
CONF = cfg.CONF
|
||||
|
||||
FAKE_UUID = lambda: str(uuid.uuid4())
|
||||
FAKE_UUID2 = lambda: str(uuid.uuid4())
|
||||
|
||||
Store = swift.Store
|
||||
FIVE_KB = 5 * units.Ki
|
||||
@ -76,10 +77,11 @@ def stub_out_swiftclient(stubs, swift_store_auth_version):
|
||||
'glance/%s' % FAKE_UUID: {
|
||||
'content-length': FIVE_KB,
|
||||
'etag': 'c2e5db72bd7fd153f53ede5da5a06de3'
|
||||
}
|
||||
},
|
||||
'glance/%s' % FAKE_UUID2: {'x-static-large-object': 'true', },
|
||||
}
|
||||
fixture_objects = {'glance/%s' % FAKE_UUID:
|
||||
six.StringIO("*" * FIVE_KB)}
|
||||
fixture_objects = {'glance/%s' % FAKE_UUID: six.StringIO("*" * FIVE_KB),
|
||||
'glance/%s' % FAKE_UUID2: six.StringIO("*" * FIVE_KB), }
|
||||
|
||||
def fake_head_container(url, token, container, **kwargs):
|
||||
if container not in fixture_containers:
|
||||
@ -810,6 +812,47 @@ class SwiftTests(object):
|
||||
|
||||
self.assertRaises(exceptions.NotFound, self.store.get, loc)
|
||||
|
||||
@mock.patch.object(swiftclient.client, 'delete_object')
|
||||
def test_delete_slo(self, mock_del_obj):
|
||||
"""
|
||||
Test we can delete an existing image stored as SLO, static large object
|
||||
"""
|
||||
conf = copy.deepcopy(SWIFT_CONF)
|
||||
self.config(**conf)
|
||||
reload(swift)
|
||||
self.store = Store(self.conf)
|
||||
self.store.configure()
|
||||
|
||||
uri = "swift://%s:key@authurl/glance/%s" % (self.swift_store_user,
|
||||
FAKE_UUID2)
|
||||
loc = location.get_location_from_uri(uri, conf=self.conf)
|
||||
self.store.delete(loc)
|
||||
|
||||
mock_del_obj.assert_called_once()
|
||||
_, kwargs = mock_del_obj.call_args
|
||||
self.assertEqual('multipart-manifest=delete',
|
||||
kwargs.get('query_string'))
|
||||
|
||||
@mock.patch.object(swiftclient.client, 'delete_object')
|
||||
def test_delete_nonslo_not_deleted_as_slo(self, mock_del_obj):
|
||||
"""
|
||||
Test that non-SLOs are not being deleted the SLO way
|
||||
"""
|
||||
conf = copy.deepcopy(SWIFT_CONF)
|
||||
self.config(**conf)
|
||||
reload(swift)
|
||||
self.store = Store(self.conf)
|
||||
self.store.configure()
|
||||
|
||||
uri = "swift://%s:key@authurl/glance/%s" % (self.swift_store_user,
|
||||
FAKE_UUID)
|
||||
loc = location.get_location_from_uri(uri, conf=self.conf)
|
||||
self.store.delete(loc)
|
||||
|
||||
mock_del_obj.assert_called_once()
|
||||
_, kwargs = mock_del_obj.call_args
|
||||
self.assertEqual(None, kwargs.get('query_string'))
|
||||
|
||||
def test_delete_with_reference_params(self):
|
||||
"""
|
||||
Test we can delete an existing image in the swift store
|
||||
|
Loading…
x
Reference in New Issue
Block a user