389-ds postop plugins, such as the managed entry and memberof plugins,
add values after the data has been returned to the client. In the case
of the managed entry plugin this affects the parent entry as well (adds
an objectclass value).
This wreaks havoc on our tests as the values don't match what we expect.
The solution is to wait for the postop plugins to finish their work,
then return. I've added this as an option. The downside is it is going
to naturally slow things down, so it is off by default.
It is currently only used in the hostgroup plugin.
The option is wait_for_attr. Add this to ~/.ipa/default.conf and set it
to True and all the current tests will pass (assuming you apply patches
814-816 as well).
So now we won't have any excuses for missing test failures in the unit
>From f00b4a5f918ff3577fe9c6237f17aedc0d360078 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Fri, 1 Jul 2011 15:32:31 -0400
Subject: [PATCH 4/4] Optionally wait for 389-ds postop plugins to complete
Add a new command that lets you wait for an attribute to appear in
a value. Using this you can do things like wait for a managed entry
to be created, adding a new objectclass to the parent entry.
This is controlled by a new booleon option, wait_for_attr, defaulting
ipalib/constants.py | 1 +
ipalib/plugins/baseldap.py | 34 +++++++++++++++++++++++++++++++++-
ipalib/plugins/hostgroup.py | 7 +++++++
3 files changed, 41 insertions(+), 1 deletions(-)
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 23e80257d0a9b513ceb2478411ede8bcf1acdbe9..026e0735441eabf8dbe63fffa85da69aa151c5d7 100644
@@ -148,6 +148,7 @@ DEFAULT_CONFIG = (
# Enable certain optional plugins:
+ ('wait_for_attr', False),
# Used when verifying that the API hasn't changed. Not for production.
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 2e9991317c5d97cae4495e957a692dfc1f6dfa75..a273798c9a7e6273b989be3c71c884a260807590 100644
@@ -225,7 +225,7 @@ def wait_for_memberof(keys, entry_start, completed, show_command, adding=True):
# FIXME: put a try/except around here? I think it is probably better
# to just let the exception filter up to the caller.
- entry_attrs = api.Command[show_command](keys[-1])['result']
+ entry_attrs = show_command(keys[-1])['result']
if 'memberof' in entry_attrs:
memberof = len(entry_attrs['memberof'])
@@ -238,6 +238,38 @@ def wait_for_memberof(keys, entry_start, completed, show_command, adding=True):
+def wait_for_value(ldap, dn, attr, value, show_command):
+ 389-ds postoperation plugins are executed after the data has been
+ returned to a client. This means that plugins that add data in a
+ postop are not included in data returned to the user.
+ The downside of waiting is that this increases the time of the
+ # Loop a few times to give the postop-plugin a chance to complete
+ # Don't sleep for more than 6 seconds.
+ x = 0
+ while x < 20:
+ # sleep first because the first search, even on a quiet system,
+ # almost always fails.
+ x = x + 1
+ # FIXME: put a try/except around here? I think it is probably better
+ # to just let the exception filter up to the caller.
+ (dn, entry_attrs) = ldap.get_entry( dn, ['*'])
+ if attr in entry_attrs:
+ if isinstance(entry_attrs[attr], (list, tuple)):
+ values = map(lambda y:y.lower(), entry_attrs[attr])
+ if value.lower() in values:
+ if value.lower() == entry_attrs[attr].lower():
+ return entry_attrs[attr]
Object representing a LDAP entry.
diff --git a/ipalib/plugins/hostgroup.py b/ipalib/plugins/hostgroup.py
index c5b96056bfdcd6d039ff1eec68124684324b081d..e22e2b65b6558b79be73cbb7b2568777f5a87966 100644
@@ -98,6 +98,13 @@ class hostgroup_add(LDAPCreate):
msg_summary = _('Added hostgroup "%(value)s"')
+ def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+ if self.api.env.wait_for_attr:
+ ldap = self.obj.backend
+ entry_attrs['objectclass'] = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry', self.api.Command.hostgroup_show)
+ return dn
Freeipa-devel mailing list