summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glance/store/swift.py26
-rw-r--r--glance/tests/functional/store/test_swift.py19
2 files changed, 42 insertions, 3 deletions
diff --git a/glance/store/swift.py b/glance/store/swift.py
index 3c6c276ea..cbb564a66 100644
--- a/glance/store/swift.py
+++ b/glance/store/swift.py
@@ -22,6 +22,7 @@ from __future__ import absolute_import
import hashlib
import httplib
import math
+import sys
import urllib
import urlparse
@@ -309,6 +310,7 @@ class BaseStore(glance.store.base.Store):
total_chunks = '?'
checksum = hashlib.md5()
+ written_chunks = []
combined_chunks_size = 0
while True:
chunk_size = self.large_object_chunk_size
@@ -324,9 +326,27 @@ class BaseStore(glance.store.base.Store):
chunk_name = "%s-%05d" % (location.obj, chunk_id)
reader = ChunkReader(image_file, checksum, chunk_size)
- chunk_etag = connection.put_object(
- location.container, chunk_name, reader,
- content_length=content_length)
+ try:
+ chunk_etag = connection.put_object(
+ location.container, chunk_name, reader,
+ content_length=content_length)
+ written_chunks.append(chunk_name)
+ except Exception:
+ # Save original traceback
+ exc_type, exc_val, exc_tb = sys.exc_info()
+
+ # Delete now stale segments from swift backend
+ for chunk in written_chunks:
+ LOG.debug(_("Deleting chunk %s" % chunk))
+ try:
+ connection.delete_object(location.container,
+ chunk)
+ except Exception:
+ msg = _("Failed to delete orphan chunk %s/%s")
+ LOG.exception(msg, location.container, chunk)
+
+ # reraise original exception with traceback intact
+ raise exc_type, exc_val, exc_tb
bytes_read = reader.bytes_read
msg = _("Wrote chunk %(chunk_name)s (%(chunk_id)d/"
"%(total_chunks)s) of length %(bytes_read)d "
diff --git a/glance/tests/functional/store/test_swift.py b/glance/tests/functional/store/test_swift.py
index 22a523bc0..923c94e81 100644
--- a/glance/tests/functional/store/test_swift.py
+++ b/glance/tests/functional/store/test_swift.py
@@ -33,6 +33,8 @@ import urlparse
import oslo.config.cfg
import testtools
+from glance.common import exception
+import glance.common.utils as common_utils
from glance.openstack.common import uuidutils
import glance.store.swift
import glance.tests.functional.store as store_tests
@@ -283,6 +285,23 @@ class TestSwiftStore(store_tests.BaseTestCase, testtools.TestCase):
self.swift_client.delete_object(manifest_container,
non_image_obj)
+ # Simulate exceeding 'image_size_cap' setting
+ image_data = StringIO.StringIO('X' * image_size)
+ image_data = common_utils.LimitingReader(image_data, image_size - 1)
+ image_id = uuidutils.generate_uuid()
+ self.assertRaises(exception.ImageSizeLimitExceeded,
+ store.add,
+ image_id,
+ image_data,
+ image_size)
+
+ # Verify written segments have been deleted
+ container = swift_get_container(self.swift_client,
+ manifest_container,
+ prefix=image_id)
+ segments = [segment['name'] for segment in container[1]]
+ self.assertEqual(0, len(segments), 'Got segments %s' % segments)
+
def stash_image(self, image_id, image_data):
container_name = self.swift_config['swift_store_container']
swift_put_object(self.swift_client,