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
38 class cmd_fsmo_seize(Command
):
41 synopsis
= "%prog fsmo seize [options]"
44 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
45 metavar
="URL", dest
="H"),
46 Option("--force", help="Force seizing of the role without attempting to transfer first.", action
="store_true"),
47 Option("--role", type="choice", choices
=["rid", "pdc", "infrastructure","schema","naming","all"],
48 help="""The FSMO role to seize or transfer.\n
49 rid=RidAllocationMasterRole\n
50 schema=SchemaMasterRole\n
51 pdc=PdcEmulationMasterRole\n
52 naming=DomainNamingMasterRole\n
53 infrastructure=InfrastructureMasterRole\n
54 all=all of the above"""),
59 def seize_role(self
, role
, samdb
, force
):
60 res
= samdb
.search("",
61 scope
=ldb
.SCOPE_BASE
, attrs
=["dsServiceName"])
63 serviceName
= res
[0]["dsServiceName"][0]
64 domain_dn
= samdb
.domain_dn()
67 m
.dn
= ldb
.Dn(samdb
, self
.rid_dn
)
69 m
.dn
= ldb
.Dn(samdb
, domain_dn
)
70 elif role
== "naming":
71 m
.dn
= ldb
.Dn(samdb
, self
.naming_dn
)
72 elif role
== "infrastructure":
73 m
.dn
= ldb
.Dn(samdb
, self
.infrastructure_dn
)
74 elif role
== "schema":
75 m
.dn
= ldb
.Dn(samdb
, self
.schema_dn
)
77 raise CommandError("Invalid FSMO role.")
78 #first try to transfer to avoid problem if the owner is still active
80 self
.message("Attempting transfer...")
82 self
.transfer_role(role
, samdb
)
83 except LdbError
, (num
, _
):
84 #transfer failed, use the big axe...
85 self
.message("Transfer unsuccessful, seizing...")
86 m
["fSMORoleOwner"]= ldb
.MessageElement(
87 serviceName
, ldb
.FLAG_MOD_REPLACE
,
90 self
.message("Will not attempt transfer, seizing...")
91 m
["fSMORoleOwner"]= ldb
.MessageElement(
92 serviceName
, ldb
.FLAG_MOD_REPLACE
,
96 except LdbError
, (num
, msg
):
97 raise CommandError("Failed to initiate role seize of '%s' role: %s" % (role
, msg
))
98 self
.outf
.write("FSMO transfer of '%s' role successful\n" % role
)
100 def run(self
, force
=None, H
=None, role
=None,
101 credopts
=None, sambaopts
=None, versionopts
=None):
103 lp
= sambaopts
.get_loadparm()
104 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
106 samdb
= SamDB(url
=H
, session_info
=system_session(),
107 credentials
=creds
, lp
=lp
)
110 self
.seize_role("rid", samdb
, force
)
111 self
.seize_role("pdc", samdb
, force
)
112 self
.seize_role("naming", samdb
, force
)
113 self
.seize_role("infrastructure", samdb
, force
)
114 self
.seize_role("schema", samdb
, force
)
116 self
.seize_role(role
, samdb
, force
)
120 class cmd_fsmo_show(Command
):
123 synopsis
= "%prog fsmo show [options]"
126 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
127 metavar
="URL", dest
="H"),
132 def run(self
, H
=None,
133 credopts
=None, sambaopts
=None, versionopts
=None):
134 lp
= sambaopts
.get_loadparm()
135 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
137 samdb
= SamDB(url
=H
, session_info
=system_session(),
138 credentials
=creds
, lp
=lp
)
140 domain_dn
= samdb
.domain_dn()
141 self
.infrastructure_dn
= "CN=Infrastructure," + domain_dn
142 self
.naming_dn
= "CN=Partitions,%s" % samdb
.get_config_basedn()
143 self
.schema_dn
= samdb
.get_schema_basedn()
144 self
.rid_dn
= "CN=RID Manager$,CN=System," + domain_dn
146 res
= samdb
.search(self
.infrastructure_dn
,
147 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
149 self
.infrastructureMaster
= res
[0]["fSMORoleOwner"][0]
151 res
= samdb
.search(domain_dn
,
152 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
154 self
.pdcEmulator
= res
[0]["fSMORoleOwner"][0]
156 res
= samdb
.search(self
.naming_dn
,
157 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
159 self
.namingMaster
= res
[0]["fSMORoleOwner"][0]
161 res
= samdb
.search(self
.schema_dn
,
162 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
164 self
.schemaMaster
= res
[0]["fSMORoleOwner"][0]
166 res
= samdb
.search(self
.rid_dn
,
167 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
169 self
.ridMaster
= res
[0]["fSMORoleOwner"][0]
171 self
.message("InfrastructureMasterRole owner: " + self
.infrastructureMaster
)
172 self
.message("RidAllocationMasterRole owner: " + self
.ridMaster
)
173 self
.message("PdcEmulationMasterRole owner: " + self
.pdcEmulator
)
174 self
.message("DomainNamingMasterRole owner: " + self
.namingMaster
)
175 self
.message("SchemaMasterRole owner: " + self
.schemaMaster
)
179 class cmd_fsmo_transfer(Command
):
180 """Transfer the role"""
182 synopsis
= "%prog fsmo transfer [options]"
185 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
186 metavar
="URL", dest
="H"),
187 Option("--role", type="choice", choices
=["rid", "pdc", "infrastructure","schema","naming","all"],
188 help="""The FSMO role to seize or transfer.\n
189 rid=RidAllocationMasterRole\n
190 schema=SchemaMasterRole\n
191 pdc=PdcEmulationMasterRole\n
192 naming=DomainNamingMasterRole\n
193 infrastructure=InfrastructureMasterRole\n
194 all=all of the above"""),
199 def transfer_role(self
, role
, samdb
):
201 m
.dn
= ldb
.Dn(samdb
, "")
203 m
["becomeRidMaster"]= ldb
.MessageElement(
204 "1", ldb
.FLAG_MOD_REPLACE
,
207 domain_dn
= samdb
.domain_dn()
208 res
= samdb
.search(domain_dn
,
209 scope
=ldb
.SCOPE_BASE
, attrs
=["objectSid"])
211 sid
= res
[0]["objectSid"][0]
212 m
["becomePdc"]= ldb
.MessageElement(
213 sid
, ldb
.FLAG_MOD_REPLACE
,
215 elif role
== "naming":
216 m
["becomeDomainMaster"]= ldb
.MessageElement(
217 "1", ldb
.FLAG_MOD_REPLACE
,
218 "becomeDomainMaster")
220 elif role
== "infrastructure":
221 m
["becomeInfrastructureMaster"]= ldb
.MessageElement(
222 "1", ldb
.FLAG_MOD_REPLACE
,
223 "becomeInfrastructureMaster")
224 elif role
== "schema":
225 m
["becomeSchemaMaster"]= ldb
.MessageElement(
226 "1", ldb
.FLAG_MOD_REPLACE
,
227 "becomeSchemaMaster")
229 raise CommandError("Invalid FSMO role.")
232 except LdbError
, (num
, msg
):
233 raise CommandError("Failed to initiate transfer of '%s' role: %s" % (role
, msg
))
234 self
.outf
.write("FSMO transfer of '%s' role successful\n" % role
)
236 def run(self
, force
=None, H
=None, role
=None,
237 credopts
=None, sambaopts
=None, versionopts
=None):
239 lp
= sambaopts
.get_loadparm()
240 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
242 samdb
= SamDB(url
=H
, session_info
=system_session(),
243 credentials
=creds
, lp
=lp
)
246 self
.transfer_role("rid", samdb
)
247 self
.transfer_role("pdc", samdb
)
248 self
.transfer_role("naming", samdb
)
249 self
.transfer_role("infrastructure", samdb
)
250 self
.transfer_role("schema", samdb
)
252 self
.transfer_role(role
, samdb
)
256 class cmd_fsmo(SuperCommand
):
257 """Flexible Single Master Operations (FSMO) roles management"""
260 subcommands
["seize"] = cmd_fsmo_seize()
261 subcommands
["show"] = cmd_fsmo_show()
262 subcommands
["transfer"] = cmd_fsmo_transfer()