diff options
Diffstat (limited to 'ipalib/plugins/baseldap.py')
-rw-r--r-- | ipalib/plugins/baseldap.py | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index 3299f801..d010cd98 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -22,8 +22,9 @@ Base classes for LDAP plugins. import re import json +import time -from ipalib import crud, errors +from ipalib import api, crud, errors from ipalib import Method, Object from ipalib import Flag, Int, List, Str from ipalib.base import NameSpace @@ -175,6 +176,50 @@ def get_effective_rights(ldap, dn, attrs=None): return rdict +def wait_for_memberof(keys, entry_start, completed, show_command, adding=True): + """ + When adding or removing reverse members we are faking an update to + object A by updating the member attribute in object B. The memberof + plugin makes this work by adding or removing the memberof attribute + to/from object A, it just takes a little bit of time. + + This will loop for 6+ seconds, retrieving object A so we can see + if all the memberof attributes have been updated. + """ + if completed == 0: + # nothing to do + return api.Command[show_command](keys[-1])['result'] + + if 'memberof' in entry_start: + starting_memberof = len(entry_start['memberof']) + else: + starting_memberof = 0 + + # Loop a few times to give the memberof plugin a chance to add the + # entries. Don't sleep for more than 6 seconds. + memberof = 0 + x = 0 + while x < 20: + # sleep first because the first search, even on a quiet system, + # almost always fails to have memberof set. + 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. + entry_attrs = api.Command[show_command](keys[-1])['result'] + if 'memberof' in entry_attrs: + memberof = len(entry_attrs['memberof']) + + if adding: + if starting_memberof + completed >= memberof: + break + else: + if starting_memberof + completed <= memberof: + break + + return entry_attrs + class LDAPObject(Object): """ Object representing a LDAP entry. @@ -1326,6 +1371,9 @@ class LDAPAddReverseMember(LDAPModReverseMember): else: attrs_list = self.obj.default_attributes + # Pull the record as it is now so we can know how many members + # there are. + entry_start = self.api.Command[self.show_command](keys[-1])['result'] completed = 0 failed = {'member': {self.reverse_attr: []}} for attr in options.get(self.reverse_attr, []): @@ -1351,7 +1399,11 @@ class LDAPAddReverseMember(LDAPModReverseMember): except errors.PublicError, e: failed['member'][self.reverse_attr].append((attr, unicode(msg))) - entry_attrs = self.api.Command[self.show_command](keys[-1])['result'] + # Wait for the memberof plugin to update the entry + try: + entry_attrs = wait_for_memberof(keys, entry_start, completed, self.show_command, adding=True) + except Exception, e: + raise errors.ReverseMemberError(verb=_('added'), exc=str(e)) for callback in self.POST_CALLBACKS: if hasattr(callback, 'im_self'): @@ -1429,6 +1481,9 @@ class LDAPRemoveReverseMember(LDAPModReverseMember): else: attrs_list = self.obj.default_attributes + # Pull the record as it is now so we can know how many members + # there are. + entry_start = self.api.Command[self.show_command](keys[-1])['result'] completed = 0 failed = {'member': {self.reverse_attr: []}} for attr in options.get(self.reverse_attr, []): @@ -1454,7 +1509,11 @@ class LDAPRemoveReverseMember(LDAPModReverseMember): except errors.PublicError, e: failed['member'][self.reverse_attr].append((attr, unicode(msg))) - entry_attrs = self.api.Command[self.show_command](keys[-1])['result'] + # Wait for the memberof plugin to update the entry + try: + entry_attrs = wait_for_memberof(keys, entry_start, completed, self.show_command, adding=False) + except Exception, e: + raise errors.ReverseMemberError(verb=_('removed'), exc=str(e)) for callback in self.POST_CALLBACKS: if hasattr(callback, 'im_self'): |