diff --git a/releasenotes/notes/cleanup-objects-f99aeecf22ac13dd.yaml b/releasenotes/notes/cleanup-objects-f99aeecf22ac13dd.yaml new file mode 100644 index 000000000..e1e0752fd --- /dev/null +++ b/releasenotes/notes/cleanup-objects-f99aeecf22ac13dd.yaml @@ -0,0 +1,6 @@ +--- +features: + - If shade has to create objects in swift to upload an + image, it will now delete those objects upon successful + image creation as they are no longer needed. They will + also be deleted on fatal import errors. diff --git a/shade/openstackcloud.py b/shade/openstackcloud.py index f56e029ba..db7b18827 100644 --- a/shade/openstackcloud.py +++ b/shade/openstackcloud.py @@ -4875,6 +4875,9 @@ class OpenStackCloud( self.log.debug( "Image Task %s imported %s in %s", glance_task.id, image_id, (time.time() - start)) + # Clean up after ourselves. The object we created is not + # needed after the import is done. + self.delete_object(container, name) return self.get_image(image_id) elif status['status'] == 'failure': if status['message'] == IMAGE_ERROR_396: @@ -4882,6 +4885,11 @@ class OpenStackCloud( '/tasks', data=task_args) self.list_images.invalidate(self) else: + # Clean up after ourselves. The image did not import + # and this isn't a 'just retry' error - glance didn't + # like the content. So we don't want to keep it for + # next time. + self.delete_object(container, name) raise OpenStackCloudException( "Image creation failed: {message}".format( message=status['message']), diff --git a/shade/tests/unit/test_image.py b/shade/tests/unit/test_image.py index 97cab614e..71d723437 100644 --- a/shade/tests/unit/test_image.py +++ b/shade/tests/unit/test_image.py @@ -360,6 +360,25 @@ class TestImage(BaseTestImage): 'Content-Type': 'application/openstack-images-v2.1-json-patch'}) ), + dict(method='HEAD', + uri='{endpoint}/{container}/{object}'.format( + endpoint=endpoint, container=container_name, + object=image_name), + headers={ + 'X-Timestamp': '1429036140.50253', + 'X-Trans-Id': 'txbbb825960a3243b49a36f-005a0dadaedfw1', + 'Content-Length': '1290170880', + 'Last-Modified': 'Tue, 14 Apr 2015 18:29:01 GMT', + 'X-Object-Meta-X-Shade-Sha256': fakes.NO_SHA256, + 'X-Object-Meta-X-Shade-Md5': fakes.NO_MD5, + 'Date': 'Thu, 16 Nov 2017 15:24:30 GMT', + 'Accept-Ranges': 'bytes', + 'Content-Type': 'application/octet-stream', + 'Etag': fakes.NO_MD5}), + dict(method='DELETE', + uri='{endpoint}/{container}/{object}'.format( + endpoint=endpoint, container=container_name, + object=image_name)), dict(method='GET', uri='https://image.example.com/v2/images', json=self.fake_search_return) ])