mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Support searches with paged results control in LDAPClient.
https://fedorahosted.org/freeipa/ticket/3971
This commit is contained in:
parent
8013056194
commit
a9bf18ab95
@ -31,6 +31,7 @@ import ldap
|
|||||||
import ldap.sasl
|
import ldap.sasl
|
||||||
import ldap.filter
|
import ldap.filter
|
||||||
from ldap.ldapobject import SimpleLDAPObject
|
from ldap.ldapobject import SimpleLDAPObject
|
||||||
|
from ldap.controls import SimplePagedResultsControl
|
||||||
import ldapurl
|
import ldapurl
|
||||||
|
|
||||||
from ipalib import errors, _
|
from ipalib import errors, _
|
||||||
@ -1380,7 +1381,7 @@ class LDAPClient(object):
|
|||||||
|
|
||||||
def find_entries(self, filter=None, attrs_list=None, base_dn=None,
|
def find_entries(self, filter=None, attrs_list=None, base_dn=None,
|
||||||
scope=ldap.SCOPE_SUBTREE, time_limit=None,
|
scope=ldap.SCOPE_SUBTREE, time_limit=None,
|
||||||
size_limit=None, search_refs=False):
|
size_limit=None, search_refs=False, paged_search=False):
|
||||||
"""
|
"""
|
||||||
Return a list of entries and indication of whether the results were
|
Return a list of entries and indication of whether the results were
|
||||||
truncated ([(dn, entry_attrs)], truncated) matching specified search
|
truncated ([(dn, entry_attrs)], truncated) matching specified search
|
||||||
@ -1396,6 +1397,7 @@ class LDAPClient(object):
|
|||||||
(default unlimited)
|
(default unlimited)
|
||||||
search_refs -- allow search references to be returned
|
search_refs -- allow search references to be returned
|
||||||
(default skips these entries)
|
(default skips these entries)
|
||||||
|
paged_search -- search using paged results control
|
||||||
"""
|
"""
|
||||||
if base_dn is None:
|
if base_dn is None:
|
||||||
base_dn = DN()
|
base_dn = DN()
|
||||||
@ -1417,24 +1419,65 @@ class LDAPClient(object):
|
|||||||
if attrs_list:
|
if attrs_list:
|
||||||
attrs_list = [a.lower() for a in set(attrs_list)]
|
attrs_list = [a.lower() for a in set(attrs_list)]
|
||||||
|
|
||||||
|
sctrls = None
|
||||||
|
cookie = ''
|
||||||
|
page_size = (size_limit if size_limit > 0 else 2000) - 1
|
||||||
|
if page_size == 0:
|
||||||
|
paged_search = False
|
||||||
|
|
||||||
# pass arguments to python-ldap
|
# pass arguments to python-ldap
|
||||||
with self.error_handler():
|
with self.error_handler():
|
||||||
try:
|
while True:
|
||||||
id = self.conn.search_ext(
|
if paged_search:
|
||||||
base_dn, scope, filter, attrs_list, timeout=time_limit,
|
sctrls = [SimplePagedResultsControl(0, page_size, cookie)]
|
||||||
sizelimit=size_limit
|
|
||||||
)
|
try:
|
||||||
while True:
|
id = self.conn.search_ext(
|
||||||
(objtype, res_list) = self.conn.result(id, 0)
|
base_dn, scope, filter, attrs_list,
|
||||||
if not res_list:
|
serverctrls=sctrls, timeout=time_limit,
|
||||||
|
sizelimit=size_limit
|
||||||
|
)
|
||||||
|
while True:
|
||||||
|
result = self.conn.result3(id, 0)
|
||||||
|
objtype, res_list, res_id, res_ctrls = result
|
||||||
|
if not res_list:
|
||||||
|
break
|
||||||
|
if (objtype == ldap.RES_SEARCH_ENTRY or
|
||||||
|
(search_refs and
|
||||||
|
objtype == ldap.RES_SEARCH_REFERENCE)):
|
||||||
|
res.append(res_list[0])
|
||||||
|
|
||||||
|
if paged_search:
|
||||||
|
# Get cookie for the next page
|
||||||
|
for ctrl in res_ctrls:
|
||||||
|
if isinstance(ctrl, SimplePagedResultsControl):
|
||||||
|
cookie = ctrl.cookie
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
cookie = ''
|
||||||
|
except ldap.LDAPError, e:
|
||||||
|
# If paged search is in progress, try to cancel it
|
||||||
|
if paged_search and cookie:
|
||||||
|
sctrls = [SimplePagedResultsControl(0, 0, cookie)]
|
||||||
|
try:
|
||||||
|
self.conn.search_ext_s(
|
||||||
|
base_dn, scope, filter, attrs_list,
|
||||||
|
serverctrls=sctrls, timeout=time_limit,
|
||||||
|
sizelimit=size_limit)
|
||||||
|
except ldap.LDAPError, e:
|
||||||
|
self.log.warning(
|
||||||
|
"Error cancelling paged search: %s", e)
|
||||||
|
cookie = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
raise e
|
||||||
|
except (ldap.ADMINLIMIT_EXCEEDED, ldap.TIMELIMIT_EXCEEDED,
|
||||||
|
ldap.SIZELIMIT_EXCEEDED):
|
||||||
|
truncated = True
|
||||||
break
|
break
|
||||||
if (objtype == ldap.RES_SEARCH_ENTRY or
|
|
||||||
(search_refs and
|
if not paged_search or not cookie:
|
||||||
objtype == ldap.RES_SEARCH_REFERENCE)):
|
break
|
||||||
res.append(res_list[0])
|
|
||||||
except (ldap.ADMINLIMIT_EXCEEDED, ldap.TIMELIMIT_EXCEEDED,
|
|
||||||
ldap.SIZELIMIT_EXCEEDED), e:
|
|
||||||
truncated = True
|
|
||||||
|
|
||||||
if not res and not truncated:
|
if not res and not truncated:
|
||||||
raise errors.NotFound(reason='no such entry')
|
raise errors.NotFound(reason='no such entry')
|
||||||
|
@ -183,7 +183,7 @@ class ldap2(LDAPClient, CrudBackend):
|
|||||||
|
|
||||||
def find_entries(self, filter=None, attrs_list=None, base_dn=None,
|
def find_entries(self, filter=None, attrs_list=None, base_dn=None,
|
||||||
scope=_ldap.SCOPE_SUBTREE, time_limit=None,
|
scope=_ldap.SCOPE_SUBTREE, time_limit=None,
|
||||||
size_limit=None, search_refs=False):
|
size_limit=None, search_refs=False, paged_search=False):
|
||||||
if time_limit is None or size_limit is None:
|
if time_limit is None or size_limit is None:
|
||||||
config = self.get_ipa_config()
|
config = self.get_ipa_config()
|
||||||
if time_limit is None:
|
if time_limit is None:
|
||||||
@ -194,7 +194,7 @@ class ldap2(LDAPClient, CrudBackend):
|
|||||||
res, truncated = super(ldap2, self).find_entries(
|
res, truncated = super(ldap2, self).find_entries(
|
||||||
filter=filter, attrs_list=attrs_list, base_dn=base_dn, scope=scope,
|
filter=filter, attrs_list=attrs_list, base_dn=base_dn, scope=scope,
|
||||||
time_limit=time_limit, size_limit=size_limit,
|
time_limit=time_limit, size_limit=size_limit,
|
||||||
search_refs=search_refs)
|
search_refs=search_refs, paged_search=paged_search)
|
||||||
|
|
||||||
if attrs_list and (
|
if attrs_list and (
|
||||||
'memberindirect' in attrs_list or '*' in attrs_list):
|
'memberindirect' in attrs_list or '*' in attrs_list):
|
||||||
|
Loading…
Reference in New Issue
Block a user