return self.len
while self.sending:
- sent = sendfile.sendfile(self.connection.sock.fileno(),
- self.body.fileno(),
- self.offset,
- CHUNKSIZE)
+ try:
+ sent = sendfile.sendfile(self.connection.sock.fileno(),
+ self.body.fileno(),
+ self.offset,
+ CHUNKSIZE)
+ except OSError as e:
+ # suprisingly, sendfile may fail transiently instead of
+ # blocking, in which case we select on the socket in order
+ # to wait on its return to a writeable state before resuming
+ # the send loop
+ if e.errno in (errno.EAGAIN, errno.EBUSY):
+ wlist = [self.connection.sock.fileno()]
+ rfds, wfds, efds = select.select([], wlist, [])
+ if wfds:
+ continue
+ raise
+
self.sending = (sent != 0)
self.offset += sent
yield OfLength(sent)
key.
If use_ssl is True, and this param is None (the
default), then an environ variable
- heat_CLIENT_KEY_FILE is looked for. If no such
+ HEAT_CLIENT_KEY_FILE is looked for. If no such
environ variable is found, ClientConnectionError
will be raised.
:param cert_file: Optional PEM-formatted certificate chain file.
If use_ssl is True, and this param is None (the
default), then an environ variable
- heat_CLIENT_CERT_FILE is looked for. If no such
+ HEAT_CLIENT_CERT_FILE is looked for. If no such
environ variable is found, ClientConnectionError
will be raised.
:param ca_file: Optional CA cert file to use in SSL connections
If use_ssl is True, and this param is None (the
default), then an environ variable
- heat_CLIENT_CA_FILE is looked for.
+ HEAT_CLIENT_CA_FILE is looked for.
:param insecure: Optional. If set then the server's certificate
will not be verified.
"""
connect_kwargs = {}
if self.use_ssl:
if self.key_file is None:
- self.key_file = os.environ.get('heat_CLIENT_KEY_FILE')
+ self.key_file = os.environ.get('HEAT_CLIENT_KEY_FILE')
if self.cert_file is None:
- self.cert_file = os.environ.get('heat_CLIENT_CERT_FILE')
+ self.cert_file = os.environ.get('HEAT_CLIENT_CERT_FILE')
if self.ca_file is None:
- self.ca_file = os.environ.get('heat_CLIENT_CA_FILE')
+ self.ca_file = os.environ.get('HEAT_CLIENT_CA_FILE')
# Check that key_file/cert_file are either both set or both unset
if self.cert_file is not None and self.key_file is None:
"and you have supplied a cert, "
"however you have failed to supply either a "
"key_file parameter or set the "
- "heat_CLIENT_KEY_FILE environ variable")
+ "HEAT_CLIENT_KEY_FILE environ variable")
raise exception.ClientConnectionError(msg)
if self.key_file is not None and self.cert_file is None:
"and you have supplied a key, "
"however you have failed to supply either a "
"cert_file parameter or set the "
- "heat_CLIENT_CERT_FILE environ variable")
+ "HEAT_CLIENT_CERT_FILE environ variable")
raise exception.ClientConnectionError(msg)
if (self.key_file is not None and
raise TypeError('Unsupported image type: %s' % body.__class__)
res = c.getresponse()
+
+ def _retry(res):
+ return res.getheader('Retry-After')
+
status_code = self.get_status_code(res)
if status_code in self.OK_RESPONSE_CODES:
return res
raise exception.Invalid(res.read())
elif status_code == httplib.MULTIPLE_CHOICES:
raise exception.MultipleChoices(body=res.read())
+ elif status_code == httplib.REQUEST_ENTITY_TOO_LARGE:
+ raise exception.LimitExceeded(retry=_retry(res),
+ body=res.read())
elif status_code == httplib.INTERNAL_SERVER_ERROR:
raise Exception("Internal Server error: %s" % res.read())
+ elif status_code == httplib.SERVICE_UNAVAILABLE:
+ raise exception.ServiceUnavailable(retry=_retry(res))
elif status_code == httplib.REQUEST_URI_TOO_LONG:
raise exception.RequestUriTooLong(body=res.read())
else:
"means that you have not included a version indicator in a "
"request URI.\n\nThe body of response returned:\n%(body)s")
+class LimitExceeded(HeatException):
+ message = _("The request returned a 413 Request Entity Too Large. This "
+ "generally means that rate limiting or a quota threshold was "
+ "breached.\n\nThe response body:\n%(body)s")
+
+ def __init__(self, *args, **kwargs):
+ self.retry_after = (int(kwargs['retry']) if kwargs.get('retry')
+ else None)
+ super(LimitExceeded, self).__init__(*args, **kwargs)
+
+
+class ServiceUnavailable(HeatException):
+ message = _("The request returned a 503 ServiceUnavilable. This "
+ "generally occurs on service overload or other transient "
+ "outage.")
+
+ def __init__(self, *args, **kwargs):
+ self.retry_after = (int(kwargs['retry']) if kwargs.get('retry')
+ else None)
+ super(ServiceUnavailable, self).__init__(*args, **kwargs)
+
class RequestUriTooLong(HeatException):
message = _("The URI was too long.")