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
def acquire_connection(self): """Check out an available HTTPConnection instance. Blocks until a connection is available. Returns: An available HTTPConnection instance or None if no api_providers are configured. """ if not self._api_providers: return None # The sleep time is to give controllers time to become consistent after # there has been a change in the controller used as the api_provider. now = time.time() if now < getattr(self, '_issue_conn_barrier', now): LOG.info("acquire_connection() waiting for timer to expire.") time.sleep(self._issue_conn_barrier - now) if self._active_conn_pool.empty(): LOG.debug("Waiting to acquire an API client connection") # get() call is blocking. conn = self._active_conn_pool.get() now = time.time() if getattr(conn, 'last_used', now) < now - self.CONN_IDLE_TIMEOUT: LOG.info("Connection %s idle for %0.2f seconds; reconnecting." % (_conn_str(conn), now - conn.last_used)) conn = self._create_connection(*self._conn_params(conn)) # Stash conn pool so conn knows where to go when it releases. conn.conn_pool = self._active_conn_pool conn.last_used = now LOG.debug("API client connection %s acquired" % _conn_str(conn)) return conn
def release_connection(self, http_conn, bad_state=False): """Mark HTTPConnection instance as available for check-out. Args: http_conn: An HTTPConnection instance obtained from this instance. bad_state: True if http_conn is known to be in a bad state (e.g. connection fault.) """ if self._conn_params(http_conn) not in self._api_providers: LOG.debug(("Released connection '%s' is no longer an API provider " "for the cluster") % _conn_str(http_conn)) return # Retrieve "home" connection pool. conn_pool = http_conn.conn_pool if bad_state: # reconnect LOG.info("API connection fault, reconnecting to %s" % _conn_str(http_conn)) http_conn = self._create_connection(*self._conn_params(http_conn)) http_conn.conn_pool = conn_pool conn_pool.put(http_conn) if self._active_conn_pool == http_conn.conn_pool: # Get next connection from the connection pool and make it # active. LOG.info("API connection fault changing active_conn_pool.") self._conn_pool.put(self._active_conn_pool) self._active_conn_pool = self._conn_pool.get() self._issue_conn_barrier = time.time() + self._failover_time else: conn_pool.put(http_conn) LOG.debug("API client connection %s released" % _conn_str(http_conn))
def acquire_connection(self): """Check out an available HTTPConnection instance. Blocks until a connection is available. Returns: An available HTTPConnection instance or None if no api_providers are configured. """ if not self._api_providers: return None # The sleep time is to give controllers time to become consistent after # there has been a change in the controller used as the api_provider. now = time.time() if now < getattr(self, '_issue_conn_barrier', now): LOG.info("acquire_connection() waiting for timer to expire.") time.sleep(self._issue_conn_barrier - now) if self._active_conn_pool.empty(): LOG.debug("Waiting to acquire an API client connection") # get() call is blocking. conn = self._active_conn_pool.get() now = time.time() if getattr(conn, 'last_used', now) < now - self.CONN_IDLE_TIMEOUT: LOG.info("Connection %s idle for %0.2f seconds; reconnecting." % (_conn_str(conn), now - conn.last_used)) conn = self._create_connection(*self._conn_params(conn)) # Stash conn pool so conn knows where to go when it releases. conn.conn_pool = self._active_conn_pool conn.last_used = now LOG.debug("API client connection %s acquired" % _conn_str(conn)) return conn
def release_connection(self, http_conn, bad_state=False): """Mark HTTPConnection instance as available for check-out. Args: http_conn: An HTTPConnection instance obtained from this instance. bad_state: True if http_conn is known to be in a bad state (e.g. connection fault.) """ if self._conn_params(http_conn) not in self._api_providers: LOG.debug(("Released connection '%s' is no longer an API provider " "for the cluster") % _conn_str(http_conn)) return # Retrieve "home" connection pool. conn_pool = http_conn.conn_pool if bad_state: # reconnect LOG.info("API connection fault, reconnecting to %s" % _conn_str(http_conn)) http_conn = self._create_connection(*self._conn_params(http_conn)) http_conn.conn_pool = conn_pool conn_pool.put(http_conn) if self._active_conn_pool == http_conn.conn_pool: # Get next connection from the connection pool and make it # active. LOG.info("API connection fault changing active_conn_pool.") self._conn_pool.put(self._active_conn_pool) self._active_conn_pool = self._conn_pool.get() self._issue_conn_barrier = time.time() + self._failover_time else: conn_pool.put(http_conn) LOG.debug("API client connection %s released" % _conn_str(http_conn))
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'))
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 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()})
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
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()
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()
def _request_str(self, conn, url): return "%s %s/%s" % (self._method, _conn_str(conn), url)
def _request_str(self, conn, url): '''Return string representation of connection.''' return "%s %s/%s" % (self._method, _conn_str(conn), url)
def _request_str(self, conn, url): return "%s %s/%s" % (self._method, _conn_str(conn), url)
def _request_str(self, conn, url): '''Return string representation of connection.''' return "%s %s/%s" % (self._method, _conn_str(conn), url)
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() })