s4-provision: cope with --realm being in getopt.py
[jra/samba/.git] / source4 / setup / provision
1 #!/usr/bin/env python
2 #
3 # Unix SMB/CIFS implementation.
4 # provision a Samba4 server
5 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
6 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
7 #
8 # Based on the original in EJS:
9 # Copyright (C) Andrew Tridgell 2005
10 #   
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
15 #   
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20 #   
21 # You should have received a copy of the GNU General Public License
22 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 #
24
25 import optparse
26 import sys
27 import tempfile
28
29 # Find right directory when running from source tree
30 sys.path.insert(0, "bin/python")
31
32 import samba
33 import samba.ntacls
34 from samba.credentials import DONT_USE_KERBEROS
35 from samba.auth import system_session
36 import samba.getopt as options
37 from samba.provision import provision, FILL_FULL, FILL_NT4SYNC, FILL_DRS, find_setup_dir, ProvisioningError
38 from samba.dsdb import (
39         DS_DOMAIN_FUNCTION_2003,
40         DS_DOMAIN_FUNCTION_2008,
41         DS_DOMAIN_FUNCTION_2008_R2,
42         )
43
44 # how do we make this case insensitive??
45
46 parser = optparse.OptionParser("provision [options]")
47 sambaopts = options.SambaOptions(parser)
48 parser.add_option_group(sambaopts)
49 parser.add_option_group(options.VersionOptions(parser))
50 credopts = options.CredentialsOptions(parser)
51 parser.add_option_group(credopts)
52 parser.add_option("--interactive", help="Ask for names", action="store_true")
53 parser.add_option("--setupdir", type="string", metavar="DIR", 
54                 help="directory with setup files")
55 parser.add_option("--domain", type="string", metavar="DOMAIN",
56                                   help="set domain")
57 parser.add_option("--domain-guid", type="string", metavar="GUID", 
58                 help="set domainguid (otherwise random)")
59 parser.add_option("--domain-sid", type="string", metavar="SID", 
60                 help="set domainsid (otherwise random)")
61 parser.add_option("--policy-guid", type="string", metavar="GUID",
62                                   help="set guid for domain policy")
63 parser.add_option("--policy-guid-dc", type="string", metavar="GUID",
64                                   help="set guid for domain controller policy")
65 parser.add_option("--ntds-guid", type="string", metavar="GUID", 
66                   help="set NTDS object GUID (otherwise random)")
67 parser.add_option("--invocationid", type="string", metavar="GUID", 
68                   help="set invocationid (otherwise random)")
69 parser.add_option("--host-name", type="string", metavar="HOSTNAME", 
70                 help="set hostname")
71 parser.add_option("--host-ip", type="string", metavar="IPADDRESS", 
72                 help="set IPv4 ipaddress")
73 parser.add_option("--host-ip6", type="string", metavar="IP6ADDRESS", 
74                 help="set IPv6 ipaddress")
75 parser.add_option("--adminpass", type="string", metavar="PASSWORD", 
76                 help="choose admin password (otherwise random)")
77 parser.add_option("--krbtgtpass", type="string", metavar="PASSWORD", 
78                 help="choose krbtgt password (otherwise random)")
79 parser.add_option("--machinepass", type="string", metavar="PASSWORD", 
80                 help="choose machine password (otherwise random)")
81 parser.add_option("--dnspass", type="string", metavar="PASSWORD", 
82                 help="choose dns password (otherwise random)")
83 parser.add_option("--ldapadminpass", type="string", metavar="PASSWORD", 
84                 help="choose password to set between Samba and it's LDAP backend (otherwise random)")
85 parser.add_option("--root", type="string", metavar="USERNAME", 
86                 help="choose 'root' unix username")
87 parser.add_option("--nobody", type="string", metavar="USERNAME", 
88                 help="choose 'nobody' user")
89 parser.add_option("--wheel", type="string", metavar="GROUPNAME", 
90                 help="choose 'wheel' privileged group")
91 parser.add_option("--users", type="string", metavar="GROUPNAME", 
92                 help="choose 'users' group")
93 parser.add_option("--quiet", help="Be quiet", action="store_true")
94 parser.add_option("--blank", action="store_true",
95                 help="do not add users or groups, just the structure")
96 parser.add_option("--ldap-backend-extra-port", type="int", metavar="LDAP-BACKEND-EXTRA-PORT", 
97                 help="Additional TCP port for LDAP backend server (to use for replication)")
98 parser.add_option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", 
99                 help="LDAP backend type (fedora-ds or openldap)",
100                 choices=["fedora-ds", "openldap"])
101 parser.add_option("--ldap-backend-nosync", help="Configure LDAP backend not to call fsync() (for performance in test environments)", action="store_true")
102 parser.add_option("--server-role", type="choice", metavar="ROLE",
103                   choices=["domain controller", "dc", "member server", "member", "standalone"],
104                 help="The server role (domain controller | dc | member server | member | standalone). Default is standalone.")
105 parser.add_option("--function-level", type="choice", metavar="FOR-FUN-LEVEL",
106                   choices=["2003", "2008", "2008_R2"],
107                 help="The domain and forest function level (2003 | 2008 | 2008_R2). Default is (Windows) 2003 (Native).")
108 parser.add_option("--partitions-only", 
109                 help="Configure Samba's partitions, but do not modify them (ie, join a BDC)", action="store_true")
110 parser.add_option("--targetdir", type="string", metavar="DIR", 
111                           help="Set target directory")
112 parser.add_option("--ol-mmr-urls", type="string", metavar="LDAPSERVER",
113                 help="List of LDAP-URLS [ ldap://<FQHN>:<PORT>/  (where <PORT> has to be different than 389!) ] separated with comma (\",\") for use with OpenLDAP-MMR (Multi-Master-Replication), e.g.: \"ldap://s4dc1:9000,ldap://s4dc2:9000\"")
114 parser.add_option("--slapd-path", type="string", metavar="SLAPD-PATH", 
115                 help="Path to slapd for LDAP backend [e.g.:'/usr/local/libexec/slapd']. Required for Setup with LDAP-Backend. OpenLDAP Version >= 2.4.17 should be used.") 
116 parser.add_option("--setup-ds-path", type="string", metavar="SETUP_DS-PATH", 
117                 help="Path to setup-ds.pl script for Fedora DS LDAP backend [e.g.:'/usr/sbin/setup-ds.pl']. Required for Setup with Fedora DS backend.") 
118 parser.add_option("--nosync", help="Configure LDAP backend not to call fsync() (for performance in test environments)", action="store_true")
119 parser.add_option("--use-xattrs", type="choice", choices=["yes","no","auto"], help="Define if we should use the native fs capabilities or a tdb file for storing attributes likes ntacl, auto tries to make an inteligent guess based on the user rights and system capabilities", default="auto")
120 parser.add_option("--ldap-dryrun-mode", help="Configure LDAP backend, but do not run any binaries and exit early.  Used only for the test environment.  DO NOT USE", action="store_true")
121
122 opts = parser.parse_args()[0]
123
124 def message(text):
125         """print a message if quiet is not set."""
126         if not opts.quiet:
127                 print text
128
129 if len(sys.argv) == 1:
130         opts.interactive = True
131
132 if opts.interactive:
133         from getpass import getpass
134         import socket
135         def ask(prompt, default=None):
136                 if default is not None:
137                         print "%s [%s]: " % (prompt,default),
138                 else:
139                         print "%s: " % (prompt,),
140                 return sys.stdin.readline().rstrip("\n") or default
141         try:
142                 default = socket.getfqdn().split(".", 1)[1].upper()
143         except IndexError:
144                 default = None
145         opts.realm = ask("Realm", default)
146         if opts.realm in (None, ""):
147                 print >>sys.stderr, "No realm set!"
148                 sys.exit(1)
149
150         try:
151                 default = opts.realm.split(".")[0]
152         except IndexError:
153                 default = None
154         opts.domain = ask("Domain", default)
155         if opts.domain is None:
156                 print >> sys.stderr, "No domain set!"
157                 sys.exit(1)
158
159         opts.server_role = ask("Server Role (dc, member, standalone)", "dc")
160         for i in range(3):
161                 opts.adminpass = getpass("Administrator password: ")
162                 if not opts.adminpass:
163                         print >>sys.stderr, "Invalid administrator password."
164                 else:
165                         break
166 else:
167         if opts.realm in (None, ""):
168                 opts.realm = sambaopts._lp.get('realm')
169         if opts.realm is None or opts.domain is None:
170                 if opts.realm is None:
171                         print >>sys.stderr, "No realm set!"
172                 if opts.domain is None:
173                         print >> sys.stderr, "No domain set!"
174                 parser.print_usage()
175                 sys.exit(1)
176
177 if not opts.adminpass:
178         message("Administrator password will be set randomly!")
179
180 lp = sambaopts.get_loadparm()
181 smbconf = lp.configfile
182
183 if opts.server_role == "dc":
184         server_role = "domain controller"
185 elif opts.server_role == "member":
186         server_role = "member server"
187 else:
188         server_role = opts.server_role
189
190 if opts.function_level is None:
191         dom_for_fun_level = None
192 elif opts.function_level == "2003":
193         dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
194 elif opts.function_level == "2008":
195         dom_for_fun_level = DS_DOMAIN_FUNCTION_2008
196 elif opts.function_level == "2008_R2":
197         dom_for_fun_level = DS_DOMAIN_FUNCTION_2008_R2
198
199 creds = credopts.get_credentials(lp)
200
201 creds.set_kerberos_state(DONT_USE_KERBEROS)
202
203 setup_dir = opts.setupdir
204 if setup_dir is None:
205         setup_dir = find_setup_dir()
206
207 samdb_fill = FILL_FULL
208 if opts.blank:
209     samdb_fill = FILL_NT4SYNC
210 elif opts.partitions_only:
211     samdb_fill = FILL_DRS
212
213 eadb = True
214 if opts.use_xattrs == "yes":
215         eadb = False
216 elif opts.use_xattrs == "auto":
217         file = tempfile.NamedTemporaryFile()
218         try:
219                 samba.ntacls.setntacl(lp, file.name, 
220                         "O:S-1-5-32G:S-1-5-32", "S-1-5-32", "native")
221                 eadb = False
222         except:
223                 # XXX: Should catch a specific exception here
224                 if lp.get("posix:eadb") is None:
225                         message("Notice: you are not root or your system do not support xattr, tdb backend for attributes has been selected")
226                         message(" if you intend to use this provision in production you'd better rerun the script as root on a system supporting xattr")
227         file.close()
228
229
230 session = system_session()
231 try:
232         provision(setup_dir, message,
233                   session, creds, smbconf=smbconf, targetdir=opts.targetdir,
234                   samdb_fill=samdb_fill, realm=opts.realm, domain=opts.domain,
235                   domainguid=opts.domain_guid, domainsid=opts.domain_sid,
236                   policyguid=opts.policy_guid, policyguid_dc=opts.policy_guid_dc,
237                   hostname=opts.host_name,
238                   hostip=opts.host_ip, hostip6=opts.host_ip6,
239                   ntdsguid=opts.ntds_guid,
240                   invocationid=opts.invocationid, adminpass=opts.adminpass,
241                   krbtgtpass=opts.krbtgtpass, machinepass=opts.machinepass,
242                   dnspass=opts.dnspass, root=opts.root, nobody=opts.nobody,
243                   wheel=opts.wheel, users=opts.users,
244                   serverrole=server_role, dom_for_fun_level=dom_for_fun_level,
245                   ldap_backend_extra_port=opts.ldap_backend_extra_port,
246                   backend_type=opts.ldap_backend_type,
247                   ldapadminpass=opts.ldapadminpass, ol_mmr_urls=opts.ol_mmr_urls,
248                   slapd_path=opts.slapd_path, setup_ds_path=opts.setup_ds_path,
249                   nosync=opts.nosync,ldap_dryrun_mode=opts.ldap_dryrun_mode,useeadb=eadb)
250 except ProvisioningError, e:
251         print str(e)
252         exit(1)