The patch now depends on freeipa-dkupka-0012 as both modifies the same part of code.

On 09/02/2014 10:29 AM, David Kupka wrote:
Forget to add str() conversion to some places when removing map(). Now
it should be working again.

On 08/27/2014 02:24 PM, David Kupka wrote:
Patch modified according to jcholast's personally-delivered feedback:

 > 1) use action='append' instead of that ugly parsing

 > 2) do not use map(), FreeIPA doesn't like it

On 08/25/2014 05:04 PM, David Kupka wrote:
https://fedorahosted.org/freeipa/ticket/3575

Also should fix https://bugzilla.redhat.com/show_bug.cgi?id=1128380 as
installation is no longer interrupted when multiple IPs are resolved.
But it does not add the option to change the IP address during second
run.



_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel




_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel




_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel


--
David Kupka
From 8eaea5ada941ac813e22efa076b6989d2dbf6be6 Mon Sep 17 00:00:00 2001
From: David Kupka <dku...@redhat.com>
Date: Wed, 27 Aug 2014 13:50:21 +0200
Subject: [PATCH] Detect and configure all usable IP addresses.

Find, verify and configure all IP addresses that can be used to reach the server
FreeIPA is being installed on. Ignore some IP address only if user specifies
subset of detected addresses using --ip-address option.
This change simplyfies FreeIPA installation on multihomed and dual-stacked servers.

https://fedorahosted.org/freeipa/ticket/3575
---
 install/tools/ipa-server-install  | 43 ++++++++++++--------
 ipaserver/install/bindinstance.py | 46 +++++++++++----------
 ipaserver/install/installutils.py | 86 +++++++++++++++++++--------------------
 3 files changed, 94 insertions(+), 81 deletions(-)

diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 6e77b434a018faec36a2808626c99a54bd493908..dde7731e5d991f3329efe8232fcd1bce434e280d 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -176,7 +176,7 @@ def parse_options():
                                 "on their first login")
     basic_group.add_option("--hostname", dest="host_name", help="fully qualified name of server")
     basic_group.add_option("--ip-address", dest="ip_address",
-                      type="ip", ip_local=True,
+                      type="ip", ip_local=True, action="append", default=[],
                       help="Master Server IP Address")
     basic_group.add_option("-N", "--no-ntp", dest="conf_ntp", action="store_false",
                       help="do not configure ntp", default=True)
@@ -236,7 +236,8 @@ def parse_options():
                       type="ip", help="Add a DNS forwarder")
     dns_group.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
                       default=False, help="Do not add any DNS forwarders, use root servers instead")
-    dns_group.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
+    dns_group.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use",
+                      action="append", default=[])
     dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
                       default=False, help="Do not create reverse DNS zone")
     dns_group.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
@@ -832,11 +833,11 @@ def main():
     realm_name = ""
     host_name = ""
     domain_name = ""
-    ip_address = ""
+    ip_address = []
     master_password = ""
     dm_password = ""
     admin_password = ""
-    reverse_zone = None
+    reverse_zone = []
 
     if not options.setup_dns and not options.unattended:
         if ipautil.user_input("Do you want to configure integrated DNS (BIND)?", False):
@@ -895,11 +896,14 @@ def main():
 
     domain_name = domain_name.lower()
 
-    ip = get_server_ip_address(host_name, fstore, options.unattended, options)
-    ip_address = str(ip)
+    ip_address = get_server_ip_address(host_name, fstore, options.unattended, options)
 
-    if options.reverse_zone and not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
-        sys.exit(1)
+    for ip in ip_address:
+        for rev_zone in reverse_zone:
+            if bindinstance.verify_reverse_zone(rev_zone, str(ip)):
+                break
+            else:
+                sys.exit(1)
 
     if not options.realm_name:
         realm_name = read_realm_name(domain_name, options.unattended)
@@ -972,16 +976,23 @@ def main():
             dns_forwarders = read_dns_forwarders()
 
         if options.reverse_zone:
-            reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
+            for rz in options.reverse_zone:
+                reverse_zone.append(bindinstance.normalize_zone(rz))
         elif not options.no_reverse:
             if options.unattended:
-                reverse_zone = util.get_reverse_zone_default(ip)
+                for ip in ip_address:
+                    rz = util.get_reverse_zone_default(str(ip))
+                    if not rz in reverse_zone:
+                        reverse_zone.append(rz)
             elif bindinstance.create_reverse():
-                reverse_zone = util.get_reverse_zone_default(ip)
-                reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
+                for ip in ip_address:
+                    rz = util.get_reverse_zone_default(str(ip))
+                    rz = bindinstance.read_reverse_zone(rz, str(ip))
+                    if not rz in reverse_zone:
+                        reverse_zone.append(rz)
 
-        if reverse_zone is not None:
-            print "Using reverse zone %s" % reverse_zone
+        if reverse_zone:
+            print "Using reverse zone %s" % ", ".join(str(rz) for rz in reverse_zone)
     else:
         dns_forwarders = ()
     root_logger.debug("will use dns_forwarders: %s\n" % str(dns_forwarders))
@@ -989,7 +1000,7 @@ def main():
     print
     print "The IPA Master Server will be configured with:"
     print "Hostname:      %s" % host_name
-    print "IP address:    %s" % ip_address
+    print "IP address:    %s" % ", ".join(str(ip) for ip in ip_address)
     print "Domain name:   %s" % domain_name
     print "Realm name:    %s" % realm_name
     print
@@ -999,7 +1010,7 @@ def main():
         print "Forwarders:    %s" % ("No forwarders" if not dns_forwarders \
                 else ", ".join([str(ip) for ip in dns_forwarders]))
         print "Reverse zone:  %s" % ("No reverse zone" if options.no_reverse \
-                or reverse_zone is None else reverse_zone)
+                or reverse_zone is None else ", ".join(str(rz) for rz in reverse_zone))
         print
 
     # If domain name and realm does not match, IPA server will not be able
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 9a27c781764f3dc311d20cfcf9150fde31307b03..371af4b892d6e3928a9dbddbe4bc4093a0306763 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -467,11 +467,11 @@ class BindInstance(service.Service):
         self.named_user = None
         self.domain = None
         self.host = None
-        self.ip_address = None
+        self.ip_address = []
         self.realm = None
         self.forwarders = None
         self.sub_dict = None
-        self.reverse_zone = None
+        self.reverse_zone = []
         self.dm_password = dm_password
 
         if fstore:
@@ -539,8 +539,9 @@ class BindInstance(service.Service):
         # get a connection to the DS
         self.ldap_connect()
 
-        if installutils.record_in_hosts(self.ip_address, self.fqdn) is None:
-            installutils.add_record_to_hosts(self.ip_address, self.fqdn)
+        for ip_address in self.ip_address:
+            if installutils.record_in_hosts(str(ip_address), self.fqdn) is None:
+                installutils.add_record_to_hosts(str(ip_address), self.fqdn)
 
         # Make sure generate-rndc-key.sh runs before named restart
         self.step("generating rndc key file", self.__generate_rndc_key)
@@ -552,7 +553,7 @@ class BindInstance(service.Service):
             self.step("adding NS record to the zone", self.__add_self_ns)
         else:
             self.step("setting up our zone", self.__setup_zone)
-        if self.reverse_zone is not None:
+        if self.reverse_zone:
             self.step("setting up reverse zone", self.__setup_reverse_zone)
 
         self.step("setting up our own record", self.__add_self)
@@ -603,18 +604,17 @@ class BindInstance(service.Service):
         else:
             optional_ntp = ""
 
-        addr = netaddr.IPAddress(self.ip_address)
-        if addr.version in (4, 6):
-            ipa_ca = "%s\t\t\tIN %s\t\t\t%s\n" % (
-                IPA_CA_RECORD,
-                "A" if addr.version == 4 else "AAAA",
-                self.ip_address)
-        else:
-            ipa_ca = ""
+        ipa_ca = ""
+        for addr in self.ip_address:
+            if addr.version in (4, 6):
+                ipa_ca += "%s\t\t\tIN %s\t\t\t%s\n" % (
+                    IPA_CA_RECORD,
+                    "A" if addr.version == 4 else "AAAA",
+                    str(addr))
 
         self.sub_dict = dict(
             FQDN=self.fqdn,
-            IP=self.ip_address,
+            IP=[str(ip) for ip in self.ip_address],
             DOMAIN=self.domain,
             HOST=self.host,
             REALM=self.realm,
@@ -635,9 +635,10 @@ class BindInstance(service.Service):
             # Nameserver is in self.host_domain, no forward record added to self.domain
             nameserver_ip_address = None
         # Always use force=True as named is not set up yet
-        add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup,
-                ns_hostname=api.env.host, ns_ip_address=nameserver_ip_address,
-                force=True)
+        for ns_ip_address in nameserver_ip_address:
+            add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup,
+                    ns_hostname=api.env.host, ns_ip_address=ns_ip_address,
+                    force=True)
 
         add_rr(self.domain, "_kerberos", "TXT", self.realm)
 
@@ -646,7 +647,8 @@ class BindInstance(service.Service):
 
     def __setup_reverse_zone(self):
         # Always use force=True as named is not set up yet
-        add_zone(self.reverse_zone, self.zonemgr, ns_hostname=api.env.host,
+        for reverse_zone in self.reverse_zone:
+            add_zone(reverse_zone, self.zonemgr, ns_hostname=api.env.host,
                 dns_backup=self.dns_backup, force=True)
 
     def __add_master_records(self, fqdn, addrs):
@@ -699,7 +701,7 @@ class BindInstance(service.Service):
                 add_ptr_rr(reverse_zone, addr, fqdn)
 
     def __add_self(self):
-        self.__add_master_records(self.fqdn, [self.ip_address])
+        self.__add_master_records(self.fqdn, self.ip_address)
 
     def __add_others(self):
         entries = self.admin_conn.get_entries(
@@ -744,7 +746,7 @@ class BindInstance(service.Service):
             pass
 
     def __add_ipa_ca_record(self):
-        self.__add_ipa_ca_records(self.fqdn, [self.ip_address],
+        self.__add_ipa_ca_records(self.fqdn, self.ip_address,
                                   self.ca_configured)
 
         if self.first_instance:
@@ -832,7 +834,9 @@ class BindInstance(service.Service):
 
     def __setup_resolv_conf(self):
         self.fstore.backup_file(RESOLV_CONF)
-        resolv_txt = "search "+self.domain+"\nnameserver "+self.ip_address+"\n"
+        resolv_txt = ''
+        for ip_address in self.ip_address:
+            resolv_txt += "search "+self.domain+"\nnameserver "+str(ip_address)+"\n"
         try:
             resolv_fd = open(RESOLV_CONF, 'w')
             resolv_fd.seek(0)
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index dc98d7a51aa743c87b2d7667246b6f029b8a648b..5661de6b6b918a61a8de3ed16c25d4b7debd212d 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -437,72 +437,70 @@ def get_server_ip_address(host_name, fstore, unattended, options):
 
     ip_add_to_hosts = False
 
+    ip = []
     if len(hostaddr) > 1:
-        print >> sys.stderr, "The server hostname resolves to more than one address:"
-        for addr in hostaddr:
-            print >> sys.stderr, "  %s" % addr
-
-        if options.ip_address:
-            if str(options.ip_address) not in hostaddr:
-                print >> sys.stderr, "Address passed in --ip-address did not match any resolved"
-                print >> sys.stderr, "address!"
-                sys.exit(1)
-            print "Selected IP address:", str(options.ip_address)
-            ip = options.ip_address
-        else:
+        for ha in hostaddr:
+            try:
+                ip.append(ipautil.CheckedIPAddress(ha, match_local=True))
+            except ValueError, e:
+                root_logger.warning("Invalid IP address %s for %s: %s", ha, host_name, unicode(e))
+        if not ip:
             if unattended:
                 print >> sys.stderr, "Please use --ip-address option to specify the address"
                 sys.exit(1)
             else:
-                ip = read_ip_address(host_name, fstore)
+                ip.append(read_ip_address(host_name, fstore))
     elif len(hostaddr) == 1:
         try:
-            ip = ipautil.CheckedIPAddress(hostaddr[0], match_local=True)
+            ip.append(ipautil.CheckedIPAddress(hostaddr[0], match_local=True))
         except ValueError, e:
             sys.exit("Invalid IP Address %s for %s: %s" % (hostaddr[0], host_name, unicode(e)))
-    else:
+    elif options.ip_address:
         # hostname is not resolvable
         ip = options.ip_address
         ip_add_to_hosts = True
 
-    if ip is None:
+    if not ip:
         print "Unable to resolve IP address for host name"
         if unattended:
             sys.exit(1)
 
     if options.ip_address:
-        if options.ip_address != ip and not options.setup_dns:
-            print >>sys.stderr, "Error: the hostname resolves to an IP address that is different"
-            print >>sys.stderr, "from the one provided on the command line.  Please fix your DNS"
-            print >>sys.stderr, "or /etc/hosts file and restart the installation."
-            sys.exit(1)
+        if options.setup_dns:
+            ip = options.ip_address
+        else:
+            # all specified addresses was resolved for this host
+            if set(options.ip_address) <= set(ip):
+                ip = options.ip_address
+            else:
+                print >>sys.stderr, "Error: the hostname resolves to an IP address that is different"
+                print >>sys.stderr, "from the one provided on the command line.  Please fix your DNS"
+                print >>sys.stderr, "or /etc/hosts file and restart the installation."
+                sys.exit(1)
 
-        ip = options.ip_address
-
-    if ip is None:
-        ip = read_ip_address(host_name, fstore)
+    if not ip:
+        ip.append(read_ip_address(host_name, fstore))
         root_logger.debug("read ip_address: %s\n" % str(ip))
 
-    ip_address = str(ip)
+    for ip_address in ip:
+        # check /etc/hosts sanity, add a record when needed
+        hosts_record = record_in_hosts(str(ip_address))
 
-    # check /etc/hosts sanity, add a record when needed
-    hosts_record = record_in_hosts(ip_address)
-
-    if hosts_record is None:
-        if ip_add_to_hosts or options.setup_dns:
-            print "Adding ["+ip_address+" "+host_name+"] to your /etc/hosts file"
-            fstore.backup_file(paths.HOSTS)
-            add_record_to_hosts(ip_address, host_name)
-    else:
-        primary_host = hosts_record[1][0]
-        if primary_host != host_name:
-            print >>sys.stderr, "Error: there is already a record in /etc/hosts for IP address %s:" \
-                    % ip_address
-            print >>sys.stderr, hosts_record[0], " ".join(hosts_record[1])
-            print >>sys.stderr, "Chosen hostname %s does not match configured canonical hostname %s" \
-                    % (host_name, primary_host)
-            print >>sys.stderr, "Please fix your /etc/hosts file and restart the installation."
-            sys.exit(1)
+        if hosts_record is None:
+            if ip_add_to_hosts:
+                print "Adding ["+str(ip_address)+" "+host_name+"] to your /etc/hosts file"
+                fstore.backup_file(paths.HOSTS)
+                add_record_to_hosts(str(ip_address), host_name)
+        else:
+            primary_host = hosts_record[1][0]
+            if primary_host != host_name:
+                print >>sys.stderr, "Error: there is already a record in /etc/hosts for IP address %s:" \
+                        % ip_address
+                print >>sys.stderr, hosts_record[0], " ".join(hosts_record[1])
+                print >>sys.stderr, "Chosen hostname %s does not match configured canonical hostname %s" \
+                        % (host_name, primary_host)
+                print >>sys.stderr, "Please fix your /etc/hosts file and restart the installation."
+                sys.exit(1)
 
     return ip
 
-- 
1.9.3

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to