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

Andrew Bartlett abartlet at samba.org
Wed Feb 26 18:54:38 MST 2014


On Mon, 2014-02-24 at 14:06 +0100, Felix Botner wrote:
> 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).

Thanks for the patch!  With real-world deployment of Samba as an AD DC,
these kind of tools are becoming really important.  See below for my
further comments.

> 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()

This looks reasonable, but wouldn't be a better that this be put in
dbcheck, a bit like the reset-well-known-acls?  That would avoid
reimplemting the all/none checks.  

My feeling is while triggered by DRS, these are not really DRS
operations.

Andrew Bartlett

-- 
Andrew Bartlett
http://samba.org/~abartlet/
Authentication Developer, Samba Team  http://samba.org
Samba Developer, Catalyst IT          http://catalyst.net.nz/services/samba






More information about the samba-technical mailing list