OLD | NEW |
1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ | 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ |
2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. |
3 # All rights reserved. | 3 # All rights reserved. |
4 # | 4 # |
5 # Permission is hereby granted, free of charge, to any person obtaining a | 5 # Permission is hereby granted, free of charge, to any person obtaining a |
6 # copy of this software and associated documentation files (the | 6 # copy of this software and associated documentation files (the |
7 # "Software"), to deal in the Software without restriction, including | 7 # "Software"), to deal in the Software without restriction, including |
8 # without limitation the rights to use, copy, modify, merge, publish, dis- | 8 # without limitation the rights to use, copy, modify, merge, publish, dis- |
9 # tribute, sublicense, and/or sell copies of the Software, and to permit | 9 # tribute, sublicense, and/or sell copies of the Software, and to permit |
10 # persons to whom the Software is furnished to do so, subject to the fol- | 10 # persons to whom the Software is furnished to do so, subject to the fol- |
(...skipping 17 matching lines...) Expand all Loading... |
28 import xml.sax | 28 import xml.sax |
29 from boto import handler | 29 from boto import handler |
30 from boto.resultset import ResultSet | 30 from boto.resultset import ResultSet |
31 | 31 |
32 | 32 |
33 class BotoClientError(StandardError): | 33 class BotoClientError(StandardError): |
34 """ | 34 """ |
35 General Boto Client error (error accessing AWS) | 35 General Boto Client error (error accessing AWS) |
36 """ | 36 """ |
37 | 37 |
38 def __init__(self, reason): | 38 def __init__(self, reason, *args): |
39 StandardError.__init__(self) | 39 StandardError.__init__(self, reason, *args) |
40 self.reason = reason | 40 self.reason = reason |
41 | 41 |
42 def __repr__(self): | 42 def __repr__(self): |
43 return 'BotoClientError: %s' % self.reason | 43 return 'BotoClientError: %s' % self.reason |
44 | 44 |
45 def __str__(self): | 45 def __str__(self): |
46 return 'BotoClientError: %s' % self.reason | 46 return 'BotoClientError: %s' % self.reason |
47 | 47 |
48 class SDBPersistenceError(StandardError): | 48 class SDBPersistenceError(StandardError): |
49 | 49 |
(...skipping 12 matching lines...) Expand all Loading... |
62 pass | 62 pass |
63 | 63 |
64 class GSPermissionsError(StoragePermissionsError): | 64 class GSPermissionsError(StoragePermissionsError): |
65 """ | 65 """ |
66 Permissions error when accessing a bucket or key on GS. | 66 Permissions error when accessing a bucket or key on GS. |
67 """ | 67 """ |
68 pass | 68 pass |
69 | 69 |
70 class BotoServerError(StandardError): | 70 class BotoServerError(StandardError): |
71 | 71 |
72 def __init__(self, status, reason, body=None): | 72 def __init__(self, status, reason, body=None, *args): |
73 StandardError.__init__(self) | 73 StandardError.__init__(self, status, reason, body, *args) |
74 self.status = status | 74 self.status = status |
75 self.reason = reason | 75 self.reason = reason |
76 self.body = body or '' | 76 self.body = body or '' |
77 self.request_id = None | 77 self.request_id = None |
78 self.error_code = None | 78 self.error_code = None |
79 self.error_message = None | 79 self.error_message = None |
80 self.box_usage = None | 80 self.box_usage = None |
81 | 81 |
82 # Attempt to parse the error response. If body isn't present, | 82 # Attempt to parse the error response. If body isn't present, |
83 # then just ignore the error response. | 83 # then just ignore the error response. |
84 if self.body: | 84 if self.body: |
85 try: | 85 try: |
86 h = handler.XmlHandler(self, self) | 86 h = handler.XmlHandler(self, self) |
87 xml.sax.parseString(self.body, h) | 87 xml.sax.parseString(self.body, h) |
88 except xml.sax.SAXParseException, pe: | 88 except xml.sax.SAXParseException, pe: |
89 # Go ahead and clean up anything that may have | 89 # Remove unparsable message body so we don't include garbage |
90 # managed to get into the error data so we | 90 # in exception. But first, save self.body in self.error_message |
91 # don't get partial garbage. | 91 # because occasionally we get error messages from Eucalyptus |
92 print "Warning: failed to parse error message from AWS: %s" % pe | 92 # that are just text strings that we want to preserve. |
93 self._cleanupParsedProperties() | 93 self.error_message = self.body |
| 94 self.body = None |
94 | 95 |
95 def __getattr__(self, name): | 96 def __getattr__(self, name): |
96 if name == 'message': | 97 if name == 'message': |
97 return self.error_message | 98 return self.error_message |
98 if name == 'code': | 99 if name == 'code': |
99 return self.error_code | 100 return self.error_code |
100 raise AttributeError | 101 raise AttributeError |
101 | 102 |
102 def __repr__(self): | 103 def __repr__(self): |
103 return '%s: %s %s\n%s' % (self.__class__.__name__, | 104 return '%s: %s %s\n%s' % (self.__class__.__name__, |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 def _cleanupParsedProperties(self): | 215 def _cleanupParsedProperties(self): |
215 BotoServerError._cleanupParsedProperties(self) | 216 BotoServerError._cleanupParsedProperties(self) |
216 for p in ('detail', 'type'): | 217 for p in ('detail', 'type'): |
217 setattr(self, p, None) | 218 setattr(self, p, None) |
218 | 219 |
219 class SQSDecodeError(BotoClientError): | 220 class SQSDecodeError(BotoClientError): |
220 """ | 221 """ |
221 Error when decoding an SQS message. | 222 Error when decoding an SQS message. |
222 """ | 223 """ |
223 def __init__(self, reason, message): | 224 def __init__(self, reason, message): |
224 BotoClientError.__init__(self, reason) | 225 BotoClientError.__init__(self, reason, message) |
225 self.message = message | 226 self.message = message |
226 | 227 |
227 def __repr__(self): | 228 def __repr__(self): |
228 return 'SQSDecodeError: %s' % self.reason | 229 return 'SQSDecodeError: %s' % self.reason |
229 | 230 |
230 def __str__(self): | 231 def __str__(self): |
231 return 'SQSDecodeError: %s' % self.reason | 232 return 'SQSDecodeError: %s' % self.reason |
232 | 233 |
233 class StorageResponseError(BotoServerError): | 234 class StorageResponseError(BotoServerError): |
234 """ | 235 """ |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 """ | 352 """ |
352 pass | 353 pass |
353 | 354 |
354 class FPSResponseError(BotoServerError): | 355 class FPSResponseError(BotoServerError): |
355 pass | 356 pass |
356 | 357 |
357 class InvalidUriError(Exception): | 358 class InvalidUriError(Exception): |
358 """Exception raised when URI is invalid.""" | 359 """Exception raised when URI is invalid.""" |
359 | 360 |
360 def __init__(self, message): | 361 def __init__(self, message): |
361 Exception.__init__(self) | 362 Exception.__init__(self, message) |
362 self.message = message | 363 self.message = message |
363 | 364 |
364 class InvalidAclError(Exception): | 365 class InvalidAclError(Exception): |
365 """Exception raised when ACL XML is invalid.""" | 366 """Exception raised when ACL XML is invalid.""" |
366 | 367 |
367 def __init__(self, message): | 368 def __init__(self, message): |
368 Exception.__init__(self) | 369 Exception.__init__(self, message) |
369 self.message = message | 370 self.message = message |
370 | 371 |
371 class NoAuthHandlerFound(Exception): | 372 class NoAuthHandlerFound(Exception): |
372 """Is raised when no auth handlers were found ready to authenticate.""" | 373 """Is raised when no auth handlers were found ready to authenticate.""" |
373 pass | 374 pass |
374 | 375 |
375 class TooManyAuthHandlerReadyToAuthenticate(Exception): | 376 class TooManyAuthHandlerReadyToAuthenticate(Exception): |
376 """Is raised when there are more than one auth handler ready. | 377 """Is raised when there are more than one auth handler ready. |
377 | 378 |
378 In normal situation there should only be one auth handler that is ready to | 379 In normal situation there should only be one auth handler that is ready to |
379 authenticate. In case where more than one auth handler is ready to | 380 authenticate. In case where more than one auth handler is ready to |
380 authenticate, we raise this exception, to prevent unpredictable behavior | 381 authenticate, we raise this exception, to prevent unpredictable behavior |
381 when multiple auth handlers can handle a particular case and the one chosen | 382 when multiple auth handlers can handle a particular case and the one chosen |
382 depends on the order they were checked. | 383 depends on the order they were checked. |
383 """ | 384 """ |
384 pass | 385 pass |
385 | 386 |
386 # Enum class for resumable upload failure disposition. | 387 # Enum class for resumable upload failure disposition. |
387 class ResumableTransferDisposition(object): | 388 class ResumableTransferDisposition(object): |
388 # START_OVER means an attempt to resume an existing transfer failed, | 389 # START_OVER means an attempt to resume an existing transfer failed, |
389 # and a new resumable upload should be attempted (without delay). | 390 # and a new resumable upload should be attempted (without delay). |
390 START_OVER = 'START_OVER' | 391 START_OVER = 'START_OVER' |
391 | 392 |
392 # WAIT_BEFORE_RETRY means the resumable transfer failed but that it can | 393 # WAIT_BEFORE_RETRY means the resumable transfer failed but that it can |
393 # be retried after a time delay. | 394 # be retried after a time delay within the current process. |
394 WAIT_BEFORE_RETRY = 'WAIT_BEFORE_RETRY' | 395 WAIT_BEFORE_RETRY = 'WAIT_BEFORE_RETRY' |
395 | 396 |
396 # ABORT means the resumable transfer failed and that delaying/retrying | 397 # ABORT_CUR_PROCESS means the resumable transfer failed and that |
397 # within the current process will not help. | 398 # delaying/retrying within the current process will not help. If |
| 399 # resumable transfer included a state tracker file the upload can be |
| 400 # retried again later, in another process (e.g., a later run of gsutil). |
| 401 ABORT_CUR_PROCESS = 'ABORT_CUR_PROCESS' |
| 402 |
| 403 # ABORT means the resumable transfer failed in a way that it does not |
| 404 # make sense to continue in the current process, and further that the |
| 405 # current tracker ID should not be preserved (in a tracker file if one |
| 406 # was specified at resumable upload start time). If the user tries again |
| 407 # later (e.g., a separate run of gsutil) it will get a new resumable |
| 408 # upload ID. |
398 ABORT = 'ABORT' | 409 ABORT = 'ABORT' |
399 | 410 |
400 class ResumableUploadException(Exception): | 411 class ResumableUploadException(Exception): |
401 """ | 412 """ |
402 Exception raised for various resumable upload problems. | 413 Exception raised for various resumable upload problems. |
403 | 414 |
404 self.disposition is of type ResumableTransferDisposition. | 415 self.disposition is of type ResumableTransferDisposition. |
405 """ | 416 """ |
406 | 417 |
407 def __init__(self, message, disposition): | 418 def __init__(self, message, disposition): |
408 Exception.__init__(self) | 419 Exception.__init__(self, message, disposition) |
409 self.message = message | 420 self.message = message |
410 self.disposition = disposition | 421 self.disposition = disposition |
411 | 422 |
412 def __repr__(self): | 423 def __repr__(self): |
413 return 'ResumableUploadException("%s", %s)' % ( | 424 return 'ResumableUploadException("%s", %s)' % ( |
414 self.message, self.disposition) | 425 self.message, self.disposition) |
415 | 426 |
416 class ResumableDownloadException(Exception): | 427 class ResumableDownloadException(Exception): |
417 """ | 428 """ |
418 Exception raised for various resumable download problems. | 429 Exception raised for various resumable download problems. |
419 | 430 |
420 self.disposition is of type ResumableTransferDisposition. | 431 self.disposition is of type ResumableTransferDisposition. |
421 """ | 432 """ |
422 | 433 |
423 def __init__(self, message, disposition): | 434 def __init__(self, message, disposition): |
424 Exception.__init__(self) | 435 Exception.__init__(self, message, disposition) |
425 self.message = message | 436 self.message = message |
426 self.disposition = disposition | 437 self.disposition = disposition |
427 | 438 |
428 def __repr__(self): | 439 def __repr__(self): |
429 return 'ResumableDownloadException("%s", %s)' % ( | 440 return 'ResumableDownloadException("%s", %s)' % ( |
430 self.message, self.disposition) | 441 self.message, self.disposition) |
OLD | NEW |