Make ipa-server-install always run unattended As a first step towards replacing the questions asked by ipa-server-install with a web-based firstboot UI, this patch removes all the prompting from ipa-server-install and always runs unattended. The realm name becomes the only required argument. If no FQDN is configured on the host, --hostname must be supplied. If that host isn't resolvable, then --ip-address must be supplied. If any of the password arguments are not supplied, then randomly generated passwords are used instead. "dirsrv" is assumed to be the directory server user unless another is supplied. ipa-server-install will just exit if there is another directory server already running. If --setup-bind is supplied, the bind configuration will be written without any warning prompt. Signed-off-by: Mark McLoughlin diff -r 5c3ff294e37d ipa-server/ipa-install/ipa-server-install --- a/ipa-server/ipa-install/ipa-server-install Tue Jan 22 11:58:06 2008 +0000 +++ b/ipa-server/ipa-install/ipa-server-install Tue Jan 22 12:07:48 2008 +0000 @@ -69,8 +69,6 @@ def parse_options(): parser.add_option("--ip-address", dest="ip_address", help="Master Server IP Address") parser.add_option("--setup-bind", dest="setup_bind", action="store_true", default=False, help="configure bind with our zone file") - parser.add_option("-U", "--unattended", dest="unattended", action="store_true", - default=False, help="unattended installation never prompts the user") parser.add_option("", "--uninstall", dest="uninstall", action="store_true", default=False, help="uninstall an existing installation") @@ -81,11 +79,8 @@ def parse_options(): options.dm_password or options.admin_password or options.master_password): parser.error("error: In uninstall mode, -u, r, -p and -P options are not allowed") - elif options.unattended: - if (not options.ds_user or not options.realm_name or - not options.dm_password or not options.admin_password or - not options.master_password): - parser.error("error: In unattended mode you need to provide at least -u, -r, -p and -P options") + elif not options.realm_name: + parser.error("error: In install mode you need to provide at least the -r option") return options @@ -98,34 +93,6 @@ def signal_handler(signum, frame): if ds.serverid: ipaserver.dsinstance.erase_ds_instance_data (ds.serverid) sys.exit(1) - -def read_host_name(host_default): - host_ok = False - host_name = "" - - print "Enter the fully qualified domain name of the computer" - print "on which you're setting up server software. Using the form" - print "." - print "Example: master.example.com." - print "" - print "" - if host_default == "": - host_default = "master.example.com" - while not host_ok: - host_input = raw_input("Server host name [" + host_default + "]: ") - print "" - if host_input == "": - host_name = host_default - else: - host_name = host_input - try: - verify_fqdn(host_name) - except: - host_name = "" - continue - else: - host_ok = True - return host_name def resolve_host(host_name): ip = "" @@ -157,109 +124,11 @@ def verify_ip_address(ip): is_ok = False return is_ok -def read_ip_address(host_name): - while True: - ip = raw_input("Please provide the IP address to be used for this host name: ") - - if ip == "": - continue - if ip == "127.0.0.1" or ip == "::1": - print "The IPA Server can't use localhost as a valid IP" - continue - - if not verify_ip_address(ip): - continue - - print "Adding ["+ip+" "+host_name+"] to your /etc/hosts file" - sysrestore.backup_file("/etc/hosts") - hosts_fd = open('/etc/hosts', 'r+') - hosts_fd.seek(0, 2) - hosts_fd.write(ip+'\t'+host_name+' '+host_name[:host_name.find('.')]+'\n') - hosts_fd.close() - - return ip - -def read_ds_user(): - print "The server must run as a specific user in a specific group." - print "It is strongly recommended that this user should have no privileges" - print "on the computer (i.e. a non-root user). The setup procedure" - print "will give this user/group some permissions in specific paths/files" - print "to perform server-specific operations." - print "" - - ds_user = "" - try: - pwd.getpwnam('dirsrv') - - print "A user account named 'dirsrv' already exists." - print "" - yesno = raw_input("Do you want to use the existing 'dirsrv' account? [yes]: ") - print "" - if not yesno or yesno.lower()[0] != "n": - ds_user = "dirsrv" - else: - ds_user = raw_input("Which account name do you want to use for the DS instance? ") - print "" - except KeyError: - ds_user = "dirsrv" - - return ds_user - -def read_realm_name(domain_name): - print "The kerberos protocol requires a Realm name to be defined." - print "This is typically the domain name converted to uppercase." - print "" - upper_dom = domain_name.upper() - realm_name = raw_input("Please provide a realm name ["+upper_dom+"]: ") - print "" - if realm_name == "": - realm_name = upper_dom - else: - upper_dom = realm_name.upper() - if upper_dom != realm_name: - print "It is strongly recommended that you use a completely uppercased name for the realm." - dom_realm = raw_input("Do you want to use "+upper_dom+" as realm name ? [yes]: ") - print "" - if dom_realm and dom_realm.lower()[0] != "y": - print "WARNING: Using a non upper-cased realm name may cause unexpected problems." - else: - realm_name = upper_dom - return realm_name - -def read_dm_password(): - print "Certain directory server operations require an administrative user." - print "This user is referred to as the Directory Manager and has full access" - print "to the Directory for system management tasks." - print "The password must be at least 8 characters long." - print "" - #TODO: provide the option of generating a random password - dm_password = read_password("Directory Manager") - return dm_password - -def read_admin_password(): - print "The IPA server requires an administrative user, named 'admin'." - print "This user is a regular system account used for IPA server administration." - print "" - #TODO: provide the option of generating a random password - admin_password = read_password("IPA admin") - return admin_password - def check_dirsrv(): - serverids = ipaserver.dsinstance.check_existing_installation() - if serverids: + if ipaserver.dsinstance.check_existing_installation(): print "" print "An existing Directory Server has been detected." - yesno = raw_input("Do you wish to remove it and create a new one? [no]: ") - if not yesno or yesno.lower()[0] != "y": - sys.exit(1) - - try: - service.stop("dirsrv") - except: - pass - - for serverid in serverids: - ipaserver.dsinstance.erase_ds_instance_data(serverid) + sys.exit(1) (ds_unsecure, ds_secure) = ipaserver.dsinstance.check_ports() if not ds_unsecure or not ds_secure: @@ -303,13 +172,11 @@ def main(): print "==============================================================================" print "This program will setup the FreeIPA Server." print "" - print "To accept the default shown in brackets, press the Enter key." - print "" check_dirsrv() ds_user = "" - realm_name = "" + realm_name = options.realm_name host_name = "" domain_name = "" ip_address = "" @@ -329,38 +196,32 @@ def main(): # utilities just use the hostname as returned by gethostbyname to set # up some of the standard entries - host_default = "" + host_name = "" if options.host_name: - host_default = options.host_name - else: - host_default = get_fqdn() + host_name = options.host_name + else: + host_name = get_fqdn() - if options.unattended: - try: - verify_fqdn(host_default) - except RuntimeError, e: - logging.error(str(e) + "\n") - return "-Fatal Error-" - - host_name = host_default - else: - host_name = read_host_name(host_default) - + try: + verify_fqdn(host_name) + except RuntimeError, e: + logging.error(str(e) + "\n") + return "-Fatal Error-" + domain_name = host_name[host_name.find(".")+1:] # Check we have a public IP that is associated with the hostname + add_host = False ip = resolve_host(host_name) if not ip: - if options.ip_address: - ip = options.ip_address - if not ip and options.unattended: - print "Unable to resolve IP address for host name" + if not options.ip_address: + print "Unable to resolve IP address for host name" + return "-Fatal Error-" + ip = options.ip_address + add_host = True + + if not verify_ip_address(ip): return "-Fatal Error-" - - if not verify_ip_address(ip): - ip = "" - if options.unattended: - return "-Fatal Error-" if options.ip_address and options.ip_address != ip: if options.setup_bind: @@ -370,53 +231,43 @@ def main(): print "from the one provided on the command line. Please fix your DNS" print "or /etc/hosts file and restart the installation." return "-Fatal Error-" - - if options.unattended: - if not ip: - print "Unable to resolve IP address" - return "-Fatal Error-" - - if not ip: - ip = read_ip_address(host_name) - ip_address = ip + + if add_host: + print "Adding [" + ip + " " + host_name + "] to your /etc/hosts file" + sysrestore.backup_file("/etc/hosts") + hosts_fd = open('/etc/hosts', 'r+') + hosts_fd.seek(0, 2) + hosts_fd.write(ip + '\t' + host_name + ' ' + host_name[:host_name.find('.')] + '\n') + hosts_fd.close() print "The IPA Master Server will be configured with" print "Hostname: " + host_name - print "IP address: " + ip_address + print "IP address: " + ip print "Domain name: " + domain_name print "" - if not options.ds_user: - ds_user = read_ds_user() - if ds_user == "": - return "-Aborted-" - else: + if options.ds_user: ds_user = options.ds_user - - if not options.realm_name: - realm_name = read_realm_name(domain_name) - else: - realm_name = options.realm_name + else: + ds_user = "dirsrv" if not options.dm_password: - dm_password = read_dm_password() + dm_password = ipa_generate_password() + print "A randomly generated password for 'cn=Directory Manager' is being used: %s" % dm_password else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() + print "A randomly generated kerberos database master password for is being used: %s" % master_password else: master_password = options.master_password if not options.admin_password: - admin_password = read_admin_password() + admin_password = ipa_generate_password() + print "A randomly generated password for the admin user is being used: %s" % admin_password else: admin_password = options.admin_password - - if not options.unattended: - print "" - print "The following operations may take some minutes to complete." - print "Please wait until the prompt is returned." # Create a directory server instance ds = ipaserver.dsinstance.DsInstance() @@ -434,18 +285,9 @@ def main(): webgui = ipaserver.httpinstance.WebGuiInstance() webgui.create_instance() - bind.setup(host_name, ip_address, realm_name) + bind.setup(host_name, ip, realm_name) if options.setup_bind: - skipbind = False - if not options.unattended: - print "This program is about to replace the DNS Server configuration," - print "with an automatically generated one, based on the data gathered so far." - print "This will REPLACE any existing configuration." - yesno = raw_input("Are you sure you want to configure the DNS Server ? [no]: ") - if not yesno or yesno.lower()[0] != 'y': - skipbind = True - if not skipbind: - bind.create_instance() + bind.create_instance() else: bind.create_sample_bind_zone()