mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
New LDAP connection pool that does locking
This commit is contained in:
parent
60ce1db581
commit
eddc5d4e42
@ -265,10 +265,11 @@ class IPAdmin(SimpleLDAPObject):
|
|||||||
def set_proxydn(self, proxydn):
|
def set_proxydn(self, proxydn):
|
||||||
self.proxydn = proxydn
|
self.proxydn = proxydn
|
||||||
|
|
||||||
def set_krbccache(self, krbccache):
|
def set_krbccache(self, krbccache, principal):
|
||||||
if krbccache is not None:
|
if krbccache is not None:
|
||||||
os.environ["KRB5CCNAME"] = krbccache
|
os.environ["KRB5CCNAME"] = krbccache
|
||||||
self.sasl_interactive_bind_s("", sasl_auth)
|
self.sasl_interactive_bind_s("", sasl_auth)
|
||||||
|
self.principal = principal
|
||||||
self.proxydn = None
|
self.proxydn = None
|
||||||
|
|
||||||
def getEntry(self,*args):
|
def getEntry(self,*args):
|
||||||
|
@ -34,6 +34,11 @@ from types import *
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
try:
|
||||||
|
from threading import Lock
|
||||||
|
except ImportError:
|
||||||
|
from dummy_threading import Lock
|
||||||
|
|
||||||
# Need a global to store this between requests
|
# Need a global to store this between requests
|
||||||
_LDAPPool = None
|
_LDAPPool = None
|
||||||
|
|
||||||
@ -45,35 +50,68 @@ DefaultGroupContainer = "cn=groups,cn=accounts"
|
|||||||
# connection. This could theoretically drive the total number of connections
|
# connection. This could theoretically drive the total number of connections
|
||||||
# very high but since this represents just the administrative interface
|
# very high but since this represents just the administrative interface
|
||||||
# this is not anticipated.
|
# this is not anticipated.
|
||||||
class IPAConnPool:
|
#
|
||||||
def __init__(self):
|
# The pool consists of two things, a dictionary keyed on the principal name
|
||||||
self.freelist = []
|
# that contains the connection and a list that is used to keep track of the
|
||||||
|
# order. If the list fills up just pop the top entry off and you've got
|
||||||
|
# the least recently used.
|
||||||
|
|
||||||
def getConn(self, host, port, bindca, bindcert, bindkey, proxydn=None, krbccache=None, debug=None):
|
# maxsize = 0 means no limit
|
||||||
|
class IPAConnPool:
|
||||||
|
def __init__(self, maxsize = 0):
|
||||||
|
self._dict = {}
|
||||||
|
self._lru = []
|
||||||
|
self._lock = Lock()
|
||||||
|
self._maxsize = maxsize
|
||||||
|
self._ctx = krbV.default_context()
|
||||||
|
|
||||||
|
def getConn(self, host, port, krbccache=None, debug=None):
|
||||||
conn = None
|
conn = None
|
||||||
if len(self.freelist) > 0:
|
ccache = krbV.CCache(name=krbccache, context=self._ctx)
|
||||||
for i in range(len(self.freelist)):
|
cprinc = ccache.principal()
|
||||||
c = self.freelist[i]
|
self._lock.acquire()
|
||||||
if ((c.host == host) and (c.port == port)):
|
try:
|
||||||
conn = self.freelist.pop(i)
|
try:
|
||||||
break
|
conn = self._dict[cprinc.name]
|
||||||
if conn is None:
|
del self._dict[cprinc.name]
|
||||||
conn = ipaserver.ipaldap.IPAdmin(host,port,bindca,bindcert,bindkey,None,debug)
|
self._lru.remove(cprinc.name)
|
||||||
if proxydn is not None:
|
except KeyError:
|
||||||
conn.set_proxydn(proxydn)
|
conn = ipaserver.ipaldap.IPAdmin(host,port,None,None,None,debug)
|
||||||
else:
|
conn.set_krbccache(krbccache, cprinc.name)
|
||||||
conn.set_krbccache(krbccache)
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
def releaseConn(self, conn):
|
def releaseConn(self, conn):
|
||||||
if conn is None:
|
if conn is None:
|
||||||
return
|
return
|
||||||
# We can't re-use SASL connections. If proxydn is None it means
|
|
||||||
# we have a Kerberos credentials cache set. See ipaldap.set_krbccache
|
cprinc = conn.principal
|
||||||
if conn.proxydn is None:
|
|
||||||
conn.unbind_s()
|
self._lock.acquire()
|
||||||
else:
|
try:
|
||||||
self.freelist.append(conn)
|
|
||||||
|
# Look to see if we are already on the list from another source and
|
||||||
|
# if so, remove it.
|
||||||
|
try:
|
||||||
|
c = self._dict[cprinc]
|
||||||
|
del self._dict[cprinc]
|
||||||
|
self._lru.remove(cprinc)
|
||||||
|
except KeyError:
|
||||||
|
# Not in the list
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self._maxsize and len(self._dict) > self._maxsize:
|
||||||
|
princ = self._lru.pop(0)
|
||||||
|
c = self._dict[princ]
|
||||||
|
c.unbind_s()
|
||||||
|
del self._dict[cprinc]
|
||||||
|
|
||||||
|
self._lru.append(cprinc)
|
||||||
|
self._dict[cprinc] = conn
|
||||||
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
class IPAServer:
|
class IPAServer:
|
||||||
|
|
||||||
@ -90,7 +128,7 @@ class IPAServer:
|
|||||||
self.realm = self.krbctx.default_realm
|
self.realm = self.krbctx.default_realm
|
||||||
|
|
||||||
if _LDAPPool is None:
|
if _LDAPPool is None:
|
||||||
_LDAPPool = IPAConnPool()
|
_LDAPPool = IPAConnPool(128)
|
||||||
self.basedn = ipa.ipautil.realm_to_suffix(self.realm)
|
self.basedn = ipa.ipautil.realm_to_suffix(self.realm)
|
||||||
self.scope = ldap.SCOPE_SUBTREE
|
self.scope = ldap.SCOPE_SUBTREE
|
||||||
self.princ = None
|
self.princ = None
|
||||||
@ -169,7 +207,7 @@ class IPAServer:
|
|||||||
raise ipaerror.gen_exception(ipaerror.CONNECTION_NO_CCACHE)
|
raise ipaerror.gen_exception(ipaerror.CONNECTION_NO_CCACHE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conn = _LDAPPool.getConn(self.host,port,bindca,bindcert,bindkey,proxy_dn,krbccache,debug)
|
conn = _LDAPPool.getConn(self.host,port,krbccache,debug)
|
||||||
except ldap.INVALID_CREDENTIALS, e:
|
except ldap.INVALID_CREDENTIALS, e:
|
||||||
raise ipaerror.gen_exception(ipaerror.CONNECTION_GSSAPI_CREDENTIALS, nested_exception=e)
|
raise ipaerror.gen_exception(ipaerror.CONNECTION_GSSAPI_CREDENTIALS, nested_exception=e)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user