| Index: third_party/boto/exception.py
|
| diff --git a/third_party/boto/exception.py b/third_party/boto/exception.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ebfd982e851af745164ca4f116bde622d8670bc1
|
| --- /dev/null
|
| +++ b/third_party/boto/exception.py
|
| @@ -0,0 +1,476 @@
|
| +# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/
|
| +# Copyright (c) 2010, Eucalyptus Systems, Inc.
|
| +# 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.
|
| +
|
| +"""
|
| +Exception classes - Subclassing allows you to check for specific errors
|
| +"""
|
| +import base64
|
| +import xml.sax
|
| +from boto import handler
|
| +from boto.resultset import ResultSet
|
| +
|
| +
|
| +class BotoClientError(StandardError):
|
| + """
|
| + General Boto Client error (error accessing AWS)
|
| + """
|
| +
|
| + def __init__(self, reason, *args):
|
| + StandardError.__init__(self, reason, *args)
|
| + self.reason = reason
|
| +
|
| + def __repr__(self):
|
| + return 'BotoClientError: %s' % self.reason
|
| +
|
| + def __str__(self):
|
| + return 'BotoClientError: %s' % self.reason
|
| +
|
| +class SDBPersistenceError(StandardError):
|
| +
|
| + pass
|
| +
|
| +class StoragePermissionsError(BotoClientError):
|
| + """
|
| + Permissions error when accessing a bucket or key on a storage service.
|
| + """
|
| + pass
|
| +
|
| +class S3PermissionsError(StoragePermissionsError):
|
| + """
|
| + Permissions error when accessing a bucket or key on S3.
|
| + """
|
| + pass
|
| +
|
| +class GSPermissionsError(StoragePermissionsError):
|
| + """
|
| + Permissions error when accessing a bucket or key on GS.
|
| + """
|
| + pass
|
| +
|
| +class BotoServerError(StandardError):
|
| +
|
| + def __init__(self, status, reason, body=None, *args):
|
| + StandardError.__init__(self, status, reason, body, *args)
|
| + self.status = status
|
| + self.reason = reason
|
| + self.body = body or ''
|
| + self.request_id = None
|
| + self.error_code = None
|
| + self.error_message = None
|
| + self.box_usage = None
|
| +
|
| + # Attempt to parse the error response. If body isn't present,
|
| + # then just ignore the error response.
|
| + if self.body:
|
| + try:
|
| + h = handler.XmlHandler(self, self)
|
| + xml.sax.parseString(self.body, h)
|
| + except (TypeError, xml.sax.SAXParseException), pe:
|
| + # Remove unparsable message body so we don't include garbage
|
| + # in exception. But first, save self.body in self.error_message
|
| + # because occasionally we get error messages from Eucalyptus
|
| + # that are just text strings that we want to preserve.
|
| + self.error_message = self.body
|
| + self.body = None
|
| +
|
| + def __getattr__(self, name):
|
| + if name == 'message':
|
| + return self.error_message
|
| + if name == 'code':
|
| + return self.error_code
|
| + raise AttributeError
|
| +
|
| + def __repr__(self):
|
| + return '%s: %s %s\n%s' % (self.__class__.__name__,
|
| + self.status, self.reason, self.body)
|
| +
|
| + def __str__(self):
|
| + return '%s: %s %s\n%s' % (self.__class__.__name__,
|
| + self.status, self.reason, self.body)
|
| +
|
| + def startElement(self, name, attrs, connection):
|
| + pass
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name in ('RequestId', 'RequestID'):
|
| + self.request_id = value
|
| + elif name == 'Code':
|
| + self.error_code = value
|
| + elif name == 'Message':
|
| + self.error_message = value
|
| + elif name == 'BoxUsage':
|
| + self.box_usage = value
|
| + return None
|
| +
|
| + def _cleanupParsedProperties(self):
|
| + self.request_id = None
|
| + self.error_code = None
|
| + self.error_message = None
|
| + self.box_usage = None
|
| +
|
| +class ConsoleOutput:
|
| +
|
| + def __init__(self, parent=None):
|
| + self.parent = parent
|
| + self.instance_id = None
|
| + self.timestamp = None
|
| + self.comment = None
|
| + self.output = None
|
| +
|
| + def startElement(self, name, attrs, connection):
|
| + return None
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name == 'instanceId':
|
| + self.instance_id = value
|
| + elif name == 'output':
|
| + self.output = base64.b64decode(value)
|
| + else:
|
| + setattr(self, name, value)
|
| +
|
| +class StorageCreateError(BotoServerError):
|
| + """
|
| + Error creating a bucket or key on a storage service.
|
| + """
|
| + def __init__(self, status, reason, body=None):
|
| + self.bucket = None
|
| + BotoServerError.__init__(self, status, reason, body)
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name == 'BucketName':
|
| + self.bucket = value
|
| + else:
|
| + return BotoServerError.endElement(self, name, value, connection)
|
| +
|
| +class S3CreateError(StorageCreateError):
|
| + """
|
| + Error creating a bucket or key on S3.
|
| + """
|
| + pass
|
| +
|
| +class GSCreateError(StorageCreateError):
|
| + """
|
| + Error creating a bucket or key on GS.
|
| + """
|
| + pass
|
| +
|
| +class StorageCopyError(BotoServerError):
|
| + """
|
| + Error copying a key on a storage service.
|
| + """
|
| + pass
|
| +
|
| +class S3CopyError(StorageCopyError):
|
| + """
|
| + Error copying a key on S3.
|
| + """
|
| + pass
|
| +
|
| +class GSCopyError(StorageCopyError):
|
| + """
|
| + Error copying a key on GS.
|
| + """
|
| + pass
|
| +
|
| +class SQSError(BotoServerError):
|
| + """
|
| + General Error on Simple Queue Service.
|
| + """
|
| + def __init__(self, status, reason, body=None):
|
| + self.detail = None
|
| + self.type = None
|
| + BotoServerError.__init__(self, status, reason, body)
|
| +
|
| + def startElement(self, name, attrs, connection):
|
| + return BotoServerError.startElement(self, name, attrs, connection)
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name == 'Detail':
|
| + self.detail = value
|
| + elif name == 'Type':
|
| + self.type = value
|
| + else:
|
| + return BotoServerError.endElement(self, name, value, connection)
|
| +
|
| + def _cleanupParsedProperties(self):
|
| + BotoServerError._cleanupParsedProperties(self)
|
| + for p in ('detail', 'type'):
|
| + setattr(self, p, None)
|
| +
|
| +class SQSDecodeError(BotoClientError):
|
| + """
|
| + Error when decoding an SQS message.
|
| + """
|
| + def __init__(self, reason, message):
|
| + BotoClientError.__init__(self, reason, message)
|
| + self.message = message
|
| +
|
| + def __repr__(self):
|
| + return 'SQSDecodeError: %s' % self.reason
|
| +
|
| + def __str__(self):
|
| + return 'SQSDecodeError: %s' % self.reason
|
| +
|
| +class StorageResponseError(BotoServerError):
|
| + """
|
| + Error in response from a storage service.
|
| + """
|
| + def __init__(self, status, reason, body=None):
|
| + self.resource = None
|
| + BotoServerError.__init__(self, status, reason, body)
|
| +
|
| + def startElement(self, name, attrs, connection):
|
| + return BotoServerError.startElement(self, name, attrs, connection)
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name == 'Resource':
|
| + self.resource = value
|
| + else:
|
| + return BotoServerError.endElement(self, name, value, connection)
|
| +
|
| + def _cleanupParsedProperties(self):
|
| + BotoServerError._cleanupParsedProperties(self)
|
| + for p in ('resource'):
|
| + setattr(self, p, None)
|
| +
|
| +class S3ResponseError(StorageResponseError):
|
| + """
|
| + Error in response from S3.
|
| + """
|
| + pass
|
| +
|
| +class GSResponseError(StorageResponseError):
|
| + """
|
| + Error in response from GS.
|
| + """
|
| + pass
|
| +
|
| +class EC2ResponseError(BotoServerError):
|
| + """
|
| + Error in response from EC2.
|
| + """
|
| +
|
| + def __init__(self, status, reason, body=None):
|
| + self.errors = None
|
| + self._errorResultSet = []
|
| + BotoServerError.__init__(self, status, reason, body)
|
| + self.errors = [ (e.error_code, e.error_message) \
|
| + for e in self._errorResultSet ]
|
| + if len(self.errors):
|
| + self.error_code, self.error_message = self.errors[0]
|
| +
|
| + def startElement(self, name, attrs, connection):
|
| + if name == 'Errors':
|
| + self._errorResultSet = ResultSet([('Error', _EC2Error)])
|
| + return self._errorResultSet
|
| + else:
|
| + return None
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name == 'RequestID':
|
| + self.request_id = value
|
| + else:
|
| + return None # don't call subclass here
|
| +
|
| + def _cleanupParsedProperties(self):
|
| + BotoServerError._cleanupParsedProperties(self)
|
| + self._errorResultSet = []
|
| + for p in ('errors'):
|
| + setattr(self, p, None)
|
| +
|
| +class JSONResponseError(BotoServerError):
|
| + """
|
| + This exception expects the fully parsed and decoded JSON response
|
| + body to be passed as the body parameter.
|
| +
|
| + :ivar status: The HTTP status code.
|
| + :ivar reason: The HTTP reason message.
|
| + :ivar body: The Python dict that represents the decoded JSON
|
| + response body.
|
| + :ivar error_message: The full description of the AWS error encountered.
|
| + :ivar error_code: A short string that identifies the AWS error
|
| + (e.g. ConditionalCheckFailedException)
|
| + """
|
| + def __init__(self, status, reason, body=None, *args):
|
| + self.status = status
|
| + self.reason = reason
|
| + self.body = body
|
| + if self.body:
|
| + self.error_message = self.body.get('message', None)
|
| + self.error_code = self.body.get('__type', None)
|
| + if self.error_code:
|
| + self.error_code = self.error_code.split('#')[-1]
|
| +
|
| +
|
| +class DynamoDBResponseError(JSONResponseError):
|
| + pass
|
| +
|
| +
|
| +class SWFResponseError(JSONResponseError):
|
| + pass
|
| +
|
| +
|
| +class EmrResponseError(BotoServerError):
|
| + """
|
| + Error in response from EMR
|
| + """
|
| + pass
|
| +
|
| +class _EC2Error:
|
| +
|
| + def __init__(self, connection=None):
|
| + self.connection = connection
|
| + self.error_code = None
|
| + self.error_message = None
|
| +
|
| + def startElement(self, name, attrs, connection):
|
| + return None
|
| +
|
| + def endElement(self, name, value, connection):
|
| + if name == 'Code':
|
| + self.error_code = value
|
| + elif name == 'Message':
|
| + self.error_message = value
|
| + else:
|
| + return None
|
| +
|
| +class SDBResponseError(BotoServerError):
|
| + """
|
| + Error in responses from SDB.
|
| + """
|
| + pass
|
| +
|
| +class AWSConnectionError(BotoClientError):
|
| + """
|
| + General error connecting to Amazon Web Services.
|
| + """
|
| + pass
|
| +
|
| +class StorageDataError(BotoClientError):
|
| + """
|
| + Error receiving data from a storage service.
|
| + """
|
| + pass
|
| +
|
| +class S3DataError(StorageDataError):
|
| + """
|
| + Error receiving data from S3.
|
| + """
|
| + pass
|
| +
|
| +class GSDataError(StorageDataError):
|
| + """
|
| + Error receiving data from GS.
|
| + """
|
| + pass
|
| +
|
| +class InvalidUriError(Exception):
|
| + """Exception raised when URI is invalid."""
|
| +
|
| + def __init__(self, message):
|
| + Exception.__init__(self, message)
|
| + self.message = message
|
| +
|
| +class InvalidAclError(Exception):
|
| + """Exception raised when ACL XML is invalid."""
|
| +
|
| + def __init__(self, message):
|
| + Exception.__init__(self, message)
|
| + self.message = message
|
| +
|
| +class InvalidCorsError(Exception):
|
| + """Exception raised when CORS XML is invalid."""
|
| +
|
| + def __init__(self, message):
|
| + Exception.__init__(self, message)
|
| + self.message = message
|
| +
|
| +class NoAuthHandlerFound(Exception):
|
| + """Is raised when no auth handlers were found ready to authenticate."""
|
| + pass
|
| +
|
| +# Enum class for resumable upload failure disposition.
|
| +class ResumableTransferDisposition(object):
|
| + # START_OVER means an attempt to resume an existing transfer failed,
|
| + # and a new resumable upload should be attempted (without delay).
|
| + START_OVER = 'START_OVER'
|
| +
|
| + # WAIT_BEFORE_RETRY means the resumable transfer failed but that it can
|
| + # be retried after a time delay within the current process.
|
| + WAIT_BEFORE_RETRY = 'WAIT_BEFORE_RETRY'
|
| +
|
| + # ABORT_CUR_PROCESS means the resumable transfer failed and that
|
| + # delaying/retrying within the current process will not help. If
|
| + # resumable transfer included a state tracker file the upload can be
|
| + # retried again later, in another process (e.g., a later run of gsutil).
|
| + ABORT_CUR_PROCESS = 'ABORT_CUR_PROCESS'
|
| +
|
| + # ABORT means the resumable transfer failed in a way that it does not
|
| + # make sense to continue in the current process, and further that the
|
| + # current tracker ID should not be preserved (in a tracker file if one
|
| + # was specified at resumable upload start time). If the user tries again
|
| + # later (e.g., a separate run of gsutil) it will get a new resumable
|
| + # upload ID.
|
| + ABORT = 'ABORT'
|
| +
|
| +class ResumableUploadException(Exception):
|
| + """
|
| + Exception raised for various resumable upload problems.
|
| +
|
| + self.disposition is of type ResumableTransferDisposition.
|
| + """
|
| +
|
| + def __init__(self, message, disposition):
|
| + Exception.__init__(self, message, disposition)
|
| + self.message = message
|
| + self.disposition = disposition
|
| +
|
| + def __repr__(self):
|
| + return 'ResumableUploadException("%s", %s)' % (
|
| + self.message, self.disposition)
|
| +
|
| +class ResumableDownloadException(Exception):
|
| + """
|
| + Exception raised for various resumable download problems.
|
| +
|
| + self.disposition is of type ResumableTransferDisposition.
|
| + """
|
| +
|
| + def __init__(self, message, disposition):
|
| + Exception.__init__(self, message, disposition)
|
| + self.message = message
|
| + self.disposition = disposition
|
| +
|
| + def __repr__(self):
|
| + return 'ResumableDownloadException("%s", %s)' % (
|
| + self.message, self.disposition)
|
| +
|
| +class TooManyRecordsException(Exception):
|
| + """
|
| + Exception raised when a search of Route53 records returns more
|
| + records than requested.
|
| + """
|
| +
|
| + def __init__(self, message):
|
| + Exception.__init__(self, message)
|
| + self.message = message
|
|
|