diff --git a/openstack/cloud/openstackcloud.py b/openstack/cloud/openstackcloud.py index 53abde1fc..5d8773803 100755 --- a/openstack/cloud/openstackcloud.py +++ b/openstack/cloud/openstackcloud.py @@ -7421,6 +7421,7 @@ class OpenStackCloud(_normalize.Normalizer): self, container, name, filename=None, md5=None, sha256=None, segment_size=None, use_slo=True, metadata=None, + generate_checksums=True, **headers): """Create a file object. @@ -7445,6 +7446,9 @@ class OpenStackCloud(_normalize.Normalizer): Object, use a static rather than dynamic object. Static Objects will delete segment objects when the manifest object is deleted. (optional, defaults to True) + :param generate_checksums: Whether to generate checksums on the client + side that get added to headers for later prevention of double + uploads of identical data. (optional, defaults to True) :param metadata: This dict will get changed into headers that set metadata of the object @@ -7463,10 +7467,12 @@ class OpenStackCloud(_normalize.Normalizer): segment_size = self.get_object_segment_size(segment_size) file_size = os.path.getsize(filename) - if not (md5 or sha256): + if generate_checksums and (md5 is None or sha256 is None): (md5, sha256) = self._get_file_hashes(filename) - headers[OBJECT_MD5_KEY] = md5 or '' - headers[OBJECT_SHA256_KEY] = sha256 or '' + if md5: + headers[OBJECT_MD5_KEY] = md5 or '' + if sha256: + headers[OBJECT_SHA256_KEY] = sha256 or '' for (k, v) in metadata.items(): headers['x-object-meta-' + k] = v diff --git a/openstack/tests/unit/cloud/test_object.py b/openstack/tests/unit/cloud/test_object.py index 7bb8506f9..b13d81446 100644 --- a/openstack/tests/unit/cloud/test_object.py +++ b/openstack/tests/unit/cloud/test_object.py @@ -895,3 +895,58 @@ class TestObjectUploads(BaseTestObject): 'etag': 'etag3', }, ], self.adapter.request_history[-1].json()) + + def test_create_object_skip_checksum(self): + + self.register_uris([ + dict(method='GET', + uri='https://object-store.example.com/info', + json=dict( + swift={'max_file_size': 1000}, + slo={'min_segment_size': 500})), + dict(method='HEAD', + uri='{endpoint}/{container}'.format( + endpoint=self.endpoint, + container=self.container), + status_code=404), + dict(method='PUT', + uri='{endpoint}/{container}'.format( + endpoint=self.endpoint, container=self.container), + status_code=201, + headers={ + 'Date': 'Fri, 16 Dec 2016 18:21:20 GMT', + 'Content-Length': '0', + 'Content-Type': 'text/html; charset=UTF-8', + }), + dict(method='HEAD', + uri='{endpoint}/{container}'.format( + endpoint=self.endpoint, container=self.container), + headers={ + 'Content-Length': '0', + 'X-Container-Object-Count': '0', + 'Accept-Ranges': 'bytes', + 'X-Storage-Policy': 'Policy-0', + 'Date': 'Fri, 16 Dec 2016 18:29:05 GMT', + 'X-Timestamp': '1481912480.41664', + 'X-Trans-Id': 'tx60ec128d9dbf44b9add68-0058543271dfw1', + 'X-Container-Bytes-Used': '0', + 'Content-Type': 'text/plain; charset=utf-8'}), + dict(method='HEAD', + uri='{endpoint}/{container}/{object}'.format( + endpoint=self.endpoint, container=self.container, + object=self.object), + status_code=200), + dict(method='PUT', + uri='{endpoint}/{container}/{object}'.format( + endpoint=self.endpoint, + container=self.container, object=self.object), + status_code=201, + validate=dict(headers={})), + ]) + + self.cloud.create_object( + container=self.container, name=self.object, + filename=self.object_file.name, + generate_checksums=False) + + self.assert_calls() diff --git a/releasenotes/notes/object-checksum-generation-ea1c1e47d2290054.yaml b/releasenotes/notes/object-checksum-generation-ea1c1e47d2290054.yaml new file mode 100644 index 000000000..e27a87396 --- /dev/null +++ b/releasenotes/notes/object-checksum-generation-ea1c1e47d2290054.yaml @@ -0,0 +1,4 @@ +--- +features: + - Add flag for disabling object checksum generation +