def __init__(self, status, reason, body=None, *args): super(BotoServerError, self).__init__(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.message = '' self.box_usage = None if isinstance(self.body, bytes): try: self.body = self.body.decode('utf-8') except UnicodeDecodeError: txboto.log.debug('Unable to decode body from bytes!') # Attempt to parse the error response. If body isn't present, # then just ignore the error response. if self.body: # Check if it looks like a ``dict``. if hasattr(self.body, 'items'): # It's not a string, so trying to parse it will fail. # But since it's data, we can work with that. self.request_id = self.body.get('RequestId', None) if 'Error' in self.body: # XML-style error = self.body.get('Error', {}) self.error_code = error.get('Code', None) self.message = error.get('Message', None) else: # JSON-style. self.message = self.body.get('message', None) else: try: h = handler.XmlHandlerWrapper(self, self) h.parseString(self.body) except (TypeError, xml.sax.SAXParseException): # What if it's JSON? Let's try that. try: parsed = json.loads(self.body) if 'RequestId' in parsed: self.request_id = parsed['RequestId'] if 'Error' in parsed: if 'Code' in parsed['Error']: self.error_code = parsed['Error']['Code'] if 'Message' in parsed['Error']: self.message = parsed['Error']['Message'] except (TypeError, ValueError): # 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.message = self.body self.body = None
def _retry_handler(self, response, i, next_sleep): status = None if response.status == 400: response_body = response.read().decode('utf-8') txboto.log.debug(response_body) data = json.loads(response_body) if self.ThruputError in data.get('__type'): self.throughput_exceeded_events += 1 msg = "%s, retry attempt %s" % (self.ThruputError, i) next_sleep = self._exponential_time(i) i += 1 status = (msg, i, next_sleep) if i == self.NumberRetries: # If this was our last retry attempt, raise # a specific error saying that the throughput # was exceeded. raise dynamodb_exceptions.DynamoDBThroughputExceededError( response.status, response.reason, data) elif self.SessionExpiredError in data.get('__type'): msg = 'Renewing Session Token' self._get_session_token() status = (msg, i + self.num_retries - 1, 0) elif self.ConditionalCheckFailedError in data.get('__type'): raise dynamodb_exceptions.DynamoDBConditionalCheckFailedError( response.status, response.reason, data) elif self.ValidationError in data.get('__type'): raise dynamodb_exceptions.DynamoDBValidationError( response.status, response.reason, data) else: raise self.ResponseError(response.status, response.reason, data) expected_crc32 = response.getheader('x-amz-crc32') if self._validate_checksums and expected_crc32 is not None: txboto.log.debug('Validating crc32 checksum for body: %s', response.read().decode('utf-8')) actual_crc32 = crc32(response.read()) & 0xffffffff expected_crc32 = int(expected_crc32) if actual_crc32 != expected_crc32: msg = ("The calculated checksum %s did not match the expected " "checksum %s" % (actual_crc32, expected_crc32)) status = (msg, i + 1, self._exponential_time(i)) return status
def make_request(self, action, body='', object_hook=None): """ :raises: ``DynamoDBExpiredTokenError`` if the security token expires. """ headers = {'X-Amz-Target': '%s_%s.%s' % (self.ServiceName, self.Version, action), 'Host': self.region.endpoint, 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': str(len(body))} http_request = self.build_base_http_request('POST', '/', '/', {}, headers, body, None) start = time.time() response, response_body = yield self._mexe( http_request, sender=None, override_num_retries=self.NumberRetries, retry_handler=self._retry_handler) elapsed = (time.time() - start) * 1000 request_id = response.getheader('x-amzn-RequestId') txboto.log.debug('RequestId: %s' % request_id) txboto.perflog.debug('%s: id=%s time=%sms', headers['X-Amz-Target'], request_id, int(elapsed)) txboto.log.debug(response_body) defer.returnValue(json.loads(response_body, object_hook=object_hook))