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:
Monty Taylor 2016-04-07 21:04:50 -04:00
parent e0ad4ece18
commit 502a4bba86
No known key found for this signature in database
GPG Key ID: 3390DB68041A12F0
2 changed files with 20 additions and 7 deletions

View File

@ -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'])

View File

@ -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)