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"""
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(samdb
)
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(samdb
)
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
.indrastructure_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
)
141 url
= lp
.get("sam database")
143 samdb
= SamDB(url
=url
, session_info
=system_session(),
144 credentials
=creds
, lp
=lp
)
146 domain_dn
= SamDB
.domain_dn(samdb
)
147 self
.infrastructure_dn
= "CN=Infrastructure," + domain_dn
148 self
.naming_dn
= "CN=Partitions,CN=Configuration," + domain_dn
149 self
.schema_dn
= "CN=Schema,CN=Configuration," + domain_dn
150 self
.rid_dn
= "CN=RID Manager$,CN=System," + domain_dn
152 res
= samdb
.search(self
.infrastructure_dn
,
153 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
154 assert(len(res
) == 1)
155 self
.infrastructureMaster
= res
[0]["fSMORoleOwner"][0]
157 res
= samdb
.search(domain_dn
,
158 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
159 assert(len(res
) == 1)
160 self
.pdcEmulator
= res
[0]["fSMORoleOwner"][0]
162 res
= samdb
.search(self
.naming_dn
,
163 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
164 assert(len(res
) == 1)
165 self
.namingMaster
= res
[0]["fSMORoleOwner"][0]
167 res
= samdb
.search(self
.schema_dn
,
168 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
169 assert(len(res
) == 1)
170 self
.schemaMaster
= res
[0]["fSMORoleOwner"][0]
172 res
= samdb
.search(self
.rid_dn
,
173 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
174 assert(len(res
) == 1)
175 self
.ridMaster
= res
[0]["fSMORoleOwner"][0]
177 if subcommand
== "show":
178 self
.message("InfrastructureMasterRole owner: " + self
.infrastructureMaster
)
179 self
.message("RidAllocationMasterRole owner: " + self
.ridMaster
)
180 self
.message("PdcEmulationMasterRole owner: " + self
.pdcEmulator
)
181 self
.message("DomainNamingMasterRole owner: " + self
.namingMaster
)
182 self
.message("SchemaMasterRole owner: " + self
.schemaMaster
)
183 elif subcommand
== "transfer":
185 self
.transfer_role("rid", samdb
)
186 self
.transfer_role("pdc", samdb
)
187 self
.transfer_role("naming", samdb
)
188 self
.transfer_role("infrastructure", samdb
)
189 self
.transfer_role("schema", samdb
)
191 self
.transfer_role(role
, samdb
)
192 elif subcommand
== "seize":
194 self
.seize_role("rid", samdb
, force
)
195 self
.seize_role("pdc", samdb
, force
)
196 self
.seize_role("naming", samdb
, force
)
197 self
.seize_role("infrastructure", samdb
, force
)
198 self
.zeize_role("schema", samdb
, force
)
200 self
.seize_role(role
, samdb
, force
)
202 raise CommandError("Wrong argument '%s'!" % subcommand
)