Implemented net fsmo command for transferring fsmo roles
[Samba/fernandojvsilva.git] / source4 / scripting / python / samba / netcmd / fsmo.py
blob6bfc2eff0a131fb0e1d2302289b7b884a9f4e577
1 #!/usr/bin/python
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
23 import ldb
24 from ldb import LdbError
26 from samba.auth import system_session
27 from samba.netcmd import (
28 Command,
29 CommandError,
30 Option,
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,
45 takes_options = [
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):
61 m = ldb.Message()
62 m.dn = ldb.Dn(samdb, "")
63 if role == "rid":
64 m["becomeRidMaster"]= ldb.MessageElement(
65 "1", ldb.FLAG_MOD_REPLACE,
66 "becomeRidMaster")
67 elif role == "pdc":
68 domain_dn = SamDB.domain_dn(samdb)
69 res = samdb.search(domain_dn,
70 scope=ldb.SCOPE_BASE, attrs=["objectSid"])
71 assert(len(res) == 1)
72 sid = res[0]["objectSid"][0]
73 m["becomePdc"]= ldb.MessageElement(
74 sid, ldb.FLAG_MOD_REPLACE,
75 "becomePdc")
76 elif role == "naming":
77 m["becomeDomainMaster"]= ldb.MessageElement(
78 "1", ldb.FLAG_MOD_REPLACE,
79 "becomeDomainMaster")
80 samdb.modify(m)
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,
88 "becomeSchemaMaster")
89 else:
90 raise CommandError("Invalid FSMO role.")
91 samdb.modify(m)
93 def seize_role(self, role, samdb, force):
94 res = samdb.search("",
95 scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
96 assert(len(res) == 1)
97 serviceName = res[0]["dsServiceName"][0]
98 domain_dn = SamDB.domain_dn(samdb)
99 m = ldb.Message()
100 if role == "rid":
101 m.dn = ldb.Dn(samdb, self.rid_dn)
102 elif role == "pdc":
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)
110 else:
111 raise CommandError("Invalid FSMO role.")
112 #first try to transfer to avoid problem if the owner is still active
113 if force is None:
114 self.message("Attempting transfer...")
115 try:
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,
122 "fSMORoleOwner")
123 samdb.modify(m)
124 else:
125 self.message("Transfer succeeded.")
126 else:
127 self.message("Will not attempt transfer, seizing...")
128 m["fSMORoleOwner"]= ldb.MessageElement(
129 serviceName, ldb.FLAG_MOD_REPLACE,
130 "fSMORoleOwner")
131 samdb.modify(m)
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)
138 if host is not None:
139 url = host
140 else:
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":
184 if role == "all":
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)
190 else:
191 self.transfer_role(role, samdb)
192 elif subcommand == "seize":
193 if role == "all":
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)
199 else:
200 self.seize_role(role, samdb, force)
201 else:
202 raise CommandError("Wrong argument '%s'!" % subcommand)