Upgrade: increase time limit for upgrades

Default ldap search limit is now 30 sec by default during upgrade.

Limits must be changed for the whole ldap2 connection, because this
connection is used inside update plugins and commands called from
upgrade.

Together with increasing the time limit, also size limit should be
unlimited during upgrade. With sizelimit=None we may get the
TimeExceeded exception from getting default value of the sizelimit from LDAP.

https://fedorahosted.org/freeipa/ticket/5267

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Martin Basti
2015-11-18 10:31:05 +01:00
committed by Jan Cholasta
parent 21f7584f9f
commit 2a1a3c498a
4 changed files with 56 additions and 33 deletions

View File

@@ -1292,8 +1292,7 @@ class permission_find(baseldap.LDAPSearch):
if 'sizelimit' in options:
max_entries = options['sizelimit']
else:
config = ldap.get_ipa_config()
max_entries = int(config.single_value['ipasearchrecordslimit'])
max_entries = self.api.Backend.ldap2.size_limit
filters = ['(objectclass=ipaPermission)',
'(!(ipaPermissionType=V2))']

View File

@@ -689,6 +689,9 @@ class LDAPClient(object):
'nsslapd-minssf-exclude-rootdse': True,
})
time_limit = -1.0 # unlimited
size_limit = 0 # unlimited
def __init__(self, ldap_uri, start_tls=False, force_schema_updates=False,
no_schema=False, decode_attrs=True):
"""Create LDAPClient object.
@@ -1294,10 +1297,14 @@ class LDAPClient(object):
res = []
truncated = False
if time_limit is None or time_limit == 0:
if time_limit is None:
time_limit = self.time_limit
if time_limit == 0:
time_limit = -1.0
if size_limit is None:
size_limit = 0
size_limit = self.size_limit
if not isinstance(size_limit, int):
size_limit = int(size_limit)
if not isinstance(time_limit, float):

View File

@@ -46,6 +46,7 @@ from ipapython.ipa_log_manager import *
from ipapython.ipautil import wait_for_open_socket
UPDATES_DIR=paths.UPDATES_DIR
UPDATE_SEARCH_TIME_LIMIT = 30 # seconds
def connect(ldapi=False, realm=None, fqdn=None, dm_password=None, pw_name=None):
@@ -867,7 +868,9 @@ class LDAPUpdate:
self.api.Backend.ldap2.connect(
bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=self.dm_password,
autobind=self.ldapi)
autobind=self.ldapi,
time_limit=UPDATE_SEARCH_TIME_LIMIT,
size_limit=0)
self.conn = self.api.Backend.ldap2
else:
raise RuntimeError("Offline updates are not supported.")

View File

@@ -72,6 +72,39 @@ class ldap2(CrudBackend, LDAPClient):
LDAPClient.__init__(self, ldap_uri,
force_schema_updates=force_schema_updates)
self.__time_limit = None
self.__size_limit = None
@property
def time_limit(self):
if self.__time_limit is None:
return float(self.get_ipa_config().single_value.get(
'ipasearchtimelimit', 2))
return self.__time_limit
@time_limit.setter
def time_limit(self, val):
self.__time_limit = float(val)
@time_limit.deleter
def time_limit(self):
self.__time_limit = None
@property
def size_limit(self):
if self.__size_limit is None:
return int(self.get_ipa_config().single_value.get(
'ipasearchrecordslimit', 0))
return self.__size_limit
@size_limit.setter
def size_limit(self, val):
self.__size_limit = int(val)
@size_limit.deleter
def size_limit(self):
self.__size_limit = None
def _connect(self):
# Connectible.conn is a proxy to thread-local storage;
# do not set it
@@ -87,7 +120,7 @@ class ldap2(CrudBackend, LDAPClient):
def create_connection(self, ccache=None, bind_dn=None, bind_pw='',
tls_cacertfile=None, tls_certfile=None, tls_keyfile=None,
debug_level=0, autobind=AUTOBIND_AUTO, serverctrls=None,
clientctrls=None):
clientctrls=None, time_limit=None, size_limit=None):
"""
Connect to LDAP server.
@@ -114,6 +147,11 @@ class ldap2(CrudBackend, LDAPClient):
if tls_keyfile is not None:
_ldap.set_option(_ldap.OPT_X_TLS_KEYFILE, tls_keyfile)
if time_limit is not None:
self.time_limit = time_limit
if size_limit is not None:
self.size_limit = size_limit
if debug_level:
_ldap.set_option(_ldap.OPT_DEBUG_LEVEL, debug_level)
@@ -175,31 +213,9 @@ class ldap2(CrudBackend, LDAPClient):
# ignore when trying to unbind multiple times
pass
def find_entries(self, filter=None, attrs_list=None, base_dn=None,
scope=_ldap.SCOPE_SUBTREE, time_limit=None,
size_limit=None, search_refs=False, paged_search=False):
del self.time_limit
del self.size_limit
def _get_limits():
"""Get configured global limits, caching them for more calls"""
if not _lims:
config = self.get_ipa_config()
_lims['time'] = int(config.get('ipasearchtimelimit', [None])[0])
_lims['size'] = int(config.get('ipasearchrecordslimit', [None])[0])
return _lims
_lims = {}
if time_limit is None:
time_limit = _get_limits()['time']
if size_limit is None:
size_limit = _get_limits()['size']
res, truncated = super(ldap2, self).find_entries(
filter=filter, attrs_list=attrs_list, base_dn=base_dn, scope=scope,
time_limit=time_limit, size_limit=size_limit,
search_refs=search_refs, paged_search=paged_search)
return (res, truncated)
config_defaults = {'ipasearchtimelimit': [2], 'ipasearchrecordslimit': [0]}
def get_ipa_config(self, attrs_list=None):
"""Returns the IPA configuration entry (dn, entry_attrs)."""
@@ -223,9 +239,7 @@ class ldap2(CrudBackend, LDAPClient):
config_entry = entries[0]
except errors.NotFound:
config_entry = self.make_entry(dn)
for a in self.config_defaults:
if a not in config_entry:
config_entry[a] = self.config_defaults[a]
context.config_entry = config_entry
return config_entry