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 (
33 from samba.samdb import SamDB
36 class cmd_fsmo_seize(Command):
39 synopsis = "%prog [options]"
41 takes_optiongroups = {
42 "sambaopts": options.SambaOptions,
43 "credopts": options.CredentialsOptions,
44 "versionopts": options.VersionOptions,
48 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
49 metavar="URL", dest="H"),
50 Option("--force", help="Force seizing of the role without attempting to transfer first.", action="store_true"),
51 Option("--role", type="choice", choices=["rid", "pdc", "infrastructure","schema","naming","all"],
52 help="""The FSMO role to seize or transfer.\n
53 rid=RidAllocationMasterRole\n
54 schema=SchemaMasterRole\n
55 pdc=PdcEmulationMasterRole\n
56 naming=DomainNamingMasterRole\n
57 infrastructure=InfrastructureMasterRole\n
58 all=all of the above"""),
63 def seize_role(self, role, samdb, force):
64 res = samdb.search("",
65 scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
67 serviceName = res[0]["dsServiceName"][0]
68 domain_dn = samdb.domain_dn()
71 m.dn = ldb.Dn(samdb, self.rid_dn)
73 m.dn = ldb.Dn(samdb, domain_dn)
74 elif role == "naming":
75 m.dn = ldb.Dn(samdb, self.naming_dn)
76 elif role == "infrastructure":
77 m.dn = ldb.Dn(samdb, self.infrastructure_dn)
78 elif role == "schema":
79 m.dn = ldb.Dn(samdb, self.schema_dn)
81 raise CommandError("Invalid FSMO role.")
82 #first try to transfer to avoid problem if the owner is still active
84 self.message("Attempting transfer...")
86 self.transfer_role(role, samdb)
87 except LdbError, (num, _):
88 #transfer failed, use the big axe...
89 self.message("Transfer unsuccessful, seizing...")
90 m["fSMORoleOwner"]= ldb.MessageElement(
91 serviceName, ldb.FLAG_MOD_REPLACE,
94 self.message("Will not attempt transfer, seizing...")
95 m["fSMORoleOwner"]= ldb.MessageElement(
96 serviceName, ldb.FLAG_MOD_REPLACE,
100 except LdbError, (num, msg):
101 raise CommandError("Failed to initiate role seize of '%s' role: %s" % (role, msg))
102 self.outf.write("FSMO transfer of '%s' role successful\n" % role)
104 def run(self, force=None, H=None, role=None,
105 credopts=None, sambaopts=None, versionopts=None):
107 lp = sambaopts.get_loadparm()
108 creds = credopts.get_credentials(lp, fallback_machine=True)
110 samdb = SamDB(url=H, session_info=system_session(),
111 credentials=creds, lp=lp)
114 self.seize_role("rid", samdb, force)
115 self.seize_role("pdc", samdb, force)
116 self.seize_role("naming", samdb, force)
117 self.seize_role("infrastructure", samdb, force)
118 self.seize_role("schema", samdb, force)
120 self.seize_role(role, samdb, force)
123 class cmd_fsmo_show(Command):
126 synopsis = "%prog [options]"
128 takes_optiongroups = {
129 "sambaopts": options.SambaOptions,
130 "credopts": options.CredentialsOptions,
131 "versionopts": options.VersionOptions,
135 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
136 metavar="URL", dest="H"),
141 def run(self, H=None, credopts=None, sambaopts=None, versionopts=None):
142 lp = sambaopts.get_loadparm()
143 creds = credopts.get_credentials(lp, fallback_machine=True)
145 samdb = SamDB(url=H, session_info=system_session(),
146 credentials=creds, lp=lp)
148 domain_dn = samdb.domain_dn()
149 self.infrastructure_dn = "CN=Infrastructure," + domain_dn
150 self.naming_dn = "CN=Partitions,%s" % samdb.get_config_basedn()
151 self.schema_dn = samdb.get_schema_basedn()
152 self.rid_dn = "CN=RID Manager$,CN=System," + domain_dn
154 res = samdb.search(self.infrastructure_dn,
155 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
157 self.infrastructureMaster = res[0]["fSMORoleOwner"][0]
159 res = samdb.search(domain_dn,
160 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
162 self.pdcEmulator = res[0]["fSMORoleOwner"][0]
164 res = samdb.search(self.naming_dn,
165 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
167 self.namingMaster = res[0]["fSMORoleOwner"][0]
169 res = samdb.search(self.schema_dn,
170 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
172 self.schemaMaster = res[0]["fSMORoleOwner"][0]
174 res = samdb.search(self.rid_dn,
175 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
177 self.ridMaster = res[0]["fSMORoleOwner"][0]
179 self.message("InfrastructureMasterRole owner: " + self.infrastructureMaster)
180 self.message("RidAllocationMasterRole owner: " + self.ridMaster)
181 self.message("PdcEmulationMasterRole owner: " + self.pdcEmulator)
182 self.message("DomainNamingMasterRole owner: " + self.namingMaster)
183 self.message("SchemaMasterRole owner: " + self.schemaMaster)
186 class cmd_fsmo_transfer(Command):
187 """Transfer the role"""
189 synopsis = "%prog [options]"
191 takes_optiongroups = {
192 "sambaopts": options.SambaOptions,
193 "credopts": options.CredentialsOptions,
194 "versionopts": options.VersionOptions,
198 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
199 metavar="URL", dest="H"),
200 Option("--role", type="choice", choices=["rid", "pdc", "infrastructure","schema","naming","all"],
201 help="""The FSMO role to seize or transfer.\n
202 rid=RidAllocationMasterRole\n
203 schema=SchemaMasterRole\n
204 pdc=PdcEmulationMasterRole\n
205 naming=DomainNamingMasterRole\n
206 infrastructure=InfrastructureMasterRole\n
207 all=all of the above"""),
212 def transfer_role(self, role, samdb):
214 m.dn = ldb.Dn(samdb, "")
216 m["becomeRidMaster"]= ldb.MessageElement(
217 "1", ldb.FLAG_MOD_REPLACE,
220 domain_dn = samdb.domain_dn()
221 res = samdb.search(domain_dn,
222 scope=ldb.SCOPE_BASE, attrs=["objectSid"])
224 sid = res[0]["objectSid"][0]
225 m["becomePdc"]= ldb.MessageElement(
226 sid, ldb.FLAG_MOD_REPLACE,
228 elif role == "naming":
229 m["becomeDomainMaster"]= ldb.MessageElement(
230 "1", ldb.FLAG_MOD_REPLACE,
231 "becomeDomainMaster")
233 elif role == "infrastructure":
234 m["becomeInfrastructureMaster"]= ldb.MessageElement(
235 "1", ldb.FLAG_MOD_REPLACE,
236 "becomeInfrastructureMaster")
237 elif role == "schema":
238 m["becomeSchemaMaster"]= ldb.MessageElement(
239 "1", ldb.FLAG_MOD_REPLACE,
240 "becomeSchemaMaster")
242 raise CommandError("Invalid FSMO role.")
245 except LdbError, (num, msg):
246 raise CommandError("Failed to initiate transfer of '%s' role: %s" % (role, msg))
247 self.outf.write("FSMO transfer of '%s' role successful\n" % role)
249 def run(self, force=None, H=None, role=None,
250 credopts=None, sambaopts=None, versionopts=None):
252 lp = sambaopts.get_loadparm()
253 creds = credopts.get_credentials(lp, fallback_machine=True)
255 samdb = SamDB(url=H, session_info=system_session(),
256 credentials=creds, lp=lp)
259 self.transfer_role("rid", samdb)
260 self.transfer_role("pdc", samdb)
261 self.transfer_role("naming", samdb)
262 self.transfer_role("infrastructure", samdb)
263 self.transfer_role("schema", samdb)
265 self.transfer_role(role, samdb)
268 class cmd_fsmo(SuperCommand):
269 """Flexible Single Master Operations (FSMO) roles management"""
272 subcommands["seize"] = cmd_fsmo_seize()
273 subcommands["show"] = cmd_fsmo_show()
274 subcommands["transfer"] = cmd_fsmo_transfer()