[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Wed Feb 15 00:22:03 UTC 2017


The branch, master has been updated
       via  b73c2e6 python/tests: improve samba-tool replicate --local test
       via  bc5dc53 python/tests: move samba_tool_drs test to proper place
       via  47db694 samba-tool/drs: do partial replication when --local is given by default
       via  e89f027 pydsdb: Add python binding for dsdb_load_udv_v2
       via  dc0c702 drs_utils: use a given highwatermark and uptodateness_vector in replicate()
       via  8de09d4 drs_utils: return number of replicated objects and links in replicate()
      from  221faba vfs_fruit: fix resource fork xattr name

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit b73c2e66f590e592b77afcc96017be00ee64fdc4
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Jan 27 15:22:27 2017 +1300

    python/tests: improve samba-tool replicate --local test
    
    It now makes sure that we only replicate incremental changes.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Wed Feb 15 01:21:06 CET 2017 on sn-devel-144

commit bc5dc536f8cc0ea36883dd3cf074bfd2c6da4b5c
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Jan 27 14:46:36 2017 +1300

    python/tests: move samba_tool_drs test to proper place
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 47db694f710b75cc7a565358499ca34c4e83676e
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Jan 27 10:40:59 2017 +1300

    samba-tool/drs: do partial replication when --local is given by default
    
    The samba-tool drs replicate --local command would previously always do
    a full replication. This changes it to only replicate changes it doesn't
    have according to appropriate highwatermark if the appropriate repsFrom
    attribute exists in the local database, or an uptodateness_vector if one
    exists.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    Pair-programmed-with: Andrew Bartlett <abartlet at samba.org>

commit e89f0275e33b6dee3fd80ce5e5c7e7a9508fd80d
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Thu Feb 9 11:22:08 2017 +1300

    pydsdb: Add python binding for dsdb_load_udv_v2
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit dc0c702f791c280a8142c8993ddd41bd356b2d21
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Jan 27 10:40:19 2017 +1300

    drs_utils: use a given highwatermark and uptodateness_vector in replicate()
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    Pair-programmed-with: Andrew Bartlett <abartlet at samba.org>

commit 8de09d491d8d0cf27324eb298b7a504f42cdaa84
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Jan 27 10:18:21 2017 +1300

    drs_utils: return number of replicated objects and links in replicate()
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    Pair-programmed-with: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 python/samba/drs_utils.py                          |  33 ++++--
 python/samba/netcmd/drs.py                         |  61 ++++++++--
 source4/dsdb/pydsdb.c                              |  67 +++++++++++
 source4/selftest/tests.py                          |   4 +-
 .../torture/drs/python}/samba_tool_drs.py          | 130 ++++++++++++++++++---
 5 files changed, 259 insertions(+), 36 deletions(-)
 rename {python/samba/tests/blackbox => source4/torture/drs/python}/samba_tool_drs.py (77%)


Changeset truncated at 500 lines:

diff --git a/python/samba/drs_utils.py b/python/samba/drs_utils.py
index 126c57e..e91a20b 100644
--- a/python/samba/drs_utils.py
+++ b/python/samba/drs_utils.py
@@ -1,7 +1,7 @@
 # DRS utility code
 #
 # Copyright Andrew Tridgell 2010
-# Copyright Andrew Bartlett 2010
+# Copyright Andrew Bartlett 2017
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -198,7 +198,7 @@ class drs_Replicate(object):
 
     def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid,
                   schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False,
-                  replica_flags=None):
+                  replica_flags=None, highwatermark=None, udv=None):
         '''replicate a single DN'''
 
         # setup for a GetNCChanges call
@@ -208,11 +208,17 @@ class drs_Replicate(object):
         req8.source_dsa_invocation_id = source_dsa_invocation_id
         req8.naming_context = drsuapi.DsReplicaObjectIdentifier()
         req8.naming_context.dn = dn
-        req8.highwatermark = drsuapi.DsReplicaHighWaterMark()
-        req8.highwatermark.tmp_highest_usn = 0
-        req8.highwatermark.reserved_usn = 0
-        req8.highwatermark.highest_usn = 0
-        req8.uptodateness_vector = None
+
+        if highwatermark is not None:
+            req8.highwatermark = highwatermark
+        else:
+            req8.highwatermark = drsuapi.DsReplicaHighWaterMark()
+            req8.highwatermark.tmp_highest_usn = 0
+            req8.highwatermark.reserved_usn = 0
+            req8.highwatermark.highest_usn = 0
+
+        req8.uptodateness_vector = udv
+
         if replica_flags is not None:
             req8.replica_flags = replica_flags
         elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET:
@@ -251,12 +257,25 @@ class drs_Replicate(object):
                     setattr(req5, a, getattr(req8, a))
             req = req5
 
+        num_objects = 0
+        num_links = 0
         while True:
             (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req)
             if ctr.first_object is None and ctr.object_count != 0:
                 raise RuntimeError("DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count))
             self.net.replicate_chunk(self.replication_state, level, ctr,
                 schema=schema, req_level=req_level, req=req)
+
+            num_objects += ctr.object_count
+
+            # Cope with servers that do not return level 6, so do not return any links
+            try:
+                num_links += ctr.linked_attributes_count
+            except AttributeError:
+                pass
+
             if ctr.more_data == 0:
                 break
             req.highwatermark = ctr.new_highwatermark
+
+        return (num_objects, num_links)
diff --git a/python/samba/netcmd/drs.py b/python/samba/netcmd/drs.py
index 67733ac..bf6829e 100644
--- a/python/samba/netcmd/drs.py
+++ b/python/samba/netcmd/drs.py
@@ -1,6 +1,7 @@
 # implement samba_tool drs commands
 #
 # Copyright Andrew Tridgell 2010
+# Copyright Andrew Bartlett 2017
 #
 # based on C implementation by Kamen Mazdrashki <kamen.mazdrashki at postpath.com>
 #
@@ -21,6 +22,7 @@
 import samba.getopt as options
 import ldb
 import logging
+import common
 
 from samba.auth import system_session
 from samba.netcmd import (
@@ -32,8 +34,9 @@ from samba.netcmd import (
 from samba.samdb import SamDB
 from samba import drs_utils, nttime2string, dsdb
 from samba.dcerpc import drsuapi, misc
-import common
 from samba.join import join_clone
+from samba.ndr import ndr_unpack
+from samba.dcerpc import drsblobs
 
 def drsuapi_connect(ctx):
     '''make a DRSUAPI connection to the server'''
@@ -238,7 +241,7 @@ class cmd_drs_kcc(Command):
 
 
 
-def drs_local_replicate(self, SOURCE_DC, NC):
+def drs_local_replicate(self, SOURCE_DC, NC, full_sync=False):
     '''replicate from a source DC to the local SAM'''
 
     self.server = SOURCE_DC
@@ -252,17 +255,51 @@ def drs_local_replicate(self, SOURCE_DC, NC):
                        credentials=self.creds, lp=self.lp)
 
     # work out the source and destination GUIDs
-    res = self.local_samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
+    res = self.local_samdb.search(base="", scope=ldb.SCOPE_BASE,
+                                  attrs=["dsServiceName"])
     self.ntds_dn = res[0]["dsServiceName"][0]
 
-    res = self.local_samdb.search(base=self.ntds_dn, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
+    res = self.local_samdb.search(base=self.ntds_dn, scope=ldb.SCOPE_BASE,
+                                  attrs=["objectGUID"])
     self.ntds_guid = misc.GUID(self.samdb.schema_format_value("objectGUID", res[0]["objectGUID"][0]))
 
-
     source_dsa_invocation_id = misc.GUID(self.samdb.get_invocation_id())
     dest_dsa_invocation_id = misc.GUID(self.local_samdb.get_invocation_id())
     destination_dsa_guid = self.ntds_guid
 
+    # If we can't find an upToDateVector, replicate fully
+    hwm = drsuapi.DsReplicaHighWaterMark()
+    hwm.tmp_highest_usn = 0
+    hwm.reserved_usn = 0
+    hwm.highest_usn = 0
+
+    udv = None
+    if not full_sync:
+        res = self.local_samdb.search(base=NC, scope=ldb.SCOPE_BASE,
+                                      attrs=["repsFrom"])
+        if "repsFrom" in res[0]:
+            for reps_from_packed in res[0]["repsFrom"]:
+                reps_from_obj = ndr_unpack(drsblobs.repsFromToBlob, reps_from_packed)
+                if reps_from_obj.ctr.source_dsa_invocation_id == source_dsa_invocation_id:
+                    hwm = reps_from_obj.ctr.highwatermark
+
+        udv = drsuapi.DsReplicaCursorCtrEx()
+        udv.version = 1
+        udv.reserved1 = 0
+        udv.reserved2 = 0
+
+        cursors_v1 = []
+        cursors_v2 = dsdb._dsdb_load_udv_v2(self.local_samdb,
+                                            self.local_samdb.get_default_basedn())
+        for cursor_v2 in cursors_v2:
+            cursor_v1 = drsuapi.DsReplicaCursor()
+            cursor_v1.source_dsa_invocation_id = cursor_v2.source_dsa_invocation_id
+            cursor_v1.highest_usn = cursor_v2.highest_usn
+            cursors_v1.append(cursor_v1)
+
+        udv.cursors = cursors_v1
+        udv.count = len(cursors_v1)
+
     self.samdb.transaction_start()
     repl = drs_utils.drs_Replicate("ncacn_ip_tcp:%s[seal]" % self.server, self.lp,
                                    self.creds, self.local_samdb, dest_dsa_invocation_id)
@@ -271,13 +308,19 @@ def drs_local_replicate(self, SOURCE_DC, NC):
     # with the admin pw does not sync passwords
     rodc = self.local_samdb.am_rodc()
     try:
-        repl.replicate(NC, source_dsa_invocation_id, destination_dsa_guid, rodc=rodc)
+        (num_objects, num_links) = repl.replicate(NC,
+                                                  source_dsa_invocation_id, destination_dsa_guid,
+                                                  rodc=rodc, highwatermark=hwm, udv=udv)
     except Exception, e:
         raise CommandError("Error replicating DN %s" % NC, e)
     self.samdb.transaction_commit()
 
-    self.message("Replicate from %s to %s was successful." % (SOURCE_DC, self.local_samdb.url))
-
+    if full_sync:
+        self.message("Full Replication of all %d objects and %d links from %s to %s was successful."
+                     % (num_objects, num_links, SOURCE_DC, self.local_samdb.url))
+    else:
+        self.message("Incremental replication of %d objects and %d links from %s to %s was successful."
+                     % (num_objects, num_links, SOURCE_DC, self.local_samdb.url))
 
 
 class cmd_drs_replicate(Command):
@@ -314,7 +357,7 @@ class cmd_drs_replicate(Command):
         self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
 
         if local:
-            drs_local_replicate(self, SOURCE_DC, NC)
+            drs_local_replicate(self, SOURCE_DC, NC, full_sync=full_sync)
             return
 
         if local_online:
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index ab1d0d2..715abdd 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1244,6 +1244,72 @@ static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *ar
 			    num_links_removed);
 }
 
+static PyObject *py_dsdb_load_udv_v2(PyObject *self, PyObject *args)
+{
+	uint32_t count;
+	int ret, i;
+	bool ok;
+	PyObject *py_ldb = NULL, *py_dn = NULL, *pylist = NULL;
+	struct ldb_context *samdb = NULL;
+	struct ldb_dn *dn = NULL;
+	struct drsuapi_DsReplicaCursor2 *cursors = NULL;
+	TALLOC_CTX *tmp_ctx = NULL;
+
+	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
+		return NULL;
+	}
+
+	PyErr_LDB_OR_RAISE(py_ldb, samdb);
+
+	tmp_ctx = talloc_new(samdb);
+	if (tmp_ctx == NULL) {
+		return PyErr_NoMemory();
+	}
+
+	ok = pyldb_Object_AsDn(tmp_ctx, py_dn, samdb, &dn);
+	if (!ok) {
+		TALLOC_FREE(tmp_ctx);
+		return NULL;
+	}
+
+	ret = dsdb_load_udv_v2(samdb, dn, tmp_ctx, &cursors, &count);
+	if (ret != LDB_SUCCESS) {
+		TALLOC_FREE(tmp_ctx);
+		PyErr_SetString(PyExc_RuntimeError,
+				"Failed to load udv from ldb");
+		return NULL;
+	}
+
+	pylist = PyList_New(count);
+	if (pylist == NULL) {
+		TALLOC_FREE(tmp_ctx);
+		return PyErr_NoMemory();
+	}
+
+	for (i = 0; i < count; i++) {
+		PyObject *py_cursor;
+		struct drsuapi_DsReplicaCursor2 *cursor;
+		cursor = talloc(tmp_ctx, struct drsuapi_DsReplicaCursor2);
+		if (cursor == NULL) {
+			TALLOC_FREE(tmp_ctx);
+			return PyErr_NoMemory();
+		}
+		*cursor = cursors[i];
+
+		py_cursor = py_return_ndr_struct("samba.dcerpc.drsuapi",
+						 "DsReplicaCursor2",
+						 cursor, cursor);
+		if (py_cursor == NULL) {
+			TALLOC_FREE(tmp_ctx);
+			return PyErr_NoMemory();
+		}
+
+		PyList_SetItem(pylist, i, py_cursor);
+	}
+
+	TALLOC_FREE(tmp_ctx);
+	return pylist;
+}
 
 static PyMethodDef py_dsdb_methods[] = {
 	{ "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
@@ -1319,6 +1385,7 @@ static PyMethodDef py_dsdb_methods[] = {
 	{ "_dsdb_allocate_rid", (PyCFunction)py_dsdb_allocate_rid, METH_VARARGS,
 		"_dsdb_allocate_rid(samdb)"
 		" -> RID" },
+	{ "_dsdb_load_udv_v2", (PyCFunction)py_dsdb_load_udv_v2, METH_VARARGS, NULL },
 	{ NULL }
 };
 
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index dec26b4..83eff52 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -670,7 +670,9 @@ planoldpythontestsuite(env, "ridalloc_exop",
                        extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])
 
 for env in ['vampire_dc', 'promoted_dc']:
-    planoldpythontestsuite("%s:local" % env, "samba.tests.blackbox.samba_tool_drs",
+    planoldpythontestsuite("%s:local" % env, "samba_tool_drs",
+                           extra_path=[os.path.join(samba4srcdir, 'torture/drs/python')],
+                           name="samba4.drs.samba_tool_drs.python(%s)" % env,
                            environ={'DC1': '$DC_SERVER', 'DC2': '$%s_SERVER' % env.upper()},
                            extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])
     planoldpythontestsuite("%s:local" % env, "replica_sync",
diff --git a/python/samba/tests/blackbox/samba_tool_drs.py b/source4/torture/drs/python/samba_tool_drs.py
similarity index 77%
rename from python/samba/tests/blackbox/samba_tool_drs.py
rename to source4/torture/drs/python/samba_tool_drs.py
index 90921f4..477529d 100644
--- a/python/samba/tests/blackbox/samba_tool_drs.py
+++ b/source4/torture/drs/python/samba_tool_drs.py
@@ -1,5 +1,6 @@
 # Blackbox tests for "samba-tool drs" command
 # Copyright (C) Kamen Mazdrashki <kamenim at samba.org> 2011
+# Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,8 +22,9 @@ import samba.tests
 import shutil
 import os
 import ldb
+import drs_base
 
-class SambaToolDrsTests(samba.tests.BlackboxTestCase):
+class SambaToolDrsTests(drs_base.DrsBaseTestCase):
     """Blackbox test case for samba-tool drs."""
 
     def setUp(self):
@@ -35,6 +37,21 @@ class SambaToolDrsTests(samba.tests.BlackboxTestCase):
         self.cmdline_creds = "-U%s/%s%%%s" % (creds.get_domain(),
                                               creds.get_username(), creds.get_password())
 
+    def tearDown(self):
+        self._enable_inbound_repl(self.dnsname_dc1)
+        self._enable_inbound_repl(self.dnsname_dc2)
+
+        try:
+            shutil.rmtree(os.path.join(self.tempdir, "private"))
+            shutil.rmtree(os.path.join(self.tempdir, "etc"))
+            shutil.rmtree(os.path.join(self.tempdir, "msg.lock"))
+            os.remove(os.path.join(self.tempdir, "names.tdb"))
+            shutil.rmtree(os.path.join(self.tempdir, "state"))
+        except Exception:
+            pass
+
+        super(SambaToolDrsTests, self).tearDown()
+
     def _get_rootDSE(self, dc, ldap_only=True):
         samdb = samba.tests.connect_samdb(dc, lp=self.get_loadparm(),
                                           credentials=self.get_credentials(),
@@ -145,7 +162,7 @@ class SambaToolDrsTests(samba.tests.BlackboxTestCase):
         out = self.check_output("samba-tool drs replicate -P --local %s %s %s" % (self.dc1,
                                                                                   self.dc2,
                                                                                   nc_name))
-        self.assertTrue("Replicate from" in out)
+        self.assertTrue("Incremental" in out)
         self.assertTrue("was successful" in out)
 
     def test_samba_tool_replicate_local(self):
@@ -153,12 +170,99 @@ class SambaToolDrsTests(samba.tests.BlackboxTestCase):
 
         # Output should be like 'Replicate from <DC-SRC> to <DC-DEST> was successful.'
         nc_name = self._get_rootDSE(self.dc1)["defaultNamingContext"]
-        out = self.check_output("samba-tool drs replicate --local %s %s %s %s" % (self.dc1,
-                                                                                  self.dc2,
-                                                                                  nc_name,
-                                                                                  self.cmdline_creds))
-        self.assertTrue("Replicate from" in out)
+
+        def get_num_obj_links(output):
+            num_objs = None
+            num_links = None
+            for word in output.split(" "):
+                try:
+                    int(word)
+                    if num_objs is None:
+                        num_objs = int(word)
+                    elif num_links is None:
+                        num_links = int(word)
+                except ValueError:
+                    pass
+
+            return (num_objs, num_links)
+
+        out = self.check_output("samba-tool drs replicate --local --full-sync %s %s %s %s"
+                                % (self.dc1, self.dc2, nc_name, self.cmdline_creds))
+        self.assertTrue("was successful" in out)
+        self.assertTrue("Full" in out)
+
+        (first_obj, _) = get_num_obj_links(out)
+
+        out = self.check_output("samba-tool drs replicate --local %s %s %s %s"
+                                % (self.dc1, self.dc2, nc_name, self.cmdline_creds))
         self.assertTrue("was successful" in out)
+        self.assertTrue("Incremental" in out)
+
+        (second_obj, _) = get_num_obj_links(out)
+
+        self.assertTrue(first_obj > second_obj)
+
+        server_rootdse = self._get_rootDSE(self.dc1)
+        server_nc_name = server_rootdse["defaultNamingContext"]
+        server_ds_name = server_rootdse["dsServiceName"]
+        server_ldap_service_name = str(server_rootdse["ldapServiceName"][0])
+        server_realm = server_ldap_service_name.split(":")[0]
+        creds = self.get_credentials()
+
+        # We have to give it a different netbiosname every time
+        # it runs, otherwise the collision causes strange issues
+        # to happen. This should be different on different environments.
+        netbiosname = "test" + self.dc2
+        if len(netbiosname) > 15:
+            netbiosname = netbiosname[:15]
+
+        out = self.check_output("samba-tool domain join %s dc --server=%s %s --targetdir=%s --option=netbiosname=%s"
+                                % (server_realm, self.dc1, self.cmdline_creds, self.tempdir, netbiosname))
+
+        new_dc_config_file = "%s/etc/smb.conf" % self.tempdir
+
+        self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s"
+                          % ("invalid", self.dc1, nc_name,
+                             self.cmdline_creds, new_dc_config_file))
+
+        self._disable_inbound_repl(self.dnsname_dc1)
+        self._disable_inbound_repl(self.dnsname_dc2)
+
+        self._net_drs_replicate(DC=self.dnsname_dc1, fromDC=self.dnsname_dc2)
+
+        # add an object with link on dc1
+        group_name = "group-repl-local-%s" % self.dc2
+        user_name = "user-repl-local-%s" % self.dc2
+
+        self.check_output("samba-tool group add %s %s -H ldap://%s"
+                          % (group_name, self.cmdline_creds, self.dc1))
+        self.check_output("samba-tool user add %s %s --random-password -H ldap://%s"
+                          % (user_name, self.cmdline_creds, self.dc1))
+        self.check_output("samba-tool group addmembers %s %s %s -H ldap://%s"
+                          % (group_name, user_name, self.cmdline_creds, self.dc1))
+
+        self._net_drs_replicate(DC=self.dnsname_dc2, fromDC=self.dnsname_dc1)
+
+        # pull that change with --local into local db from dc1: should send link and some objects
+        out = self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s"
+                                % ("invalid", self.dc1, nc_name,
+                                   self.cmdline_creds, new_dc_config_file))
+
+        (obj_1, link_1) = get_num_obj_links(out)
+
+        self.assertEqual(obj_1, 2)
+        self.assertEqual(link_1, 1)
+
+        # pull that change with --local into local db from dc2: shouldn't send link or object
+        # as we sent an up-to-dateness vector showing that we had already synced with DC1
+        out = self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s"
+                                % ("invalid", self.dc2, nc_name,
+                                   self.cmdline_creds, new_dc_config_file))
+
+        (obj_2, link_2) = get_num_obj_links(out)
+
+        self.assertEqual(obj_2, 0)
+        self.assertEqual(link_2, 0)
 
     def test_samba_tool_replicate_machine_creds_P(self):
         """Tests 'samba-tool drs replicate -P' command with machine creds."""
@@ -246,12 +350,6 @@ class SambaToolDrsTests(samba.tests.BlackboxTestCase):
                              attrs=[])
             self.assertRaises(ldb.LdbError, check_dns_account_obj)
 
-        shutil.rmtree(os.path.join(self.tempdir, "private"))
-        shutil.rmtree(os.path.join(self.tempdir, "etc"))
-        shutil.rmtree(os.path.join(self.tempdir, "msg.lock"))
-        os.remove(os.path.join(self.tempdir, "names.tdb"))
-        shutil.rmtree(os.path.join(self.tempdir, "state"))
-
     def test_samba_tool_drs_clone_dc_secrets(self):
         """Tests 'samba-tool drs clone-dc-database --include-secrets' command ."""
         server_rootdse = self._get_rootDSE(self.dc1)
@@ -324,12 +422,6 @@ class SambaToolDrsTests(samba.tests.BlackboxTestCase):
                              attrs=[])
             self.assertRaises(ldb.LdbError, check_dns_account_obj)
 
-        shutil.rmtree(os.path.join(self.tempdir, "private"))
-        shutil.rmtree(os.path.join(self.tempdir, "etc"))
-        shutil.rmtree(os.path.join(self.tempdir, "msg.lock"))
-        os.remove(os.path.join(self.tempdir, "names.tdb"))
-        shutil.rmtree(os.path.join(self.tempdir, "state"))
-
     def test_samba_tool_drs_clone_dc_secrets_without_targetdir(self):
         """Tests 'samba-tool drs clone-dc-database' command without --targetdir."""
         server_rootdse = self._get_rootDSE(self.dc1)


-- 
Samba Shared Repository



More information about the samba-cvs mailing list