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