diff options
author | Florence Blanc-Renaud <flo@redhat.com> | 2018-02-08 16:55:20 +0100 |
---|---|---|
committer | Florence Blanc-Renaud <flo@redhat.com> | 2018-02-12 17:30:52 +0100 |
commit | 7364c268ebc241c2fa456951f0790ee5d83a7b3a (patch) | |
tree | 1a495ccb8d08e016b0b26d843b940ccbac6be280 | |
parent | 93b7c40158313b9f0f125706265ea0ac07fb4c0e (diff) | |
download | freeipa-7364c268ebc241c2fa456951f0790ee5d83a7b3a.tar.gz freeipa-7364c268ebc241c2fa456951f0790ee5d83a7b3a.tar.xz freeipa-7364c268ebc241c2fa456951f0790ee5d83a7b3a.zip |
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
Reviewed-By: Christian Heimes <cheimes@redhat.com>
-rw-r--r-- | ipaserver/plugins/dns.py | 9 | ||||
-rw-r--r-- | ipatests/test_xmlrpc/test_host_plugin.py | 72 |
2 files changed, 80 insertions, 1 deletions
diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py index e6a1f580e..016be0c6f 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 e0df6bc04..0acb6cf10 100644 --- a/ipatests/test_xmlrpc/test_host_plugin.py +++ b/ipatests/test_xmlrpc/test_host_plugin.py @@ -100,6 +100,9 @@ hostgroup1_dn = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'), 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): @@ -120,6 +123,12 @@ def host3(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' tracker = HostTracker(name=name, @@ -591,6 +600,69 @@ class TestHostFalsePwdChange(XMLRPC_test): @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: host.run_command('dnszone_del', dnszone, revzone, revipv6zone, |