3 # Changes a FSMO role owner
5 # Copyright Nadezhda Ivanova 2009
6 # Copyright Jelmer Vernooij 2009
7 # Copyright Giampaolo Lauria 2011 <lauria2@yahoo.com>
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import samba
.getopt
as options
25 from ldb
import LdbError
27 from samba
.auth
import system_session
28 from samba
.netcmd
import (
34 from samba
.samdb
import SamDB
37 class cmd_fsmo_seize(Command
):
40 synopsis
= "%prog [options]"
43 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
44 metavar
="URL", dest
="H"),
45 Option("--force", help="Force seizing of the role without attempting to transfer first.", action
="store_true"),
46 Option("--role", type="choice", choices
=["rid", "pdc", "infrastructure","schema","naming","all"],
47 help="""The FSMO role to seize or transfer.\n
48 rid=RidAllocationMasterRole\n
49 schema=SchemaMasterRole\n
50 pdc=PdcEmulationMasterRole\n
51 naming=DomainNamingMasterRole\n
52 infrastructure=InfrastructureMasterRole\n
53 all=all of the above"""),
58 def seize_role(self
, role
, samdb
, force
):
59 res
= samdb
.search("",
60 scope
=ldb
.SCOPE_BASE
, attrs
=["dsServiceName"])
62 serviceName
= res
[0]["dsServiceName"][0]
63 domain_dn
= samdb
.domain_dn()
66 m
.dn
= ldb
.Dn(samdb
, self
.rid_dn
)
68 m
.dn
= ldb
.Dn(samdb
, domain_dn
)
69 elif role
== "naming":
70 m
.dn
= ldb
.Dn(samdb
, self
.naming_dn
)
71 elif role
== "infrastructure":
72 m
.dn
= ldb
.Dn(samdb
, self
.infrastructure_dn
)
73 elif role
== "schema":
74 m
.dn
= ldb
.Dn(samdb
, self
.schema_dn
)
76 raise CommandError("Invalid FSMO role.")
77 #first try to transfer to avoid problem if the owner is still active
79 self
.message("Attempting transfer...")
81 self
.transfer_role(role
, samdb
)
82 except LdbError
, (num
, _
):
83 #transfer failed, use the big axe...
84 self
.message("Transfer unsuccessful, seizing...")
85 m
["fSMORoleOwner"]= ldb
.MessageElement(
86 serviceName
, ldb
.FLAG_MOD_REPLACE
,
89 self
.message("Will not attempt transfer, seizing...")
90 m
["fSMORoleOwner"]= ldb
.MessageElement(
91 serviceName
, ldb
.FLAG_MOD_REPLACE
,
95 except LdbError
, (num
, msg
):
96 raise CommandError("Failed to initiate role seize of '%s' role: %s" % (role
, msg
))
97 self
.outf
.write("FSMO transfer of '%s' role successful\n" % role
)
99 def run(self
, force
=None, H
=None, role
=None,
100 credopts
=None, sambaopts
=None, versionopts
=None):
102 lp
= sambaopts
.get_loadparm()
103 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
105 samdb
= SamDB(url
=H
, session_info
=system_session(),
106 credentials
=creds
, lp
=lp
)
109 self
.seize_role("rid", samdb
, force
)
110 self
.seize_role("pdc", samdb
, force
)
111 self
.seize_role("naming", samdb
, force
)
112 self
.seize_role("infrastructure", samdb
, force
)
113 self
.seize_role("schema", samdb
, force
)
115 self
.seize_role(role
, samdb
, force
)
118 class cmd_fsmo_show(Command
):
121 synopsis
= "%prog [options]"
124 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
125 metavar
="URL", dest
="H"),
130 def run(self
, H
=None, credopts
=None, sambaopts
=None, versionopts
=None):
131 lp
= sambaopts
.get_loadparm()
132 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
134 samdb
= SamDB(url
=H
, session_info
=system_session(),
135 credentials
=creds
, lp
=lp
)
137 domain_dn
= samdb
.domain_dn()
138 self
.infrastructure_dn
= "CN=Infrastructure," + domain_dn
139 self
.naming_dn
= "CN=Partitions,%s" % samdb
.get_config_basedn()
140 self
.schema_dn
= samdb
.get_schema_basedn()
141 self
.rid_dn
= "CN=RID Manager$,CN=System," + domain_dn
143 res
= samdb
.search(self
.infrastructure_dn
,
144 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
146 self
.infrastructureMaster
= res
[0]["fSMORoleOwner"][0]
148 res
= samdb
.search(domain_dn
,
149 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
151 self
.pdcEmulator
= res
[0]["fSMORoleOwner"][0]
153 res
= samdb
.search(self
.naming_dn
,
154 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
156 self
.namingMaster
= res
[0]["fSMORoleOwner"][0]
158 res
= samdb
.search(self
.schema_dn
,
159 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
161 self
.schemaMaster
= res
[0]["fSMORoleOwner"][0]
163 res
= samdb
.search(self
.rid_dn
,
164 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
166 self
.ridMaster
= res
[0]["fSMORoleOwner"][0]
168 self
.message("InfrastructureMasterRole owner: " + self
.infrastructureMaster
)
169 self
.message("RidAllocationMasterRole owner: " + self
.ridMaster
)
170 self
.message("PdcEmulationMasterRole owner: " + self
.pdcEmulator
)
171 self
.message("DomainNamingMasterRole owner: " + self
.namingMaster
)
172 self
.message("SchemaMasterRole owner: " + self
.schemaMaster
)
175 class cmd_fsmo_transfer(Command
):
176 """Transfer the role"""
178 synopsis
= "%prog [options]"
181 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
182 metavar
="URL", dest
="H"),
183 Option("--role", type="choice", choices
=["rid", "pdc", "infrastructure","schema","naming","all"],
184 help="""The FSMO role to seize or transfer.\n
185 rid=RidAllocationMasterRole\n
186 schema=SchemaMasterRole\n
187 pdc=PdcEmulationMasterRole\n
188 naming=DomainNamingMasterRole\n
189 infrastructure=InfrastructureMasterRole\n
190 all=all of the above"""),
195 def transfer_role(self
, role
, samdb
):
197 m
.dn
= ldb
.Dn(samdb
, "")
199 m
["becomeRidMaster"]= ldb
.MessageElement(
200 "1", ldb
.FLAG_MOD_REPLACE
,
203 domain_dn
= samdb
.domain_dn()
204 res
= samdb
.search(domain_dn
,
205 scope
=ldb
.SCOPE_BASE
, attrs
=["objectSid"])
207 sid
= res
[0]["objectSid"][0]
208 m
["becomePdc"]= ldb
.MessageElement(
209 sid
, ldb
.FLAG_MOD_REPLACE
,
211 elif role
== "naming":
212 m
["becomeDomainMaster"]= ldb
.MessageElement(
213 "1", ldb
.FLAG_MOD_REPLACE
,
214 "becomeDomainMaster")
216 elif role
== "infrastructure":
217 m
["becomeInfrastructureMaster"]= ldb
.MessageElement(
218 "1", ldb
.FLAG_MOD_REPLACE
,
219 "becomeInfrastructureMaster")
220 elif role
== "schema":
221 m
["becomeSchemaMaster"]= ldb
.MessageElement(
222 "1", ldb
.FLAG_MOD_REPLACE
,
223 "becomeSchemaMaster")
225 raise CommandError("Invalid FSMO role.")
228 except LdbError
, (num
, msg
):
229 raise CommandError("Failed to initiate transfer of '%s' role: %s" % (role
, msg
))
230 self
.outf
.write("FSMO transfer of '%s' role successful\n" % role
)
232 def run(self
, force
=None, H
=None, role
=None,
233 credopts
=None, sambaopts
=None, versionopts
=None):
235 lp
= sambaopts
.get_loadparm()
236 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
238 samdb
= SamDB(url
=H
, session_info
=system_session(),
239 credentials
=creds
, lp
=lp
)
242 self
.transfer_role("rid", samdb
)
243 self
.transfer_role("pdc", samdb
)
244 self
.transfer_role("naming", samdb
)
245 self
.transfer_role("infrastructure", samdb
)
246 self
.transfer_role("schema", samdb
)
248 self
.transfer_role(role
, samdb
)
251 class cmd_fsmo(SuperCommand
):
252 """Flexible Single Master Operations (FSMO) roles management"""
255 subcommands
["seize"] = cmd_fsmo_seize()
256 subcommands
["show"] = cmd_fsmo_show()
257 subcommands
["transfer"] = cmd_fsmo_transfer()