2010-01-27 17:57:37 +02:00
# Changes a FSMO role owner
#
# Copyright Nadezhda Ivanova 2009
# Copyright Jelmer Vernooij 2009
#
# 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
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import samba . getopt as options
import ldb
from ldb import LdbError
from samba . auth import system_session
from samba . netcmd import (
Command ,
CommandError ,
2011-08-02 18:05:54 -04:00
SuperCommand ,
2010-01-27 17:57:37 +02:00
Option ,
)
from samba . samdb import SamDB
2012-04-19 13:57:29 +10:00
def transfer_role ( outf , role , samdb ) :
m = ldb . Message ( )
m . dn = ldb . Dn ( samdb , " " )
if role == " rid " :
m [ " becomeRidMaster " ] = ldb . MessageElement (
" 1 " , ldb . FLAG_MOD_REPLACE ,
" becomeRidMaster " )
elif role == " pdc " :
domain_dn = samdb . domain_dn ( )
res = samdb . search ( domain_dn ,
scope = ldb . SCOPE_BASE , attrs = [ " objectSid " ] )
assert len ( res ) == 1
sid = res [ 0 ] [ " objectSid " ] [ 0 ]
m [ " becomePdc " ] = ldb . MessageElement (
sid , ldb . FLAG_MOD_REPLACE ,
" becomePdc " )
elif role == " naming " :
m [ " becomeDomainMaster " ] = ldb . MessageElement (
" 1 " , ldb . FLAG_MOD_REPLACE ,
" becomeDomainMaster " )
samdb . modify ( m )
elif role == " infrastructure " :
m [ " becomeInfrastructureMaster " ] = ldb . MessageElement (
" 1 " , ldb . FLAG_MOD_REPLACE ,
" becomeInfrastructureMaster " )
elif role == " schema " :
m [ " becomeSchemaMaster " ] = ldb . MessageElement (
" 1 " , ldb . FLAG_MOD_REPLACE ,
" becomeSchemaMaster " )
else :
raise CommandError ( " Invalid FSMO role. " )
try :
samdb . modify ( m )
except LdbError , ( num , msg ) :
raise CommandError ( " Failed to initiate transfer of ' %s ' role: %s " % ( role , msg ) )
outf . write ( " FSMO transfer of ' %s ' role successful \n " % role )
2010-01-27 17:57:37 +02:00
2011-08-02 18:05:54 -04:00
class cmd_fsmo_seize ( Command ) :
""" Seize the role """
2011-10-13 23:27:22 +02:00
synopsis = " % prog [options] "
2010-01-27 17:57:37 +02:00
2012-02-06 16:33:38 +01:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
}
2010-01-27 17:57:37 +02:00
takes_options = [
2011-07-25 11:56:10 -04:00
Option ( " -H " , " --URL " , help = " LDB URL for database or target server " , type = str ,
metavar = " URL " , dest = " H " ) ,
2010-01-27 17:57:37 +02:00
Option ( " --force " , help = " Force seizing of the role without attempting to transfer first. " , action = " store_true " ) ,
Option ( " --role " , type = " choice " , choices = [ " rid " , " pdc " , " infrastructure " , " schema " , " naming " , " all " ] ,
help = """ The FSMO role to seize or transfer. \n
rid = RidAllocationMasterRole \n
schema = SchemaMasterRole \n
pdc = PdcEmulationMasterRole \n
naming = DomainNamingMasterRole \n
infrastructure = InfrastructureMasterRole \n
all = all of the above """ ),
]
2011-08-02 18:05:54 -04:00
takes_args = [ ]
2010-01-27 17:57:37 +02:00
def seize_role ( self , role , samdb , force ) :
res = samdb . search ( " " ,
scope = ldb . SCOPE_BASE , attrs = [ " dsServiceName " ] )
2010-04-08 23:18:17 +02:00
assert len ( res ) == 1
2010-01-27 17:57:37 +02:00
serviceName = res [ 0 ] [ " dsServiceName " ] [ 0 ]
2010-04-08 23:18:17 +02:00
domain_dn = samdb . domain_dn ( )
2012-04-19 13:57:29 +10:00
self . infrastructure_dn = " CN=Infrastructure, " + domain_dn
self . naming_dn = " CN=Partitions, %s " % samdb . get_config_basedn ( )
self . schema_dn = samdb . get_schema_basedn ( )
self . rid_dn = " CN=RID Manager$,CN=System, " + domain_dn
2010-01-27 17:57:37 +02:00
m = ldb . Message ( )
if role == " rid " :
m . dn = ldb . Dn ( samdb , self . rid_dn )
elif role == " pdc " :
m . dn = ldb . Dn ( samdb , domain_dn )
elif role == " naming " :
m . dn = ldb . Dn ( samdb , self . naming_dn )
elif role == " infrastructure " :
2010-01-29 15:42:46 +02:00
m . dn = ldb . Dn ( samdb , self . infrastructure_dn )
2010-01-27 17:57:37 +02:00
elif role == " schema " :
m . dn = ldb . Dn ( samdb , self . schema_dn )
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 :
2012-04-19 13:57:29 +10:00
transfer_role ( self . outf , role , samdb )
except CommandError :
2010-01-27 17:57:37 +02:00
#transfer failed, use the big axe...
2011-03-28 15:32:41 +11:00
self . message ( " Transfer unsuccessful, seizing... " )
2010-01-27 17:57:37 +02:00
m [ " fSMORoleOwner " ] = ldb . MessageElement (
serviceName , ldb . FLAG_MOD_REPLACE ,
" fSMORoleOwner " )
else :
self . message ( " Will not attempt transfer, seizing... " )
m [ " fSMORoleOwner " ] = ldb . MessageElement (
serviceName , ldb . FLAG_MOD_REPLACE ,
" fSMORoleOwner " )
2011-03-28 15:32:41 +11:00
try :
2010-01-27 17:57:37 +02:00
samdb . modify ( m )
2011-03-28 15:32:41 +11:00
except LdbError , ( num , msg ) :
2011-03-28 16:48:46 +11:00
raise CommandError ( " Failed to initiate role seize of ' %s ' role: %s " % ( role , msg ) )
2011-10-13 00:36:44 +02:00
self . outf . write ( " FSMO transfer of ' %s ' role successful \n " % role )
2011-03-28 15:32:41 +11:00
2011-08-02 18:05:54 -04:00
def run ( self , force = None , H = None , role = None ,
credopts = None , sambaopts = None , versionopts = None ) :
2011-10-13 23:27:22 +02:00
2011-08-02 18:05:54 -04:00
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp , fallback_machine = True )
samdb = SamDB ( url = H , session_info = system_session ( ) ,
credentials = creds , lp = lp )
if role == " all " :
self . seize_role ( " rid " , samdb , force )
self . seize_role ( " pdc " , samdb , force )
self . seize_role ( " naming " , samdb , force )
self . seize_role ( " infrastructure " , samdb , force )
self . seize_role ( " schema " , samdb , force )
else :
self . seize_role ( role , samdb , force )
2010-01-27 17:57:37 +02:00
2011-08-02 18:05:54 -04:00
class cmd_fsmo_show ( Command ) :
""" Show the roles """
2011-10-13 23:27:22 +02:00
synopsis = " % prog [options] "
2011-08-02 18:05:54 -04:00
2012-02-17 21:24:48 +01:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
}
2011-08-02 18:05:54 -04:00
takes_options = [
Option ( " -H " , " --URL " , help = " LDB URL for database or target server " , type = str ,
metavar = " URL " , dest = " H " ) ,
]
takes_args = [ ]
2011-10-13 23:27:22 +02:00
def run ( self , H = None , credopts = None , sambaopts = None , versionopts = None ) :
2010-01-27 17:57:37 +02:00
lp = sambaopts . get_loadparm ( )
2010-12-08 08:20:54 +11:00
creds = credopts . get_credentials ( lp , fallback_machine = True )
2010-01-27 17:57:37 +02:00
2011-07-25 11:56:10 -04:00
samdb = SamDB ( url = H , session_info = system_session ( ) ,
2010-01-27 17:57:37 +02:00
credentials = creds , lp = lp )
2010-04-08 23:18:17 +02:00
domain_dn = samdb . domain_dn ( )
2010-01-27 17:57:37 +02:00
self . infrastructure_dn = " CN=Infrastructure, " + domain_dn
2011-09-16 15:15:35 +10:00
self . naming_dn = " CN=Partitions, %s " % samdb . get_config_basedn ( )
2011-09-16 11:18:05 +10:00
self . schema_dn = samdb . get_schema_basedn ( )
2010-01-27 17:57:37 +02:00
self . rid_dn = " CN=RID Manager$,CN=System, " + domain_dn
res = samdb . search ( self . infrastructure_dn ,
scope = ldb . SCOPE_BASE , attrs = [ " fSMORoleOwner " ] )
2010-04-08 23:18:17 +02:00
assert len ( res ) == 1
2010-01-27 17:57:37 +02:00
self . infrastructureMaster = res [ 0 ] [ " fSMORoleOwner " ] [ 0 ]
res = samdb . search ( domain_dn ,
scope = ldb . SCOPE_BASE , attrs = [ " fSMORoleOwner " ] )
2010-04-08 23:18:17 +02:00
assert len ( res ) == 1
2010-01-27 17:57:37 +02:00
self . pdcEmulator = res [ 0 ] [ " fSMORoleOwner " ] [ 0 ]
res = samdb . search ( self . naming_dn ,
scope = ldb . SCOPE_BASE , attrs = [ " fSMORoleOwner " ] )
2010-04-08 23:18:17 +02:00
assert len ( res ) == 1
2010-01-27 17:57:37 +02:00
self . namingMaster = res [ 0 ] [ " fSMORoleOwner " ] [ 0 ]
res = samdb . search ( self . schema_dn ,
scope = ldb . SCOPE_BASE , attrs = [ " fSMORoleOwner " ] )
2010-04-08 23:18:17 +02:00
assert len ( res ) == 1
2010-01-27 17:57:37 +02:00
self . schemaMaster = res [ 0 ] [ " fSMORoleOwner " ] [ 0 ]
res = samdb . search ( self . rid_dn ,
scope = ldb . SCOPE_BASE , attrs = [ " fSMORoleOwner " ] )
2010-04-08 23:18:17 +02:00
assert len ( res ) == 1
2010-01-27 17:57:37 +02:00
self . ridMaster = res [ 0 ] [ " fSMORoleOwner " ] [ 0 ]
2011-08-02 18:05:54 -04:00
self . message ( " InfrastructureMasterRole owner: " + self . infrastructureMaster )
self . message ( " RidAllocationMasterRole owner: " + self . ridMaster )
self . message ( " PdcEmulationMasterRole owner: " + self . pdcEmulator )
self . message ( " DomainNamingMasterRole owner: " + self . namingMaster )
self . message ( " SchemaMasterRole owner: " + self . schemaMaster )
class cmd_fsmo_transfer ( Command ) :
""" Transfer the role """
2011-10-13 23:27:22 +02:00
synopsis = " % prog [options] "
2011-08-02 18:05:54 -04:00
2012-02-17 21:24:48 +01:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
}
2011-08-02 18:05:54 -04:00
takes_options = [
Option ( " -H " , " --URL " , help = " LDB URL for database or target server " , type = str ,
metavar = " URL " , dest = " H " ) ,
Option ( " --role " , type = " choice " , choices = [ " rid " , " pdc " , " infrastructure " , " schema " , " naming " , " all " ] ,
help = """ The FSMO role to seize or transfer. \n
rid = RidAllocationMasterRole \n
schema = SchemaMasterRole \n
pdc = PdcEmulationMasterRole \n
naming = DomainNamingMasterRole \n
infrastructure = InfrastructureMasterRole \n
all = all of the above """ ),
]
takes_args = [ ]
def run ( self , force = None , H = None , role = None ,
credopts = None , sambaopts = None , versionopts = None ) :
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp , fallback_machine = True )
samdb = SamDB ( url = H , session_info = system_session ( ) ,
2012-09-27 09:30:47 -07:00
credentials = creds , lp = lp )
2011-08-02 18:05:54 -04:00
if role == " all " :
2012-04-19 13:57:29 +10:00
transfer_role ( self . outf , " rid " , samdb )
transfer_role ( self . outf , " pdc " , samdb )
transfer_role ( self . outf , " naming " , samdb )
transfer_role ( self . outf , " infrastructure " , samdb )
transfer_role ( self . outf , " schema " , samdb )
2011-08-02 18:05:54 -04:00
else :
2012-04-19 13:57:29 +10:00
transfer_role ( self . outf , role , samdb )
2011-08-02 18:05:54 -04:00
class cmd_fsmo ( SuperCommand ) :
2011-09-09 13:27:13 +10:00
""" Flexible Single Master Operations (FSMO) roles management """
2011-08-02 18:05:54 -04:00
subcommands = { }
subcommands [ " seize " ] = cmd_fsmo_seize ( )
subcommands [ " show " ] = cmd_fsmo_show ( )
subcommands [ " transfer " ] = cmd_fsmo_transfer ( )