From: Hiroyuki Homma Date: Wed, 10 Jan 2024 06:06:49 +0000 (+0900) Subject: ITS#10080 Fix refreshAndPersist synchronization problem with glue + rwm X-Git-Tag: OPENLDAP_REL_ENG_2_6_7~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8074a30bebe84fd8f70a34b272f16a9101106661;p=thirdparty%2Fopenldap.git ITS#10080 Fix refreshAndPersist synchronization problem with glue + rwm --- diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c index a0d4dad60d..00a672d4cd 100644 --- a/servers/slapd/backglue.c +++ b/servers/slapd/backglue.c @@ -369,6 +369,8 @@ glue_sub_search( Operation *op, SlapReply *rs, BackendDB *b0, BackendInfo *bi = op->o_bd->bd_info; int rc = SLAP_CB_CONTINUE; for ( on=on->on_next; on; on=on->on_next ) { + if ( on->on_bi.bi_flags & SLAPO_BFLAG_DISABLED ) + continue; op->o_bd->bd_info = (BackendInfo *)on; if ( on->on_bi.bi_op_search ) { rc = on->on_bi.bi_op_search( op, rs ); @@ -550,6 +552,11 @@ glue_op_search ( Operation *op, SlapReply *rs ) rs->sr_err = glue_sub_search( op, rs, b0, on ); } + if ( rs->sr_err == SLAPD_NO_REPLY ) { + gs.err = rs->sr_err; + break; + } + switch ( gs.err ) { /* @@ -716,7 +723,8 @@ end_of_loop:; } rs->sr_ctrls = gs.ctrls; - send_ldap_result( op, rs ); + if ( rs->sr_err != SLAPD_NO_REPLY ) + send_ldap_result( op, rs ); op->o_bd = b0; op->o_bd->bd_info = bi0; diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index 43043df630..af10f6df22 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -1815,6 +1815,16 @@ rwm_response( Operation *op, SlapReply *rs ) break; } + if ( op->o_tag == LDAP_REQ_ADD && op->ora_e ) { + /* + * Rewrite back the dn and attributes of the added entry op->ora_e + */ + SlapReply rs2 = *rs; + rs2.sr_entry = op->ora_e; + rs2.sr_flags |= REP_ENTRY_MODIFIABLE; + return rwm_send_entry( op, &rs2 ); + } + return SLAP_CB_CONTINUE; } diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index 3c2290d1aa..f208846fa9 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -698,6 +698,7 @@ syncprov_findcsn( Operation *op, find_csn_t mode, struct berval *csn ) "FIND_PRESENT", csn ? csn->bv_val : "" ); +again: fop = *op; fop.o_sync_mode &= SLAP_CONTROL_MASK; /* turn off sync_mode */ /* We want pure entries, not referrals */ @@ -714,7 +715,6 @@ syncprov_findcsn( Operation *op, find_csn_t mode, struct berval *csn ) fop.ors_filter = &cf; fop.ors_filterstr.bv_val = buf; -again: switch( mode ) { case FIND_MAXCSN: cf.f_choice = LDAP_FILTER_GE; @@ -1319,17 +1319,9 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit ) Entry *e = NULL; Attribute *a; int rc, gonext; - struct berval newdn; - int freefdn = 0; BackendDB *b0 = op->o_bd, db; - fc.fdn = &op->o_req_ndn; - /* compute new DN */ - if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) { - ber_dupbv_x( &newdn, &op->orr_nnewDN, op->o_tmpmemctx ); - fc.fdn = &newdn; - freefdn = 1; - } + fc.fdn = saveit ? &op->o_req_ndn : &opc->sndn; if ( !saveit && op->o_tag == LDAP_REQ_DELETE ) { /* Delete succeeded, there is no entry */ } else if ( op->o_tag != LDAP_REQ_ADD ) { @@ -1362,8 +1354,13 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit ) } if ( saveit || op->o_tag == LDAP_REQ_ADD ) { - ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx ); - ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx ); + if ( op->o_tag == LDAP_REQ_MODRDN ) { + ber_dupbv_x( &opc->sdn, &op->orr_newDN, op->o_tmpmemctx ); + ber_dupbv_x( &opc->sndn, &op->orr_nnewDN, op->o_tmpmemctx ); + } else { + ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx ); + ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx ); + } opc->sreference = is_entry_referral( e ); a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID ); if ( a ) @@ -1371,11 +1368,6 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit ) Debug( LDAP_DEBUG_SYNC, "%s syncprov_matchops: " "%srecording uuid for dn=%s on opc=%p\n", op->o_log_prefix, a ? "" : "not ", opc->sdn.bv_val, opc ); - } else if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) { - op->o_tmpfree( opc->sndn.bv_val, op->o_tmpmemctx ); - op->o_tmpfree( opc->sdn.bv_val, op->o_tmpmemctx ); - ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx ); - ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx ); } ldap_pvt_thread_mutex_lock( &si->si_ops_mutex ); @@ -1520,9 +1512,6 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit ) else if ( opc->se ) entry_free( opc->se ); } - if ( freefdn ) { - op->o_tmpfree( fc.fdn->bv_val, op->o_tmpmemctx ); - } op->o_bd = b0; } @@ -2955,6 +2944,7 @@ syncprov_search_response( Operation *op, SlapReply *rs ) { searchstate *ss = op->o_callback->sc_private; slap_overinst *on = ss->ss_on; + syncops *so = ss->ss_so; syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private; sync_control *srs = op->o_controls[slap_cids.sc_LDAPsync]; @@ -2983,7 +2973,7 @@ syncprov_search_response( Operation *op, SlapReply *rs ) sid = slap_parse_csn_sid( &a->a_nvals[0] ); /* If not a persistent search */ - if ( !ss->ss_so ) { + if ( !so ) { /* Make sure entry is less than the snapshot'd contextCSN */ for ( i=0; iss_numcsns; i++ ) { if ( sid == ss->ss_sids[i] && ber_bvcmp( &a->a_nvals[0], @@ -3048,7 +3038,7 @@ syncprov_search_response( Operation *op, SlapReply *rs ) /* Is this a regular refresh? * Note: refresh never gets here if there were no changes */ - if ( !ss->ss_so ) { + if ( !so ) { rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2, op->o_tmpmemctx ); rs->sr_ctrls[1] = NULL; @@ -3059,6 +3049,7 @@ syncprov_search_response( Operation *op, SlapReply *rs ) op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx ); } else { /* It's RefreshAndPersist, transition to Persist phase */ + rs->sr_err = SLAPD_NO_REPLY; syncprov_sendinfo( op, rs, ( ss->ss_flags & SS_PRESENT ) ? LDAP_TAG_SYNC_REFRESH_PRESENT : LDAP_TAG_SYNC_REFRESH_DELETE, ( ss->ss_flags & SS_CHANGED ) ? &cookie : NULL, @@ -3076,21 +3067,21 @@ syncprov_search_response( Operation *op, SlapReply *rs ) return SLAPD_ABANDON; } else { - ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex ); + ldap_pvt_thread_mutex_lock( &so->s_mutex ); /* Turn off the refreshing flag */ - ss->ss_so->s_flags ^= PS_IS_REFRESHING; + so->s_flags ^= PS_IS_REFRESHING; Debug( LDAP_DEBUG_SYNC, "%s syncprov_search_response: " "detaching op\n", op->o_log_prefix ); - syncprov_detach_op( op, ss->ss_so, on ); + syncprov_detach_op( op, so, on ); ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); /* If there are queued responses, fire them off */ - if ( ss->ss_so->s_res ) - syncprov_qstart( ss->ss_so ); - ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex ); - return SLAPD_NO_REPLY; + if ( so->s_res ) + syncprov_qstart( so ); + ldap_pvt_thread_mutex_unlock( &so->s_mutex ); + return rs->sr_err; } } } @@ -3098,6 +3089,33 @@ syncprov_search_response( Operation *op, SlapReply *rs ) return SLAP_CB_CONTINUE; } +static int +syncprov_search_cb( Operation *op, SlapReply *rs ) +{ + /* + * Prevent the glue overlay from processing subordinates when it is + * configured (explicitly or implicitly) below the syncprov overlay. + */ + if ( rs->sr_type == REP_RESULT ) + op->o_no_subordinate_glue = 1; + return SLAP_CB_CONTINUE; +} + +static int +syncprov_search_cleanup( Operation *op, SlapReply *rs ) +{ + if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_INTERMEDIATE || + rs->sr_err == SLAPD_ABANDON || op->o_abandon ) { + searchstate *ss = op->o_callback->sc_private; + if ( ss && ss->ss_numcsns ) { + ber_bvarray_free_x( ss->ss_ctxcsn, op->o_tmpmemctx ); + op->o_tmpfree( ss->ss_sids, op->o_tmpmemctx ); + } + slap_freeself_cb( op, rs ); + } + return SLAP_CB_CONTINUE; +} + static int syncprov_op_search( Operation *op, SlapReply *rs ) { @@ -3114,6 +3132,14 @@ syncprov_op_search( Operation *op, SlapReply *rs ) int minsid, maxsid; int dirty = 0; + if ( op->o_sync > SLAP_CONTROL_IGNORED ) { + cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); + cb->sc_response = syncprov_search_cb; + cb->sc_cleanup = syncprov_search_cleanup; + cb->sc_next = op->o_callback; + op->o_callback = cb; + } + if ( !(op->o_sync_mode & SLAP_SYNC_REFRESH) ) return SLAP_CB_CONTINUE; if ( op->ors_deref & LDAP_DEREF_SEARCHING ) { @@ -3320,6 +3346,10 @@ bailout: } rs->sr_ctrls = NULL; send_ldap_result( op, rs ); + if ( numcsns ) { + ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx ); + op->o_tmpfree( sids, op->o_tmpmemctx ); + } return rs->sr_err; } } @@ -3342,6 +3372,10 @@ no_change: if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) { rs->sr_err = LDAP_SUCCESS; send_ldap_result( op, rs ); rs->sr_ctrls = NULL; + if ( numcsns ) { + ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx ); + op->o_tmpfree( sids, op->o_tmpmemctx ); + } return rs->sr_err; } Debug( LDAP_DEBUG_SYNC, "%s syncprov_op_search: " @@ -3429,10 +3463,6 @@ no_change: if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) { /* No, so a reload is required */ /* the 2.2 consumer doesn't send this hint */ if ( si->si_usehint && srs->sr_rhint == 0 ) { - if ( ctxcsn ) - ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx ); - if ( sids ) - op->o_tmpfree( sids, op->o_tmpmemctx ); rs->sr_err = LDAP_SYNC_REFRESH_REQUIRED; rs->sr_text = "sync cookie is stale"; goto bailout; @@ -3452,13 +3482,8 @@ no_change: if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) { } else { gotstate = 1; /* If changed and doing Present lookup, send Present UUIDs */ - if ( syncprov_findcsn( op, FIND_PRESENT, 0 ) != LDAP_SUCCESS ) { - if ( ctxcsn ) - ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx ); - if ( sids ) - op->o_tmpfree( sids, op->o_tmpmemctx ); + if ( syncprov_findcsn( op, FIND_PRESENT, 0 ) != LDAP_SUCCESS ) goto bailout; - } } } else { /* The consumer knows nothing, we know nothing. OK. */ @@ -3516,6 +3541,7 @@ shortcut: ss->ss_numcsns = numcsns; ss->ss_sids = sids; cb->sc_response = syncprov_search_response; + cb->sc_cleanup = syncprov_search_cleanup; cb->sc_private = ss; cb->sc_next = op->o_callback; op->o_callback = cb; diff --git a/tests/scripts/test088-syncprov-glue-rwm b/tests/scripts/test088-syncprov-glue-rwm new file mode 100755 index 0000000000..435a04a532 --- /dev/null +++ b/tests/scripts/test088-syncprov-glue-rwm @@ -0,0 +1,448 @@ +#! /bin/sh +# $OpenLDAP$ +## This work is part of OpenLDAP Software . +## +## Copyright 1998-2022 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## . + +echo "running defines.sh" +. $SRCDIR/scripts/defines.sh + +if test $BACKLDAP = ldapno; then + echo "LDAP backend not available, test skipped" + exit 0 +fi + +if test $RWM = rwmno; then + echo "rwm (rewrite/remap) overlay not available, test skipped" + exit 0 +fi + +if test $SYNCPROV = syncprovno; then + echo "Syncrepl provider overlay not available, test skipped" + exit 0 +fi + +RMTSUFFIX="dc=remote,$BASEDN" +RMTROOTDN="cn=Manager,$RMTSUFFIX" + +RMTDIR=$TESTDIR/remote +PR1DIR=$TESTDIR/provider1 +PR2DIR=$TESTDIR/provider2 +RMTCONF=$RMTDIR/slapd.d +PR1CONF=$PR1DIR/slapd.d +PR2CONF=$PR2DIR/slapd.d + +ENTRIES=$TESTDIR/entries.ldif +SYNC1OUT=$TESTDIR/syncrepl1.out +SYNC2OUT=$TESTDIR/syncrepl2.out + +mkdir -p $RMTDIR $RMTCONF $RMTDIR/db +mkdir -p $PR1DIR $PR1CONF $PR1DIR/db +mkdir -p $PR2DIR $PR2CONF $PR2DIR/db + +cd $TESTDIR + +KILLPIDS= + +$SLAPPASSWD -g -n > $CONFIGPWF + +cat < $CONFLDIF +dn: cn=config +objectClass: olcGlobal +cn: config + +dn: olcDatabase={0}config,cn=config +objectClass: olcDatabaseConfig +olcDatabase: {0}config +olcRootPW:< file://$CONFIGPWF + +dn: cn=schema,cn=config +objectClass: olcSchemaConfig +cn: schema + +include: file://$ABS_SCHEMADIR/core.ldif +include: file://$ABS_SCHEMADIR/cosine.ldif +include: file://$ABS_SCHEMADIR/nis.ldif +include: file://$ABS_SCHEMADIR/inetorgperson.ldif + +dn: cn=module,cn=config +objectClass: olcModuleList +cn: module +olcModulePath: $TESTWD/../servers/slapd/overlays +EOF + +[ "$BACKENDTYPE" = mod ] && echo "olcModuleLoad: $TESTWD/../servers/slapd/back-$BACKEND/back_$BACKEND.la" >> $CONFLDIF + +echo "Initializing remote configurations..." +cat $CONFLDIF - <> $CONFLDIF +[ "$RWM" = rwmmod ] && echo "olcModuleLoad: rwm.la" >> $CONFLDIF +[ "$SYNCPROV" = syncprovmod ] && echo "olcModuleLoad: syncprov.la" >> $CONFLDIF +cat <> $CONFLDIF + +dn: olcDatabase={1}ldap,cn=config +objectClass: olcDatabaseConfig +objectClass: olcLDAPConfig +olcDatabase: {1}ldap +olcSuffix: ou=remote,ou=users,$BASEDN +olcSubordinate: TRUE +olcDbURI: $URI1 +olcDbIDAssertBind: bindmethod=simple + binddn="$RMTROOTDN" + credentials=$PASSWD + mode=none +olcDbIDAssertAuthzFrom: dn.exact:$MANAGERDN +olcRootDN: $MANAGERDN + +dn: olcOverlay={0}rwm,olcDatabase={1}ldap,cn=config +objectClass: olcOverlayConfig +objectClass: olcRwmConfig +olcOverlay: {0}rwm +olcRwmRewrite: rwm-suffixmassage "ou=users,$RMTSUFFIX" +EOF + +echo "Initializing provider1 configurations..." +cat $CONFLDIF - < $LOG1 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +KILLPIDS="$KILLPIDS $PID" +cd $TESTWD +sleep 1 +echo "Using ldapsearch to check that remote slapd is running..." +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "" -H $URI1 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for slapd to start..." + sleep 5 +done +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Starting provider1 slapd on TCP/IP port $PORT2..." +cd $PR1DIR +$SLAPD -F slapd.d -h $URI2 -d $LVL > $LOG2 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +KILLPIDS="$KILLPIDS $PID" +cd $TESTWD +sleep 1 +echo "Using ldapsearch to check that provider1 slapd is running..." +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "" -H $URI2 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for slapd to start..." + sleep 5 +done +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Starting provider2 slapd on TCP/IP port $PORT3..." +cd $PR2DIR +$SLAPD -F slapd.d -h $URI3 -d $LVL > $LOG3 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +KILLPIDS="$KILLPIDS $PID" +cd $TESTWD +sleep 1 +echo "Using ldapsearch to check that provider2 slapd is running..." +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "" -H $URI3 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for slapd to start..." + sleep 5 +done +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Populating remote database entries..." +$LDAPADD -D "$RMTROOTDN" -H $URI1 -w $PASSWD <> $TESTOUT 2>&1 +dn: $RMTSUFFIX +objectClass: dcObject +objectClass: organization +dc: `echo $RMTSUFFIX | sed 's/^dc=\([^,]*\),.*/\1/'` +o: Example, Inc + +dn: ou=users,$RMTSUFFIX +objectClass: organizationalUnit +ou: users + +dn: cn=remote_user,ou=users,$RMTSUFFIX +objectClass: person +cn: remote_user +sn: remote_user +userPassword: $PASSWD +EOF +RC=$? +if test $RC != 0 ; then + echo "ldapadd failed to populate remote database entries ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +cat < $ENTRIES +dn: $BASEDN +objectClass: dcObject +objectClass: organization +dc: example +o: Example, Inc + +dn: ou=users,$BASEDN +objectClass: organizationalUnit +ou: users + +dn: ou=local,ou=users,$BASEDN +objectClass: organizationalUnit +ou: local + +dn: cn=local_user,ou=local,ou=users,$BASEDN +objectClass: person +cn: local_user +sn: local_user +userPassword: $PASSWD +EOF + +echo "Populating provider1 database entries..." +$LDAPADD -D "$MANAGERDN" -H $URI2 -w $PASSWD < $ENTRIES >> $TESTOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "ldapadd failed to populate provider1 database entries ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Populating provider2 database entries..." +$LDAPADD -D "$MANAGERDN" -H $URI3 -w $PASSWD < $ENTRIES >> $TESTOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "ldapadd failed to populate provider2 database entries ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Starting refreshAndPersist search on provider1..." +$LDAPRSEARCH -D $MANAGERDN -H $URI2 -w $PASSWD -MM -E sync=rp -b $BASEDN '*' + 2>&1 > $SYNC1OUT & +PID=$! +RC=32 +for i in 0 1 2 3 4 5; do + echo "Waiting for refreshDone message..." + sleep $SLEEP0 + if grep '^# refresh done, switching to persist stage' $SYNC1OUT; then + awk '/^result:/{print; exit $2}' $SYNC1OUT + RC=$? + break + fi +done +if test $RC != 0 ; then + echo "refresh failed ($RC)!" + kill $PID + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Using ldapmodify to modify local entry on provider1..." +$LDAPMODIFY -D $MANAGERDN -H $URI2 -w $PASSWD <> $TESTOUT 2>&1 +dn: cn=local_user,ou=local,ou=users,$BASEDN +changeType: modify +replace: description +description: Syncrepl local_user +EOF +RC=32 +for i in 0 1 2 3 4 5; do + echo "Waiting for syncrepl to receive changes..." + sleep $SLEEP0 + if grep -q '^description: Syncrepl local_user' $SYNC1OUT; then + RC=0 + break + fi +done +kill $PID +if test $RC != 0 ; then + echo "syncrepl failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Check that remote entries are NOT replicated..." +if grep 'ou=remote,' $SYNC1OUT; then + echo "remote entries were unexpectedly replicated!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Starting refreshAndPersist search on provider2..." +$LDAPRSEARCH -D $MANAGERDN -H $URI3 -w $PASSWD -MM -E sync=rp -b $BASEDN '*' + 2>&1 > $SYNC2OUT & +PID=$! +RC=32 +for i in 0 1 2 3 4 5; do + echo "Waiting for refreshDone message..." + sleep $SLEEP0 + if grep '^# refresh done, switching to persist stage' $SYNC2OUT; then + awk '/^result:/{print; exit $2}' $SYNC2OUT + RC=$? + break + fi +done +if test $RC != 0 ; then + echo "refresh failed ($RC)!" + kill $PID + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Using ldapmodify to modify local entry on privider2..." +$LDAPMODIFY -D $MANAGERDN -H $URI3 -w $PASSWD <> $TESTOUT 2>&1 +dn: cn=local_user,ou=local,ou=users,$BASEDN +changeType: modify +replace: description +description: Syncrepl local_user +EOF +RC=32 +for i in 0 1 2 3 4 5; do + echo "Waiting for syncrepl to receive changes..." + sleep $SLEEP0 + if grep -q '^description: Syncrepl local_user' $SYNC2OUT; then + RC=0 + break + fi +done +if test $RC != 0 ; then + echo "syncrepl failed ($RC)!" + kill $PID + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Using ldapmodify to modify remote entry on privider2..." +$LDAPMODIFY -D $MANAGERDN -H $URI3 -w $PASSWD <> $TESTOUT 2>&1 +dn: cn=remote_user,ou=remote,ou=users,$BASEDN +changeType: modify +replace: description +description: Syncrepl remote_user +EOF +RC=32 +for i in 0 1 2 3 4 5; do + echo "Waiting for syncrepl to receive changes..." + sleep $SLEEP0 + if grep -q '^description: Syncrepl remote_user' $SYNC2OUT; then + RC=0 + break + fi +done +kill $PID +if test $RC != 0 ; then + echo "syncrepl failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +test $KILLSERVERS != no && kill -HUP $KILLPIDS + +echo ">>>>> Test succeeded" +exit 0