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 (
33 from samba
.samdb
import SamDB
35 class cmd_fsmo(Command
):
36 """Flexible Single Master Operations (FSMO) roles management *"""
38 synopsis
= "(show | transfer <options> | seize <options>)"
41 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
42 metavar
="URL", dest
="H"),
43 Option("--force", help="Force seizing of the role without attempting to transfer first.", action
="store_true"),
44 Option("--role", type="choice", choices
=["rid", "pdc", "infrastructure","schema","naming","all"],
45 help="""The FSMO role to seize or transfer.\n
46 rid=RidAllocationMasterRole\n
47 schema=SchemaMasterRole\n
48 pdc=PdcEmulationMasterRole\n
49 naming=DomainNamingMasterRole\n
50 infrastructure=InfrastructureMasterRole\n
51 all=all of the above"""),
54 takes_args
= ["subcommand"]
56 def transfer_role(self
, role
, samdb
):
58 m
.dn
= ldb
.Dn(samdb
, "")
60 m
["becomeRidMaster"]= ldb
.MessageElement(
61 "1", ldb
.FLAG_MOD_REPLACE
,
64 domain_dn
= samdb
.domain_dn()
65 res
= samdb
.search(domain_dn
,
66 scope
=ldb
.SCOPE_BASE
, attrs
=["objectSid"])
68 sid
= res
[0]["objectSid"][0]
69 m
["becomePdc"]= ldb
.MessageElement(
70 sid
, ldb
.FLAG_MOD_REPLACE
,
72 elif role
== "naming":
73 m
["becomeDomainMaster"]= ldb
.MessageElement(
74 "1", ldb
.FLAG_MOD_REPLACE
,
77 elif role
== "infrastructure":
78 m
["becomeInfrastructureMaster"]= ldb
.MessageElement(
79 "1", ldb
.FLAG_MOD_REPLACE
,
80 "becomeInfrastructureMaster")
81 elif role
== "schema":
82 m
["becomeSchemaMaster"]= ldb
.MessageElement(
83 "1", ldb
.FLAG_MOD_REPLACE
,
86 raise CommandError("Invalid FSMO role.")
89 except LdbError
, (num
, msg
):
90 raise CommandError("Failed to initiate transfer of '%s' role: %s" % (role
, msg
))
91 print("FSMO transfer of '%s' role successful" % role
)
94 def seize_role(self
, role
, samdb
, force
):
95 res
= samdb
.search("",
96 scope
=ldb
.SCOPE_BASE
, attrs
=["dsServiceName"])
98 serviceName
= res
[0]["dsServiceName"][0]
99 domain_dn
= samdb
.domain_dn()
102 m
.dn
= ldb
.Dn(samdb
, self
.rid_dn
)
104 m
.dn
= ldb
.Dn(samdb
, domain_dn
)
105 elif role
== "naming":
106 m
.dn
= ldb
.Dn(samdb
, self
.naming_dn
)
107 elif role
== "infrastructure":
108 m
.dn
= ldb
.Dn(samdb
, self
.infrastructure_dn
)
109 elif role
== "schema":
110 m
.dn
= ldb
.Dn(samdb
, self
.schema_dn
)
112 raise CommandError("Invalid FSMO role.")
113 #first try to transfer to avoid problem if the owner is still active
115 self
.message("Attempting transfer...")
117 self
.transfer_role(role
, samdb
)
118 except LdbError
, (num
, _
):
119 #transfer failed, use the big axe...
120 self
.message("Transfer unsuccessful, seizing...")
121 m
["fSMORoleOwner"]= ldb
.MessageElement(
122 serviceName
, ldb
.FLAG_MOD_REPLACE
,
125 self
.message("Will not attempt transfer, seizing...")
126 m
["fSMORoleOwner"]= ldb
.MessageElement(
127 serviceName
, ldb
.FLAG_MOD_REPLACE
,
131 except LdbError
, (num
, msg
):
132 raise CommandError("Failed to initiate role seize of '%s' role: %s" % (role
, msg
))
133 print("FSMO transfer of '%s' role successful" % role
)
136 def run(self
, subcommand
, force
=None, H
=None, role
=None,
137 credopts
=None, sambaopts
=None, versionopts
=None):
138 lp
= sambaopts
.get_loadparm()
139 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
141 samdb
= SamDB(url
=H
, session_info
=system_session(),
142 credentials
=creds
, lp
=lp
)
144 domain_dn
= samdb
.domain_dn()
145 self
.infrastructure_dn
= "CN=Infrastructure," + domain_dn
146 self
.naming_dn
= "CN=Partitions,CN=Configuration," + domain_dn
147 self
.schema_dn
= "CN=Schema,CN=Configuration," + domain_dn
148 self
.rid_dn
= "CN=RID Manager$,CN=System," + domain_dn
150 res
= samdb
.search(self
.infrastructure_dn
,
151 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
153 self
.infrastructureMaster
= res
[0]["fSMORoleOwner"][0]
155 res
= samdb
.search(domain_dn
,
156 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
158 self
.pdcEmulator
= res
[0]["fSMORoleOwner"][0]
160 res
= samdb
.search(self
.naming_dn
,
161 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
163 self
.namingMaster
= res
[0]["fSMORoleOwner"][0]
165 res
= samdb
.search(self
.schema_dn
,
166 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
168 self
.schemaMaster
= res
[0]["fSMORoleOwner"][0]
170 res
= samdb
.search(self
.rid_dn
,
171 scope
=ldb
.SCOPE_BASE
, attrs
=["fSMORoleOwner"])
173 self
.ridMaster
= res
[0]["fSMORoleOwner"][0]
175 if subcommand
== "show":
176 self
.message("InfrastructureMasterRole owner: " + self
.infrastructureMaster
)
177 self
.message("RidAllocationMasterRole owner: " + self
.ridMaster
)
178 self
.message("PdcEmulationMasterRole owner: " + self
.pdcEmulator
)
179 self
.message("DomainNamingMasterRole owner: " + self
.namingMaster
)
180 self
.message("SchemaMasterRole owner: " + self
.schemaMaster
)
181 elif subcommand
== "transfer":
183 self
.transfer_role("rid", samdb
)
184 self
.transfer_role("pdc", samdb
)
185 self
.transfer_role("naming", samdb
)
186 self
.transfer_role("infrastructure", samdb
)
187 self
.transfer_role("schema", samdb
)
189 self
.transfer_role(role
, samdb
)
190 elif subcommand
== "seize":
192 self
.seize_role("rid", samdb
, force
)
193 self
.seize_role("pdc", samdb
, force
)
194 self
.seize_role("naming", samdb
, force
)
195 self
.seize_role("infrastructure", samdb
, force
)
196 self
.seize_role("schema", samdb
, force
)
198 self
.seize_role(role
, samdb
, force
)
200 raise CommandError("Wrong argument '%s'!" % subcommand
)