3
# Changes a FSMO role owner
5
# Copyright Nadezhda Ivanova 2009
6
# Copyright Jelmer Vernooij 2009
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
import samba.getopt as options
24
from ldb import LdbError
26
from samba.auth import system_session
27
from samba.netcmd import (
32
from samba.samdb import SamDB
34
class cmd_fsmo(Command):
35
"""Makes the targer DC transfer or seize a fsmo role [server connection needed]"""
37
synopsis = "(show | transfer <options> | seize <options>)"
39
takes_optiongroups = {
40
"sambaopts": options.SambaOptions,
41
"credopts": options.CredentialsOptions,
42
"versionopts": options.VersionOptions,
46
Option("--host", help="LDB URL for database or target server", type=str),
47
Option("--force", help="Force seizing of the role without attempting to transfer first.", action="store_true"),
48
Option("--role", type="choice", choices=["rid", "pdc", "infrastructure","schema","naming","all"],
49
help="""The FSMO role to seize or transfer.\n
50
rid=RidAllocationMasterRole\n
51
schema=SchemaMasterRole\n
52
pdc=PdcEmulationMasterRole\n
53
naming=DomainNamingMasterRole\n
54
infrastructure=InfrastructureMasterRole\n
55
all=all of the above"""),
58
takes_args = ["subcommand"]
60
def transfer_role(self, role, samdb):
62
m.dn = ldb.Dn(samdb, "")
64
m["becomeRidMaster"]= ldb.MessageElement(
65
"1", ldb.FLAG_MOD_REPLACE,
68
domain_dn = samdb.domain_dn()
69
res = samdb.search(domain_dn,
70
scope=ldb.SCOPE_BASE, attrs=["objectSid"])
72
sid = res[0]["objectSid"][0]
73
m["becomePdc"]= ldb.MessageElement(
74
sid, ldb.FLAG_MOD_REPLACE,
76
elif role == "naming":
77
m["becomeDomainMaster"]= ldb.MessageElement(
78
"1", ldb.FLAG_MOD_REPLACE,
81
elif role == "infrastructure":
82
m["becomeInfrastructureMaster"]= ldb.MessageElement(
83
"1", ldb.FLAG_MOD_REPLACE,
84
"becomeInfrastructureMaster")
85
elif role == "schema":
86
m["becomeSchemaMaster"]= ldb.MessageElement(
87
"1", ldb.FLAG_MOD_REPLACE,
90
raise CommandError("Invalid FSMO role.")
93
def seize_role(self, role, samdb, force):
94
res = samdb.search("",
95
scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
97
serviceName = res[0]["dsServiceName"][0]
98
domain_dn = samdb.domain_dn()
101
m.dn = ldb.Dn(samdb, self.rid_dn)
103
m.dn = ldb.Dn(samdb, domain_dn)
104
elif role == "naming":
105
m.dn = ldb.Dn(samdb, self.naming_dn)
106
elif role == "infrastructure":
107
m.dn = ldb.Dn(samdb, self.infrastructure_dn)
108
elif role == "schema":
109
m.dn = ldb.Dn(samdb, self.schema_dn)
111
raise CommandError("Invalid FSMO role.")
112
#first try to transfer to avoid problem if the owner is still active
114
self.message("Attempting transfer...")
116
self.transfer_role(role, samdb)
117
except LdbError, (num, _):
118
#transfer failed, use the big axe...
119
self.message("Transfer unsuccessfull, seizing...")
120
m["fSMORoleOwner"]= ldb.MessageElement(
121
serviceName, ldb.FLAG_MOD_REPLACE,
125
self.message("Transfer succeeded.")
127
self.message("Will not attempt transfer, seizing...")
128
m["fSMORoleOwner"]= ldb.MessageElement(
129
serviceName, ldb.FLAG_MOD_REPLACE,
133
def run(self, subcommand, force=None, host=None, role=None,
134
credopts=None, sambaopts=None, versionopts=None):
135
lp = sambaopts.get_loadparm()
136
creds = credopts.get_credentials(lp, fallback_machine=True)
138
samdb = SamDB(url=host, session_info=system_session(),
139
credentials=creds, lp=lp)
141
domain_dn = samdb.domain_dn()
142
self.infrastructure_dn = "CN=Infrastructure," + domain_dn
143
self.naming_dn = "CN=Partitions,CN=Configuration," + domain_dn
144
self.schema_dn = "CN=Schema,CN=Configuration," + domain_dn
145
self.rid_dn = "CN=RID Manager$,CN=System," + domain_dn
147
res = samdb.search(self.infrastructure_dn,
148
scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
150
self.infrastructureMaster = res[0]["fSMORoleOwner"][0]
152
res = samdb.search(domain_dn,
153
scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
155
self.pdcEmulator = res[0]["fSMORoleOwner"][0]
157
res = samdb.search(self.naming_dn,
158
scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
160
self.namingMaster = res[0]["fSMORoleOwner"][0]
162
res = samdb.search(self.schema_dn,
163
scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
165
self.schemaMaster = res[0]["fSMORoleOwner"][0]
167
res = samdb.search(self.rid_dn,
168
scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
170
self.ridMaster = res[0]["fSMORoleOwner"][0]
172
if subcommand == "show":
173
self.message("InfrastructureMasterRole owner: " + self.infrastructureMaster)
174
self.message("RidAllocationMasterRole owner: " + self.ridMaster)
175
self.message("PdcEmulationMasterRole owner: " + self.pdcEmulator)
176
self.message("DomainNamingMasterRole owner: " + self.namingMaster)
177
self.message("SchemaMasterRole owner: " + self.schemaMaster)
178
elif subcommand == "transfer":
180
self.transfer_role("rid", samdb)
181
self.transfer_role("pdc", samdb)
182
self.transfer_role("naming", samdb)
183
self.transfer_role("infrastructure", samdb)
184
self.transfer_role("schema", samdb)
186
self.transfer_role(role, samdb)
187
elif subcommand == "seize":
189
self.seize_role("rid", samdb, force)
190
self.seize_role("pdc", samdb, force)
191
self.seize_role("naming", samdb, force)
192
self.seize_role("infrastructure", samdb, force)
193
self.seize_role("schema", samdb, force)
195
self.seize_role(role, samdb, force)
197
raise CommandError("Wrong argument '%s'!" % subcommand)