s4:samba-tool fsmo * - fix missing "takes_optiongroups"
[ira/wip.git] / source4 / scripting / python / samba / netcmd / fsmo.py
1 #!/usr/bin/env python
2 #
3 # Changes a FSMO role owner
4 #
5 # Copyright Nadezhda Ivanova 2009
6 # Copyright Jelmer Vernooij 2009
7 #
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.
12 #
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.
17 #
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/>.
20 #
21
22 import samba.getopt as options
23 import ldb
24 from ldb import LdbError
25
26 from samba.auth import system_session
27 from samba.netcmd import (
28     Command,
29     CommandError,
30     SuperCommand,
31     Option,
32     )
33 from samba.samdb import SamDB
34
35
36 class cmd_fsmo_seize(Command):
37     """Seize the role"""
38
39     synopsis = "%prog [options]"
40
41     takes_optiongroups = {
42         "sambaopts": options.SambaOptions,
43         "credopts": options.CredentialsOptions,
44         "versionopts": options.VersionOptions,
45         }
46
47     takes_options = [
48         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
49                metavar="URL", dest="H"),
50         Option("--force", help="Force seizing of the role without attempting to transfer first.", action="store_true"),
51         Option("--role", type="choice", choices=["rid", "pdc", "infrastructure","schema","naming","all"],
52                help="""The FSMO role to seize or transfer.\n
53 rid=RidAllocationMasterRole\n
54 schema=SchemaMasterRole\n
55 pdc=PdcEmulationMasterRole\n
56 naming=DomainNamingMasterRole\n
57 infrastructure=InfrastructureMasterRole\n
58 all=all of the above"""),
59         ]
60
61     takes_args = []
62
63     def seize_role(self, role, samdb, force):
64         res = samdb.search("",
65                            scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
66         assert len(res) == 1
67         serviceName = res[0]["dsServiceName"][0]
68         domain_dn = samdb.domain_dn()
69         m = ldb.Message()
70         if role == "rid":
71             m.dn = ldb.Dn(samdb, self.rid_dn)
72         elif role == "pdc":
73             m.dn = ldb.Dn(samdb, domain_dn)
74         elif role == "naming":
75             m.dn = ldb.Dn(samdb, self.naming_dn)
76         elif role == "infrastructure":
77             m.dn = ldb.Dn(samdb, self.infrastructure_dn)
78         elif role == "schema":
79             m.dn = ldb.Dn(samdb, self.schema_dn)
80         else:
81             raise CommandError("Invalid FSMO role.")
82         #first try to transfer to avoid problem if the owner is still active
83         if force is None:
84             self.message("Attempting transfer...")
85             try:
86                 self.transfer_role(role, samdb)
87             except LdbError, (num, _):
88             #transfer failed, use the big axe...
89                 self.message("Transfer unsuccessful, seizing...")
90                 m["fSMORoleOwner"]= ldb.MessageElement(
91                     serviceName, ldb.FLAG_MOD_REPLACE,
92                     "fSMORoleOwner")
93         else:
94             self.message("Will not attempt transfer, seizing...")
95             m["fSMORoleOwner"]= ldb.MessageElement(
96                 serviceName, ldb.FLAG_MOD_REPLACE,
97                 "fSMORoleOwner")
98         try:
99             samdb.modify(m)
100         except LdbError, (num, msg):
101             raise CommandError("Failed to initiate role seize of '%s' role: %s" % (role, msg))
102         self.outf.write("FSMO transfer of '%s' role successful\n" % role)
103
104     def run(self, force=None, H=None, role=None,
105             credopts=None, sambaopts=None, versionopts=None):
106
107         lp = sambaopts.get_loadparm()
108         creds = credopts.get_credentials(lp, fallback_machine=True)
109
110         samdb = SamDB(url=H, session_info=system_session(),
111                       credentials=creds, lp=lp)
112
113         if role == "all":
114             self.seize_role("rid", samdb, force)
115             self.seize_role("pdc", samdb, force)
116             self.seize_role("naming", samdb, force)
117             self.seize_role("infrastructure", samdb, force)
118             self.seize_role("schema", samdb, force)
119         else:
120             self.seize_role(role, samdb, force)
121
122
123 class cmd_fsmo_show(Command):
124     """Show the roles"""
125
126     synopsis = "%prog [options]"
127
128     takes_optiongroups = {
129         "sambaopts": options.SambaOptions,
130         "credopts": options.CredentialsOptions,
131         "versionopts": options.VersionOptions,
132         }
133
134     takes_options = [
135         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
136                metavar="URL", dest="H"),
137         ]
138
139     takes_args = []
140
141     def run(self, H=None, credopts=None, sambaopts=None, versionopts=None):
142         lp = sambaopts.get_loadparm()
143         creds = credopts.get_credentials(lp, fallback_machine=True)
144
145         samdb = SamDB(url=H, session_info=system_session(),
146             credentials=creds, lp=lp)
147
148         domain_dn = samdb.domain_dn()
149         self.infrastructure_dn = "CN=Infrastructure," + domain_dn
150         self.naming_dn = "CN=Partitions,%s" % samdb.get_config_basedn()
151         self.schema_dn = samdb.get_schema_basedn()
152         self.rid_dn = "CN=RID Manager$,CN=System," + domain_dn
153
154         res = samdb.search(self.infrastructure_dn,
155                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
156         assert len(res) == 1
157         self.infrastructureMaster = res[0]["fSMORoleOwner"][0]
158
159         res = samdb.search(domain_dn,
160                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
161         assert len(res) == 1
162         self.pdcEmulator = res[0]["fSMORoleOwner"][0]
163
164         res = samdb.search(self.naming_dn,
165                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
166         assert len(res) == 1
167         self.namingMaster = res[0]["fSMORoleOwner"][0]
168
169         res = samdb.search(self.schema_dn,
170                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
171         assert len(res) == 1
172         self.schemaMaster = res[0]["fSMORoleOwner"][0]
173
174         res = samdb.search(self.rid_dn,
175                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
176         assert len(res) == 1
177         self.ridMaster = res[0]["fSMORoleOwner"][0]
178
179         self.message("InfrastructureMasterRole owner: " + self.infrastructureMaster)
180         self.message("RidAllocationMasterRole owner: " + self.ridMaster)
181         self.message("PdcEmulationMasterRole owner: " + self.pdcEmulator)
182         self.message("DomainNamingMasterRole owner: " + self.namingMaster)
183         self.message("SchemaMasterRole owner: " + self.schemaMaster)
184
185
186 class cmd_fsmo_transfer(Command):
187     """Transfer the role"""
188
189     synopsis = "%prog [options]"
190
191     takes_optiongroups = {
192         "sambaopts": options.SambaOptions,
193         "credopts": options.CredentialsOptions,
194         "versionopts": options.VersionOptions,
195         }
196
197     takes_options = [
198         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
199                metavar="URL", dest="H"),
200         Option("--role", type="choice", choices=["rid", "pdc", "infrastructure","schema","naming","all"],
201                help="""The FSMO role to seize or transfer.\n
202 rid=RidAllocationMasterRole\n
203 schema=SchemaMasterRole\n
204 pdc=PdcEmulationMasterRole\n
205 naming=DomainNamingMasterRole\n
206 infrastructure=InfrastructureMasterRole\n
207 all=all of the above"""),
208         ]
209
210     takes_args = []
211
212     def transfer_role(self, role, samdb):
213         m = ldb.Message()
214         m.dn = ldb.Dn(samdb, "")
215         if role == "rid":
216             m["becomeRidMaster"]= ldb.MessageElement(
217                 "1", ldb.FLAG_MOD_REPLACE,
218                 "becomeRidMaster")
219         elif role == "pdc":
220             domain_dn = samdb.domain_dn()
221             res = samdb.search(domain_dn,
222                                scope=ldb.SCOPE_BASE, attrs=["objectSid"])
223             assert len(res) == 1
224             sid = res[0]["objectSid"][0]
225             m["becomePdc"]= ldb.MessageElement(
226                 sid, ldb.FLAG_MOD_REPLACE,
227                 "becomePdc")
228         elif role == "naming":
229             m["becomeDomainMaster"]= ldb.MessageElement(
230                 "1", ldb.FLAG_MOD_REPLACE,
231                 "becomeDomainMaster")
232             samdb.modify(m)
233         elif role == "infrastructure":
234             m["becomeInfrastructureMaster"]= ldb.MessageElement(
235                 "1", ldb.FLAG_MOD_REPLACE,
236                 "becomeInfrastructureMaster")
237         elif role == "schema":
238             m["becomeSchemaMaster"]= ldb.MessageElement(
239                 "1", ldb.FLAG_MOD_REPLACE,
240                 "becomeSchemaMaster")
241         else:
242             raise CommandError("Invalid FSMO role.")
243         try:
244             samdb.modify(m)
245         except LdbError, (num, msg):
246             raise CommandError("Failed to initiate transfer of '%s' role: %s" % (role, msg))
247         self.outf.write("FSMO transfer of '%s' role successful\n" % role)
248
249     def run(self, force=None, H=None, role=None,
250             credopts=None, sambaopts=None, versionopts=None):
251
252         lp = sambaopts.get_loadparm()
253         creds = credopts.get_credentials(lp, fallback_machine=True)
254
255         samdb = SamDB(url=H, session_info=system_session(),
256                       credentials=creds, lp=lp)   
257
258         if role == "all":
259             self.transfer_role("rid", samdb)
260             self.transfer_role("pdc", samdb)
261             self.transfer_role("naming", samdb)
262             self.transfer_role("infrastructure", samdb)
263             self.transfer_role("schema", samdb)
264         else:
265             self.transfer_role(role, samdb)
266
267
268 class cmd_fsmo(SuperCommand):
269     """Flexible Single Master Operations (FSMO) roles management"""
270
271     subcommands = {}
272     subcommands["seize"] = cmd_fsmo_seize()
273     subcommands["show"] = cmd_fsmo_show()
274     subcommands["transfer"] = cmd_fsmo_transfer()