Revision ec928235 kamaki/clients/__init__.py
b/kamaki/clients/__init__.py | ||
---|---|---|
36 | 36 |
from threading import Thread |
37 | 37 |
from json import dumps, loads |
38 | 38 |
from time import time |
39 |
from httplib import ResponseNotReady |
|
39 |
from httplib import ResponseNotReady, HTTPException
|
|
40 | 40 |
from time import sleep |
41 | 41 |
from random import random |
42 | 42 |
from logging import getLogger |
... | ... | |
185 | 185 |
class ResponseManager(Logged): |
186 | 186 |
"""Manage the http request and handle the response data, headers, etc.""" |
187 | 187 |
|
188 |
def __init__(self, request, poolsize=None): |
|
188 |
def __init__(self, request, poolsize=None, connection_retry_limit=0):
|
|
189 | 189 |
""" |
190 | 190 |
:param request: (RequestManager) |
191 |
|
|
192 |
:param poolsize: (int) the size of the connection pool |
|
193 |
|
|
194 |
:param connection_retry_limit: (int) |
|
191 | 195 |
""" |
196 |
self.CONNECTION_TRY_LIMIT = 1 + connection_retry_limit |
|
192 | 197 |
self.request = request |
193 | 198 |
self._request_performed = False |
194 | 199 |
self.poolsize = poolsize |
... | ... | |
198 | 203 |
return |
199 | 204 |
|
200 | 205 |
pool_kw = dict(size=self.poolsize) if self.poolsize else dict() |
201 |
try: |
|
202 |
with PooledHTTPConnection( |
|
203 |
self.request.netloc, self.request.scheme, |
|
204 |
**pool_kw) as connection: |
|
205 |
self.request.LOG_TOKEN = self.LOG_TOKEN |
|
206 |
self.request.LOG_DATA = self.LOG_DATA |
|
207 |
r = self.request.perform(connection) |
|
208 |
recvlog.info('\n%s <-- %s <-- [req: %s]\n' % ( |
|
209 |
self, r, self.request)) |
|
210 |
self._request_performed = True |
|
211 |
self._status_code, self._status = r.status, unquote(r.reason) |
|
212 |
recvlog.info( |
|
213 |
'%d %s\t[p: %s]' % (self.status_code, self.status, self)) |
|
214 |
self._headers = dict() |
|
215 |
for k, v in r.getheaders(): |
|
216 |
if (not self.LOG_TOKEN) and k.lower() == 'x-auth-token': |
|
217 |
continue |
|
218 |
v = unquote(v) |
|
219 |
self._headers[k] = v |
|
220 |
recvlog.info(' %s: %s\t[p: %s]' % (k, v, self)) |
|
221 |
self._content = r.read() |
|
222 |
recvlog.info('data size: %s\t[p: %s]' % ( |
|
223 |
len(self._content) if self._content else 0, |
|
224 |
self)) |
|
225 |
if self.LOG_DATA and self._content: |
|
226 |
recvlog.info('%s\t[p: %s]' % (self._content, self)) |
|
227 |
except Exception as err: |
|
228 |
from traceback import format_stack |
|
229 |
recvlog.debug('\n'.join(['%s' % type(err)] + format_stack())) |
|
230 |
raise ClientError( |
|
231 |
'Failed while http-connecting to %s (%s)' % ( |
|
232 |
self.request.url, |
|
233 |
err)) |
|
206 |
for retries in range(1, self.CONNECTION_TRY_LIMIT + 1): |
|
207 |
try: |
|
208 |
with PooledHTTPConnection( |
|
209 |
self.request.netloc, self.request.scheme, |
|
210 |
**pool_kw) as connection: |
|
211 |
self.request.LOG_TOKEN = self.LOG_TOKEN |
|
212 |
self.request.LOG_DATA = self.LOG_DATA |
|
213 |
r = self.request.perform(connection) |
|
214 |
recvlog.info('\n%s <-- %s <-- [req: %s]\n' % ( |
|
215 |
self, r, self.request)) |
|
216 |
self._request_performed = True |
|
217 |
self._status_code, self._status = r.status, unquote( |
|
218 |
r.reason) |
|
219 |
recvlog.info( |
|
220 |
'%d %s\t[p: %s]' % ( |
|
221 |
self.status_code, self.status, self)) |
|
222 |
self._headers = dict() |
|
223 |
for k, v in r.getheaders(): |
|
224 |
if (not self.LOG_TOKEN) and ( |
|
225 |
k.lower() == 'x-auth-token'): |
|
226 |
continue |
|
227 |
v = unquote(v) |
|
228 |
self._headers[k] = v |
|
229 |
recvlog.info(' %s: %s\t[p: %s]' % (k, v, self)) |
|
230 |
self._content = r.read() |
|
231 |
recvlog.info('data size: %s\t[p: %s]' % ( |
|
232 |
len(self._content) if self._content else 0, |
|
233 |
self)) |
|
234 |
if self.LOG_DATA and self._content: |
|
235 |
recvlog.info('%s\t[p: %s]' % (self._content, self)) |
|
236 |
break |
|
237 |
except Exception as err: |
|
238 |
if isinstance(err, HTTPException): |
|
239 |
if retries >= self.CONNECTION_TRY_LIMIT: |
|
240 |
raise ClientError( |
|
241 |
'Connection to %s failed %s times (%s: %s )' % ( |
|
242 |
self.request.url, retries, type(err), err)) |
|
243 |
else: |
|
244 |
from traceback import format_stack |
|
245 |
recvlog.debug( |
|
246 |
'\n'.join(['%s' % type(err)] + format_stack())) |
|
247 |
raise ClientError( |
|
248 |
'Failed while http-connecting to %s (%s)' % ( |
|
249 |
self.request.url, |
|
250 |
err)) |
|
234 | 251 |
|
235 | 252 |
@property |
236 | 253 |
def status_code(self): |
... | ... | |
309 | 326 |
'%a, %d %b %Y %H:%M:%S GMT'] |
310 | 327 |
LOG_TOKEN = False |
311 | 328 |
LOG_DATA = False |
329 |
CONNECTION_RETRY_LIMIT = 0 |
|
312 | 330 |
|
313 | 331 |
def __init__(self, base_url, token): |
314 | 332 |
assert base_url, 'No base_url for client %s' % self |
... | ... | |
395 | 413 |
method, self.base_url, path, |
396 | 414 |
data=data, headers=headers, params=params) |
397 | 415 |
# req.log() |
398 |
r = ResponseManager(req) |
|
416 |
r = ResponseManager( |
|
417 |
req, connection_retry_limit=self.CONNECTION_RETRY_LIMIT) |
|
399 | 418 |
r.LOG_TOKEN, r.LOG_DATA = self.LOG_TOKEN, self.LOG_DATA |
400 | 419 |
finally: |
401 | 420 |
self.headers = dict() |
Also available in: Unified diff