diff options
author | Cyril Roelandt <cyril@redhat.com> | 2016-01-11 14:19:09 +0100 |
---|---|---|
committer | Cyril Roelandt <cyril@redhat.com> | 2016-01-11 16:09:45 +0100 |
commit | 399aec1f81853d66c8319405c9170ac69e346e78 (patch) | |
tree | 18581ffa28443ee8cfae664f6aa1f7dccfd19805 | |
parent | 434031792a6a3f2d84a95a5658d68b3b25a6f8dd (diff) | |
download | glance_store-399aec1f81853d66c8319405c9170ac69e346e78.tar.gz |
Swift store: do not send a 0 byte chunk
When a chunk of size 0 is added, it is immediately deleted. Swift might try to
delete it before its creation is complete, though, leading to a race condition.
Not sending this 0 byte chunk soves this issue.
Co-Authored-By: Stuart McLaren <stuart.mclaren@hp.com>
Change-Id: I2179a1e6e27a636bfca448fa18481eb11e64e6da
Closes-Bug: #1518431
-rw-r--r-- | glance_store/_drivers/swift/store.py | 14 | ||||
-rw-r--r-- | glance_store/exceptions.py | 4 | ||||
-rw-r--r-- | glance_store/tests/unit/test_swift_store.py | 7 |
3 files changed, 14 insertions, 11 deletions
diff --git a/glance_store/_drivers/swift/store.py b/glance_store/_drivers/swift/store.py index bdf4bbd..591b16d 100644 --- a/glance_store/_drivers/swift/store.py +++ b/glance_store/_drivers/swift/store.py @@ -551,6 +551,9 @@ class BaseStore(driver.Store): location.container, chunk_name, reader, content_length=content_length) written_chunks.append(chunk_name) + except exceptions.ZeroSizeChunk: + LOG.debug('Not writing zero-length chunk') + break except Exception: # Delete orphaned segments from swift backend with excutils.save_and_reraise_exception(): @@ -572,14 +575,6 @@ class BaseStore(driver.Store): 'chunk_etag': chunk_etag}) LOG.debug(msg) - if bytes_read == 0: - # Delete the last chunk, because it's of zero size. - # This will happen if size == 0. - LOG.debug("Deleting final zero-length chunk") - connection.delete_object(location.container, - chunk_name) - break - chunk_id += 1 combined_chunks_size += bytes_read @@ -960,6 +955,9 @@ class ChunkReader(object): if i > left: i = left result = self.fd.read(i) + if len(result) == 0 and self.bytes_read == 0: + # fd was empty + raise exceptions.ZeroSizeChunk() self.bytes_read += len(result) self.checksum.update(result) return result diff --git a/glance_store/exceptions.py b/glance_store/exceptions.py index ea7b61b..45c790d 100644 --- a/glance_store/exceptions.py +++ b/glance_store/exceptions.py @@ -81,6 +81,10 @@ class NotFound(GlanceStoreException): message = _("Image %(image)s not found") +class ZeroSizeChunk(GlanceStoreException): + message = _("Zero size chunk") + + class UnknownScheme(GlanceStoreException): message = _("Unknown scheme '%(scheme)s' found in URI") diff --git a/glance_store/tests/unit/test_swift_store.py b/glance_store/tests/unit/test_swift_store.py index a71024c..813f623 100644 --- a/glance_store/tests/unit/test_swift_store.py +++ b/glance_store/tests/unit/test_swift_store.py @@ -1500,10 +1500,11 @@ class TestChunkReader(base.StoreBaseTest): bytes_read = 0 while True: cr = swift.ChunkReader(infile, checksum, CHUNKSIZE) - chunk = cr.read(CHUNKSIZE) - bytes_read += len(chunk) - if not chunk: + try: + chunk = cr.read(CHUNKSIZE) + except exceptions.ZeroSizeChunk: break + bytes_read += len(chunk) self.assertEqual(units.Ki, bytes_read) data_file.close() infile.close() |