Exemple #1
0
    def acquire_connection(self, auto_login=True, headers=None, rid=-1):
        '''Check out an available HTTPConnection instance.

        Blocks until a connection is available.
        :auto_login: automatically logins before returning conn
        :headers: header to pass on to login attempt
        :param rid: request id passed in from request eventlet.
        :returns: An available HTTPConnection instance or None if no
                 api_providers are configured.
        '''
        if not self._api_providers:
            LOG.warn(_("[%d] no API providers currently available."), rid)
            return None
        if self._conn_pool.empty():
            LOG.debug(_("[%d] Waiting to acquire API client connection."), rid)
        priority, conn = self._conn_pool.get()
        now = time.time()
        if getattr(conn, 'last_used', now) < now - self.CONN_IDLE_TIMEOUT:
            LOG.info(_("[%(rid)d] Connection %(conn)s idle for %(sec)0.2f "
                       "seconds; reconnecting."),
                     {'rid': rid, 'conn': _conn_str(conn),
                      'sec': now - conn.last_used})
            conn = self._create_connection(*self._conn_params(conn))

        conn.last_used = now
        conn.priority = priority  # stash current priority for release
        qsize = self._conn_pool.qsize()
        LOG.debug(_("[%(rid)d] Acquired connection %(conn)s. %(qsize)d "
                    "connection(s) available."),
                  {'rid': rid, 'conn': _conn_str(conn), 'qsize': qsize})
        if auto_login and self.auth_cookie(conn) is None:
            self._wait_for_login(conn, headers)
        return conn
Exemple #2
0
    def test_conn_str(self):
        conn = httplib.HTTPSConnection("localhost", 4242, timeout=0)
        self.assertTrue(naco._conn_str(conn) == "https://localhost:4242")

        conn = httplib.HTTPConnection("localhost", 4242, timeout=0)
        self.assertTrue(naco._conn_str(conn) == "http://localhost:4242")

        self.assertRaises(TypeError, naco._conn_str, ("not an httplib.HTTPSConnection"))
    def test_conn_str(self):
        conn = httplib.HTTPSConnection('localhost', 4242, timeout=0)
        self.assertTrue(
            naco._conn_str(conn) == 'https://localhost:4242')

        conn = httplib.HTTPConnection('localhost', 4242, timeout=0)
        self.assertTrue(
            naco._conn_str(conn) == 'http://localhost:4242')

        self.assertRaises(TypeError, naco._conn_str,
                          ('not an httplib.HTTPSConnection'))
Exemple #4
0
    def release_connection(self, http_conn, bad_state=False,
                           service_unavail=False, rid=-1):
        '''Mark HTTPConnection instance as available for check-out.

        :param http_conn: An HTTPConnection instance obtained from this
            instance.
        :param bad_state: True if http_conn is known to be in a bad state
                (e.g. connection fault.)
        :service_unavail: True if http_conn returned 503 response.
        :param rid: request id passed in from request eventlet.
        '''
        conn_params = self._conn_params(http_conn)
        if self._conn_params(http_conn) not in self._api_providers:
            LOG.debug(_("[%(rid)d] Released connection %(conn)s is not an "
                        "API provider for the cluster"),
                      {'rid': rid, 'conn': _conn_str(http_conn)})
            return
        elif hasattr(http_conn, "no_release"):
            return

        if bad_state:
            # Reconnect to provider.
            LOG.warn(_("[%(rid)d] Connection returned in bad state, "
                       "reconnecting to %(conn)s"),
                     {'rid': rid, 'conn': _conn_str(http_conn)})
            http_conn = self._create_connection(*self._conn_params(http_conn))
            priority = self._next_conn_priority
            self._next_conn_priority += 1
        elif service_unavail:
            # http_conn returned a service unaviable response, put other
            # connections to the same controller at end of priority queue,
            conns = []
            while not self._conn_pool.empty():
                priority, conn = self._conn_pool.get()
                if self._conn_params(conn) == conn_params:
                    priority = self._next_conn_priority
                    self._next_conn_priority += 1
                conns.append((priority, conn))
            for priority, conn in conns:
                self._conn_pool.put((priority, conn))
            # put http_conn at end of queue also
            priority = self._next_conn_priority
            self._next_conn_priority += 1
        else:
            priority = http_conn.priority

        self._conn_pool.put((priority, http_conn))
        LOG.debug(_("[%(rid)d] Released connection %(conn)s. %(qsize)d "
                    "connection(s) available."),
                  {'rid': rid, 'conn': _conn_str(http_conn),
                   'qsize': self._conn_pool.qsize()})
Exemple #5
0
    def _wait_for_login(self, conn, headers=None):
        '''Block until a login has occurred for the current API provider.'''

        data = self._get_provider_data(conn)
        if data is None:
            LOG.error(_("Login request for an invalid connection: '%s'"),
                      _conn_str(conn))
            return
        provider_sem = data[0]
        if provider_sem.acquire(blocking=False):
            try:
                cookie = self._login(conn, headers)
                self.set_auth_cookie(conn, cookie)
            finally:
                provider_sem.release()
        else:
            LOG.debug(_("Waiting for auth to complete"))
            # Wait until we can aquire then release
            provider_sem.acquire(blocking=True)
            provider_sem.release()
Exemple #6
0
 def _request_str(self, conn, url):
     '''Return string representation of connection.'''
     return "%s %s/%s" % (self._method, _conn_str(conn), url)
Exemple #7
0
 def _request_str(self, conn, url):
     '''Return string representation of connection.'''
     return "%s %s/%s" % (self._method, _conn_str(conn), url)
Exemple #8
0
    def release_connection(self,
                           http_conn,
                           bad_state=False,
                           service_unavail=False,
                           rid=-1):
        '''Mark HTTPConnection instance as available for check-out.

        :param http_conn: An HTTPConnection instance obtained from this
            instance.
        :param bad_state: True if http_conn is known to be in a bad state
                (e.g. connection fault.)
        :service_unavail: True if http_conn returned 503 response.
        :param rid: request id passed in from request eventlet.
        '''
        conn_params = self._conn_params(http_conn)
        if self._conn_params(http_conn) not in self._api_providers:
            LOG.debug(
                _("[%(rid)d] Released connection %(conn)s is not an "
                  "API provider for the cluster"), {
                      'rid': rid,
                      'conn': _conn_str(http_conn)
                  })
            return
        elif hasattr(http_conn, "no_release"):
            return

        if bad_state:
            # Reconnect to provider.
            LOG.warn(
                _("[%(rid)d] Connection returned in bad state, "
                  "reconnecting to %(conn)s"), {
                      'rid': rid,
                      'conn': _conn_str(http_conn)
                  })
            http_conn = self._create_connection(*self._conn_params(http_conn))
            priority = self._next_conn_priority
            self._next_conn_priority += 1
        elif service_unavail:
            # http_conn returned a service unaviable response, put other
            # connections to the same controller at end of priority queue,
            conns = []
            while not self._conn_pool.empty():
                priority, conn = self._conn_pool.get()
                if self._conn_params(conn) == conn_params:
                    priority = self._next_conn_priority
                    self._next_conn_priority += 1
                conns.append((priority, conn))
            for priority, conn in conns:
                self._conn_pool.put((priority, conn))
            # put http_conn at end of queue also
            priority = self._next_conn_priority
            self._next_conn_priority += 1
        else:
            priority = http_conn.priority

        self._conn_pool.put((priority, http_conn))
        LOG.debug(
            _("[%(rid)d] Released connection %(conn)s. %(qsize)d "
              "connection(s) available."), {
                  'rid': rid,
                  'conn': _conn_str(http_conn),
                  'qsize': self._conn_pool.qsize()
              })