samba-tool: Changed fsmo implementation
[Samba.git] / source4 / scripting / python / samba / netcmd / fsmo.py
blob58b920d0a370d39fcb7bce9838000204a7c3de39
1 #!/usr/bin/env python
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
24 import ldb
25 from ldb import LdbError
27 from samba.auth import system_session
28 from samba.netcmd import (
29 Command,
30 CommandError,
31 SuperCommand,
32 Option,
34 from samba.samdb import SamDB
38 class cmd_fsmo_seize(Command):
39 """Seize the role"""
41 synopsis = "%prog fsmo seize [options]"
43 takes_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"""),
57 takes_args = []
59 def seize_role(self, role, samdb, force):
60 res = samdb.search("",
61 scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
62 assert len(res) == 1
63 serviceName = res[0]["dsServiceName"][0]
64 domain_dn = samdb.domain_dn()
65 m = ldb.Message()
66 if role == "rid":
67 m.dn = ldb.Dn(samdb, self.rid_dn)
68 elif role == "pdc":
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)
76 else:
77 raise CommandError("Invalid FSMO role.")
78 #first try to transfer to avoid problem if the owner is still active
79 if force is None:
80 self.message("Attempting transfer...")
81 try:
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,
88 "fSMORoleOwner")
89 else:
90 self.message("Will not attempt transfer, seizing...")
91 m["fSMORoleOwner"]= ldb.MessageElement(
92 serviceName, ldb.FLAG_MOD_REPLACE,
93 "fSMORoleOwner")
94 try:
95 samdb.modify(m)
96 except LdbError, (num, msg):
97 raise CommandError("Failed to initiate role seize of '%s' role: %s" % (role, msg))
98 print("FSMO transfer of '%s' role successful" % 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)
109 if role == "all":
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)
115 else:
116 self.seize_role(role, samdb, force)
120 class cmd_fsmo_show(Command):
121 """Show the roles"""
123 synopsis = "%prog fsmo show [options]"
125 takes_options = [
126 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
127 metavar="URL", dest="H"),
130 takes_args = []
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,CN=Configuration," + domain_dn
143 self.schema_dn = "CN=Schema,CN=Configuration," + domain_dn
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"])
148 assert len(res) == 1
149 self.infrastructureMaster = res[0]["fSMORoleOwner"][0]
151 res = samdb.search(domain_dn,
152 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
153 assert len(res) == 1
154 self.pdcEmulator = res[0]["fSMORoleOwner"][0]
156 res = samdb.search(self.naming_dn,
157 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
158 assert len(res) == 1
159 self.namingMaster = res[0]["fSMORoleOwner"][0]
161 res = samdb.search(self.schema_dn,
162 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
163 assert len(res) == 1
164 self.schemaMaster = res[0]["fSMORoleOwner"][0]
166 res = samdb.search(self.rid_dn,
167 scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
168 assert len(res) == 1
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]"
184 takes_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"""),
197 takes_args = []
199 def transfer_role(self, role, samdb):
200 m = ldb.Message()
201 m.dn = ldb.Dn(samdb, "")
202 if role == "rid":
203 m["becomeRidMaster"]= ldb.MessageElement(
204 "1", ldb.FLAG_MOD_REPLACE,
205 "becomeRidMaster")
206 elif role == "pdc":
207 domain_dn = samdb.domain_dn()
208 res = samdb.search(domain_dn,
209 scope=ldb.SCOPE_BASE, attrs=["objectSid"])
210 assert len(res) == 1
211 sid = res[0]["objectSid"][0]
212 m["becomePdc"]= ldb.MessageElement(
213 sid, ldb.FLAG_MOD_REPLACE,
214 "becomePdc")
215 elif role == "naming":
216 m["becomeDomainMaster"]= ldb.MessageElement(
217 "1", ldb.FLAG_MOD_REPLACE,
218 "becomeDomainMaster")
219 samdb.modify(m)
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")
228 else:
229 raise CommandError("Invalid FSMO role.")
230 try:
231 samdb.modify(m)
232 except LdbError, (num, msg):
233 raise CommandError("Failed to initiate transfer of '%s' role: %s" % (role, msg))
234 print("FSMO transfer of '%s' role successful" % 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)
245 if role == "all":
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)
251 else:
252 self.transfer_role(role, samdb)
256 class cmd_fsmo(SuperCommand):
257 """Flexible Single Master Operations (FSMO) roles management *"""
259 subcommands = {}
260 subcommands["seize"] = cmd_fsmo_seize()
261 subcommands["show"] = cmd_fsmo_show()
262 subcommands["transfer"] = cmd_fsmo_transfer()