diff --git a/glance/artifacts/location.py b/glance/artifacts/location.py index d63be7cf1e..3f7df74231 100644 --- a/glance/artifacts/location.py +++ b/glance/artifacts/location.py @@ -136,6 +136,8 @@ class ArtifactBlobProxy(proxy.ArtifactBlob): LOG.error(msg) def upload_to_store(self, data, size): + if size is None: # NOTE(ativelkov): None is "unknown size" + size = 0 location, ret_size, checksum, loc_meta = self.store_api.add_to_backend( CONF, self.blob.item_key, diff --git a/glance/tests/functional/artifacts/test_artifacts.py b/glance/tests/functional/artifacts/test_artifacts.py index 1aa199577b..45175e4670 100644 --- a/glance/tests/functional/artifacts/test_artifacts.py +++ b/glance/tests/functional/artifacts/test_artifacts.py @@ -969,6 +969,29 @@ paste.filter_factory = glance.tests.utils:FakeAuthMiddleware.factory '/withblob/%s/blob1/download' % art['id']) self.assertEqual('ZZZZZ', data) + def test_file_w_unknown_size(self): + # Upload and download data provided by an iterator, thus without + # knowing the length in advance + art = self._create_artifact('withblob') + artifact_id = art['id'] + + def iterate_string(val): + for char in val: + yield char + + headers = self._headers({'Content-Type': 'application/octet-stream'}) + self._check_artifact_post('/withblob/v1/%s/blob1' % art['id'], + headers=headers, + data=iterate_string('ZZZZZ'), status=200) + + art = self._check_artifact_get('/withblob/%s' % artifact_id) + self.assertEqual(artifact_id, art['id']) + self.assertIn('download_link', art['blob1']) + + data = self._check_artifact_get( + '/withblob/%s/blob1/download' % art['id']) + self.assertEqual('ZZZZZ', data) + def test_limit(self): artifact_data = {'name': 'artifact-1', 'version': '12'}