Delete uploaded swift objects on image delete
If shade auto-uploads swift objects for a glance upload, then shade should auto-delete them when it deletes the image. To that end, also add metadata to the image that records what swift container/object it uploads as. Change-Id: If422d33dafec58c805a0d2bb5b8746727c8761d9
This commit is contained in:
parent
e0ad4ece18
commit
502a4bba86
@ -52,6 +52,7 @@ OBJECT_MD5_KEY = 'x-object-meta-x-shade-md5'
|
||||
OBJECT_SHA256_KEY = 'x-object-meta-x-shade-sha256'
|
||||
IMAGE_MD5_KEY = 'owner_specified.shade.md5'
|
||||
IMAGE_SHA256_KEY = 'owner_specified.shade.sha256'
|
||||
IMAGE_OBJECT_KEY = 'owner_specified.shade.object'
|
||||
# Rackspace returns this for intermittent import errors
|
||||
IMAGE_ERROR_396 = "Image cannot be imported. Error code: '396'"
|
||||
DEFAULT_OBJECT_SEGMENT_SIZE = 1073741824 # 1GB
|
||||
@ -2170,7 +2171,9 @@ class OpenStackCloud(object):
|
||||
raise OpenStackCloudException(
|
||||
'Image {image} hit error state'.format(image=image_id))
|
||||
|
||||
def delete_image(self, name_or_id, wait=False, timeout=3600):
|
||||
def delete_image(
|
||||
self, name_or_id, wait=False, timeout=3600,
|
||||
delete_objects=True):
|
||||
image = self.get_image(name_or_id)
|
||||
with _utils.shade_exceptions("Error in deleting image"):
|
||||
# Note that in v1, the param name is image, but in v2,
|
||||
@ -2184,6 +2187,11 @@ class OpenStackCloud(object):
|
||||
_tasks.ImageDelete(image=image.id))
|
||||
self.list_images.invalidate(self)
|
||||
|
||||
# Task API means an image was uploaded to swift
|
||||
if self.image_api_use_tasks and IMAGE_OBJECT_KEY in image:
|
||||
(container, objname) = image[IMAGE_OBJECT_KEY].split('/', 1)
|
||||
self.delete_object(container=container, name=name)
|
||||
|
||||
if wait:
|
||||
for count in _utils._iterate_timeout(
|
||||
timeout,
|
||||
@ -2280,6 +2288,7 @@ class OpenStackCloud(object):
|
||||
return current_image
|
||||
kwargs[IMAGE_MD5_KEY] = md5
|
||||
kwargs[IMAGE_SHA256_KEY] = sha256
|
||||
kwargs[IMAGE_OBJECT_KEY] = '/'.join([container, name])
|
||||
|
||||
if disable_vendor_agent:
|
||||
kwargs.update(self.cloud_config.config['disable_vendor_agent'])
|
||||
|
@ -364,13 +364,12 @@ class TestMemoryCache(base.TestCase):
|
||||
# therefore we should _not_ expect to see the new one here
|
||||
self.assertEqual([first_image], self.cloud.list_images())
|
||||
|
||||
def _call_create_image(self, name, container=None, **kwargs):
|
||||
def _call_create_image(self, name, **kwargs):
|
||||
imagefile = tempfile.NamedTemporaryFile(delete=False)
|
||||
imagefile.write(b'\0')
|
||||
imagefile.close()
|
||||
self.cloud.create_image(
|
||||
name, imagefile.name, container=container, wait=True,
|
||||
is_public=False, **kwargs)
|
||||
name, imagefile.name, wait=True, is_public=False, **kwargs)
|
||||
|
||||
@mock.patch.object(occ.cloud_config.CloudConfig, 'get_api_version')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'glance_client')
|
||||
@ -385,9 +384,11 @@ class TestMemoryCache(base.TestCase):
|
||||
self._call_create_image('42 name')
|
||||
args = {'name': '42 name',
|
||||
'container_format': 'bare', 'disk_format': 'qcow2',
|
||||
'properties': {'owner_specified.shade.md5': mock.ANY,
|
||||
'owner_specified.shade.sha256': mock.ANY,
|
||||
'is_public': False}}
|
||||
'properties': {
|
||||
'owner_specified.shade.md5': mock.ANY,
|
||||
'owner_specified.shade.sha256': mock.ANY,
|
||||
'owner_specified.shade.object': 'images/42 name',
|
||||
'is_public': False}}
|
||||
fake_image_dict = meta.obj_to_dict(fake_image)
|
||||
glance_mock.images.create.assert_called_with(**args)
|
||||
glance_mock.images.update.assert_called_with(
|
||||
@ -411,6 +412,7 @@ class TestMemoryCache(base.TestCase):
|
||||
'container_format': 'bare', 'disk_format': 'qcow2',
|
||||
'owner_specified.shade.md5': mock.ANY,
|
||||
'owner_specified.shade.sha256': mock.ANY,
|
||||
'owner_specified.shade.object': 'images/42 name',
|
||||
'visibility': 'private',
|
||||
'min_disk': 0, 'min_ram': 0}
|
||||
glance_mock.images.create.assert_called_with(**args)
|
||||
@ -482,8 +484,10 @@ class TestMemoryCache(base.TestCase):
|
||||
glance_mock.tasks.create.assert_called_with(type='import', input={
|
||||
'import_from': 'image_upload_v2_test_container/name-99',
|
||||
'image_properties': {'name': 'name-99'}})
|
||||
object_path = 'image_upload_v2_test_container/name-99'
|
||||
args = {'owner_specified.shade.md5': fake_md5,
|
||||
'owner_specified.shade.sha256': fake_sha256,
|
||||
'owner_specified.shade.object': object_path,
|
||||
'image_id': 'a35e8afc-cae9-4e38-8441-2cd465f79f7b'}
|
||||
glance_mock.images.update.assert_called_with(**args)
|
||||
fake_image_dict = meta.obj_to_dict(fake_image)
|
||||
|
Loading…
x
Reference in New Issue
Block a user