s4:netcmd/gpo.py: we don't need to set autogenerated attributes
[metze/samba/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 # Copyright Giampaolo Lauria 2011 <lauria2@yahoo.com>
8 #
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.
13 #
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.
18 #
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/>.
21 #
22
23 import samba.getopt as options
24 import ldb
25 from ldb import LdbError
26
27 from samba.auth import system_session
28 from samba.netcmd import (
29     Command,
30     CommandError,
31     Option,
32     )
33 from samba.samdb import SamDB
34
35 class cmd_fsmo(Command):
36     """Manage flexible single master (FSMO) roles [server connection needed]"""
37
38     synopsis = "(show | transfer <options> | seize <options>)"
39
40     takes_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"""),
52         ]
53
54     takes_args = ["subcommand"]
55
56     def transfer_role(self, role, samdb):
57         m = ldb.Message()
58         m.dn = ldb.Dn(samdb, "")
59         if role == "rid":
60             m["becomeRidMaster"]= ldb.MessageElement(
61                 "1", ldb.FLAG_MOD_REPLACE,
62                 "becomeRidMaster")
63         elif role == "pdc":
64             domain_dn = samdb.domain_dn()
65             res = samdb.search(domain_dn,
66                                scope=ldb.SCOPE_BASE, attrs=["objectSid"])
67             assert len(res) == 1
68             sid = res[0]["objectSid"][0]
69             m["becomePdc"]= ldb.MessageElement(
70                 sid, ldb.FLAG_MOD_REPLACE,
71                 "becomePdc")
72         elif role == "naming":
73             m["becomeDomainMaster"]= ldb.MessageElement(
74                 "1", ldb.FLAG_MOD_REPLACE,
75                 "becomeDomainMaster")
76             samdb.modify(m)
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,
84                 "becomeSchemaMaster")
85         else:
86             raise CommandError("Invalid FSMO role.")
87         try:
88             samdb.modify(m)
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)
92
93
94     def seize_role(self, role, samdb, force):
95         res = samdb.search("",
96                            scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
97         assert len(res) == 1
98         serviceName = res[0]["dsServiceName"][0]
99         domain_dn = samdb.domain_dn()
100         m = ldb.Message()
101         if role == "rid":
102             m.dn = ldb.Dn(samdb, self.rid_dn)
103         elif role == "pdc":
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)
111         else:
112             raise CommandError("Invalid FSMO role.")
113         #first try to transfer to avoid problem if the owner is still active
114         if force is None:
115             self.message("Attempting transfer...")
116             try:
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,
123                     "fSMORoleOwner")
124         else:
125             self.message("Will not attempt transfer, seizing...")
126             m["fSMORoleOwner"]= ldb.MessageElement(
127                 serviceName, ldb.FLAG_MOD_REPLACE,
128                 "fSMORoleOwner")
129         try:
130             samdb.modify(m)
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)
134
135
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)
140
141         samdb = SamDB(url=H, session_info=system_session(),
142             credentials=creds, lp=lp)
143
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
149
150         res = samdb.search(self.infrastructure_dn,
151                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
152         assert len(res) == 1
153         self.infrastructureMaster = res[0]["fSMORoleOwner"][0]
154
155         res = samdb.search(domain_dn,
156                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
157         assert len(res) == 1
158         self.pdcEmulator = res[0]["fSMORoleOwner"][0]
159
160         res = samdb.search(self.naming_dn,
161                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
162         assert len(res) == 1
163         self.namingMaster = res[0]["fSMORoleOwner"][0]
164
165         res = samdb.search(self.schema_dn,
166                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
167         assert len(res) == 1
168         self.schemaMaster = res[0]["fSMORoleOwner"][0]
169
170         res = samdb.search(self.rid_dn,
171                            scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
172         assert len(res) == 1
173         self.ridMaster = res[0]["fSMORoleOwner"][0]
174
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":
182             if role == "all":
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)
188             else:
189                 self.transfer_role(role, samdb)
190         elif subcommand == "seize":
191             if role == "all":
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)
197             else:
198                 self.seize_role(role, samdb, force)
199         else:
200             raise CommandError("Wrong argument '%s'!" % subcommand)