Merge "Enable a parameters on ldap to allow paged_search of ldap queries This fixes bug 1083463"

This commit is contained in:
Jenkins 2013-03-04 23:44:07 +00:00 committed by Gerrit Code Review
commit 2505662bba
3 changed files with 57 additions and 4 deletions

View File

@ -137,6 +137,7 @@
# use_dumb_member = False
# allow_subtree_delete = False
# dumb_member = cn=dumb,dc=example,dc=com
# page_size = 0
# The LDAP scope for queries, this can be either 'one'
# (onelevel/singleLevel) or 'sub' (subtree/wholeSubtree)

View File

@ -88,6 +88,7 @@ class BaseLdap(object):
self.LDAP_USER = conf.ldap.user
self.LDAP_PASSWORD = conf.ldap.password
self.LDAP_SCOPE = ldap_scope(conf.ldap.query_scope)
self.page_size = conf.ldap.page_size
if self.options_name is not None:
self.suffix = conf.ldap.suffix
@ -128,7 +129,8 @@ class BaseLdap(object):
if self.LDAP_URL.startswith('fake://'):
conn = fakeldap.FakeLdap(self.LDAP_URL)
else:
conn = LdapWrapper(self.LDAP_URL)
conn = LdapWrapper(self.LDAP_URL,
self.page_size)
if user is None:
user = self.LDAP_USER
@ -361,9 +363,10 @@ class BaseLdap(object):
class LdapWrapper(object):
def __init__(self, url):
def __init__(self, url, page_size):
LOG.debug(_("LDAP init: url=%s"), url)
self.conn = ldap.initialize(url)
self.page_size = page_size
def simple_bind_s(self, user, password):
LOG.debug(_("LDAP bind: dn=%s"), user)
@ -387,15 +390,59 @@ class LdapWrapper(object):
scope,
query,
attrlist)
res = self.conn.search_s(dn, scope, query, attrlist)
if self.page_size:
res = self.paged_search_s(dn, scope, query, attrlist)
else:
res = self.conn.search_s(dn, scope, query, attrlist)
o = []
for dn, attrs in res:
o.append((dn, dict((kind, [ldap2py(x) for x in values])
for kind, values in attrs.iteritems())))
return o
def paged_search_s(self, dn, scope, query, attrlist=None):
res = []
lc = ldap.controls.SimplePagedResultsControl(
controlType=ldap.LDAP_CONTROL_PAGE_OID,
criticality=True,
controlValue=(self.page_size, ''))
msgid = self.conn.search_ext(dn,
scope,
query,
attrlist,
serverctrls=[lc])
# Endless loop request pages on ldap server until it has no data
while True:
# Request to the ldap server a page with 'page_size' entries
rtype, rdata, rmsgid, serverctrls = self.conn.result3(msgid)
# Receive the data
res.extend(rdata)
pctrls = [c for c in serverctrls
if c.controlType == ldap.LDAP_CONTROL_PAGE_OID]
if pctrls:
# LDAP server supports pagination
est, cookie = pctrls[0].controlValue
if cookie:
# There is more data still on the server
# so we request another page
lc.controlValue = (self.page_size, cookie)
msgid = self.conn.search_ext(dn,
scope,
query,
attrlist,
serverctrls=[lc])
else:
# Exit condition no more data on server
break
else:
LOG.warning(_('LDAP Server does not support paging.'
'Disable paging in keystone.conf to'
'avoid this message'))
self._disable_paging()
break
return res
def modify_s(self, dn, modlist):
ldap_modlist = [
(op, kind, (None if values is None
@ -418,6 +465,10 @@ class LdapWrapper(object):
LOG.debug(_("LDAP delete_ext: dn=%s, serverctrls=%s"), dn, serverctrls)
return self.conn.delete_ext_s(dn, serverctrls)
def _disable_paging(self):
# Disable the pagination from now on
self.page_size = 0
class EnabledEmuMixIn(BaseLdap):
"""Emulates boolean 'enabled' attribute if turned on.

View File

@ -250,6 +250,7 @@ register_bool('use_dumb_member', group='ldap', default=False)
register_str('dumb_member', group='ldap', default='cn=dumb,dc=nonexistent')
register_bool('allow_subtree_delete', group='ldap', default=False)
register_str('query_scope', group='ldap', default='one')
register_int('page_size', group='ldap', default=0)
register_str('user_tree_dn', group='ldap', default=None)
register_str('user_filter', group='ldap', default=None)