From 6367ead33baa35939d591b76ffa9563887d1b25b Mon Sep 17 00:00:00 2001 From: Clint Byrum Date: Thu, 18 Jun 2015 09:20:58 -0700 Subject: [PATCH] Fix MD5 headers regression This regression was introduced when we switched to swiftclient.service.SwiftService for uploading because of a documentation bug. The option was listed as 'headers' but it should be 'header'. Change-Id: Id590f624aa084af0747b93ae70b214600147ebb2 --- shade/__init__.py | 3 ++- shade/tests/functional/test_object.py | 2 ++ shade/tests/unit/test_caching.py | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/shade/__init__.py b/shade/__init__.py index 9a8aec07d..87a1bf57e 100644 --- a/shade/__init__.py +++ b/shade/__init__.py @@ -2022,6 +2022,7 @@ class OpenStackCloud(object): (md5, sha256) = self._get_file_hashes(filename) headers[OBJECT_MD5_KEY] = md5 headers[OBJECT_SHA256_KEY] = sha256 + header_list = sorted([':'.join([k, v]) for (k, v) in headers.items()]) # On some clouds this is not necessary. On others it is. I'm confused. self.create_container(container) @@ -2034,7 +2035,7 @@ class OpenStackCloud(object): object_name=name) for r in self.manager.submitTask(_tasks.ObjectCreate( container=container, objects=[upload], - options=dict(headers=headers, + options=dict(header=header_list, segment_size=segment_size))): if not r['success']: raise OpenStackCloudException( diff --git a/shade/tests/functional/test_object.py b/shade/tests/functional/test_object.py index 6202c79a5..8ca213986 100644 --- a/shade/tests/functional/test_object.py +++ b/shade/tests/functional/test_object.py @@ -54,6 +54,8 @@ class TestObject(base.TestCase): name = 'test-%d' % size self.cloud.create_object(container, name, sparse_file.name, segment_size=segment_size) + self.assertFalse(self.cloud.is_object_stale(container, name, + sparse_file.name)) self.assertIsNotNone( self.cloud.get_object_metadata(container, name)) self.cloud.delete_object(container, name) diff --git a/shade/tests/unit/test_caching.py b/shade/tests/unit/test_caching.py index ef4b103c1..cd6ca6cbb 100644 --- a/shade/tests/unit/test_caching.py +++ b/shade/tests/unit/test_caching.py @@ -301,13 +301,15 @@ class TestMemoryCache(base.TestCase): fake_image_dict = meta.obj_to_dict(fake_image) self.assertEqual([fake_image_dict], self.cloud.list_images()) + @mock.patch.object(shade.OpenStackCloud, '_get_file_hashes') @mock.patch.object(shade.OpenStackCloud, 'glance_client') @mock.patch.object(shade.OpenStackCloud, 'swift_client') @mock.patch.object(shade.OpenStackCloud, 'swift_service') def test_create_image_task(self, swift_service_mock, swift_mock, - glance_mock): + glance_mock, + get_file_hashes): self.cloud.api_versions['image'] = '2' self.cloud.image_api_use_tasks = True @@ -325,6 +327,10 @@ class TestMemoryCache(base.TestCase): glance_mock.images.list.return_value = [] self.assertEqual([], self.cloud.list_images()) + fake_md5 = "fake-md5" + fake_sha256 = "fake-sha256" + get_file_hashes.return_value = (fake_md5, fake_sha256) + # V2's warlock objects just work like dicts class FakeImage(dict): status = 'CREATED' @@ -335,8 +341,8 @@ class TestMemoryCache(base.TestCase): fake_image.update({ 'id': '99', 'name': '99 name', - shade.IMAGE_MD5_KEY: '', - shade.IMAGE_SHA256_KEY: '', + shade.IMAGE_MD5_KEY: fake_md5, + shade.IMAGE_SHA256_KEY: fake_sha256, }) glance_mock.images.list.return_value = [fake_image] @@ -352,8 +358,8 @@ class TestMemoryCache(base.TestCase): glance_mock.tasks.get.return_value = fake_task self._call_create_image(name='99 name', container='image_upload_v2_test_container') - args = {'headers': {'x-object-meta-x-shade-md5': mock.ANY, - 'x-object-meta-x-shade-sha256': mock.ANY}, + args = {'header': ['x-object-meta-x-shade-md5:fake-md5', + 'x-object-meta-x-shade-sha256:fake-sha256'], 'segment_size': 1000} swift_service_mock.upload.assert_called_with( container='image_upload_v2_test_container', @@ -362,8 +368,8 @@ class TestMemoryCache(base.TestCase): glance_mock.tasks.create.assert_called_with(type='import', input={ 'import_from': 'image_upload_v2_test_container/99 name', 'image_properties': {'name': '99 name'}}) - args = {'owner_specified.shade.md5': mock.ANY, - 'owner_specified.shade.sha256': mock.ANY, + args = {'owner_specified.shade.md5': fake_md5, + 'owner_specified.shade.sha256': fake_sha256, 'image_id': '99'} glance_mock.images.update.assert_called_with(**args) fake_image_dict = meta.obj_to_dict(fake_image)