d0d35f807e0a1cc3cc34aafdfbc0fcd8c541ae86
[kai/samba-autobuild/.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("--realm", type="string", metavar="REALM", help="set realm")
56 parser.add_option("--domain", type="string", metavar="DOMAIN",
57                                   help="set domain")
58 parser.add_option("--domain-guid", type="string", metavar="GUID", 
59                 help="set domainguid (otherwise random)")
60 parser.add_option("--domain-sid", type="string", metavar="SID", 
61                 help="set domainsid (otherwise random)")
62 parser.add_option("--policy-guid", type="string", metavar="GUID",
63                                   help="set guid for domain policy")
64 parser.add_option("--policy-guid-dc", type="string", metavar="GUID",
65                                   help="set guid for domain controller policy")
66 parser.add_option("--ntds-guid", type="string", metavar="GUID", 
67                   help="set NTDS object GUID (otherwise random)")
68 parser.add_option("--invocationid", type="string", metavar="GUID", 
69                   help="set invocationid (otherwise random)")
70 parser.add_option("--host-name", type="string", metavar="HOSTNAME", 
71                 help="set hostname")
72 parser.add_option("--host-ip", type="string", metavar="IPADDRESS", 
73                 help="set IPv4 ipaddress")
74 parser.add_option("--host-ip6", type="string", metavar="IP6ADDRESS", 
75                 help="set IPv6 ipaddress")
76 parser.add_option("--adminpass", type="string", metavar="PASSWORD", 
77                 help="choose admin password (otherwise random)")
78 parser.add_option("--krbtgtpass", type="string", metavar="PASSWORD", 
79                 help="choose krbtgt password (otherwise random)")
80 parser.add_option("--machinepass", type="string", metavar="PASSWORD", 
81                 help="choose machine password (otherwise random)")
82 parser.add_option("--dnspass", type="string", metavar="PASSWORD", 
83                 help="choose dns password (otherwise random)")
84 parser.add_option("--ldapadminpass", type="string", metavar="PASSWORD", 
85                 help="choose password to set between Samba and it's LDAP backend (otherwise random)")
86 parser.add_option("--root", type="string", metavar="USERNAME", 
87                 help="choose 'root' unix username")
88 parser.add_option("--nobody", type="string", metavar="USERNAME", 
89                 help="choose 'nobody' user")
90 parser.add_option("--wheel", type="string", metavar="GROUPNAME", 
91                 help="choose 'wheel' privileged group")
92 parser.add_option("--users", type="string", metavar="GROUPNAME", 
93                 help="choose 'users' group")
94 parser.add_option("--quiet", help="Be quiet", action="store_true")
95 parser.add_option("--blank", action="store_true",
96                 help="do not add users or groups, just the structure")
97 parser.add_option("--ldap-backend-extra-port", type="int", metavar="LDAP-BACKEND-EXTRA-PORT", 
98                 help="Additional TCP port for LDAP backend server (to use for replication)")
99 parser.add_option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", 
100                 help="LDAP backend type (fedora-ds or openldap)",
101                 choices=["fedora-ds", "openldap"])
102 parser.add_option("--ldap-backend-nosync", help="Configure LDAP backend not to call fsync() (for performance in test environments)", action="store_true")
103 parser.add_option("--server-role", type="choice", metavar="ROLE",
104                   choices=["domain controller", "dc", "member server", "member", "standalone"],
105                 help="The server role (domain controller | dc | member server | member | standalone). Default is standalone.")
106 parser.add_option("--function-level", type="choice", metavar="FOR-FUN-LEVEL",
107                   choices=["2003", "2008", "2008_R2"],
108                 help="The domain and forest function level (2003 | 2008 | 2008_R2). Default is (Windows) 2003 (Native).")
109 parser.add_option("--partitions-only", 
110                 help="Configure Samba's partitions, but do not modify them (ie, join a BDC)", action="store_true")
111 parser.add_option("--targetdir", type="string", metavar="DIR", 
112                           help="Set target directory")
113 parser.add_option("--ol-mmr-urls", type="string", metavar="LDAPSERVER",
114                 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\"")
115 parser.add_option("--slapd-path", type="string", metavar="SLAPD-PATH", 
116                 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.") 
117 parser.add_option("--setup-ds-path", type="string", metavar="SETUP_DS-PATH", 
118                 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.") 
119 parser.add_option("--nosync", help="Configure LDAP backend not to call fsync() (for performance in test environments)", action="store_true")
120 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")
121 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")
122
123 opts = parser.parse_args()[0]
124
125 def message(text):
126         """print a message if quiet is not set."""
127         if not opts.quiet:
128                 print text
129
130 if len(sys.argv) == 1:
131         opts.interactive = True
132
133 if opts.interactive:
134         from getpass import getpass
135         import socket
136         def ask(prompt, default=None):
137                 if default is not None:
138                         print "%s [%s]: " % (prompt,default),
139                 else:
140                         print "%s: " % (prompt,),
141                 return sys.stdin.readline().rstrip("\n") or default
142         try:
143                 default = socket.getfqdn().split(".", 1)[1].upper()
144         except IndexError:
145                 default = None
146         opts.realm = ask("Realm", default)
147         if opts.realm in (None, ""):
148                 print >>sys.stderr, "No realm set!"
149                 sys.exit(1)
150
151         try:
152                 default = opts.realm.split(".")[0]
153         except IndexError:
154                 default = None
155         opts.domain = ask("Domain", default)
156         if opts.domain is None:
157                 print >> sys.stderr, "No domain set!"
158                 sys.exit(1)
159
160         opts.server_role = ask("Server Role (dc, member, standalone)", "dc")
161         for i in range(3):
162                 opts.adminpass = getpass("Administrator password: ")
163                 if not opts.adminpass:
164                         print >>sys.stderr, "Invalid administrator password."
165                 else:
166                         break
167 else:
168         if opts.realm is None or opts.domain is None:
169                 if opts.realm is None:
170                         print >>sys.stderr, "No realm set!"
171                 if opts.domain is None:
172                         print >> sys.stderr, "No domain set!"
173                 parser.print_usage()
174                 sys.exit(1)
175
176 if not opts.adminpass:
177         message("Administrator password will be set randomly!")
178
179 lp = sambaopts.get_loadparm()
180 smbconf = lp.configfile
181
182 if opts.server_role == "dc":
183         server_role = "domain controller"
184 elif opts.server_role == "member":
185         server_role = "member server"
186 else:
187         server_role = opts.server_role
188
189 if opts.function_level is None:
190         dom_for_fun_level = None
191 elif opts.function_level == "2003":
192         dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
193 elif opts.function_level == "2008":
194         dom_for_fun_level = DS_DOMAIN_FUNCTION_2008
195 elif opts.function_level == "2008_R2":
196         dom_for_fun_level = DS_DOMAIN_FUNCTION_2008_R2
197
198 creds = credopts.get_credentials(lp)
199
200 creds.set_kerberos_state(DONT_USE_KERBEROS)
201
202 setup_dir = opts.setupdir
203 if setup_dir is None:
204         setup_dir = find_setup_dir()
205
206 samdb_fill = FILL_FULL
207 if opts.blank:
208     samdb_fill = FILL_NT4SYNC
209 elif opts.partitions_only:
210     samdb_fill = FILL_DRS
211
212 eadb = True
213 if opts.use_xattrs == "yes":
214         eadb = False
215 elif opts.use_xattrs == "auto":
216         file = tempfile.NamedTemporaryFile()
217         try:
218                 samba.ntacls.setntacl(lp, file.name, 
219                         "O:S-1-5-32G:S-1-5-32", "S-1-5-32", "native")
220                 eadb = False
221         except:
222                 if lp.get("posix:eadb") == None:
223                         message("Notice: you are not root or your system do not support xattr, tdb backend for attributes has been selected")
224                         message(" if you intend to use this provision in production you'd better rerun the script as root on a system supporting xattr")
225         file.close()
226
227
228 session = system_session()
229 try:
230         provision(setup_dir, message,
231                   session, creds, smbconf=smbconf, targetdir=opts.targetdir,
232                   samdb_fill=samdb_fill, realm=opts.realm, domain=opts.domain,
233                   domainguid=opts.domain_guid, domainsid=opts.domain_sid,
234                   policyguid=opts.policy_guid, policyguid_dc=opts.policy_guid_dc,
235                   hostname=opts.host_name,
236                   hostip=opts.host_ip, hostip6=opts.host_ip6,
237                   ntdsguid=opts.ntds_guid,
238                   invocationid=opts.invocationid, adminpass=opts.adminpass,
239                   krbtgtpass=opts.krbtgtpass, machinepass=opts.machinepass,
240                   dnspass=opts.dnspass, root=opts.root, nobody=opts.nobody,
241                   wheel=opts.wheel, users=opts.users,
242                   serverrole=server_role, dom_for_fun_level=dom_for_fun_level,
243                   ldap_backend_extra_port=opts.ldap_backend_extra_port,
244                   backend_type=opts.ldap_backend_type,
245                   ldapadminpass=opts.ldapadminpass, ol_mmr_urls=opts.ol_mmr_urls,
246                   slapd_path=opts.slapd_path, setup_ds_path=opts.setup_ds_path,
247                   nosync=opts.nosync,ldap_dryrun_mode=opts.ldap_dryrun_mode,useeadb=eadb)
248 except ProvisioningError, e:
249         print str(e)
250         exit(1)