mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Improve and fix timeout bug in wait_for_entry()
replication.wait_for_entry() now can wait for an attribute value to appear on a replica. Fixed timeout handling caused by bad rounding and comparison. For small timeouts, the actual time was rounded down. For example for 60 seconds timeout and fast replica, the query accumulated to about 0.45 seconds plus 60 seconds sleep. 60.45 is large enough to terminate the loop "while int(time.time()) < timeout", but not large enough to trigger the exception in "if int(time.time()) > timeout", because int(60.65) == 60. See: https://pagure.io/freeipa/issue/7593 Fixes: https://pagure.io/freeipa/issue/7595 Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
This commit is contained in:
parent
de8d308196
commit
14c869b347
@ -20,6 +20,7 @@
|
|||||||
from __future__ import print_function, absolute_import
|
from __future__ import print_function, absolute_import
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import itertools
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import time
|
import time
|
||||||
@ -160,40 +161,43 @@ def wait_for_task(conn, dn):
|
|||||||
return exit_code
|
return exit_code
|
||||||
|
|
||||||
|
|
||||||
def wait_for_entry(connection, dn, timeout=7200, attr='', quiet=True):
|
def wait_for_entry(connection, dn, timeout=7200, attr=None, attrvalue='*',
|
||||||
"""Wait for entry and/or attr to show up"""
|
quiet=True):
|
||||||
|
"""Wait for entry and/or attr to show up
|
||||||
filter = "(objectclass=*)"
|
"""
|
||||||
|
log = logger.debug if quiet else logger.info
|
||||||
attrlist = []
|
attrlist = []
|
||||||
if attr:
|
if attr is not None:
|
||||||
filter = "(%s=*)" % attr
|
filterstr = ipaldap.LDAPClient.make_filter_from_attr(attr, attrvalue)
|
||||||
attrlist.append(attr)
|
attrlist.append(attr)
|
||||||
timeout += int(time.time())
|
else:
|
||||||
|
filterstr = "(objectclass=*)"
|
||||||
if not quiet:
|
log("Waiting for replication (%s) %s %s", connection, dn, filterstr)
|
||||||
sys.stdout.write("Waiting for %s %s:%s " % (connection, dn, attr))
|
entry = []
|
||||||
sys.stdout.flush()
|
deadline = time.time() + timeout
|
||||||
entry = None
|
for i in itertools.count(start=1):
|
||||||
while not entry and int(time.time()) < timeout:
|
|
||||||
try:
|
try:
|
||||||
[entry] = connection.get_entries(
|
entry = connection.get_entries(
|
||||||
dn, ldap.SCOPE_BASE, filter, attrlist)
|
dn, ldap.SCOPE_BASE, filterstr, attrlist)
|
||||||
except errors.NotFound:
|
except errors.NotFound:
|
||||||
pass # no entry yet
|
pass # no entry yet
|
||||||
except Exception as e: # badness
|
except Exception as e: # badness
|
||||||
logger.error("Error reading entry %s: %s", dn, e)
|
logger.error("Error reading entry %s: %s", dn, e)
|
||||||
raise
|
raise
|
||||||
if not entry:
|
|
||||||
if not quiet:
|
|
||||||
sys.stdout.write(".")
|
|
||||||
sys.stdout.flush()
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
if not entry and int(time.time()) > timeout:
|
if entry:
|
||||||
raise errors.NotFound(
|
log("Entry found %r", entry)
|
||||||
reason="wait_for_entry timeout for %s for %s" % (connection, dn))
|
return
|
||||||
elif entry and not quiet:
|
elif time.time() > deadline:
|
||||||
logger.error("The waited for entry is: %s", entry)
|
raise errors.NotFound(
|
||||||
|
reason="wait_for_entry timeout on {} for {}".format(
|
||||||
|
connection, dn
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if i % 10 == 0:
|
||||||
|
logger.debug("Still waiting for replication of %s", dn)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
class ReplicationManager(object):
|
class ReplicationManager(object):
|
||||||
|
Loading…
Reference in New Issue
Block a user