These patches fix https://fedorahosted.org/freeipa/ticket/4305

Actually only the last patch does the work itself (suppress autodiscovery when installing client on master), but when I saw the state of autodiscovery code I have taken the liberty to clean it up a bit.

Patch #78 has separate versions for master and 4-2 branch, other patches should apply on top of it in both branches.

--
Martin^3 Babinsky
From 86918274dc583278b331783e51d9713ef170f8e6 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Wed, 7 Oct 2015 15:21:12 +0200
Subject: [PATCH 4/4] do not perform autodiscovery when installing client-side
 components on master

the IPA master FQDN, realm, and domain name will be taken directly from CLI
options and no DNS discovery (apart of fetching LDAP suffix) will be performed
when ipa-client-install is run with '-on-master' option.

https://fedorahosted.org/freeipa/ticket/4305
---
 ipa-client/ipa-install/ipa-client-install | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index a1b1783f3ffda1e7625f872499d45eb7761207af..44c9e58887074833f877c82869dce1c0796753ff 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -2394,6 +2394,29 @@ def perform_autodiscovery(ds, hostname, options):
     return dnsok
 
 
+def set_ipa_domain_params(ds, servers, domain_name, realm_name,
+                          ca_cert_path=None):
+    """
+    set IPA server, domain, realm name and other parameters directly without
+    DNS discovery
+    :param ds: IPADiscovery instance
+    :param servers: IPA server FQDN
+    :param domain_name: name of IPA domain
+    :param realm_name: IPA realm name
+    """
+    ds.servers = servers
+    ds.server = servers[0]
+
+    ds.domain = domain_name
+    ds.realm = realm_name
+    ds.kdc = servers[0]
+
+    # use ipacheckldap to get basedn from IPA master
+    if ds.ipacheckldap(ds.server, ds.realm, ca_cert_path=ca_cert_path)[0]:
+        raise RuntimeError("Failed to get basedn from IPA master %s"
+                           % ds.server)
+
+
 def install(options, env, fstore, statestore):
     dnsok=False
 
@@ -2463,7 +2486,13 @@ def install(options, env, fstore, statestore):
     ds = ipadiscovery.IPADiscovery()
 
     try:
-        dnsok = perform_autodiscovery(ds, hostname, options)
+        if options.on_master:
+            set_ipa_domain_params(ds, options.server, options.domain,
+                                  options.realm_name, CACERT)
+            ds.server_source = ds.domain_source = ds.realm_source = (
+                "set by IPA master")
+        else:
+            dnsok = perform_autodiscovery(ds, hostname, options)
     except RuntimeError as e:
         root_logger.error("Error running IPA discovery: %s", e)
         return CLIENT_INSTALL_ERROR
-- 
2.4.3

From fed560b03169d73376deb590777f618b82c6f5a0 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Wed, 7 Oct 2015 15:16:25 +0200
Subject: [PATCH 3/4] ipa-client-install: store server/domain/realm info in
 IPADiscovery object

https://fedorahosted.org/freeipa/ticket/4305
---
 ipa-client/ipa-install/ipa-client-install | 107 +++++++++++++++---------------
 1 file changed, 52 insertions(+), 55 deletions(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 0c62875553d2c6577e3b71aaa439f52096161475..a1b1783f3ffda1e7625f872499d45eb7761207af 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -2215,14 +2215,16 @@ def configure_firefox(options, statestore, domain):
 
 
 def perform_autodiscovery(ds, hostname, options):
+    """
+    Perform automated DNS discovery of domain, realm, IPA servers and KDCs
+
+    :param ds: IPADiscovery instance
+    :param hostname: machine FQDN
+    :param options: options passed to installer
+    :return: True if DNS discovery works in IPA domain, False otherwise
+    """
     dnsok = False
 
-    cli_domain = None
-    cli_server = None
-
-    cli_domain_source = 'Unknown source'
-    cli_server_source = 'Unknown source'
-
     ret = ds.search(domain=options.domain, servers=options.server,
                     realm=options.realm_name, hostname=hostname,
                     ca_cert_path=get_cert_path(options.ca_cert_file))
@@ -2259,47 +2261,44 @@ def perform_autodiscovery(ds, hostname, options):
         else:
             root_logger.debug("Domain not found")
         if options.domain:
-            cli_domain = options.domain
-            cli_domain_source = 'Provided as option'
+            ds.domain = options.domain
+            ds.domain_source = 'Provided as option'
         elif options.unattended:
             raise RuntimeError("Unable to discover domain, not provided on "
                                "command line")
         else:
             root_logger.info(
                 "DNS discovery failed to determine your DNS domain")
-            cli_domain = user_input("Provide the domain name of your IPA "
-                                    "server (ex: example.com)",
-                                    allow_empty=False)
-            cli_domain_source = 'Provided interactively'
+            ds.domain = user_input("Provide the domain name of your IPA "
+                                   "server (ex: example.com)",
+                                   allow_empty=False)
+            ds.domain_source = 'Provided interactively'
             root_logger.debug(
-                "will use interactively provided domain: %s", cli_domain)
-        ret = ds.search(domain=cli_domain, servers=options.server,
+                "will use interactively provided domain: %s", ds.domain)
+        ret = ds.search(domain=ds.domain, servers=options.server,
                         hostname=hostname,
                         ca_cert_path=get_cert_path(options.ca_cert_file))
 
-    if not cli_domain:
-        if ds.domain:
-            cli_domain = ds.domain
-            cli_domain_source = ds.domain_source
-            root_logger.debug("will use discovered domain: %s", cli_domain)
+    if ds.domain:
+        root_logger.debug("will use discovered domain: %s", ds.domain)
 
     if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
             or not ds.server:
         root_logger.debug("IPA Server not found")
         if options.server:
-            cli_server = options.server
-            cli_server_source = 'Provided as option'
+            ds.server = options.server
+            ds.server_source = 'Provided as option'
         elif options.unattended:
             raise RuntimeError("Unable to find IPA Server to join")
         else:
             root_logger.debug("DNS discovery failed to find the IPA Server")
-            cli_server = [user_input("Provide your IPA server name "
+            ds.servers = [user_input("Provide your IPA server name "
                                      "(ex: ipa.example.com)",
                                      allow_empty = False)]
-            cli_server_source = 'Provided interactively'
+            ds.server_source = 'Provided interactively'
             root_logger.debug("will use interactively provided server: %s",
-                              cli_server[0])
-        ret = ds.search(domain=cli_domain, servers=cli_server,
+                              ds.servers[0])
+        ret = ds.search(domain=ds.domain, servers=ds.servers,
                         hostname=hostname,
                         ca_cert_path=get_cert_path(options.ca_cert_file))
 
@@ -2318,21 +2317,19 @@ def perform_autodiscovery(ds, hostname, options):
             root_logger.debug("Using servers from command line, disabling DNS "
                               "discovery")
 
-    if not cli_server:
+    if not ds.servers:
         if options.server:
-            cli_server = ds.servers
-            cli_server_source = 'Provided as option'
+            ds.servers = options.server
+            ds.server_source = 'Provided as option'
             root_logger.debug("will use provided server: %s", ', '.join(
                 options.server))
-        elif ds.server:
-            cli_server = ds.servers
-            cli_server_source = ds.server_source
-            root_logger.debug("will use discovered server: %s", cli_server[0])
+        elif ds.servers:
+            root_logger.debug("will use discovered server: %s", ds.servers[0])
 
     if ret == ipadiscovery.NOT_IPA_SERVER:
         print_port_conf_info()
-        root_logger.debug("(%s: %s)", cli_server[0], cli_server_source)
-        raise RuntimeError("%s is not an IPA v2 Server.", cli_server[0])
+        root_logger.debug("(%s: %s)", ds.servers[0], ds.server_source)
+        raise RuntimeError("%s is not an IPA v2 Server.", ds.servers[0])
 
     if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
         root_logger.warning("Anonymous access to the LDAP server is disabled.")
@@ -2349,16 +2346,15 @@ def perform_autodiscovery(ds, hostname, options):
 
     if ret != 0:
         root_logger.error("Failed to verify that %s is an IPA Server.",
-                          cli_server[0])
+                          ds.servers[0])
         root_logger.error("This may mean that the remote server is not up "
                           "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)
+        root_logger.debug("(%s: %s)", ds.servers[0], ds.server_source)
         raise RuntimeError("IPA server verification failed")
 
-    cli_kdc = ds.kdc
-    if dnsok and not cli_kdc:
+    if dnsok and not ds.kdc:
         root_logger.error("DNS domain '%s' is not configured for automatic "
                           "KDC address lookup.", ds.realm.lower())
         root_logger.debug("(%s: %s)", ds.realm, ds.realm_source)
@@ -2384,24 +2380,18 @@ def perform_autodiscovery(ds, hostname, options):
                           False):
             raise RuntimeError("Operation aborted by user")
 
-    cli_realm = ds.realm
-    cli_realm_source = ds.realm_source
-    root_logger.debug("will use discovered realm: %s", cli_realm)
+    root_logger.debug("will use discovered realm: %s", ds.realm)
 
-    if options.realm_name and options.realm_name != cli_realm:
+    if options.realm_name and options.realm_name != ds.realm:
         root_logger.error(
             "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)
+            options.realm_name, ds.realm)
+        root_logger.debug("(%s: %s)", ds.realm, ds.realm_source)
         raise RuntimeError("IPA server verification failed")
 
-    cli_basedn = ds.basedn
-    cli_basedn_source = ds.basedn_source
-    root_logger.debug("will use discovered basedn: %s", cli_basedn)
+    root_logger.debug("will use discovered basedn: %s", ds.basedn)
 
-    return (dnsok, cli_domain, cli_domain_source, cli_server,
-            cli_server_source, cli_realm, cli_realm_source, cli_kdc,
-            cli_basedn, cli_basedn_source)
+    return dnsok
 
 
 def install(options, env, fstore, statestore):
@@ -2473,14 +2463,21 @@ def install(options, env, fstore, statestore):
     ds = ipadiscovery.IPADiscovery()
 
     try:
-        (dnsok, cli_domain, cli_domain_source, cli_server,
-         cli_server_source, cli_realm, cli_realm_source, cli_kdc,
-         cli_basedn, cli_basedn_source) = perform_autodiscovery(
-            ds, hostname, options)
+        dnsok = perform_autodiscovery(ds, hostname, options)
     except RuntimeError as e:
-        root_logger.error("Error running IPA discovery: %s", e.message)
+        root_logger.error("Error running IPA discovery: %s", e)
         return CLIENT_INSTALL_ERROR
 
+    cli_domain = ds.domain
+    cli_domain_source = ds.domain_source
+    cli_server = ds.servers
+    cli_server_source = ds.server_source
+    cli_realm = ds.realm
+    cli_realm_source = ds.realm_source
+    cli_kdc = ds.kdc
+    cli_basedn = ds.basedn
+    cli_basedn_source = ds.basedn_source
+
     client_domain = hostname[hostname.find(".")+1:]
     subject_base = DN(('O', cli_realm))
 
-- 
2.4.3

From e120fb5b14d233ed508d4d1b4298d2dc60629675 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Tue, 6 Oct 2015 19:33:39 +0200
Subject: [PATCH 2/4] ipa-client-install: fix formatting of perform_discovery
 code

The code has been formatted to be PEP8-conformant.

https://fedorahosted.org/freeipa/ticket/4305
---
 ipa-client/ipa-install/ipa-client-install | 76 +++++++++++++++++++------------
 1 file changed, 48 insertions(+), 28 deletions(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 88eb22da1dc62c28ba4212ab1f2d670736d7adee..0c62875553d2c6577e3b71aaa439f52096161475 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -2223,16 +2223,19 @@ def perform_autodiscovery(ds, hostname, options):
     cli_domain_source = 'Unknown source'
     cli_server_source = 'Unknown source'
 
-    ret = ds.search(domain=options.domain, servers=options.server, realm=options.realm_name, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file))
+    ret = ds.search(domain=options.domain, servers=options.server,
+                    realm=options.realm_name, hostname=hostname,
+                    ca_cert_path=get_cert_path(options.ca_cert_file))
 
     if options.server and ret != 0:
         # There is no point to continue with installation as server list was
         # passed as a fixed list of server and thus we cannot discover any
         # better result
         root_logger.error("Failed to verify that %s is an IPA Server.",
-                ', '.join(options.server))
+                          ', '.join(options.server))
         root_logger.error("This may mean that the remote server is not up "
-            "or is not reachable due to network or firewall settings.")
+                          "or is not reachable due to network or firewall "
+                          "settings.")
         print_port_conf_info()
         raise RuntimeError("IPA server verification failed")
 
@@ -2241,8 +2244,8 @@ def perform_autodiscovery(ds, hostname, options):
         raise RuntimeError("Can't get the fully qualified name of this host")
     if ret == ipadiscovery.NOT_FQDN:
         raise RuntimeError("%s is not a fully-qualified hostname" % hostname)
-    if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
-            or not ds.domain:
+    if (ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER)
+            or not ds.domain):
         if ret == ipadiscovery.NO_LDAP_SERVER:
             if ds.server:
                 root_logger.debug("%s is not an LDAP server" % ds.server)
@@ -2264,11 +2267,15 @@ def perform_autodiscovery(ds, hostname, options):
         else:
             root_logger.info(
                 "DNS discovery failed to determine your DNS domain")
-            cli_domain = user_input("Provide the domain name of your IPA server (ex: example.com)", allow_empty = False)
+            cli_domain = user_input("Provide the domain name of your IPA "
+                                    "server (ex: example.com)",
+                                    allow_empty=False)
             cli_domain_source = 'Provided interactively'
             root_logger.debug(
                 "will use interactively provided domain: %s", cli_domain)
-        ret = ds.search(domain=cli_domain, servers=options.server, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file))
+        ret = ds.search(domain=cli_domain, servers=options.server,
+                        hostname=hostname,
+                        ca_cert_path=get_cert_path(options.ca_cert_file))
 
     if not cli_domain:
         if ds.domain:
@@ -2286,29 +2293,37 @@ def perform_autodiscovery(ds, hostname, options):
             raise RuntimeError("Unable to find IPA Server to join")
         else:
             root_logger.debug("DNS discovery failed to find the IPA Server")
-            cli_server = [user_input("Provide your IPA server name (ex: ipa.example.com)", allow_empty = False)]
+            cli_server = [user_input("Provide your IPA server name "
+                                     "(ex: ipa.example.com)",
+                                     allow_empty = False)]
             cli_server_source = 'Provided interactively'
-            root_logger.debug("will use interactively provided server: %s", cli_server[0])
-        ret = ds.search(domain=cli_domain, servers=cli_server, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file))
+            root_logger.debug("will use interactively provided server: %s",
+                              cli_server[0])
+        ret = ds.search(domain=cli_domain, servers=cli_server,
+                        hostname=hostname,
+                        ca_cert_path=get_cert_path(options.ca_cert_file))
 
     else:
         # Only set dnsok to True if we were not passed in one or more servers
         # and if DNS discovery actually worked.
         if not options.server:
-            (server, domain) = ds.check_domain(ds.domain, set(), "Validating DNS Discovery")
+            (server, domain) = ds.check_domain(ds.domain, set(),
+                                               "Validating DNS Discovery")
             if server and domain:
                 root_logger.debug("DNS validated, enabling discovery")
                 dnsok = True
             else:
                 root_logger.debug("DNS discovery failed, disabling discovery")
         else:
-            root_logger.debug("Using servers from command line, disabling DNS discovery")
+            root_logger.debug("Using servers from command line, disabling DNS "
+                              "discovery")
 
     if not cli_server:
         if options.server:
             cli_server = ds.servers
             cli_server_source = 'Provided as option'
-            root_logger.debug("will use provided server: %s", ', '.join(options.server))
+            root_logger.debug("will use provided server: %s", ', '.join(
+                options.server))
         elif ds.server:
             cli_server = ds.servers
             cli_server_source = ds.server_source
@@ -2322,29 +2337,30 @@ def perform_autodiscovery(ds, hostname, options):
     if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
         root_logger.warning("Anonymous access to the LDAP server is disabled.")
         root_logger.info("Proceeding without strict verification.")
-        root_logger.info("Note: This is not an error if anonymous access " +
-            "has been explicitly restricted.")
+        root_logger.info("Note: This is not an error if anonymous access "
+                         "has been explicitly restricted.")
         ret = 0
 
     if ret == ipadiscovery.NO_TLS_LDAP:
-        root_logger.warning("The LDAP server requires TLS is but we do not " +
-            "have the CA.")
+        root_logger.warning("The LDAP server requires TLS is but we do not "
+                            "have the CA.")
         root_logger.info("Proceeding without strict verification.")
         ret = 0
 
     if ret != 0:
         root_logger.error("Failed to verify that %s is an IPA Server.",
-            cli_server[0])
+                          cli_server[0])
         root_logger.error("This may mean that the remote server is not up "
-            "or is not reachable due to network or firewall settings.")
+                          "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)
         raise RuntimeError("IPA server verification failed")
 
     cli_kdc = ds.kdc
     if dnsok and not cli_kdc:
-        root_logger.error("DNS domain '%s' is not configured for automatic " +
-            "KDC address lookup.", ds.realm.lower())
+        root_logger.error("DNS domain '%s' is not configured for automatic "
+                          "KDC address lookup.", ds.realm.lower())
         root_logger.debug("(%s: %s)", ds.realm, ds.realm_source)
         root_logger.error("KDC address will be set to fixed value.")
 
@@ -2352,16 +2368,20 @@ def perform_autodiscovery(ds, hostname, options):
         root_logger.info("Discovery was successful!")
     elif not options.unattended:
         if not options.server:
-            root_logger.warning("The failure to use DNS to find your IPA" +
-                " server indicates that your resolv.conf file is not properly" +
+            root_logger.warning(
+                "The failure to use DNS to find your IPA"
+                " server indicates that your resolv.conf file is not properly"
                 " configured.")
-        root_logger.info("Autodiscovery of servers for failover cannot work " +
+        root_logger.info(
+            "Autodiscovery of servers for failover cannot work "
             "with this configuration.")
-        root_logger.info("If you proceed with the installation, services " +
-            "will be configured to always access the discovered server for " +
-            "all operations and will not fail over to other servers in case " +
+        root_logger.info(
+            "If you proceed with the installation, services "
+            "will be configured to always access the discovered server for "
+            "all operations and will not fail over to other servers in case "
             "of failure.")
-        if not user_input("Proceed with fixed values and no DNS discovery?", False):
+        if not user_input("Proceed with fixed values and no DNS discovery?",
+                          False):
             raise RuntimeError("Operation aborted by user")
 
     cli_realm = ds.realm
-- 
2.4.3

From 9e821d3f368b53558ca07a7dc1c21d7ecbc3a643 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Tue, 6 Oct 2015 18:22:51 +0200
Subject: [PATCH 1/4] ipa-client-install: factor DNS discovery to a separate
 function

https://fedorahosted.org/freeipa/ticket/4305
---
 ipa-client/ipa-install/ipa-client-install | 179 ++++++++++++++++--------------
 1 file changed, 95 insertions(+), 84 deletions(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index c50ea67cbf9b878c4b5aab4ae83cd9d46ee503cf..88eb22da1dc62c28ba4212ab1f2d670736d7adee 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -2214,81 +2214,15 @@ def configure_firefox(options, statestore, domain):
         root_logger.error("Firefox configuration failed.")
 
 
-def install(options, env, fstore, statestore):
+def perform_autodiscovery(ds, hostname, options):
     dnsok = False
 
     cli_domain = None
     cli_server = None
-    subject_base = None
 
     cli_domain_source = 'Unknown source'
     cli_server_source = 'Unknown source'
 
-    if options.conf_ntp and not options.on_master and not options.force_ntpd:
-        try:
-            ipaclient.ntpconf.check_timedate_services()
-        except ipaclient.ntpconf.NTPConflictingService as e:
-            print("WARNING: ntpd time&date synchronization service will not" \
-                  " be configured as")
-            print("conflicting service (%s) is enabled" % e.conflicting_service)
-            print("Use --force-ntpd option to disable it and force configuration" \
-                  " of ntpd")
-            print("")
-
-            # configuration of ntpd is disabled in this case
-            options.conf_ntp = False
-        except ipaclient.ntpconf.NTPConfigurationError:
-            pass
-
-    if options.unattended and (options.password is None and
-                               options.principal is None and
-                               options.keytab is None and
-                               options.prompt_password is False and
-                               not options.on_master):
-        root_logger.error("One of password / principal / keytab is required.")
-        return CLIENT_INSTALL_ERROR
-
-    if options.hostname:
-        hostname = options.hostname
-        hostname_source = 'Provided as option'
-    else:
-        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
-    if (hostname == 'localhost') or (hostname == 'localhost.localdomain'):
-        root_logger.error("Invalid hostname, '%s' must not be used.", hostname)
-        return CLIENT_INSTALL_ERROR
-
-    # when installing with '--no-sssd' option, check whether nss-ldap is installed
-    if not options.sssd:
-        (nssldap_installed, nosssd_files) = nssldap_exists()
-        if not nssldap_installed:
-            root_logger.error("One of these packages must be installed: " +
-                "nss_ldap or nss-pam-ldapd")
-            return CLIENT_INSTALL_ERROR
-
-    if options.keytab and options.principal:
-        root_logger.error("Options 'principal' and 'keytab' cannot be used "
-                          "together.")
-        return CLIENT_INSTALL_ERROR
-
-    if options.keytab and options.force_join:
-        root_logger.warning("Option 'force-join' has no additional effect "
-                            "when used with together with option 'keytab'.")
-
-    # Check if old certificate exist and show warning
-    if not options.ca_cert_file and get_cert_path(options.ca_cert_file) == CACERT:
-        root_logger.warning("Using existing certificate '%s'.", CACERT)
-
-    if not check_ip_addresses(options):
-        return CLIENT_INSTALL_ERROR
-
-    # Create the discovery instance
-    ds = ipadiscovery.IPADiscovery()
-
     ret = ds.search(domain=options.domain, servers=options.server, realm=options.realm_name, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file))
 
     if options.server and ret != 0:
@@ -2300,15 +2234,13 @@ def install(options, env, fstore, statestore):
         root_logger.error("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 RuntimeError("IPA server verification failed")
 
     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 RuntimeError("Can't get the fully qualified name of this host")
     if ret == ipadiscovery.NOT_FQDN:
-        root_logger.error("%s is not a fully-qualified hostname", hostname)
-        return CLIENT_INSTALL_ERROR
+        raise RuntimeError("%s is not a fully-qualified hostname" % hostname)
     if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
             or not ds.domain:
         if ret == ipadiscovery.NO_LDAP_SERVER:
@@ -2327,9 +2259,8 @@ def install(options, env, fstore, statestore):
             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 RuntimeError("Unable to discover domain, not provided on "
+                               "command line")
         else:
             root_logger.info(
                 "DNS discovery failed to determine your DNS domain")
@@ -2345,8 +2276,6 @@ def install(options, env, fstore, statestore):
             cli_domain_source = ds.domain_source
             root_logger.debug("will use discovered domain: %s", cli_domain)
 
-    client_domain = hostname[hostname.find(".")+1:]
-
     if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
             or not ds.server:
         root_logger.debug("IPA Server not found")
@@ -2354,8 +2283,7 @@ def install(options, env, fstore, statestore):
             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 RuntimeError("Unable to find IPA Server to join")
         else:
             root_logger.debug("DNS discovery failed to find the IPA Server")
             cli_server = [user_input("Provide your IPA server name (ex: ipa.example.com)", allow_empty = False)]
@@ -2387,10 +2315,9 @@ def install(options, env, fstore, statestore):
             root_logger.debug("will use discovered server: %s", cli_server[0])
 
     if ret == ipadiscovery.NOT_IPA_SERVER:
-        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 RuntimeError("%s is not an IPA v2 Server.", cli_server[0])
 
     if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
         root_logger.warning("Anonymous access to the LDAP server is disabled.")
@@ -2412,7 +2339,7 @@ def install(options, env, fstore, statestore):
             "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 RuntimeError("IPA server verification failed")
 
     cli_kdc = ds.kdc
     if dnsok and not cli_kdc:
@@ -2435,7 +2362,7 @@ def install(options, env, fstore, statestore):
             "all operations and will not fail over to other servers in case " +
             "of failure.")
         if not user_input("Proceed with fixed values and no DNS discovery?", False):
-            return CLIENT_INSTALL_ERROR
+            raise RuntimeError("Operation aborted by user")
 
     cli_realm = ds.realm
     cli_realm_source = ds.realm_source
@@ -2446,11 +2373,95 @@ def install(options, env, fstore, statestore):
             "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 RuntimeError("IPA server verification failed")
 
     cli_basedn = ds.basedn
     cli_basedn_source = ds.basedn_source
     root_logger.debug("will use discovered basedn: %s", cli_basedn)
+
+    return (dnsok, cli_domain, cli_domain_source, cli_server,
+            cli_server_source, cli_realm, cli_realm_source, cli_kdc,
+            cli_basedn, cli_basedn_source)
+
+
+def install(options, env, fstore, statestore):
+    dnsok=False
+
+    if options.conf_ntp and not options.on_master and not options.force_ntpd:
+        try:
+            ipaclient.ntpconf.check_timedate_services()
+        except ipaclient.ntpconf.NTPConflictingService as e:
+            print("WARNING: ntpd time&date synchronization service will not" \
+                  " be configured as")
+            print("conflicting service (%s) is enabled" % e.conflicting_service)
+            print("Use --force-ntpd option to disable it and force configuration" \
+                  " of ntpd")
+            print("")
+
+            # configuration of ntpd is disabled in this case
+            options.conf_ntp = False
+        except ipaclient.ntpconf.NTPConfigurationError:
+            pass
+
+    if options.unattended and (options.password is None and
+                               options.principal is None and
+                               options.keytab is None and
+                               options.prompt_password is False and
+                               not options.on_master):
+        root_logger.error("One of password / principal / keytab is required.")
+        return CLIENT_INSTALL_ERROR
+
+    if options.hostname:
+        hostname = options.hostname
+        hostname_source = 'Provided as option'
+    else:
+        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
+    if (hostname == 'localhost') or (hostname == 'localhost.localdomain'):
+        root_logger.error("Invalid hostname, '%s' must not be used.", hostname)
+        return CLIENT_INSTALL_ERROR
+
+    # when installing with '--no-sssd' option, check whether nss-ldap is installed
+    if not options.sssd:
+        (nssldap_installed, nosssd_files) = nssldap_exists()
+        if not nssldap_installed:
+            root_logger.error("One of these packages must be installed: " +
+                "nss_ldap or nss-pam-ldapd")
+            return CLIENT_INSTALL_ERROR
+
+    if options.keytab and options.principal:
+        root_logger.error("Options 'principal' and 'keytab' cannot be used "
+                          "together.")
+        return CLIENT_INSTALL_ERROR
+
+    if options.keytab and options.force_join:
+        root_logger.warning("Option 'force-join' has no additional effect "
+                            "when used with together with option 'keytab'.")
+
+    # Check if old certificate exist and show warning
+    if not options.ca_cert_file and get_cert_path(options.ca_cert_file) == CACERT:
+        root_logger.warning("Using existing certificate '%s'.", CACERT)
+
+    if not check_ip_addresses(options):
+        return CLIENT_INSTALL_ERROR
+
+    # Create the discovery instance
+    ds = ipadiscovery.IPADiscovery()
+
+    try:
+        (dnsok, cli_domain, cli_domain_source, cli_server,
+         cli_server_source, cli_realm, cli_realm_source, cli_kdc,
+         cli_basedn, cli_basedn_source) = perform_autodiscovery(
+            ds, hostname, options)
+    except RuntimeError as e:
+        root_logger.error("Error running IPA discovery: %s", e.message)
+        return CLIENT_INSTALL_ERROR
+
+    client_domain = hostname[hostname.find(".")+1:]
     subject_base = DN(('O', cli_realm))
 
     root_logger.info("Client hostname: %s", hostname)
-- 
2.4.3

From 30775a463e7ec69ff87bdcdfa9ec239163e2a116 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Tue, 6 Oct 2015 18:22:51 +0200
Subject: [PATCH 1/4] ipa-client-install: factor DNS discovery to a separate
 function

https://fedorahosted.org/freeipa/ticket/4305
---
 ipa-client/ipa-install/ipa-client-install | 179 ++++++++++++++++--------------
 1 file changed, 95 insertions(+), 84 deletions(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index a08cd833f003615982dd711b50e47e2e513b8ba1..81cae4c967bdec7dd0772148bcd14edfa9a92ed9 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -2212,81 +2212,15 @@ def configure_firefox(options, statestore, domain):
         root_logger.error("Firefox configuration failed.")
 
 
-def install(options, env, fstore, statestore):
+def perform_autodiscovery(ds, hostname, options):
     dnsok = False
 
     cli_domain = None
     cli_server = None
-    subject_base = None
 
     cli_domain_source = 'Unknown source'
     cli_server_source = 'Unknown source'
 
-    if options.conf_ntp and not options.on_master and not options.force_ntpd:
-        try:
-            ipaclient.ntpconf.check_timedate_services()
-        except ipaclient.ntpconf.NTPConflictingService, e:
-            print "WARNING: ntpd time&date synchronization service will not" \
-                  " be configured as"
-            print "conflicting service (%s) is enabled" % e.conflicting_service
-            print "Use --force-ntpd option to disable it and force configuration" \
-                  " of ntpd"
-            print ""
-
-            # configuration of ntpd is disabled in this case
-            options.conf_ntp = False
-        except ipaclient.ntpconf.NTPConfigurationError:
-            pass
-
-    if options.unattended and (options.password is None and
-                               options.principal is None and
-                               options.keytab is None and
-                               options.prompt_password is False and
-                               not options.on_master):
-        root_logger.error("One of password / principal / keytab is required.")
-        return CLIENT_INSTALL_ERROR
-
-    if options.hostname:
-        hostname = options.hostname
-        hostname_source = 'Provided as option'
-    else:
-        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
-    if (hostname == 'localhost') or (hostname == 'localhost.localdomain'):
-        root_logger.error("Invalid hostname, '%s' must not be used.", hostname)
-        return CLIENT_INSTALL_ERROR
-
-    # when installing with '--no-sssd' option, check whether nss-ldap is installed
-    if not options.sssd:
-        (nssldap_installed, nosssd_files) = nssldap_exists()
-        if not nssldap_installed:
-            root_logger.error("One of these packages must be installed: " +
-                "nss_ldap or nss-pam-ldapd")
-            return CLIENT_INSTALL_ERROR
-
-    if options.keytab and options.principal:
-        root_logger.error("Options 'principal' and 'keytab' cannot be used "
-                          "together.")
-        return CLIENT_INSTALL_ERROR
-
-    if options.keytab and options.force_join:
-        root_logger.warning("Option 'force-join' has no additional effect "
-                            "when used with together with option 'keytab'.")
-
-    # Check if old certificate exist and show warning
-    if not options.ca_cert_file and get_cert_path(options.ca_cert_file) == CACERT:
-        root_logger.warning("Using existing certificate '%s'.", CACERT)
-
-    if not check_ip_addresses(options):
-        return CLIENT_INSTALL_ERROR
-
-    # Create the discovery instance
-    ds = ipadiscovery.IPADiscovery()
-
     ret = ds.search(domain=options.domain, servers=options.server, realm=options.realm_name, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file))
 
     if options.server and ret != 0:
@@ -2298,15 +2232,13 @@ def install(options, env, fstore, statestore):
         root_logger.error("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 RuntimeError("IPA server verification failed")
 
     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 RuntimeError("Can't get the fully qualified name of this host")
     if ret == ipadiscovery.NOT_FQDN:
-        root_logger.error("%s is not a fully-qualified hostname", hostname)
-        return CLIENT_INSTALL_ERROR
+        raise RuntimeError("%s is not a fully-qualified hostname" % hostname)
     if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
             or not ds.domain:
         if ret == ipadiscovery.NO_LDAP_SERVER:
@@ -2325,9 +2257,8 @@ def install(options, env, fstore, statestore):
             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 RuntimeError("Unable to discover domain, not provided on "
+                               "command line")
         else:
             root_logger.info(
                 "DNS discovery failed to determine your DNS domain")
@@ -2343,8 +2274,6 @@ def install(options, env, fstore, statestore):
             cli_domain_source = ds.domain_source
             root_logger.debug("will use discovered domain: %s", cli_domain)
 
-    client_domain = hostname[hostname.find(".")+1:]
-
     if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
             or not ds.server:
         root_logger.debug("IPA Server not found")
@@ -2352,8 +2281,7 @@ def install(options, env, fstore, statestore):
             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 RuntimeError("Unable to find IPA Server to join")
         else:
             root_logger.debug("DNS discovery failed to find the IPA Server")
             cli_server = [user_input("Provide your IPA server name (ex: ipa.example.com)", allow_empty = False)]
@@ -2385,10 +2313,9 @@ def install(options, env, fstore, statestore):
             root_logger.debug("will use discovered server: %s", cli_server[0])
 
     if ret == ipadiscovery.NOT_IPA_SERVER:
-        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 RuntimeError("%s is not an IPA v2 Server.", cli_server[0])
 
     if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
         root_logger.warning("Anonymous access to the LDAP server is disabled.")
@@ -2410,7 +2337,7 @@ def install(options, env, fstore, statestore):
             "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 RuntimeError("IPA server verification failed")
 
     cli_kdc = ds.kdc
     if dnsok and not cli_kdc:
@@ -2433,7 +2360,7 @@ def install(options, env, fstore, statestore):
             "all operations and will not fail over to other servers in case " +
             "of failure.")
         if not user_input("Proceed with fixed values and no DNS discovery?", False):
-            return CLIENT_INSTALL_ERROR
+            raise RuntimeError("Operation aborted by user")
 
     cli_realm = ds.realm
     cli_realm_source = ds.realm_source
@@ -2444,11 +2371,95 @@ def install(options, env, fstore, statestore):
             "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 RuntimeError("IPA server verification failed")
 
     cli_basedn = ds.basedn
     cli_basedn_source = ds.basedn_source
     root_logger.debug("will use discovered basedn: %s", cli_basedn)
+
+    return (dnsok, cli_domain, cli_domain_source, cli_server,
+            cli_server_source, cli_realm, cli_realm_source, cli_kdc,
+            cli_basedn, cli_basedn_source)
+
+
+def install(options, env, fstore, statestore):
+    dnsok=False
+
+    if options.conf_ntp and not options.on_master and not options.force_ntpd:
+        try:
+            ipaclient.ntpconf.check_timedate_services()
+        except ipaclient.ntpconf.NTPConflictingService as e:
+            print("WARNING: ntpd time&date synchronization service will not" \
+                  " be configured as")
+            print("conflicting service (%s) is enabled" % e.conflicting_service)
+            print("Use --force-ntpd option to disable it and force configuration" \
+                  " of ntpd")
+            print("")
+
+            # configuration of ntpd is disabled in this case
+            options.conf_ntp = False
+        except ipaclient.ntpconf.NTPConfigurationError:
+            pass
+
+    if options.unattended and (options.password is None and
+                               options.principal is None and
+                               options.keytab is None and
+                               options.prompt_password is False and
+                               not options.on_master):
+        root_logger.error("One of password / principal / keytab is required.")
+        return CLIENT_INSTALL_ERROR
+
+    if options.hostname:
+        hostname = options.hostname
+        hostname_source = 'Provided as option'
+    else:
+        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
+    if (hostname == 'localhost') or (hostname == 'localhost.localdomain'):
+        root_logger.error("Invalid hostname, '%s' must not be used.", hostname)
+        return CLIENT_INSTALL_ERROR
+
+    # when installing with '--no-sssd' option, check whether nss-ldap is installed
+    if not options.sssd:
+        (nssldap_installed, nosssd_files) = nssldap_exists()
+        if not nssldap_installed:
+            root_logger.error("One of these packages must be installed: " +
+                "nss_ldap or nss-pam-ldapd")
+            return CLIENT_INSTALL_ERROR
+
+    if options.keytab and options.principal:
+        root_logger.error("Options 'principal' and 'keytab' cannot be used "
+                          "together.")
+        return CLIENT_INSTALL_ERROR
+
+    if options.keytab and options.force_join:
+        root_logger.warning("Option 'force-join' has no additional effect "
+                            "when used with together with option 'keytab'.")
+
+    # Check if old certificate exist and show warning
+    if not options.ca_cert_file and get_cert_path(options.ca_cert_file) == CACERT:
+        root_logger.warning("Using existing certificate '%s'.", CACERT)
+
+    if not check_ip_addresses(options):
+        return CLIENT_INSTALL_ERROR
+
+    # Create the discovery instance
+    ds = ipadiscovery.IPADiscovery()
+
+    try:
+        (dnsok, cli_domain, cli_domain_source, cli_server,
+         cli_server_source, cli_realm, cli_realm_source, cli_kdc,
+         cli_basedn, cli_basedn_source) = perform_autodiscovery(
+            ds, hostname, options)
+    except RuntimeError as e:
+        root_logger.error("Error running IPA discovery: %s", e.message)
+        return CLIENT_INSTALL_ERROR
+
+    client_domain = hostname[hostname.find(".")+1:]
     subject_base = DN(('O', cli_realm))
 
     root_logger.info("Client hostname: %s", hostname)
-- 
2.4.3

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to