| Index: third_party/gsutil/boto/boto/glacier/layer1.py
|
| diff --git a/third_party/gsutil/boto/boto/glacier/layer1.py b/third_party/gsutil/boto/boto/glacier/layer1.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e5a39630344d1e33c7216054544c9cab0396673c
|
| --- /dev/null
|
| +++ b/third_party/gsutil/boto/boto/glacier/layer1.py
|
| @@ -0,0 +1,637 @@
|
| +# -*- coding: utf-8 -*-
|
| +# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
|
| +# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved
|
| +#
|
| +# Permission is hereby granted, free of charge, to any person obtaining a
|
| +# copy of this software and associated documentation files (the
|
| +# "Software"), to deal in the Software without restriction, including
|
| +# without limitation the rights to use, copy, modify, merge, publish, dis-
|
| +# tribute, sublicense, and/or sell copies of the Software, and to permit
|
| +# persons to whom the Software is furnished to do so, subject to the fol-
|
| +# lowing conditions:
|
| +#
|
| +# The above copyright notice and this permission notice shall be included
|
| +# in all copies or substantial portions of the Software.
|
| +#
|
| +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
| +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
| +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
| +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
| +# IN THE SOFTWARE.
|
| +#
|
| +
|
| +import os
|
| +
|
| +import boto.glacier
|
| +from boto.compat import json
|
| +from boto.connection import AWSAuthConnection
|
| +from .exceptions import UnexpectedHTTPResponseError
|
| +from .response import GlacierResponse
|
| +from .utils import ResettingFileSender
|
| +
|
| +
|
| +class Layer1(AWSAuthConnection):
|
| +
|
| + Version = '2012-06-01'
|
| + """Glacier API version."""
|
| +
|
| + def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
|
| + account_id='-', is_secure=True, port=None,
|
| + proxy=None, proxy_port=None,
|
| + proxy_user=None, proxy_pass=None, debug=0,
|
| + https_connection_factory=None, path='/',
|
| + provider='aws', security_token=None,
|
| + suppress_consec_slashes=True,
|
| + region=None, region_name='us-east-1'):
|
| +
|
| + if not region:
|
| + for reg in boto.glacier.regions():
|
| + if reg.name == region_name:
|
| + region = reg
|
| + break
|
| +
|
| + self.region = region
|
| + self.account_id = account_id
|
| + AWSAuthConnection.__init__(self, region.endpoint,
|
| + aws_access_key_id, aws_secret_access_key,
|
| + is_secure, port, proxy, proxy_port,
|
| + proxy_user, proxy_pass, debug,
|
| + https_connection_factory,
|
| + path, provider, security_token,
|
| + suppress_consec_slashes)
|
| +
|
| + def _required_auth_capability(self):
|
| + return ['hmac-v4']
|
| +
|
| + def make_request(self, verb, resource, headers=None,
|
| + data='', ok_responses=(200,), params=None,
|
| + sender=None, response_headers=None):
|
| + if headers is None:
|
| + headers = {}
|
| + headers['x-amz-glacier-version'] = self.Version
|
| + uri = '/%s/%s' % (self.account_id, resource)
|
| + response = AWSAuthConnection.make_request(self, verb, uri,
|
| + params=params,
|
| + headers=headers,
|
| + sender=sender,
|
| + data=data)
|
| + if response.status in ok_responses:
|
| + return GlacierResponse(response, response_headers)
|
| + else:
|
| + # create glacier-specific exceptions
|
| + raise UnexpectedHTTPResponseError(ok_responses, response)
|
| +
|
| + # Vaults
|
| +
|
| + def list_vaults(self, limit=None, marker=None):
|
| + """
|
| + This operation lists all vaults owned by the calling user’s
|
| + account. The list returned in the response is ASCII-sorted by
|
| + vault name.
|
| +
|
| + By default, this operation returns up to 1,000 items. If there
|
| + are more vaults to list, the marker field in the response body
|
| + contains the vault Amazon Resource Name (ARN) at which to
|
| + continue the list with a new List Vaults request; otherwise,
|
| + the marker field is null. In your next List Vaults request you
|
| + set the marker parameter to the value Amazon Glacier returned
|
| + in the responses to your previous List Vaults request. You can
|
| + also limit the number of vaults returned in the response by
|
| + specifying the limit parameter in the request.
|
| +
|
| + :type limit: int
|
| + :param limit: The maximum number of items returned in the
|
| + response. If you don't specify a value, the List Vaults
|
| + operation returns up to 1,000 items.
|
| +
|
| + :type marker: str
|
| + :param marker: A string used for pagination. marker specifies
|
| + the vault ARN after which the listing of vaults should
|
| + begin. (The vault specified by marker is not included in
|
| + the returned list.) Get the marker value from a previous
|
| + List Vaults response. You need to include the marker only
|
| + if you are continuing the pagination of results started in
|
| + a previous List Vaults request. Specifying an empty value
|
| + ("") for the marker returns a list of vaults starting
|
| + from the first vault.
|
| + """
|
| + params = {}
|
| + if limit:
|
| + params['limit'] = limit
|
| + if marker:
|
| + params['marker'] = marker
|
| + return self.make_request('GET', 'vaults', params=params)
|
| +
|
| + def describe_vault(self, vault_name):
|
| + """
|
| + This operation returns information about a vault, including
|
| + the vault Amazon Resource Name (ARN), the date the vault was
|
| + created, the number of archives contained within the vault,
|
| + and the total size of all the archives in the vault. The
|
| + number of archives and their total size are as of the last
|
| + vault inventory Amazon Glacier generated. Amazon Glacier
|
| + generates vault inventories approximately daily. This means
|
| + that if you add or remove an archive from a vault, and then
|
| + immediately send a Describe Vault request, the response might
|
| + not reflect the changes.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| + """
|
| + uri = 'vaults/%s' % vault_name
|
| + return self.make_request('GET', uri)
|
| +
|
| + def create_vault(self, vault_name):
|
| + """
|
| + This operation creates a new vault with the specified name.
|
| + The name of the vault must be unique within a region for an
|
| + AWS account. You can create up to 1,000 vaults per
|
| + account. For information on creating more vaults, go to the
|
| + Amazon Glacier product detail page.
|
| +
|
| + You must use the following guidelines when naming a vault.
|
| +
|
| + Names can be between 1 and 255 characters long.
|
| +
|
| + Allowed characters are a–z, A–Z, 0–9, '_' (underscore),
|
| + '-' (hyphen), and '.' (period).
|
| +
|
| + This operation is idempotent, you can send the same request
|
| + multiple times and it has no further effect after the first
|
| + time Amazon Glacier creates the specified vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| + """
|
| + uri = 'vaults/%s' % vault_name
|
| + return self.make_request('PUT', uri, ok_responses=(201,),
|
| + response_headers=[('Location', 'Location')])
|
| +
|
| + def delete_vault(self, vault_name):
|
| + """
|
| + This operation deletes a vault. Amazon Glacier will delete a
|
| + vault only if there are no archives in the vault as per the
|
| + last inventory and there have been no writes to the vault
|
| + since the last inventory. If either of these conditions is not
|
| + satisfied, the vault deletion fails (that is, the vault is not
|
| + removed) and Amazon Glacier returns an error.
|
| +
|
| + This operation is idempotent, you can send the same request
|
| + multiple times and it has no further effect after the first
|
| + time Amazon Glacier delete the specified vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| + """
|
| + uri = 'vaults/%s' % vault_name
|
| + return self.make_request('DELETE', uri, ok_responses=(204,))
|
| +
|
| + def get_vault_notifications(self, vault_name):
|
| + """
|
| + This operation retrieves the notification-configuration
|
| + subresource set on the vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| + """
|
| + uri = 'vaults/%s/notification-configuration' % vault_name
|
| + return self.make_request('GET', uri)
|
| +
|
| + def set_vault_notifications(self, vault_name, notification_config):
|
| + """
|
| + This operation retrieves the notification-configuration
|
| + subresource set on the vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| +
|
| + :type notification_config: dict
|
| + :param notification_config: A Python dictionary containing
|
| + an SNS Topic and events for which you want Amazon Glacier
|
| + to send notifications to the topic. Possible events are:
|
| +
|
| + * ArchiveRetrievalCompleted - occurs when a job that was
|
| + initiated for an archive retrieval is completed.
|
| + * InventoryRetrievalCompleted - occurs when a job that was
|
| + initiated for an inventory retrieval is completed.
|
| +
|
| + The format of the dictionary is:
|
| +
|
| + {'SNSTopic': 'mytopic',
|
| + 'Events': [event1,...]}
|
| + """
|
| + uri = 'vaults/%s/notification-configuration' % vault_name
|
| + json_config = json.dumps(notification_config)
|
| + return self.make_request('PUT', uri, data=json_config,
|
| + ok_responses=(204,))
|
| +
|
| + def delete_vault_notifications(self, vault_name):
|
| + """
|
| + This operation deletes the notification-configuration
|
| + subresource set on the vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| + """
|
| + uri = 'vaults/%s/notification-configuration' % vault_name
|
| + return self.make_request('DELETE', uri, ok_responses=(204,))
|
| +
|
| + # Jobs
|
| +
|
| + def list_jobs(self, vault_name, completed=None, status_code=None,
|
| + limit=None, marker=None):
|
| + """
|
| + This operation lists jobs for a vault including jobs that are
|
| + in-progress and jobs that have recently finished.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type completed: boolean
|
| + :param completed: Specifies the state of the jobs to return.
|
| + If a value of True is passed, only completed jobs will
|
| + be returned. If a value of False is passed, only
|
| + uncompleted jobs will be returned. If no value is
|
| + passed, all jobs will be returned.
|
| +
|
| + :type status_code: string
|
| + :param status_code: Specifies the type of job status to return.
|
| + Valid values are: InProgress|Succeeded|Failed. If not
|
| + specified, jobs with all status codes are returned.
|
| +
|
| + :type limit: int
|
| + :param limit: The maximum number of items returned in the
|
| + response. If you don't specify a value, the List Jobs
|
| + operation returns up to 1,000 items.
|
| +
|
| + :type marker: str
|
| + :param marker: An opaque string used for pagination. marker
|
| + specifies the job at which the listing of jobs should
|
| + begin. Get the marker value from a previous List Jobs
|
| + response. You need only include the marker if you are
|
| + continuing the pagination of results started in a previous
|
| + List Jobs request.
|
| +
|
| + """
|
| + params = {}
|
| + if limit:
|
| + params['limit'] = limit
|
| + if marker:
|
| + params['marker'] = marker
|
| + if status_code:
|
| + params['statuscode'] = status_code
|
| + if completed is not None:
|
| + params['completed'] = 'true' if completed else 'false'
|
| + uri = 'vaults/%s/jobs' % vault_name
|
| + return self.make_request('GET', uri, params=params)
|
| +
|
| + def describe_job(self, vault_name, job_id):
|
| + """
|
| + This operation returns information about a job you previously
|
| + initiated, including the job initiation date, the user who
|
| + initiated the job, the job status code/message and the Amazon
|
| + Simple Notification Service (Amazon SNS) topic to notify after
|
| + Amazon Glacier completes the job.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| +
|
| + :type job_id: str
|
| + :param job_id: The ID of the job.
|
| + """
|
| + uri = 'vaults/%s/jobs/%s' % (vault_name, job_id)
|
| + return self.make_request('GET', uri, ok_responses=(200,))
|
| +
|
| + def initiate_job(self, vault_name, job_data):
|
| + """
|
| + This operation initiates a job of the specified
|
| + type. Retrieving an archive or a vault inventory are
|
| + asynchronous operations that require you to initiate a job. It
|
| + is a two-step process:
|
| +
|
| + * Initiate a retrieval job.
|
| + * After the job completes, download the bytes.
|
| +
|
| + The retrieval is executed asynchronously. When you initiate
|
| + a retrieval job, Amazon Glacier creates a job and returns a
|
| + job ID in the response.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| +
|
| + :type job_data: dict
|
| + :param job_data: A Python dictionary containing the
|
| + information about the requested job. The dictionary
|
| + can contain the following attributes:
|
| +
|
| + * ArchiveId - The ID of the archive you want to retrieve.
|
| + This field is required only if the Type is set to
|
| + archive-retrieval.
|
| + * Description - The optional description for the job.
|
| + * Format - When initiating a job to retrieve a vault
|
| + inventory, you can optionally add this parameter to
|
| + specify the output format. Valid values are: CSV|JSON.
|
| + * SNSTopic - The Amazon SNS topic ARN where Amazon Glacier
|
| + sends a notification when the job is completed and the
|
| + output is ready for you to download.
|
| + * Type - The job type. Valid values are:
|
| + archive-retrieval|inventory-retrieval
|
| + * RetrievalByteRange - Optionally specify the range of
|
| + bytes to retrieve.
|
| +
|
| + """
|
| + uri = 'vaults/%s/jobs' % vault_name
|
| + response_headers = [('x-amz-job-id', u'JobId'),
|
| + ('Location', u'Location')]
|
| + json_job_data = json.dumps(job_data)
|
| + return self.make_request('POST', uri, data=json_job_data,
|
| + ok_responses=(202,),
|
| + response_headers=response_headers)
|
| +
|
| + def get_job_output(self, vault_name, job_id, byte_range=None):
|
| + """
|
| + This operation downloads the output of the job you initiated
|
| + using Initiate a Job. Depending on the job type
|
| + you specified when you initiated the job, the output will be
|
| + either the content of an archive or a vault inventory.
|
| +
|
| + You can download all the job output or download a portion of
|
| + the output by specifying a byte range. In the case of an
|
| + archive retrieval job, depending on the byte range you
|
| + specify, Amazon Glacier returns the checksum for the portion
|
| + of the data. You can compute the checksum on the client and
|
| + verify that the values match to ensure the portion you
|
| + downloaded is the correct data.
|
| +
|
| + :type vault_name: str :param
|
| + :param vault_name: The name of the new vault
|
| +
|
| + :type job_id: str
|
| + :param job_id: The ID of the job.
|
| +
|
| + :type byte_range: tuple
|
| + :param range: A tuple of integers specifying the slice (in bytes)
|
| + of the archive you want to receive
|
| + """
|
| + response_headers = [('x-amz-sha256-tree-hash', u'TreeHash'),
|
| + ('Content-Range', u'ContentRange'),
|
| + ('Content-Type', u'ContentType')]
|
| + headers = None
|
| + if byte_range:
|
| + headers = {'Range': 'bytes=%d-%d' % byte_range}
|
| + uri = 'vaults/%s/jobs/%s/output' % (vault_name, job_id)
|
| + response = self.make_request('GET', uri, headers=headers,
|
| + ok_responses=(200, 206),
|
| + response_headers=response_headers)
|
| + return response
|
| +
|
| + # Archives
|
| +
|
| + def upload_archive(self, vault_name, archive,
|
| + linear_hash, tree_hash, description=None):
|
| + """
|
| + This operation adds an archive to a vault. For a successful
|
| + upload, your data is durably persisted. In response, Amazon
|
| + Glacier returns the archive ID in the x-amz-archive-id header
|
| + of the response. You should save the archive ID returned so
|
| + that you can access the archive later.
|
| +
|
| + :type vault_name: str :param
|
| + :param vault_name: The name of the vault
|
| +
|
| + :type archive: bytes
|
| + :param archive: The data to upload.
|
| +
|
| + :type linear_hash: str
|
| + :param linear_hash: The SHA256 checksum (a linear hash) of the
|
| + payload.
|
| +
|
| + :type tree_hash: str
|
| + :param tree_hash: The user-computed SHA256 tree hash of the
|
| + payload. For more information on computing the
|
| + tree hash, see http://goo.gl/u7chF.
|
| +
|
| + :type description: str
|
| + :param description: An optional description of the archive.
|
| + """
|
| + response_headers = [('x-amz-archive-id', u'ArchiveId'),
|
| + ('Location', u'Location'),
|
| + ('x-amz-sha256-tree-hash', u'TreeHash')]
|
| + uri = 'vaults/%s/archives' % vault_name
|
| + try:
|
| + content_length = str(len(archive))
|
| + except (TypeError, AttributeError):
|
| + # If a file like object is provided, try to retrieve
|
| + # the file size via fstat.
|
| + content_length = str(os.fstat(archive.fileno()).st_size)
|
| + headers = {'x-amz-content-sha256': linear_hash,
|
| + 'x-amz-sha256-tree-hash': tree_hash,
|
| + 'Content-Length': content_length}
|
| + if description:
|
| + headers['x-amz-archive-description'] = description
|
| + if self._is_file_like(archive):
|
| + sender = ResettingFileSender(archive)
|
| + else:
|
| + sender = None
|
| + return self.make_request('POST', uri, headers=headers,
|
| + sender=sender,
|
| + data=archive, ok_responses=(201,),
|
| + response_headers=response_headers)
|
| +
|
| + def _is_file_like(self, archive):
|
| + return hasattr(archive, 'seek') and hasattr(archive, 'tell')
|
| +
|
| + def delete_archive(self, vault_name, archive_id):
|
| + """
|
| + This operation deletes an archive from a vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the new vault
|
| +
|
| + :type archive_id: str
|
| + :param archive_id: The ID for the archive to be deleted.
|
| + """
|
| + uri = 'vaults/%s/archives/%s' % (vault_name, archive_id)
|
| + return self.make_request('DELETE', uri, ok_responses=(204,))
|
| +
|
| + # Multipart
|
| +
|
| + def initiate_multipart_upload(self, vault_name, part_size,
|
| + description=None):
|
| + """
|
| + Initiate a multipart upload. Amazon Glacier creates a
|
| + multipart upload resource and returns it's ID. You use this
|
| + ID in subsequent multipart upload operations.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type description: str
|
| + :param description: An optional description of the archive.
|
| +
|
| + :type part_size: int
|
| + :param part_size: The size of each part except the last, in bytes.
|
| + The part size must be a multiple of 1024 KB multiplied by
|
| + a power of 2. The minimum allowable part size is 1MB and the
|
| + maximum is 4GB.
|
| + """
|
| + response_headers = [('x-amz-multipart-upload-id', u'UploadId'),
|
| + ('Location', u'Location')]
|
| + headers = {'x-amz-part-size': str(part_size)}
|
| + if description:
|
| + headers['x-amz-archive-description'] = description
|
| + uri = 'vaults/%s/multipart-uploads' % vault_name
|
| + response = self.make_request('POST', uri, headers=headers,
|
| + ok_responses=(201,),
|
| + response_headers=response_headers)
|
| + return response
|
| +
|
| + def complete_multipart_upload(self, vault_name, upload_id,
|
| + sha256_treehash, archive_size):
|
| + """
|
| + Call this to inform Amazon Glacier that all of the archive parts
|
| + have been uploaded and Amazon Glacier can now assemble the archive
|
| + from the uploaded parts.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type upload_id: str
|
| + :param upload_id: The unique ID associated with this upload
|
| + operation.
|
| +
|
| + :type sha256_treehash: str
|
| + :param sha256_treehash: The SHA256 tree hash of the entire
|
| + archive. It is the tree hash of SHA256 tree hash of the
|
| + individual parts. If the value you specify in the request
|
| + does not match the SHA256 tree hash of the final assembled
|
| + archive as computed by Amazon Glacier, Amazon Glacier
|
| + returns an error and the request fails.
|
| +
|
| + :type archive_size: int
|
| + :param archive_size: The total size, in bytes, of the entire
|
| + archive. This value should be the sum of all the sizes of
|
| + the individual parts that you uploaded.
|
| + """
|
| + response_headers = [('x-amz-archive-id', u'ArchiveId'),
|
| + ('Location', u'Location')]
|
| + headers = {'x-amz-sha256-tree-hash': sha256_treehash,
|
| + 'x-amz-archive-size': str(archive_size)}
|
| + uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id)
|
| + response = self.make_request('POST', uri, headers=headers,
|
| + ok_responses=(201,),
|
| + response_headers=response_headers)
|
| + return response
|
| +
|
| + def abort_multipart_upload(self, vault_name, upload_id):
|
| + """
|
| + Call this to abort a multipart upload identified by the upload ID.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type upload_id: str
|
| + :param upload_id: The unique ID associated with this upload
|
| + operation.
|
| + """
|
| + uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id)
|
| + return self.make_request('DELETE', uri, ok_responses=(204,))
|
| +
|
| + def list_multipart_uploads(self, vault_name, limit=None, marker=None):
|
| + """
|
| + Lists in-progress multipart uploads for the specified vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type limit: int
|
| + :param limit: The maximum number of items returned in the
|
| + response. If you don't specify a value, the operation
|
| + returns up to 1,000 items.
|
| +
|
| + :type marker: str
|
| + :param marker: An opaque string used for pagination. marker
|
| + specifies the item at which the listing should
|
| + begin. Get the marker value from a previous
|
| + response. You need only include the marker if you are
|
| + continuing the pagination of results started in a previous
|
| + request.
|
| + """
|
| + params = {}
|
| + if limit:
|
| + params['limit'] = limit
|
| + if marker:
|
| + params['marker'] = marker
|
| + uri = 'vaults/%s/multipart-uploads' % vault_name
|
| + return self.make_request('GET', uri, params=params)
|
| +
|
| + def list_parts(self, vault_name, upload_id, limit=None, marker=None):
|
| + """
|
| + Lists in-progress multipart uploads for the specified vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type upload_id: str
|
| + :param upload_id: The unique ID associated with this upload
|
| + operation.
|
| +
|
| + :type limit: int
|
| + :param limit: The maximum number of items returned in the
|
| + response. If you don't specify a value, the operation
|
| + returns up to 1,000 items.
|
| +
|
| + :type marker: str
|
| + :param marker: An opaque string used for pagination. marker
|
| + specifies the item at which the listing should
|
| + begin. Get the marker value from a previous
|
| + response. You need only include the marker if you are
|
| + continuing the pagination of results started in a previous
|
| + request.
|
| + """
|
| + params = {}
|
| + if limit:
|
| + params['limit'] = limit
|
| + if marker:
|
| + params['marker'] = marker
|
| + uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id)
|
| + return self.make_request('GET', uri, params=params)
|
| +
|
| + def upload_part(self, vault_name, upload_id, linear_hash,
|
| + tree_hash, byte_range, part_data):
|
| + """
|
| + Lists in-progress multipart uploads for the specified vault.
|
| +
|
| + :type vault_name: str
|
| + :param vault_name: The name of the vault.
|
| +
|
| + :type linear_hash: str
|
| + :param linear_hash: The SHA256 checksum (a linear hash) of the
|
| + payload.
|
| +
|
| + :type tree_hash: str
|
| + :param tree_hash: The user-computed SHA256 tree hash of the
|
| + payload. For more information on computing the
|
| + tree hash, see http://goo.gl/u7chF.
|
| +
|
| + :type upload_id: str
|
| + :param upload_id: The unique ID associated with this upload
|
| + operation.
|
| +
|
| + :type byte_range: tuple of ints
|
| + :param byte_range: Identfies the range of bytes in the assembled
|
| + archive that will be uploaded in this part.
|
| +
|
| + :type part_data: bytes
|
| + :param part_data: The data to be uploaded for the part
|
| + """
|
| + headers = {'x-amz-content-sha256': linear_hash,
|
| + 'x-amz-sha256-tree-hash': tree_hash,
|
| + 'Content-Range': 'bytes %d-%d/*' % byte_range}
|
| + response_headers = [('x-amz-sha256-tree-hash', u'TreeHash')]
|
| + uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id)
|
| + return self.make_request('PUT', uri, headers=headers,
|
| + data=part_data, ok_responses=(204,),
|
| + response_headers=response_headers)
|
|
|