def _put_object(self, container, object_name, upload_func, upload_func_kwargs, extra=None, file_path=None, iterator=None, file_hash=None, storage_class=None): headers = {} extra = extra or {} storage_class = storage_class or 'standard' if storage_class not in ['standard', 'reduced_redundancy']: raise ValueError('Invalid storage class value: %s' % (storage_class)) headers['x-amz-storage-class'] = storage_class.upper() container_name_cleaned = container.name object_name_cleaned = self._clean_name(object_name) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) if not iterator and file_hash: # TODO: This driver also needs to access to the headers in the # add_default_params method so the correct signature can be # calculated when a MD5 hash is provided. # Uncomment this line when we decide what is the best way to handle # this. #headers['Content-MD5'] = file_hash pass if meta_data: for key, value in meta_data.iteritems(): key = 'x-amz-meta--%s' % (key) headers[key] = value request_path = '/%s/%s' % (container_name_cleaned, object_name_cleaned) # TODO: Let the underlying exceptions bubble up and capture the SIGPIPE # here. # SIGPIPE is thrown if the provided container does not exist or the user # does not have correct permission result_dict = self._upload_object(object_name=object_name, content_type=content_type, upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, request_path=request_path, request_method='PUT', headers=headers, file_path=file_path, iterator=iterator) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response.response if file_hash and file_hash != headers['etag'].replace('"', ''): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=file_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj
def _put_object(self, container, object_name, object_size, upload_func, upload_func_kwargs, file_path=None, extra=None, verify_hash=True, blob_type=None, use_lease=False): """ Control function that does the real job of uploading data to a blob """ extra = extra or {} meta_data = extra.get('meta_data', {}) content_type = extra.get('content_type', None) headers = self._prepare_upload_headers(object_name, object_size, extra, meta_data, blob_type) object_path = self._get_object_path(container, object_name) # Get a lease if required and do the operations with AzureBlobLease(self, object_path, use_lease) as lease: if 'lease' in upload_func_kwargs: upload_func_kwargs['lease'] = lease lease.update_headers(headers) iterator = iter('') result_dict = self._upload_object(object_name, content_type, upload_func, upload_func_kwargs, object_path, headers=headers, file_path=file_path, iterator=iterator) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] data_hash = result_dict['data_hash'] headers = response.headers response = response.response if response.status != httplib.CREATED: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self) server_hash = headers['content-md5'] if server_hash: server_hash = binascii.hexlify(base64.b64decode(b(server_hash))) server_hash = server_hash.decode('utf-8') else: # TODO: HACK - We could poll the object for a while and get # the hash pass if (verify_hash and server_hash and data_hash != server_hash): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) return Object(name=object_name, size=bytes_transferred, hash=headers['etag'], extra=None, meta_data=meta_data, container=container, driver=self)
def _put_object(self, container, object_name, upload_func, upload_func_kwargs, method='PUT', query_args=None, extra=None, file_path=None, iterator=None, verify_hash=True, storage_class=None): headers = {} extra = extra or {} storage_class = storage_class or 'standard' if storage_class not in ['standard', 'reduced_redundancy']: raise ValueError( 'Invalid storage class value: %s' % (storage_class)) headers['x-amz-storage-class'] = storage_class.upper() content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) if meta_data: for key, value in list(meta_data.items()): key = 'x-amz-meta-%s' % (key) headers[key] = value request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) # TODO: Let the underlying exceptions bubble up and capture the SIGPIPE # here. #SIGPIPE is thrown if the provided container does not exist or the user # does not have correct permission result_dict = self._upload_object( object_name=object_name, content_type=content_type, upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, request_path=request_path, request_method=method, headers=headers, file_path=file_path, iterator=iterator) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response.response server_hash = headers['etag'].replace('"', '') if (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self)
def _put_object(self, container, object_name, upload_func, upload_func_kwargs, extra=None, file_path=None, iterator=None, file_hash=None): extra = extra or {} container_name_cleaned = self._clean_container_name(container.name) object_name_cleaned = self._clean_object_name(object_name) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) headers = {} if not iterator and file_hash: headers['ETag'] = file_hash if meta_data: for key, value in meta_data.iteritems(): key = 'X-Object-Meta-%s' % (key) headers[key] = value request_path = '/%s/%s' % (container_name_cleaned, object_name_cleaned) result_dict = self._upload_object( object_name=object_name, content_type=content_type, upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, request_path=request_path, request_method='PUT', headers=headers, file_path=file_path, iterator=iterator) response = result_dict['response'].response bytes_transferred = result_dict['bytes_transferred'] if response.status == httplib.EXPECTATION_FAILED: raise LibcloudError(value='Missing content-type header', driver=self) elif response.status == httplib.UNPROCESSABLE_ENTITY: raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) elif response.status == httplib.CREATED: obj = Object(name=object_name, size=bytes_transferred, hash=file_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj
def _put_object(self, container, object_name, method='PUT', query_args=None, extra=None, file_path=None, stream=None, verify_hash=True, storage_class=None): headers = {} extra = extra or {} headers.update(self._to_storage_class_headers(storage_class)) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + '-meta-%s' % (key) headers[key] = value if acl: headers[self.http_vendor_prefix + '-acl'] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) # TODO: Let the underlying exceptions bubble up and capture the SIGPIPE # here. # SIGPIPE is thrown if the provided container does not exist or the # user does not have correct permission result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response server_hash = headers.get('etag', '').replace('"', '') if (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value='MD5 hash {0} checksum does not match {1}'.format( server_hash, result_dict['data_hash']), object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self)
def _put_object(self, container, object_name, method='PUT', query_args=None, extra=None, file_path=None, stream=None, verify_hash=False): """ Create an object and upload data using the given function. """ headers = {} extra = extra or {} content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + 'meta-%s' % (key) headers[key] = value if acl: if acl not in ['public-read', 'private', 'public-read-write']: raise AttributeError('invalid acl value: %s' % acl) headers[self.http_vendor_prefix + 'object-acl'] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers server_hash = headers['etag'].replace('"', '') if (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value='MD5 hash {0} checksum does not match {1}'.format( server_hash, result_dict['data_hash']), object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self)
def _upload_object_manifest(self, container, object_name, extra=None, verify_hash=True): extra = extra or {} meta_data = extra.get("meta_data") container_name_encoded = self._encode_container_name(container.name) object_name_encoded = self._encode_object_name(object_name) request_path = "/%s/%s" % (container_name_encoded, object_name_encoded) # pylint: disable=no-member headers = { "X-Auth-Token": self.connection.auth_token, "X-Object-Manifest": "%s/%s/" % (container_name_encoded, object_name_encoded), } data = "" response = self.connection.request(request_path, method="PUT", data=data, headers=headers, raw=True) object_hash = None if verify_hash: hash_function = self._get_hash_function() hash_function.update(b(data)) data_hash = hash_function.hexdigest() object_hash = response.headers.get("etag") if object_hash != data_hash: raise ObjectHashMismatchError( value=("MD5 hash checksum does not match (expected=%s, " + "actual=%s)") % (data_hash, object_hash), object_name=object_name, driver=self, ) obj = Object( name=object_name, size=0, hash=object_hash, extra=None, meta_data=meta_data, container=container, driver=self, ) return obj
def _put_object(self, container, object_name, upload_func, upload_func_kwargs, extra=None, file_path=None, iterator=None, verify_hash=True): extra = extra or {} container_name_encoded = self._encode_container_name(container.name) object_name_encoded = self._encode_object_name(object_name) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) content_disposition = extra.get('content_disposition', None) headers = {} if meta_data: for key, value in list(meta_data.items()): key = 'X-Object-Meta-%s' % (key) headers[key] = value if content_disposition is not None: headers['Content-Disposition'] = content_disposition request_path = '/%s/%s' % (container_name_encoded, object_name_encoded) result_dict = self._upload_object( object_name=object_name, content_type=content_type, upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, request_path=request_path, request_method='PUT', headers=headers, file_path=file_path, iterator=iterator) response = result_dict['response'].response bytes_transferred = result_dict['bytes_transferred'] server_hash = result_dict['response'].headers.get('etag', None) if response.status == httplib.EXPECTATION_FAILED: raise LibcloudError(value='Missing content-type header', driver=self) elif verify_hash and not server_hash: raise LibcloudError(value='Server didn\'t return etag', driver=self) elif (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value=('MD5 hash checksum does not match (expected=%s, ' + 'actual=%s)') % (result_dict['data_hash'], server_hash), object_name=object_name, driver=self) elif response.status == httplib.CREATED: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj else: # @TODO: Add test case for this condition (probably 411) raise LibcloudError('status_code=%s' % (response.status), driver=self)
def _upload_object_manifest(self, container, object_name, extra=None, verify_hash=True): extra = extra or {} meta_data = extra.get('meta_data') container_name_encoded = self._encode_container_name(container.name) object_name_encoded = self._encode_object_name(object_name) request_path = '/%s/%s' % (container_name_encoded, object_name_encoded) # pylint: disable=no-member headers = { 'X-Auth-Token': self.connection.auth_token, 'X-Object-Manifest': '%s/%s/' % (container_name_encoded, object_name_encoded) } data = '' response = self.connection.request(request_path, method='PUT', data=data, headers=headers, raw=True) object_hash = None if verify_hash: hash_function = self._get_hash_function() hash_function.update(b(data)) data_hash = hash_function.hexdigest() object_hash = response.headers.get('etag') if object_hash != data_hash: raise ObjectHashMismatchError( value=('MD5 hash checksum does not match (expected=%s, ' + 'actual=%s)') % (data_hash, object_hash), object_name=object_name, driver=self) obj = Object(name=object_name, size=0, hash=object_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj
def _put_object(self, container, object_name, method='PUT', query_args=None, extra=None, file_path=None, stream=None, verify_hash=True, storage_class=None, headers=None): headers = headers or {} extra = extra or {} headers.update(self._to_storage_class_headers(storage_class)) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + '-meta-%s' % (key) headers[key] = value if acl: headers[self.http_vendor_prefix + '-acl'] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) result_dict = self._upload_object(object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response server_hash = headers.get('etag', '').replace('"', '') server_side_encryption = headers.get('x-amz-server-side-encryption', None) aws_kms_encryption = (server_side_encryption == 'aws:kms') hash_matches = (result_dict['data_hash'] == server_hash) # NOTE: If AWS KMS server side encryption is enabled, ETag won't # contain object MD5 digest so we skip the checksum check # See https://docs.aws.amazon.com/AmazonS3/latest/API # /RESTCommonResponseHeaders.html # and https://github.com/apache/libcloud/issues/1401 # for details if verify_hash and not aws_kms_encryption and not hash_matches: raise ObjectHashMismatchError( value='MD5 hash {0} checksum does not match {1}'.format( server_hash, result_dict['data_hash']), object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object(name=object_name, size=bytes_transferred, hash=server_hash, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError('Unexpected status code, status_code=%s' % (response.status), driver=self)
def _put_object(self, container, object_name, stream, extra=None, verify_hash=True, headers=None, blob_size=None, file_path=None, use_lease=False): """ Control function that does the real job of uploading data to a blob """ extra = extra or {} content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', {}) object_path = self._get_object_path(container, object_name) # Get a lease if required and do the operations with AzureBlobLease(self, object_path, use_lease) as lease: if blob_size is not None and blob_size <= AZURE_UPLOAD_CHUNK_SIZE: result_dict = self._upload_directly(stream=stream, object_path=object_path, lease=lease, blob_size=blob_size, meta_data=meta_data, headers=headers, content_type=content_type, object_name=object_name, file_path=file_path) else: result_dict = self._upload_in_chunks(stream=stream, object_path=object_path, lease=lease, meta_data=meta_data, headers=headers, content_type=content_type, object_name=object_name, file_path=file_path, verify_hash=verify_hash) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] data_hash = result_dict['data_hash'] headers = response.headers if response.status != httplib.CREATED: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self) server_hash = headers.get('content-md5') if server_hash: server_hash = binascii.hexlify(base64.b64decode(b(server_hash))) server_hash = server_hash.decode('utf-8') else: # TODO: HACK - We could poll the object for a while and get # the hash pass if (verify_hash and server_hash and data_hash != server_hash): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) return Object(name=object_name, size=bytes_transferred, hash=headers['etag'], extra=None, meta_data=meta_data, container=container, driver=self)
def _put_object(self, container, object_name, upload_func, upload_func_kwargs, extra=None, file_path=None, iterator=None, file_hash=None, storage_class=None): headers = {} extra = extra or {} storage_class = storage_class or 'standard' if storage_class not in ['standard', 'reduced_redundancy']: raise ValueError('Invalid storage class value: %s' % (storage_class)) headers['x-amz-storage-class'] = storage_class.upper() container_name_cleaned = container.name object_name_cleaned = self._clean_object_name(object_name) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) if not iterator and file_hash: headers['Content-MD5'] = base64.b64encode(file_hash.decode('hex')) if meta_data: for key, value in meta_data.iteritems(): key = 'x-amz-meta-%s' % (key) headers[key] = value request_path = '/%s/%s' % (container_name_cleaned, object_name_cleaned) # TODO: Let the underlying exceptions bubble up and capture the SIGPIPE # here. # SIGPIPE is thrown if the provided container does not exist or the user # does not have correct permission result_dict = self._upload_object( object_name=object_name, content_type=content_type, upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, request_path=request_path, request_method='PUT', headers=headers, file_path=file_path, iterator=iterator) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response.response if (file_hash and response.status == httplib.BAD_REQUEST) or \ (file_hash and file_hash != headers['etag'].replace('"', '')): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object(name=object_name, size=bytes_transferred, hash=file_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj
def _put_object( self, container, object_name, method="PUT", query_args=None, extra=None, file_path=None, stream=None, verify_hash=False, headers=None, ): """ Create an object and upload data using the given function. """ headers = headers or {} extra = extra or {} content_type = extra.get("content_type", None) meta_data = extra.get("meta_data", None) acl = extra.get("acl", None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + "meta-%s" % (key) headers[key] = value if acl: if acl not in ["public-read", "private", "public-read-write"]: raise AttributeError("invalid acl value: %s" % acl) headers[self.http_vendor_prefix + "object-acl"] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = "?".join((request_path, query_args)) result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers=headers, file_path=file_path, stream=stream, ) response = result_dict["response"] bytes_transferred = result_dict["bytes_transferred"] headers = response.headers server_hash = headers["etag"].replace('"', "") if verify_hash and result_dict["data_hash"] != server_hash: raise ObjectHashMismatchError( value="MD5 hash {0} checksum does not match {1}".format( server_hash, result_dict["data_hash"]), object_name=object_name, driver=self, ) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra={"acl": acl}, meta_data=meta_data, container=container, driver=self, ) return obj else: raise LibcloudError( "Unexpected status code, status_code=%s" % (response.status), driver=self, )
def _put_object(self, upload_func, upload_func_args, container, object_name, extra=None, file_path=None, iterator=None, file_hash=None): container_name_cleaned = self._clean_container_name(container.name) object_name_cleaned = self._clean_object_name(object_name) extra = extra or {} content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) if not content_type: if file_path: name = file_path else: name = object_name content_type, _ = utils.guess_file_mime_type(name) if not content_type: raise AttributeError( 'File content-type could not be guessed and' + ' no content_type value provided') headers = {} if iterator: headers['Transfer-Encoding'] = 'chunked' upload_func_args['chunked'] = True else: file_size = os.path.getsize(file_path) headers['Content-Length'] = file_size upload_func_args['chunked'] = False if file_hash: headers['ETag'] = file_hash headers['Content-Type'] = content_type if meta_data: for key, value in meta_data.iteritems(): key = 'X-Object-Meta-%s' % (key) headers[key] = value response = self.connection.request( '/%s/%s' % (container_name_cleaned, object_name_cleaned), method='PUT', data=None, headers=headers, raw=True) upload_func_args['response'] = response success, data_hash, bytes_transferred = upload_func(**upload_func_args) if not success: raise LibcloudError('Object upload failed, Perhaps a timeout?') response = response.response if response.status == httplib.EXPECTATION_FAILED: raise LibcloudError('Missing content-type header') elif response.status == httplib.UNPROCESSABLE_ENTITY: raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) elif response.status == httplib.CREATED: obj = Object(name=object_name, size=bytes_transferred, hash=file_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj
def _put_object(self, container, object_name, upload_func, upload_func_kwargs, method='PUT', query_args=None, extra=None, file_path=None, iterator=None, verify_hash=False): """ Create an object and upload data using the given function. """ headers = {} extra = extra or {} content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + 'meta-%s' % (key) headers[key] = value if acl: if acl not in ['public-read', 'private', 'public-read-write']: raise AttributeError('invalid acl value: %s' % acl) headers[self.http_vendor_prefix + 'object-acl'] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) # TODO: Let the underlying exceptions bubble up and capture the SIGPIPE # here. # SIGPIPE is thrown if the provided container does not exist or the # user does not have correct permission result_dict = self._upload_object( object_name=object_name, content_type=content_type, upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, request_path=request_path, request_method=method, headers=headers, file_path=file_path, iterator=iterator, container=container) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response.response server_hash = headers['etag'].replace('"', '') if (verify_hash and result_dict['data_hash'].upper() != server_hash): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object(name=object_name, size=bytes_transferred, hash=server_hash, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError('Unexpected status code, status_code=%s' % (response.status), driver=self)
def _put_object( self, container, object_name, extra=None, file_path=None, stream=None, verify_hash=True, headers=None, ): extra = extra or {} container_name_encoded = self._encode_container_name(container.name) object_name_encoded = self._encode_object_name(object_name) content_type = extra.get("content_type", None) meta_data = extra.get("meta_data", None) content_disposition = extra.get("content_disposition", None) headers = headers or {} if meta_data: for key, value in list(meta_data.items()): key = "X-Object-Meta-%s" % (key) headers[key] = value if content_disposition is not None: headers["Content-Disposition"] = content_disposition request_path = "/%s/%s" % (container_name_encoded, object_name_encoded) result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method="PUT", headers=headers, file_path=file_path, stream=stream, ) response = result_dict["response"] bytes_transferred = result_dict["bytes_transferred"] server_hash = result_dict["response"].headers.get("etag", None) if response.status == httplib.EXPECTATION_FAILED: raise LibcloudError(value="Missing content-type header", driver=self) elif verify_hash and not server_hash: raise LibcloudError(value="Server didn't return etag", driver=self) elif verify_hash and result_dict["data_hash"] != server_hash: raise ObjectHashMismatchError( value=("MD5 hash checksum does not match (expected=%s, " + "actual=%s)") % (result_dict["data_hash"], server_hash), object_name=object_name, driver=self, ) elif response.status == httplib.CREATED: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra=None, meta_data=meta_data, container=container, driver=self, ) return obj else: # @TODO: Add test case for this condition (probably 411) raise LibcloudError("status_code=%s" % (response.status), driver=self)