diff options
| -rwxr-xr-x | client/ipa-client-install | 19 | ||||
| -rw-r--r-- | ipaclient/install/client.py | 181 |
2 files changed, 109 insertions, 91 deletions
diff --git a/client/ipa-client-install b/client/ipa-client-install index ab80bab2d..9ce26976a 100755 --- a/client/ipa-client-install +++ b/client/ipa-client-install @@ -30,6 +30,7 @@ from ipaclient.install import client from ipapython.ipa_log_manager import standard_logging_setup, root_logger from ipaplatform.paths import paths from ipapython import version +from ipapython.admintool import ScriptError from ipapython.config import IPAOptionParser from ipalib import x509 from ipalib.util import normalize_hostname, validate_domain_name @@ -230,21 +231,19 @@ def main(): root_logger.debug('IPA version %s' % version.VENDOR_VERSION) if options.uninstall: - rval_check = client.uninstall_check(options) - if rval_check != client.SUCCESS: - return rval_check - - return client.uninstall(options) + client.uninstall_check(options) + client.uninstall(options) else: - rval_check = client.install_check(options) - if rval_check != client.SUCCESS: - return rval_check - - return client.install(options) + client.install_check(options) + client.install(options) if __name__ == "__main__": try: sys.exit(main()) + except ScriptError as e: + if e.rval != client.SUCCESS and e.msg: + root_logger.error(e.msg) + sys.exit(e.rval) except KeyboardInterrupt: sys.exit(1) except RuntimeError as e: diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index 4403283f2..d1f845ff6 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -23,6 +23,7 @@ import socket import sys import tempfile import time +import traceback from cryptography.hazmat.primitives import serialization # pylint: disable=import-error @@ -59,6 +60,7 @@ from ipapython import ( ipautil, sysrestore, ) +from ipapython.admintool import ScriptError from ipapython.dn import DN from ipapython.ipa_log_manager import root_logger from ipapython.ipautil import ( @@ -1955,10 +1957,14 @@ def install_check(options): fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if not os.getegid() == 0: - sys.exit("\nYou must be root to run ipa-client-install.\n") + raise ScriptError( + "You must be root to run ipa-client-install.", + rval=CLIENT_INSTALL_ERROR) if is_fips_enabled(): - sys.exit("Installing IPA client in FIPS mode is not supported") + raise ScriptError( + "Installing IPA client in FIPS mode is not supported", + rval=CLIENT_INSTALL_ERROR) tasks.check_selinux_status() @@ -1967,7 +1973,7 @@ def install_check(options): root_logger.info( "If you want to reinstall the IPA client, uninstall it first " + "using 'ipa-client-install --uninstall'.") - return CLIENT_ALREADY_CONFIGURED + raise ScriptError(rval=CLIENT_ALREADY_CONFIGURED) if options.conf_ntp and not options.on_master and not options.force_ntpd: try: @@ -1993,8 +1999,9 @@ def install_check(options): options.prompt_password is False and not options.on_master ): - root_logger.error("One of password / principal / keytab is required.") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "One of password / principal / keytab is required.", + rval=CLIENT_INSTALL_ERROR) if options.hostname: hostname = options.hostname @@ -2003,32 +2010,35 @@ def install_check(options): hostname = socket.getfqdn() hostname_source = "Machine's FQDN" if hostname != hostname.lower(): - root_logger.error( - "Invalid hostname '%s', must be lower-case.", hostname) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Invalid hostname '{}', must be lower-case.".format(hostname), + rval=CLIENT_INSTALL_ERROR + ) if (hostname == 'localhost') or (hostname == 'localhost.localdomain'): - root_logger.error("Invalid hostname, '%s' must not be used.", hostname) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Invalid hostname, '{}' must not be used.".format(hostname), + rval=CLIENT_INSTALL_ERROR) # when installing with '--no-sssd' option, check whether nss-ldap is # installed if not options.sssd: if not os.path.exists(paths.PAM_KRB5_SO): - root_logger.error("The pam_krb5 package must be installed") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "The pam_krb5 package must be installed", + rval=CLIENT_INSTALL_ERROR) (nssldap_installed, nosssd_files) = nssldap_exists() if not nssldap_installed: - root_logger.error( + raise ScriptError( "One of these packages must be installed: nss_ldap or " - "nss-pam-ldapd") - return CLIENT_INSTALL_ERROR + "nss-pam-ldapd", + rval=CLIENT_INSTALL_ERROR) if options.keytab and options.principal: - root_logger.error( - "Options 'principal' and 'keytab' cannot be used together.") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Options 'principal' and 'keytab' cannot be used together.", + rval=CLIENT_INSTALL_ERROR) if options.keytab and options.force_join: root_logger.warning("Option 'force-join' has no additional effect " @@ -2042,7 +2052,7 @@ def install_check(options): root_logger.warning("Using existing certificate '%s'.", CACERT) if not check_ip_addresses(options): - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) # Create the discovery instance ds = ipadiscovery.IPADiscovery() @@ -2066,15 +2076,16 @@ def install_check(options): "This may mean that the remote server is not up " "or is not reachable due to network or firewall settings.") print_port_conf_info() - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) if ret == ipadiscovery.BAD_HOST_CONFIG: root_logger.error("Can't get the fully qualified name of this host") root_logger.info("Check that the client is properly configured") - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) if ret == ipadiscovery.NOT_FQDN: - root_logger.error("%s is not a fully-qualified hostname", hostname) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "{} is not a fully-qualified hostname".format(hostname), + rval=CLIENT_INSTALL_ERROR) if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \ or not ds.domain: if ret == ipadiscovery.NO_LDAP_SERVER: @@ -2093,9 +2104,9 @@ def install_check(options): cli_domain = options.domain cli_domain_source = 'Provided as option' elif options.unattended: - root_logger.error( - "Unable to discover domain, not provided on command line") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Unable to discover domain, not provided on command line", + rval=CLIENT_INSTALL_ERROR) else: root_logger.info( "DNS discovery failed to determine your DNS domain") @@ -2126,8 +2137,9 @@ def install_check(options): cli_server = options.server cli_server_source = 'Provided as option' elif options.unattended: - root_logger.error("Unable to find IPA Server to join") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Unable to find IPA Server to join", + rval=CLIENT_INSTALL_ERROR) else: root_logger.debug("DNS discovery failed to find the IPA Server") cli_server = [ @@ -2174,7 +2186,7 @@ def install_check(options): root_logger.error("%s is not an IPA v2 Server.", cli_server[0]) print_port_conf_info() root_logger.debug("(%s: %s)", cli_server[0], cli_server_source) - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) if ret == ipadiscovery.NO_ACCESS_TO_LDAP: root_logger.warning("Anonymous access to the LDAP server is disabled.") @@ -2199,7 +2211,7 @@ def install_check(options): "or is not reachable due to network or firewall settings.") print_port_conf_info() root_logger.debug("(%s: %s)", cli_server[0], cli_server_source) - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) cli_kdc = ds.kdc if dnsok and not cli_kdc: @@ -2227,7 +2239,7 @@ def install_check(options): "of failure.") if not user_input( "Proceed with fixed values and no DNS discovery?", False): - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) cli_realm = ds.realm cli_realm_source = ds.realm_source @@ -2238,7 +2250,7 @@ def install_check(options): "The provided realm name [%s] does not match discovered one [%s]", options.realm_name, cli_realm) root_logger.debug("(%s: %s)", cli_realm, cli_realm_source) - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) cli_basedn = ds.basedn cli_basedn_source = ds.basedn_source @@ -2279,15 +2291,14 @@ def install_check(options): print() if not options.unattended and not user_input( "Continue to configure the system with these values?", False): - return CLIENT_INSTALL_ERROR - - return SUCCESS + raise ScriptError(rval=CLIENT_INSTALL_ERROR) def install(options): try: - rval = _install(options) - if rval == CLIENT_INSTALL_ERROR: + _install(options) + except ScriptError as e: + if e.rval == CLIENT_INSTALL_ERROR: if options.force: root_logger.warning( "Installation failed. Force set so not rolling back " @@ -2299,8 +2310,12 @@ def install(options): else: root_logger.error("Installation failed. Rolling back changes.") options.unattended = True - uninstall(options) - return rval + try: + uninstall(options) + except Exception as ex: + root_logger.debug(traceback.format_exc()) + root_logger.error(ex) + raise finally: try: os.remove(CCACHE_FILE) @@ -2411,9 +2426,10 @@ def _install(options): except EOFError: stdin = None if not stdin: - root_logger.error( - "Password must be provided for %s.", principal) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Password must be provided for {}.".format( + principal), + rval=CLIENT_INSTALL_ERROR) else: if sys.stdin.isatty(): root_logger.error( @@ -2423,7 +2439,7 @@ def _install(options): "This can be done via " "echo password | ipa-client-install ... " "or with the -w option.") - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) else: stdin = sys.stdin.readline() @@ -2432,8 +2448,9 @@ def _install(options): config=krb_name) except RuntimeError as e: print_port_conf_info() - root_logger.error("Kerberos authentication failed: %s", e) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Kerberos authentication failed: {}".format(e), + rval=CLIENT_INSTALL_ERROR) elif options.keytab: join_args.append("-f") if os.path.exists(options.keytab): @@ -2444,29 +2461,31 @@ def _install(options): attempts=options.kinit_attempts) except gssapi.exceptions.GSSError as e: print_port_conf_info() - root_logger.error("Kerberos authentication failed: %s" - % e) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Kerberos authentication failed: {}".format(e), + rval=CLIENT_INSTALL_ERROR) else: - root_logger.error("Keytab file could not be found: %s" - % options.keytab) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Keytab file could not be found: {}".format( + options.keytab), + rval=CLIENT_INSTALL_ERROR) elif options.password: nolog = (options.password,) join_args.append("-w") join_args.append(options.password) elif options.prompt_password: if options.unattended: - root_logger.error( - "Password must be provided in non-interactive mode") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Password must be provided in non-interactive mode", + rval=CLIENT_INSTALL_ERROR) try: password = getpass.getpass("Password: ") except EOFError: password = None if not password: - root_logger.error("Password must be provided.") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Password must be provided.", + rval=CLIENT_INSTALL_ERROR) join_args.append("-w") join_args.append(password) nolog = (password,) @@ -2480,10 +2499,10 @@ def _install(options): del os.environ['KRB5_CONFIG'] except errors.FileError as e: root_logger.error(e) - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) except Exception as e: root_logger.error("Cannot obtain CA certificate\n%s", e) - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) # Now join the domain result = run( @@ -2498,7 +2517,7 @@ def _install(options): root_logger.info( "Use --force-join option to override the host " "entry on the server and force client enrollment.") - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) root_logger.info( "Use ipa-getkeytab to obtain a host " "principal for this server.") @@ -2530,7 +2549,7 @@ def _install(options): root_logger.error("Failed to obtain host TGT: %s" % e) # failure to get ticket makes it impossible to login and bind # from sssd to LDAP, abort installation and rollback changes - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) finally: try: @@ -2558,15 +2577,16 @@ def _install(options): delegate=False, nss_dir=tmp_db.secdir) if 'config_loaded' not in api.env: - root_logger.error("Failed to initialize IPA API.") - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Failed to initialize IPA API.", + rval=CLIENT_INSTALL_ERROR) # Always back up sssd.conf. It gets updated by authconfig --enablekrb5. fstore.backup_file(paths.SSSD_CONF) if options.sssd: if configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server, options, client_domain, hostname): - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) root_logger.info("Configured /etc/sssd/sssd.conf") if options.on_master: @@ -2579,7 +2599,7 @@ def _install(options): os.environ['KRB5CCNAME'] = CCACHE_FILE except gssapi.exceptions.GSSError as e: root_logger.error("Failed to obtain host TGT: %s" % e) - return CLIENT_INSTALL_ERROR + raise ScriptError(rval=CLIENT_INSTALL_ERROR) else: # Configure krb5.conf fstore.backup_file(paths.KRB5_CONF) @@ -2616,9 +2636,10 @@ def _install(options): for i, cert in enumerate(ca_certs): tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1), 'C,,') - except CalledProcessError as e: - root_logger.info("Failed to add CA to temporary NSS database.") - return CLIENT_INSTALL_ERROR + except CalledProcessError: + raise ScriptError( + "Failed to add CA to temporary NSS database.", + rval=CLIENT_INSTALL_ERROR) api.finalize() @@ -2894,24 +2915,21 @@ def _install(options): root_logger.info('Client configuration complete.') - return SUCCESS - def uninstall_check(options): fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if not is_ipa_client_installed(fstore): - root_logger.error("IPA client is not configured on this system.") - return CLIENT_NOT_CONFIGURED + raise ScriptError( + "IPA client is not configured on this system.", + rval=CLIENT_NOT_CONFIGURED) server_fstore = sysrestore.FileStore(paths.SYSRESTORE) if server_fstore.has_files() and not options.on_master: root_logger.error( "IPA client is configured as a part of IPA server on this system.") root_logger.info("Refer to ipa-server-install for uninstallation.") - return CLIENT_NOT_CONFIGURED - - return SUCCESS + raise ScriptError(rval=CLIENT_NOT_CONFIGURED) def uninstall(options): @@ -3060,9 +3078,9 @@ def uninstall(options): was_sssd_installed, was_sssd_configured) except Exception as e: - root_logger.error( - "Failed to remove krb5/LDAP configuration: %s", str(e)) - return CLIENT_INSTALL_ERROR + raise ScriptError( + "Failed to remove krb5/LDAP configuration: {}".format(e), + rval=CLIENT_INSTALL_ERROR) # Clean up the SSSD cache before SSSD service is stopped or restarted remove_file(paths.SSSD_MC_GROUP) @@ -3270,10 +3288,11 @@ def uninstall(options): try: run([paths.SBIN_REBOOT]) except Exception as e: - root_logger.error( - "Reboot command failed to exceute: %s", str(e)) - return CLIENT_UNINSTALL_ERROR + raise ScriptError( + "Reboot command failed to execute: {}".format(e), + rval=CLIENT_UNINSTALL_ERROR) # IMPORTANT: Do not put any client uninstall logic after the block above - return rv + if rv: + raise ScriptError(rval=rv) |
