URL: https://github.com/freeipa/freeipa/pull/1551
Author: flo-renaud
 Title: #1551: ipa host-add --ip-address: properly handle NoNameservers
Action: opened

PR body:
"""
When ipa host-add --ip-address is called but no DNS server is able to answer
for the reverse zone, get_reverse_zone raises a NoNameservers exception.
The exception is not managed by add_records_for_host_validation, and this
leads to the command exiting on failure with an InternalError:
    $ ipa host-add testhost.ipadomain.com --ip-address 172.16.30.22
    ipa: ERROR: an internal error has occurred
A traceback is also logged in httpd error_log.

This commit properly handles the exception, and adds a test.

https://pagure.io/freeipa/issue/7397
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1551/head:pr1551
git checkout pr1551
From 34e6532b4f80dd5c36d745d19bd54f19848db661 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <f...@redhat.com>
Date: Thu, 8 Feb 2018 16:55:20 +0100
Subject: [PATCH] ipa host-add --ip-address: properly handle NoNameservers

When ipa host-add --ip-address is called but no DNS server is able to answer
for the reverse zone, get_reverse_zone raises a NoNameservers exception.
The exception is not managed by add_records_for_host_validation, and this
leads to the command exiting on failure with an InternalError:
    $ ipa host-add testhost.ipadomain.com --ip-address 172.16.30.22
    ipa: ERROR: an internal error has occurred
A traceback is also logged in httpd error_log.

This commit properly handles the exception, and adds a test.

https://pagure.io/freeipa/issue/7397
---
 ipaserver/plugins/dns.py                 |  9 +++-
 ipatests/test_xmlrpc/test_host_plugin.py | 71 ++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py
index e6a1f580e9..016be0c6f1 100644
--- a/ipaserver/plugins/dns.py
+++ b/ipaserver/plugins/dns.py
@@ -539,7 +539,14 @@ def get_reverse_zone(ipaddr):
     """
     ip = netaddr.IPAddress(str(ipaddr))
     revdns = DNSName(unicode(ip.reverse_dns))
-    revzone = DNSName(dns.resolver.zone_for_name(revdns))
+    try:
+        revzone = DNSName(dns.resolver.zone_for_name(revdns))
+    except dns.resolver.NoNameservers:
+        raise errors.NotFound(
+            reason=_(
+                'All nameservers failed to answer the query '
+                'for DNS reverse zone %(revdns)s') % dict(revdns=revdns)
+        )
 
     try:
         api.Command['dnszone_show'](revzone)
diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
index e0df6bc04c..d516abaa87 100644
--- a/ipatests/test_xmlrpc/test_host_plugin.py
+++ b/ipatests/test_xmlrpc/test_host_plugin.py
@@ -100,6 +100,8 @@
 host_cert = get_testcert(DN(('CN', api.env.host), subject_base()),
                          'host/%s@%s' % (api.env.host, api.env.realm))
 
+missingrevzone = u'22.30.16.172.in-addr.arpa.'
+ipv4_in_missingrevzone_ip = u'172.16.30.22'
 
 @pytest.fixture(scope='class')
 def host(request):
@@ -119,6 +121,12 @@ def host3(request):
     return tracker.make_fixture(request)
 
 
+@pytest.fixture(scope='class')
+def host4(request):
+    tracker = HostTracker(name=u'testhost4')
+    return tracker.make_fixture(request)
+
+
 @pytest.fixture(scope='class')
 def lab_host(request):
     name = u'testhost1'
@@ -590,6 +598,69 @@ def test_join_host(self, host, keytabname):
             command()
 
 
+@yield_fixture(scope='class')
+def dns_setup_nonameserver(host4):
+    # Make sure that the server does not handle the reverse zone used
+    # for the test
+    try:
+        host4.run_command('dnszone_del', missingrevzone, **{'continue': True})
+    except (errors.NotFound, errors.EmptyModlist):
+        pass
+
+    # Save the current forward policy
+    result = host4.run_command('dnsserver_show', api.env.host)
+    current_fwd_pol = result['result']['idnsforwardpolicy'][0]
+
+    # Configure the forward policy to none to make sure that no DNS
+    # server will answer for the reverse zone either
+    try:
+        host4.run_command('dnsserver_mod', api.env.host,
+            idnsforwardpolicy=u'none')
+    except errors.EmptyModlist:
+        pass
+
+    try:
+        yield
+    finally:
+        # Restore the previous forward-policy
+        try:
+            host4.run_command('dnsserver_mod', api.env.host,
+                idnsforwardpolicy=current_fwd_pol)
+        except errors.EmptyModlist:
+            pass
+
+
+@pytest.mark.tier1
+class TestHostNoNameserversForRevZone(XMLRPC_test):
+    def test_create_host_with_ip(self, dns_setup_nonameserver, host4):
+        """
+        Regression test for ticket 7397
+
+        Configure the master with forward-policy = none to make sure
+        that no DNS server will answer for the reverse zone
+        Try to add a new host with an IP address in the missing reverse
+        zone.
+        With issue 7397, a NoNameserver exception generates a Traceback in
+        httpd error_log, and the command returns an InternalError. 
+        """
+        try:
+            command = host4.make_create_command()
+            with raises_exact(errors.NonFatalError(
+                reason=u'The host was added but the DNS update failed with'
+                    ': All nameservers failed to answer the query for DNS '
+                    'reverse zone %s' % missingrevzone)):
+                command(ip_address=ipv4_in_missingrevzone_ip)
+            # Make sure the host is added
+            host4.run_command('host_show', host4.fqdn)
+        finally:
+            # Delete the host entry
+            command = host4.make_delete_command()
+            try:
+                command(updatedns=True)
+            except Exception:
+                pass
+
+
 @yield_fixture(scope='class')
 def dns_setup(host):
     try:
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to