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>
This commit is contained in:
Florence Blanc-Renaud 2018-02-08 16:55:20 +01:00
parent 93b7c40158
commit 7364c268eb
2 changed files with 80 additions and 1 deletions

View File

@ -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)

View File

@ -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):
@ -119,6 +122,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 +599,69 @@ class TestHostFalsePwdChange(XMLRPC_test):
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: