[PATCH] samba-tool drs: new subcommand "conflicts"

Felix Botner botner at univention.de
Mon Feb 24 06:06:42 MST 2014


http://technet.microsoft.com/en-us/library/bb727059.aspx explains how
to deal with object name conflicts in a multimaster environment. One step is
to delete conflicting objects.

Since we have encountered conflicting objects in many s4 multimaster
environments an easy way to list (and delete) them would be very helpful.

Here a patch to add a new subcommand "conflicts" to samba-tool drs to list all
conflicts with the option to delete them (or to delete a specific conflict).

Signed-off-by: Felix Botner <botner at univention.de>
---
 python/samba/netcmd/drs.py |   48 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/python/samba/netcmd/drs.py b/python/samba/netcmd/drs.py
index 36dc48e..b783e54 100644
--- a/python/samba/netcmd/drs.py
+++ b/python/samba/netcmd/drs.py
@@ -32,6 +32,7 @@ from samba.samdb import SamDB
 from samba import drs_utils, nttime2string, dsdb
 from samba.dcerpc import drsuapi, misc
 import common
+import samba.common
 
 def drsuapi_connect(ctx):
     '''make a DRSUAPI connection to the server'''
@@ -234,7 +235,53 @@ class cmd_drs_kcc(Command):
             raise CommandError("DsExecuteKCC failed", e)
         self.message("Consistency check on %s successful." % DC)
 
+class cmd_drs_conflicts(Command):
+    '''list/remove conflicts in local db'''
 
+    synopsis = "%prog [options]"
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "versionopts": options.VersionOptions,
+        "credopts": options.CredentialsOptions,
+    }
+
+    takes_options = [
+        Option("--verbose", help="print ldif of conflict objects", action="store_true", default=False),
+        Option("--delete", help="delete all conflict objects", action="store_true", default=False),
+        Option("--dn", help="delete only given dn/conflict (if found)", type=str),
+        Option("--non-interactive", help="do not ask for deletion", action="store_true", default=False)
+        ]
+
+    def run(self, delete, verbose, dn, non_interactive,
+            credopts=None, sambaopts=None, versionopts=None):
+        lp = sambaopts.get_loadparm()
+        creds = credopts.get_credentials(lp, fallback_machine=True)
+        samdb = SamDB(session_info=system_session(), url=None,
+                      credentials=creds, lp=lp)
+
+        domain_dn = samdb.domain_dn()
+        scope = ldb.SCOPE_SUBTREE
+        if dn:
+            domain_dn = dn
+            scope = ldb.SCOPE_BASE
+        controls = []
+        for msg in samdb.search(base=domain_dn, scope=scope, controls=controls):
+            if "\\0ACNF" in str(msg.dn):
+                print "Conflict: " + str(msg.dn)
+                if verbose:
+                    print samdb.write_ldif(msg, ldb.CHANGETYPE_NONE)
+                if delete:
+                    if not non_interactive == True:
+                        answer = samba.common.confirm("Delete object with dn %s?" % msg.dn, allow_all=True)
+                    if answer == "ALL":
+                        non_interactive = True
+                    elif answer == "NONE":
+                        return
+                    elif answer == False:
+                        continue
+                    samdb.delete(msg.dn)
+                    print "%s deleted" % str(msg.dn)
 
 def drs_local_replicate(self, SOURCE_DC, NC):
     '''replicate from a source DC to the local SAM'''
@@ -519,3 +566,4 @@ class cmd_drs(SuperCommand):
     subcommands["replicate"] = cmd_drs_replicate()
     subcommands["showrepl"] = cmd_drs_showrepl()
     subcommands["options"] = cmd_drs_options()
+    subcommands["conflicts"] = cmd_drs_conflicts()
-- 
1.7.9.5



More information about the samba-technical mailing list