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

Andrew Bartlett abartlet at samba.org
Thu Feb 27 20:19:00 MST 2014


On Thu, 2014-02-27 at 14:54 +1300, Andrew Bartlett wrote:
> 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.

We also should have a test for this, running on and fixing real
conflicts generated by source4/torture/drs/python/replica_sync.py

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