Index: ad-connector.py =================================================================== --- ad-connector.py (Revision 71682) +++ ad-connector.py (Arbeitskopie) @@ -57,8 +57,59 @@ else: univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "ad-connector: additional config basename %s given, but %s/ad/listener/dir not set; ignore basename." % (configbasename, configbasename)) +def _save_old_object(directory, dn, old): + filename=os.path.join(directory, 'tmp','old_dn') + + f=open(filename, 'w+') + os.chmod(filename, 0600) + p=cPickle.Pickler(f) + old_dn=p.dump((dn,old)) + p.clear_memo() + f.close() + +def _load_old_object(directory): + f=open(os.path.join(directory, 'tmp','old_dn'),'r') + p=cPickle.Unpickler(f) + (old_dn,old_object)=p.load() + f.close() + + return (old_dn,old_object) +def _dump_object_to_file(filename, ob): + f=open(filename, 'w+') + os.chmod(filename, 0600) + p=cPickle.Pickler(f) + p.dump(ob) + p.clear_memo() + f.close() +def _dump_changes_to_file_and_check_file(directory, dn, new, old, old_dn): + + ob=(dn, new, old, old_dn) + + filename=os.path.join(directory,"%f"%time.time()) + + _dump_object_to_file(filename, ob) + + tmp_array = [] + f=open(filename, 'r') + tmp_array = cPickle.load(f) + f.close() + + tmp_array_len = len(tmp_array) + if tmp_array_len != 4: + univention.debug.debug(univention.debug.LDAP, univention.debug.WARN, 'replacing broken cPickle in %s (len=%s) with plain pickle' % (filename, tmp_array_len)) + _dump_object_to_file(filename, ob) + + tmp_array = [] + f=open(filename, 'r') + tmp_array = cPickle.load(f) + f.close() + + tmp_array_len = len(tmp_array) + if tmp_array_len != 4: + univention.debug.debug(univention.debug.LDAP, univention.debug.ERROR, 'pickle in %s (len=%s) seems to be broken' % (filename, tmp_array_len)) + def handler(dn, new, old, command): global group_objects @@ -70,36 +121,27 @@ if not os.path.exists(os.path.join(directory, 'tmp')): os.makedirs(os.path.join(directory, 'tmp')) - old_dn=None + old_dn = None + old_object = {} + if os.path.exists(os.path.join(directory, 'tmp','old_dn')): - f=open(os.path.join(directory, 'tmp','old_dn'),'r') - p=cPickle.Unpickler(f) - old_dn=p.load() - f.close() + (old_dn,old_object) = _load_old_object(directory) if command == 'r': - filename=os.path.join(directory, 'tmp','old_dn') - - f=open(filename, 'w+') - os.chmod(filename, 0600) - p=cPickle.Pickler(f) - old_dn=p.dump(dn) - p.clear_memo() - f.close() + _save_old_object(directory, dn, old) else: - ob=(dn, new, old, old_dn) + # Normally we see two steps for the modrdn operation. But in case of the selective replication we + # might only see the first step. + # https://forge.univention.org/bugzilla/show_bug.cgi?id=32542 + if old_dn and new.get('entryUUID') != old_object.get('entryUUID'): + univention.debug.debug(univention.debug.LISTENER, univention.debug.PROCESS, "The entryUUID attribute of the saved object (%s) does not match the entryUUID attribute of the current object (%s). This can be normal in a selective replication scenario." % (old_dn, dn)) + _dump_changes_to_file_and_check_file(directory, old_dn, {}, old_object, None) + old_dn = None - filename=os.path.join(directory,"%f"%time.time()) - if init_mode: if new and 'univentionGroup' in new.get('objectClass', []): - group_objects.append(ob) + group_objects.append((dn, new, old, old_dn)) - f=open(filename, 'w+') - os.chmod(filename, 0600) - p=cPickle.Pickler(f) - p.dump(ob) - p.clear_memo() - f.close() + _dump_changes_to_file_and_check_file(directory, dn, new, old, old_dn) if os.path.exists(os.path.join(directory, 'tmp','old_dn')): os.unlink(os.path.join(directory, 'tmp','old_dn'))