diff options
-rw-r--r-- | python/samba/join.py | 19 | ||||
-rw-r--r-- | selftest/knownfail.d/replicate_against_deleted | 1 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 13 |
3 files changed, 31 insertions, 2 deletions
diff --git a/python/samba/join.py b/python/samba/join.py index 70b3c9729b0..6c1ab3be7b4 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -50,6 +50,7 @@ import tempfile from collections import OrderedDict from samba.common import get_string from samba.netcmd import CommandError +from samba import dsdb class DCJoinException(Exception): @@ -937,6 +938,10 @@ class DCJoinContext(object): """Replicate the SAM.""" ctx.logger.info("Starting replication") + + # A global transaction is started so that linked attributes + # are applied at the very end, once all partitions are + # replicated. This helps get all cross-partition links. ctx.local_samdb.transaction_start() try: source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id()) @@ -1057,7 +1062,21 @@ class DCJoinContext(object): ctx.local_samdb.transaction_cancel() raise else: + + # This is a special case, we have completed a full + # replication so if a link comes to us that points to a + # deleted object, and we asked for all objects already, we + # just have to ignore it, the chance to re-try the + # replication with GET_TGT has long gone. This can happen + # if the object is deleted and sent to us after the link + # was sent, as we are processing all links in the + # transaction_commit(). + if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY: + ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 1) ctx.local_samdb.transaction_commit() + ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 0) ctx.logger.info("Committed SAM database") # A large replication may have caused our LDB connection to the diff --git a/selftest/knownfail.d/replicate_against_deleted b/selftest/knownfail.d/replicate_against_deleted deleted file mode 100644 index 9caa5346a45..00000000000 --- a/selftest/knownfail.d/replicate_against_deleted +++ /dev/null @@ -1 +0,0 @@ -samba4.drs.ridalloc_exop.python\(.*\).ridalloc_exop.DrsReplicaSyncTestCase.test_replicate_against_deleted_objects_transaction diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index c1ea5ad90f8..175a02d3ba7 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -7533,6 +7533,16 @@ static int replmd_allow_missing_target(struct ldb_module *module, source_dn, target_dn); if (is_in_same_nc) { + /* + * We allow the join.py code to point out that all + * replication is completed, so failing now would just + * trigger errors, rather than trigger a GET_TGT + */ + int *finished_full_join_ptr = + talloc_get_type(ldb_get_opaque(ldb, + DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME), + int); + bool finished_full_join = finished_full_join_ptr && *finished_full_join_ptr; /* * if the target is already be up-to-date there's no point in @@ -7540,7 +7550,8 @@ static int replmd_allow_missing_target(struct ldb_module *module, * on a one-way link was deleted. We ignore the link rather * than failing the replication cycle completely */ - if (dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) { + if (finished_full_join + || dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) { *ignore_link = true; DBG_WARNING("%s is %s " "but up to date. Ignoring link from %s\n", |