summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2011-07-01 15:32:31 -0400
committerMartin Kosek <mkosek@redhat.com>2011-07-19 13:06:16 +0200
commit1dd9e1407361bdd6ed337c70dcb1d209ce034cb6 (patch)
tree1b81a20a3835de965f40f35195ea22fbbe731afc /ipalib
parentc09f116f4331175b3fb01f0bd62e78ef47fab716 (diff)
downloadfreeipa-1dd9e1407361bdd6ed337c70dcb1d209ce034cb6.tar.gz
freeipa-1dd9e1407361bdd6ed337c70dcb1d209ce034cb6.tar.xz
freeipa-1dd9e1407361bdd6ed337c70dcb1d209ce034cb6.zip
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 to False. https://fedorahosted.org/freeipa/ticket/1144
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/constants.py1
-rw-r--r--ipalib/plugins/baseldap.py53
-rw-r--r--ipalib/plugins/hostgroup.py8
-rw-r--r--ipalib/plugins/user.py5
4 files changed, 67 insertions, 0 deletions
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 23e80257d..026e07354 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -148,6 +148,7 @@ DEFAULT_CONFIG = (
# Enable certain optional plugins:
('enable_ra', False),
('ra_plugin', 'selfsign'),
+ ('wait_for_attr', False),
# Used when verifying that the API hasn't changed. Not for production.
('validate_api', False),
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 8d58422bd..1ff7a2a6d 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -194,6 +194,25 @@ def get_effective_rights(ldap, dn, attrs=None):
return rdict
+def entry_from_entry(entry, newentry):
+ """
+ Python is more or less pass-by-value except for immutable objects. So if
+ you pass in a dict to a function you are free to change members of that
+ dict but you can't create a new dict in the function and expect to replace
+ what was passed in.
+
+ In some post-op plugins that is exactly what we want to do, so here is a
+ clumsy way around the problem.
+ """
+
+ # Wipe out the current data
+ for e in entry.keys():
+ del entry[e]
+
+ # Re-populate it with new wentry
+ for e in newentry:
+ entry[e] = newentry[e]
+
def wait_for_memberof(keys, entry_start, completed, show_command, adding=True):
"""
When adding or removing reverse members we are faking an update to
@@ -238,6 +257,40 @@ def wait_for_memberof(keys, entry_start, completed, show_command, adding=True):
return entry_attrs
+def wait_for_value(ldap, dn, attr, value):
+ """
+ 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
+ command.
+
+ The updated entry is returned.
+ """
+ # 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.
+ time.sleep(.3)
+ 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:
+ break
+ else:
+ if value.lower() == entry_attrs[attr].lower():
+ break
+
+ return entry_attrs
+
class LDAPObject(Object):
"""
Object representing a LDAP entry.
diff --git a/ipalib/plugins/hostgroup.py b/ipalib/plugins/hostgroup.py
index 11ed66376..ef44a8b9b 100644
--- a/ipalib/plugins/hostgroup.py
+++ b/ipalib/plugins/hostgroup.py
@@ -98,6 +98,14 @@ 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:
+ newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry')
+ entry_from_entry(entry_attrs, newentry)
+
+ return dn
+
+
api.register(hostgroup_add)
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index e6060c0f3..3068c6291 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -402,6 +402,11 @@ class user_add(LDAPCreate):
self.api.Command['user_mod'](keys[-1], **kw)
except (errors.EmptyModlist, errors.NotFound):
pass
+ else:
+ if self.api.env.wait_for_attr:
+ newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry')
+ entry_from_entry(entry_attrs, newentry)
+
return dn
api.register(user_add)