Split from patch 3.

https://fedorahosted.org/freeipa/ticket/1212

Honza

--
Jan Cholasta
>From 68dacbd0b4ada4c2f02570c167c34c299ceec57e Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Tue, 10 May 2011 19:23:31 +0200
Subject: [PATCH] Parse netmasks in IP addresses passed to server install.

ticket 1212
---
 install/tools/ipa-dns-install     |    6 ++-
 install/tools/ipa-replica-install |    2 +
 install/tools/ipa-replica-prepare |   11 ++++--
 install/tools/ipa-server-install  |   30 +++++++----------
 ipaserver/install/installutils.py |   65 ++++++++++++++++++++++++++++--------
 tests/test_install/test_utils.py  |   55 +++++++++++++++++++++++++++++++
 6 files changed, 131 insertions(+), 38 deletions(-)
 create mode 100644 tests/test_install/test_utils.py

diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index aac85bf..256c670 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -131,11 +131,13 @@ def main():
         ip_address = options.ip_address
     else:
         ip_address = resolve_host(api.env.host)
-    if not ip_address or not verify_ip_address(ip_address):
+    ip = parse_ip_address(ip_address)
+    if not verify_ip_address(ip):
         if options.unattended:
             sys.exit("Unable to resolve IP address for host name")
         else:
-            ip_address = read_ip_address(api.env.host, fstore)
+            ip = read_ip_address(api.env.host, fstore)
+    ip_address = str(ip)
     logging.debug("will use ip_address: %s\n", ip_address)
 
     if options.no_forwarders:
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 64f1577..722da37 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -285,6 +285,8 @@ def install_bind(config, options):
     ip_address = resolve_host(config.host_name)
     if not ip_address:
         sys.exit("Unable to resolve IP address for host name")
+    ip = installutils.parse_ip_address(ip_address)
+    ip_address = str(ip)
 
     create_reverse = True
     if options.unattended:
diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare
index e912235..6a4e413 100755
--- a/install/tools/ipa-replica-prepare
+++ b/install/tools/ipa-replica-prepare
@@ -425,10 +425,13 @@ def main():
         name = domain.pop(0)
         domain = ".".join(domain)
 
-        zone = add_zone(domain, nsaddr=options.ip_address)
-        add_rr(zone, name, "A", options.ip_address)
-        add_reverse_zone(options.ip_address)
-        add_ptr_rr(options.ip_address, replica_fqdn)
+        ip = installutils.parse_ip_address(options.ip_address)
+        ip_address = str(ip)
+
+        zone = add_zone(domain, nsaddr=ip_address)
+        add_rr(zone, name, "A", ip_address)
+        add_reverse_zone(ip_address)
+        add_ptr_rr(ip_address, replica_fqdn)
 
 try:
     if not os.geteuid()==0:
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index d50dc61..c256d0e 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -615,37 +615,33 @@ def main():
     domain_name = domain_name.lower()
 
     # Check we have a public IP that is associated with the hostname
-    ip = resolve_host(host_name)
-    if ip is None:
-        if options.ip_address:
-            ip = options.ip_address
-    if ip is None and options.unattended:
+    ip = parse_ip_address(resolve_host(host_name))
+    ip_opt = parse_ip_address(options.ip_address)
+    if not ip and ip_opt:
+        ip = ip_opt
+    if not ip and options.unattended:
         sys.exit("Unable to resolve IP address for host name")
 
     if not verify_ip_address(ip):
-        ip = ""
+        ip = None
         if options.unattended:
             sys.exit(1)
 
-    if options.ip_address and options.ip_address != ip:
-        if options.setup_dns:
-            if not verify_ip_address(options.ip_address):
-                return 1
-            ip = options.ip_address
-        else:
+    if ip_opt:
+        if ip_opt != 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."
             return 1
 
-    if options.unattended:
-        if not ip:
-            sys.exit("Unable to resolve IP address")
+        ip = ip_opt
+        if not verify_ip_address(ip):
+            return 1
 
     if not ip:
         ip = read_ip_address(host_name, fstore)
-        logging.debug("read ip_address: %s\n" % ip)
-    ip_address = ip
+        logging.debug("read ip_address: %s\n" % str(ip))
+    ip_address = str(ip)
 
     print "The IPA Master Server will be configured with"
     print "Hostname:    " + host_name
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 3868c4d..8ac24c9 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -148,17 +148,49 @@ def verify_fqdn(host_name,no_host_dns=False):
     else:
         print "Warning: Hostname (%s) not found in DNS" % host_name
 
-def verify_ip_address(ip):
-    is_ok = True
-    try:
-        socket.inet_pton(socket.AF_INET, ip)
-    except:
+class _ParsedIPAddress(netaddr.IPAddress):
+    def __init__(self, net):
+        super(_ParsedIPAddress, self).__init__(net.ip)
+
+        self.prefixlen = net.prefixlen
+
+def parse_ip_address(addr):
+    if addr is None:
+        return None
+    if isinstance(addr, _ParsedIPAddress):
+        return addr
+
+    if isinstance(addr, netaddr.IPNetwork):
+        net = addr
+    else:
         try:
-            socket.inet_pton(socket.AF_INET6, ip)
+            ip = netaddr.IPAddress(addr)
+            if ip.version == 4:
+                net = netaddr.IPNetwork(netaddr.cidr_abbrev_to_verbose(str(ip)))
+            elif ip.version == 6:
+                net = netaddr.IPNetwork(ip)
+                net.prefixlen = 64
+        except ValueError:
+            try:
+                net = netaddr.IPNetwork(addr)
+            except:
+                return None
         except:
-            print "Unable to verify IP address"
-            is_ok = False
-    return is_ok
+            return None
+
+    if net is None or net.version not in (4, 6):
+        return None
+
+    return _ParsedIPAddress(net)
+
+def verify_ip_address(addr):
+    ip = parse_ip_address(addr)
+
+    if ip is None:
+        print "Unable to verify IP address"
+        return False
+
+    return True
 
 def record_in_hosts(ip, host_name, file="/etc/hosts"):
     hosts = open(file, 'r').readlines()
@@ -192,18 +224,20 @@ def read_ip_address(host_name, fstore):
     while True:
         ip = ipautil.user_input("Please provide the IP address to be used for this host name", allow_empty = False)
 
-        if ip == "127.0.0.1" or ip == "::1":
+        ip_parsed = parse_ip_address(ip)
+        if ip_parsed.is_loopback():
             print "The IPA Server can't use localhost as a valid IP"
             continue
 
-        if verify_ip_address(ip):
+        if verify_ip_address(ip_parsed):
             break
 
+    ip = str(ip_parsed)
     print "Adding ["+ip+" "+host_name+"] to your /etc/hosts file"
     fstore.backup_file("/etc/hosts")
     add_record_to_hosts(ip, host_name)
 
-    return ip
+    return ip_parsed
 
 def read_dns_forwarders():
     addrs = []
@@ -215,15 +249,16 @@ def read_dns_forwarders():
                                     allow_empty=True)
             if not ip:
                 break
-            if ip == "127.0.0.1" or ip == "::1":
+            ip_parsed = parse_ip_address(ip)
+            if ip_parsed.is_loopback():
                 print "You cannot use localhost as a DNS forwarder"
                 continue
-            if not verify_ip_address(ip):
+            if not verify_ip_address(ip_parsed):
                 print "DNS forwarder %s not added" % ip
                 continue
 
             print "DNS forwarder %s added" % ip
-            addrs.append(ip)
+            addrs.append(str(ip_parsed))
 
     if not addrs:
         print "No DNS forwarders configured"
diff --git a/tests/test_install/test_utils.py b/tests/test_install/test_utils.py
new file mode 100644
index 0000000..70949a5
--- /dev/null
+++ b/tests/test_install/test_utils.py
@@ -0,0 +1,55 @@
+# Authors:
+#   Jan Cholasta <jchol...@redhat.com>
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+Test the `ipaserver/install/installutils.py` module.
+"""
+
+import nose
+
+from ipaserver.install import installutils
+
+class CheckIPAddress:
+    def __init__(self, addr):
+        self.description = "Test IP address parsing and verification (%s)" % addr
+
+    def __call__(self, addr, words=None, prefixlen=None, verified=None):
+        ip = installutils.parse_ip_address(addr)
+        if ip:
+            assert ip.words == words and ip.prefixlen == prefixlen
+            assert not verified or installutils.verify_ip_address(ip)
+        else:
+            assert words is None and prefixlen is None and verified is None
+
+def test_ip_address():
+    addrs = [
+        ('10.11.12.13',     (10, 11, 12, 13),   8,  True),
+        ('10.11.12.13/14',  (10, 11, 12, 13),   14, True),
+        ('10.11.12.1337',),
+        ('10.11.12.13/33',),
+
+        ('2001::1',     (0x2001, 0, 0, 0, 0, 0, 0, 1), 64,  True),
+        ('2001::1/72',  (0x2001, 0, 0, 0, 0, 0, 0, 1), 72,  True),
+        ('2001::1beef',),
+        ('2001::1/129',),
+
+        ('junk',)
+    ]
+
+    for addr in addrs:
+        yield (CheckIPAddress(addr[0]),) + addr
-- 
1.7.4.4

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

Reply via email to