drs_utils: Always set the GET_TGT flag for clone renames
authorTim Beale <timbeale@catalyst.net.nz>
Wed, 13 Jun 2018 02:09:06 +0000 (14:09 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Thu, 5 Jul 2018 02:01:25 +0000 (04:01 +0200)
The DCCloneAndRenameContext replication was a little inefficient, in
that it would essentially replicate the entire DB twice. This was due to
resolving the link targets - it finds a target object it doesn't know
about, so retries the entire replication again with the GET_TGT flag set
this time.

Normally, the repl_meta_data code will use the target object's GUID,
however, it can't do this for cross-partition links (if it hasn't
replicated the target partition yet). The repl_md code can normally
detect that the link is a cross-parition link by checking the base-DN,
however, this doesn't work in the DCCloneAndRenameContext case because
we have renamed the base-DN.

This is not a big deal - it just means extra work. However, because the
domains being backed up could potentially be quite large, it probably
makes sense to just always set the GET_TGT in the rename case and skip
this extra work.

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/drs_utils.py

index db8326739d51cad3bd4d3d51baeb8c4dbbb94f3d..66f47503ca8a850f5f36e445b0bbf16b37d594e2 100644 (file)
@@ -200,6 +200,7 @@ class drs_Replicate(object):
         if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"):
             raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id")
         self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id)
+        self.more_flags = 0
 
     def _should_retry_with_get_tgt(self, error_code, req):
 
@@ -228,7 +229,7 @@ class drs_Replicate(object):
         # setup for a GetNCChanges call
         if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10:
             req = drsuapi.DsGetNCChangesRequest10()
-            req.more_flags = more_flags
+            req.more_flags = (more_flags | self.more_flags)
             req_level = 10
         else:
             req_level = 8
@@ -367,6 +368,12 @@ class drs_ReplicateRenamer(drs_Replicate):
         self.old_base_dn = old_base_dn
         self.new_base_dn = new_base_dn
 
+        # because we're renaming the DNs, we know we're going to have trouble
+        # resolving link targets. Normally we'd get to the end of replication
+        # only to find we need to retry the whole replication with the GET_TGT
+        # flag set. Always setting the GET_TGT flag avoids this extra work.
+        self.more_flags = drsuapi.DRSUAPI_DRS_GET_TGT
+
     def rename_dn(self, dn_str):
         '''Uses string substitution to replace the base DN'''
         return re.sub('%s$' % self.old_base_dn, self.new_base_dn, dn_str)