[PATCH] make samba-tool aware of all 7 fsmo roles

Jelmer Vernooij jelmer at jelmer.uk
Fri Jun 5 09:37:11 MDT 2015


On Fri, Jun 05, 2015 at 11:10:10AM +0100, Rowland Penny wrote:
> On 04/06/15 17:57, Jelmer Vernooij wrote:
> >On Thu, Jun 04, 2015 at 05:17:11PM +0100, Rowland Penny wrote:
> >>On 04/06/15 16:16, Jelmer Vernooij wrote:
> >>>On Thu, Jun 04, 2015 at 02:00:47PM +0100, Rowland Penny wrote:
> >>>>On 04/06/15 13:23, Jelmer Vernooij wrote:
> >>>>>On Thu, Jun 04, 2015 at 11:36:29AM +0100, Rowland Penny wrote:
> >Jelmer
> 
> OK, lets try again (still not holding my breath :-D )

Almost there :)

> +def transfer_dns_role(outf, sambaopts, credopts, role, samdb):
> +    """Transfer dns FSMO role. """
> +
> +    if role == "domaindns":
> +        domain_dn = samdb.domain_dn()
> +        role_object = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn
> +    elif role == "forestdns":
> +        forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name())
> +        role_object = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn
> +
> +    try:
> +        res = samdb.search(role_object,
> +                           attrs=["fSMORoleOwner"],
> +                           scope=ldb.SCOPE_BASE,
> +                           controls=["extended_dn:1:1"])
> +
> +        if 'fSMORoleOwner' in res[0]:
> +            try:
> +                master_guid = str(misc.GUID(ldb.Dn(samdb,
> +                                  res[0]['fSMORoleOwner'][0])
> +                                  .get_extended_component('GUID')))
> +                master_owner = str(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0]))
> +            except:
^^ Please catch LdbError here rather than everything (including e.g. KeyboardInterrupt).

> +                outf.write("GUID not found in partition naming master DN %s\n" %
> +                           res[0]['fSMORoleOwner'][0])
> +                return
Perhaps return False?

> +    except LdbError, (num, msg):
> +        raise CommandError("DNS partion %s not found : %s" % (role, msg))
> +
> +    if role == "domaindns":
> +        master_dns_name = '%s._msdcs.%s' % (master_guid,
> +                                            samdb.domain_dns_name())
> +        new_dns_name = '%s._msdcs.%s' % (samdb.get_ntds_GUID(),
> +                                         samdb.domain_dns_name())
> +    elif role == "forestdns":
> +        master_dns_name = '%s._msdcs.%s' % (master_guid,
> +                                            samdb.forest_dns_name())
> +        new_dns_name = '%s._msdcs.%s' % (samdb.get_ntds_GUID(),
> +                                         samdb.forest_dns_name())
> +
> +    new_owner = samdb.get_dsServiceName()
> +
> +    if master_dns_name != new_dns_name:
> +        lp = sambaopts.get_loadparm()
> +        creds = credopts.get_credentials(lp, fallback_machine=True)
> +        samdb = SamDB(url="ldap://%s" % (master_dns_name),
> +                      session_info=system_session(),
> +                      credentials=creds, lp=lp)
> +
> +        m = ldb.Message()
> +        m.dn = ldb.Dn(samdb, role_object)
> +        m["fSMORoleOwner"] = ldb.MessageElement(master_owner,
> +                                                ldb.FLAG_MOD_DELETE,
> +                                                "fSMORoleOwner")
> +
> +        try:
> +            samdb.modify(m)
> +        except LdbError, (num, msg):
> +            raise CommandError("Failed to delete role '%s': %s" %
> +                               (role, msg))
> +
> +        m = ldb.Message()
> +        m.dn = ldb.Dn(samdb, role_object)
> +        m["fSMORoleOwner"]= ldb.MessageElement(new_owner,
> +                                               ldb.FLAG_MOD_ADD,
> +                                               "fSMORoleOwner")
> +        try:
> +            samdb.modify(m)
> +        except LdbError, (num, msg):
> +            raise CommandError("Failed to add role '%s': %s" % (role, msg))
> +
> +        try:
> +            connection = samba.drs_utils.drsuapi_connect(samdb.host_dns_name(),
> +                                                         lp, creds)
> +        except samba.drs_utils.drsException, e:
> +            raise CommandError("Drsuapi Connect failed", e)
> +
> +        try:
> +            drsuapi_connection = connection[0]
> +            drsuapi_handle = connection[1]
> +            req_options = drsuapi.DRSUAPI_DRS_WRIT_REP
> +            NC = role_object[18:]
> +            samba.drs_utils.sendDsReplicaSync(drsuapi_connection,
> +                                              drsuapi_handle,
> +                                              master_guid,
> +                                              NC, req_options)
> +        except samba.drs_utils.drsException, estr:
> +            raise CommandError("Replication failed", estr)
> +
> +        outf.write("FSMO transfer of '%s' role successful\n" % role)
> +        return True        
> +    else:
> +        outf.write("This DC already has the '%s' FSMO role\n" % role)
Perhaps return False?

>  def transfer_role(outf, role, samdb):
> +    """Transfer standard FSMO role. """
> +
> +    domain_dn = samdb.domain_dn()
> +    rid_dn = "CN=RID Manager$,CN=System," + domain_dn
> +    naming_dn = "CN=Partitions,%s" % samdb.get_config_basedn()
> +    infrastructure_dn = "CN=Infrastructure," + domain_dn
> +    schema_dn = str(samdb.get_schema_basedn())
> +    new_owner = samdb.get_dsServiceName()
>      m = ldb.Message()
>      m.dn = ldb.Dn(samdb, "")
>      if role == "rid":
> +        master_owner = get_fsmo_roleowner(samdb, rid_dn)
>          m["becomeRidMaster"]= ldb.MessageElement(
>              "1", ldb.FLAG_MOD_REPLACE,
>              "becomeRidMaster")
>      elif role == "pdc":
> -        domain_dn = samdb.domain_dn()
> +        master_owner = get_fsmo_roleowner(samdb, domain_dn)
> +
>          res = samdb.search(domain_dn,
>                             scope=ldb.SCOPE_BASE, attrs=["objectSid"])
>          assert len(res) == 1
> @@ -119,26 +252,77 @@ all=all of the above"""),
>          else:
>              raise CommandError("Invalid FSMO role.")
>          #first try to transfer to avoid problem if the owner is still active
> -        if force is None:
> -            self.message("Attempting transfer...")
> -            try:
> -                transfer_role(self.outf, role, samdb)
> -                self.outf.write("FSMO seize was not required, as transfer of '%s' role was successful\n" % role)
> -                return
> -            except CommandError:
> -            #transfer failed, use the big axe...
> -                self.message("Transfer unsuccessful, seizing...")
> +        seize = "no"
^^ please use 'seize = False' / 'seize = True' rather than a string.

Overall, looks much better. Thanks!

Jelmer


More information about the samba-technical mailing list