diff options
author | Yuriy Nesenenko <ynesenenko@mirantis.com> | 2016-06-22 17:36:49 +0300 |
---|---|---|
committer | Yuriy Nesenenko <ynesenenko@mirantis.com> | 2016-07-06 11:42:20 +0300 |
commit | f8eef18297ec2dba4abf45f8ca57c40c2380cad9 (patch) | |
tree | 85afe6c794d1bd58996064f19056aada532f4210 /cinderclient/exceptions.py | |
parent | 0a92c9fb199b4b6cc32d9081a721d36eaa78a77e (diff) | |
download | python-cinderclient-f8eef18297ec2dba4abf45f8ca57c40c2380cad9.tar.gz |
Cinder client should retry with Retry-After value
If a request fails but the response contains a "Retry-After",
the cinder client should wait the amount of time and then retry.
Cinder client should report a warning to user and continue with
retry, so that user can cancel the operation if not interested
in retry. The value in "Retry-After" header will be in seconds
or GMT value, client should handle both the cases.
How many times client should retry will be controlled by user
through "--retries" argument to cinder api example,
$ cinder --retries 3 availability-zone-list
If request was not sucessful within the retries, client should
raise the exception.
Change-Id: I99af957bfbbe3a202b148dc2fcafdd20b5d7cda0
Partial-Bug: #1263069
Diffstat (limited to 'cinderclient/exceptions.py')
-rw-r--r-- | cinderclient/exceptions.py | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/cinderclient/exceptions.py b/cinderclient/exceptions.py index cab74c6..03a50e7 100644 --- a/cinderclient/exceptions.py +++ b/cinderclient/exceptions.py @@ -16,6 +16,9 @@ """ Exception definitions. """ +from datetime import datetime + +from oslo_utils import timeutils class UnsupportedVersion(Exception): @@ -80,7 +83,8 @@ class ClientException(Exception): """ The base exception class for all exceptions this library raises. """ - def __init__(self, code, message=None, details=None, request_id=None): + def __init__(self, code, message=None, details=None, + request_id=None, response=None): self.code = code # NOTE(mriedem): Use getattr on self.__class__.message since # BaseException.message was dropped in python 3, see PEP 0352. @@ -147,6 +151,27 @@ class OverLimit(ClientException): http_status = 413 message = "Over limit" + def __init__(self, code, message=None, details=None, + request_id=None, response=None): + super(OverLimit, self).__init__(code, message=message, + details=details, request_id=request_id, + response=response) + self.retry_after = 0 + self._get_rate_limit(response) + + def _get_rate_limit(self, resp): + if resp.headers: + utc_now = timeutils.utcnow() + value = resp.headers.get('Retry-After', '0') + try: + value = datetime.strptime(value, '%a, %d %b %Y %H:%M:%S %Z') + if value > utc_now: + self.retry_after = ((value - utc_now).seconds) + else: + self.retry_after = 0 + except ValueError: + self.retry_after = int(value) + # NotImplemented is a python keyword. class HTTPNotImplemented(ClientException): @@ -193,10 +218,10 @@ def from_response(response, body): message = error.get('message', message) details = error.get('details', details) return cls(code=response.status_code, message=message, details=details, - request_id=request_id) + request_id=request_id, response=response) else: return cls(code=response.status_code, request_id=request_id, - message=response.reason) + message=response.reason, response=response) class VersionNotFoundForAPIMethod(Exception): |