From cbb3bfae23267270e1310c1c1e23b1aed78fe9c6 Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Fri, 24 Feb 2012 14:15:24 +0100 Subject: Add reverse DNS record when forward is created Adding reverse DNS record may be a time consuming task, especially for IPv6 addresses. Having a way to automatically create a reverse record when a forward record is created could speed up the process. host-add command already has this possibility. This patch takes advantage of the new per-type API and adds new options for A/AAAA record types: --a-create-reverse and --aaaa-create-reverse. These commands can be used to automatically create reverse records for new A/AAAA addresses (both forward and reverse zones need to be managed by FreeIPA server): ipa dnsrecord-add example.com foo --a-rec=10.0.0.1 --a-create-reverse This command would add a new A record to record foo in zone example.com and a PTR record to appropriate reverse zone for IP address 10.0.0.1 (for example PTR record 1 in zone 0.0.10.in-addr.arpa. pointing to foo.example.com.). Few modification were done to new DNS API to support this feature: - Refactor --ip-address option handling from host-add and place it to dns.py to be used by both modules - Add support for "extra" per-type options - Hide DNS record part options in dnsrecord_find command as they have no effect for this command https://fedorahosted.org/freeipa/ticket/2009 --- ipalib/plugins/host.py | 104 +++++++------------------------------------------ 1 file changed, 15 insertions(+), 89 deletions(-) (limited to 'ipalib/plugins/host.py') diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index 012817e6b..df9ad7370 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -31,8 +31,8 @@ from ipalib.plugins.baseldap import * from ipalib.plugins.service import split_principal from ipalib.plugins.service import validate_certificate from ipalib.plugins.service import set_certificate_attrs -from ipalib.plugins.dns import dns_container_exists, _record_types -from ipalib.plugins.dns import add_forward_record +from ipalib.plugins.dns import dns_container_exists, _record_types, add_records_for_host_validation, add_records_for_host +from ipalib.plugins.dns import get_reverse_zone from ipalib import _, ngettext from ipalib import x509 from ipalib.dn import * @@ -105,51 +105,6 @@ def validate_host(ugettext, fqdn): return _('Fully-qualified hostname required') return None -def is_forward_record(zone, str_address): - addr = netaddr.IPAddress(str_address) - if addr.version == 4: - result = api.Command['dnsrecord_find'](zone, arecord=str_address) - elif addr.version == 6: - result = api.Command['dnsrecord_find'](zone, aaaarecord=str_address) - else: - raise ValueError('Invalid address family') - - return result['count'] > 0 - -def get_reverse_zone(ipaddr, prefixlen=None): - ip = netaddr.IPAddress(ipaddr) - revdns = unicode(ip.reverse_dns) - - if prefixlen is None: - revzone = u'' - - result = api.Command['dnszone_find']()['result'] - for zone in result: - zonename = zone['idnsname'][0] - if revdns.endswith(zonename) and len(zonename) > len(revzone): - revzone = zonename - else: - if ip.version == 4: - pos = 4 - prefixlen / 8 - elif ip.version == 6: - pos = 32 - prefixlen / 4 - items = ip.reverse_dns.split('.') - revzone = u'.'.join(items[pos:]) - - try: - api.Command['dnszone_show'](revzone) - except errors.NotFound: - revzone = u'' - - if len(revzone) == 0: - raise errors.NotFound( - reason=_('DNS reverse zone for IP address %(addr)s not found') % dict(addr=ipaddr) - ) - - revname = revdns[:-len(revzone)-1] - - return revzone, revname - def remove_fwd_ptr(ipaddr, host, domain, recordtype): api.log.debug('deleting ipaddr %s' % ipaddr) try: @@ -421,35 +376,15 @@ class host_add(LDAPCreate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - if 'ip_address' in options and dns_container_exists(ldap): + if options.get('ip_address') and dns_container_exists(ldap): parts = keys[-1].split('.') + host = parts[0] domain = unicode('.'.join(parts[1:])) - result = api.Command['dnszone_find']()['result'] - match = False - for zone in result: - if domain == zone['idnsname'][0]: - match = True - break - if not match: - raise errors.NotFound( - reason=_('DNS zone %(zone)s not found') % dict(zone=domain) - ) - ip = CheckedIPAddress(options['ip_address'], match_local=False) - if not options.get('no_reverse', False): - try: - prefixlen = None - if not ip.defaultnet: - prefixlen = ip.prefixlen - # we prefer lookup of the IP through the reverse zone - revzone, revname = get_reverse_zone(ip, prefixlen) - reverse = api.Command['dnsrecord_find'](revzone, idnsname=revname) - if reverse['count'] > 0: - raise errors.DuplicateEntry(message=u'This IP address is already assigned.') - except errors.NotFound: - pass - else: - if is_forward_record(domain, unicode(ip)): - raise errors.DuplicateEntry(message=u'This IP address is already assigned.') + check_reverse = not options.get('no_reverse', False) + add_records_for_host_validation('ip_address', host, domain, + options['ip_address'], + check_forward=True, + check_reverse=check_reverse) if not options.get('force', False) and not 'ip_address' in options: util.validate_host_dns(self.log, keys[-1]) if 'locality' in entry_attrs: @@ -489,24 +424,15 @@ class host_add(LDAPCreate): if dns_container_exists(ldap): try: parts = keys[-1].split('.') + host = parts[0] domain = unicode('.'.join(parts[1:])) - if 'ip_address' in options: - ip = CheckedIPAddress(options['ip_address'], match_local=False) - add_forward_record(domain, parts[0], unicode(ip)) - - if not options.get('no_reverse', False): - try: - prefixlen = None - if not ip.defaultnet: - prefixlen = ip.prefixlen - revzone, revname = get_reverse_zone(ip, prefixlen) - addkw = { 'ptrrecord' : keys[-1]+'.' } - api.Command['dnsrecord_add'](revzone, revname, **addkw) - except errors.EmptyModlist: - # the entry already exists and matches - pass + if options.get('ip_address'): + add_reverse = not options.get('no_reverse', False) + add_records_for_host(host, domain, options['ip_address'], + add_forward=True, + add_reverse=add_reverse) del options['ip_address'] update_sshfp_record(domain, unicode(parts[0]), entry_attrs) -- cgit