Batch the creation of dns entries
This should reduce the time spent creating dns entries by doing most of the pre-processing in a python module, and reducing the number of calls made to IPA. Also modified the molecule tests to allow for cases where more than one IP record is returned. In this case, the regex was too restrictive. Also modified the reverse DNS test to handle the ipv6 case correctly. It looks like we were creating zones incorrectly for ipv6 before. Also added some code to the end of the prepare.yml for the deregister test, to make sure the ipa server is really up before continuing. Change-Id: If88fc20c52e8ff4af77efaef920dd3de62723d0f
This commit is contained in:
parent
f54ffe985b
commit
efdc9022e3
107
tripleo_ipa/ansible_plugins/filter/dns_data.py
Normal file
107
tripleo_ipa/ansible_plugins/filter/dns_data.py
Normal file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2023 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from ipaddress import ip_address, IPv4Address
|
||||
|
||||
|
||||
def _parse_host_entry(entry):
|
||||
if len(entry.split()) >= 2:
|
||||
value = entry.split()[0]
|
||||
try:
|
||||
ip = ip_address(value)
|
||||
record_type = 'A' if (type(ip) is IPv4Address) else 'AAAA'
|
||||
except ValueError:
|
||||
return "", "", "Invalid", ""
|
||||
|
||||
host = entry.split()[1]
|
||||
host_split = host.split('.', 1)
|
||||
if (len(host_split) == 2):
|
||||
name = host_split[0]
|
||||
zone = host_split[1]
|
||||
return value, name, record_type, zone
|
||||
return "", "", "Invalid", ""
|
||||
|
||||
|
||||
def _parse_hosts_entries(hosts_entries, cdomain):
|
||||
"""Extract parameters to add dns entries from hosts_data
|
||||
|
||||
---
|
||||
:param hosts_data: is a list of strings, with each string being a line
|
||||
in the /etc/hosts file.
|
||||
|
||||
:returns: two lists. a list of dicts containing the parameters needed for
|
||||
ansible-freeipa dnsrecord to add, and a list of dicts containing
|
||||
dnszones to add.
|
||||
"""
|
||||
zones = set()
|
||||
records = list()
|
||||
ips = set()
|
||||
for host_entry in hosts_entries:
|
||||
value, name, record_type, zone = _parse_host_entry(host_entry)
|
||||
|
||||
print("cdomain is " + cdomain)
|
||||
if record_type == "Invalid":
|
||||
continue
|
||||
|
||||
if not zone.endswith(cdomain):
|
||||
print("zone " + zone + " not added")
|
||||
continue
|
||||
|
||||
# add forward zone
|
||||
if zone not in zones:
|
||||
print("adding " + zone)
|
||||
zones.add(zone)
|
||||
|
||||
# add ips to get reverse zones
|
||||
if value not in ips:
|
||||
ips.add(value)
|
||||
|
||||
# add forward record
|
||||
if (record_type == "A"):
|
||||
record = {"record_name": name,
|
||||
"zone_name": zone,
|
||||
"record_type": record_type,
|
||||
"create_reverse": "true",
|
||||
"a_rec": value}
|
||||
else:
|
||||
record = {"record_name": name,
|
||||
"zone_name": zone,
|
||||
"record_type": record_type,
|
||||
"create_reverse": "true",
|
||||
"aaaa_rec": value}
|
||||
records.append(record)
|
||||
|
||||
return [list(zones), list(ips), records]
|
||||
|
||||
|
||||
def get_dns_zones(hosts_entries, cdomain):
|
||||
return _parse_hosts_entries(hosts_entries, cdomain)[0]
|
||||
|
||||
|
||||
def get_ips(hosts_entries, cdomain):
|
||||
return _parse_hosts_entries(hosts_entries, cdomain)[1]
|
||||
|
||||
|
||||
def get_dns_entries(hosts_entries, cdomain):
|
||||
return _parse_hosts_entries(hosts_entries, cdomain)[2]
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
def filters(self):
|
||||
return {
|
||||
'get_dns_entries': get_dns_entries,
|
||||
'get_ips': get_ips,
|
||||
'get_dns_zones': get_dns_zones}
|
@ -197,7 +197,7 @@ def test_dns(host, ip, name):
|
||||
result = host.check_output(
|
||||
'ipa dnsrecord-find {} --name={}'.format(
|
||||
zone_name, record_name))
|
||||
assert 'record: {}'.format(ip) in result
|
||||
assert ip in result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ip, name', [
|
||||
@ -234,12 +234,15 @@ def test_dns_absent(host, ip, name):
|
||||
('172.16.0.195', 'overcloud-novacompute-0.tenant'),
|
||||
('192.168.24.128', 'overcloud-novacompute-0.ctlplane')])
|
||||
def test_reverse_dns(host, ip, name):
|
||||
reverse = ipaddress.ip_address(ip).reverse_pointer
|
||||
record, zone = reverse.split('.', 1)
|
||||
split_char = '.'
|
||||
addr = ipaddress.ip_address(ip)
|
||||
k = 1 if (addr.version == 4) else 16
|
||||
temp = addr.reverse_pointer.split(split_char)
|
||||
record, zone = split_char.join(temp[:k]), split_char.join(temp[k:])
|
||||
result = host.check_output(
|
||||
'ipa dnsrecord-find {} --name={}'.format(
|
||||
zone, record))
|
||||
assert 'record: {}'.format(name) in result
|
||||
assert name in result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ip, name', [
|
||||
|
@ -74,3 +74,22 @@
|
||||
search_regex: "(INFO The ipa-server-install command was successful|ERROR The ipa-server-install command failed)"
|
||||
timeout: 900
|
||||
become: true
|
||||
|
||||
- name: Wait for FreeIPA LDAP port to open
|
||||
wait_for:
|
||||
host=10.88.0.22
|
||||
port=389
|
||||
delay=1
|
||||
timeout=300
|
||||
ignore_errors: true
|
||||
|
||||
- name: Check the status of ipactl to make sure all services are started
|
||||
command: "sudo podman exec freeipa-server-container ipactl status"
|
||||
retries: 10
|
||||
delay: 3
|
||||
register: result
|
||||
until: result.rc == 0
|
||||
|
||||
- name: Print ipactl status
|
||||
debug:
|
||||
msg: "{{ result.stdout }}"
|
||||
|
@ -1,123 +0,0 @@
|
||||
---
|
||||
# Copyright 2020 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
- name: set forward dns record values
|
||||
set_fact:
|
||||
record_value: "{{ item.split()[0] }}"
|
||||
record_name: "{{ item.split()[1].split('.', 1)[0] }}"
|
||||
zone_name: "{{ item.split()[1].split('.', 1)[1] }}"
|
||||
when: item.split() | length >= 2 and item.split()[1].split('.') | length >= 2
|
||||
|
||||
- name: set alternative record values
|
||||
set_fact:
|
||||
record_value: "no record value"
|
||||
record_name: "no record name"
|
||||
zone_name: "no record zone name provided"
|
||||
when: item.split() | length < 2 or item.split()[1].split('.') | length < 2
|
||||
|
||||
- name: Notify about not adding entries
|
||||
debug:
|
||||
msg: |
|
||||
"{{ item }}" not added to DNS due to not being managed by us.
|
||||
Entries with domains outside of cloud_domain are skipped.
|
||||
when: not zone_name is match("^(|.+\.)" + cloud_domain + "$")
|
||||
|
||||
- name: add entries
|
||||
block:
|
||||
- name: set record type
|
||||
set_fact:
|
||||
record_type: "{{ 'A' if record_value| ansible.netcommon.ipv4 else 'AAAA' }}"
|
||||
|
||||
- name: add dns zone
|
||||
ipadnszone:
|
||||
name: "{{ zone_name }}"
|
||||
become: true
|
||||
|
||||
- name: Modify or add forward dns
|
||||
block:
|
||||
- name: try modifying forward dns record
|
||||
ipadnsrecord:
|
||||
zone_name: "{{ zone_name }}"
|
||||
record_name: "{{ record_name }}"
|
||||
record_type: "{{ record_type }}"
|
||||
a_rec: "{{ record_value }}"
|
||||
a_ip_address: ""
|
||||
when: record_type == 'A'
|
||||
become: true
|
||||
|
||||
- name: try modifying forward dns record
|
||||
ipadnsrecord:
|
||||
zone_name: "{{ zone_name }}"
|
||||
record_name: "{{ record_name }}"
|
||||
record_type: "{{ record_type }}"
|
||||
aaaa_rec: "{{ record_value }}"
|
||||
aaaa_ip_address: ""
|
||||
when: record_type == 'AAAA'
|
||||
become: true
|
||||
rescue:
|
||||
- name: add forward dns record
|
||||
ipadnsrecord:
|
||||
zone_name: "{{ zone_name }}"
|
||||
record_name: "{{ record_name }}"
|
||||
record_type: "{{ record_type }}"
|
||||
record_value: "{{ record_value }}"
|
||||
become: true
|
||||
|
||||
- name: get reverse record data
|
||||
set_fact:
|
||||
reverse_addr: "{{ record_value | ipaddr('revdns') }}"
|
||||
|
||||
- name: set reverse record entries for ipv4
|
||||
set_fact:
|
||||
reverse_record_zone: "{{ reverse_addr.split('.', tripleo_ipa_ptr_zone_split_ipv4|int)[-1] }}"
|
||||
reverse_record_name: "{{ '.'.join(reverse_addr.split('.', tripleo_ipa_ptr_zone_split_ipv4|int)[:-1]) }}"
|
||||
when: record_type == 'A'
|
||||
|
||||
- name: set reverse record entries for ipv6
|
||||
set_fact:
|
||||
reverse_record_zone: "{{ reverse_addr.split('.', tripleo_ipa_ptr_zone_split_ipv6|int)[-1] }}"
|
||||
reverse_record_name: "{{ '.'.join(reverse_addr.split('.', tripleo_ipa_ptr_zone_split_ipv6|int)[:-1]) }}"
|
||||
when: record_type == 'AAAA'
|
||||
|
||||
- name: add reverse record dns zone
|
||||
ipadnszone:
|
||||
name: "{{ reverse_record_zone }}"
|
||||
register: reverse_zone_result
|
||||
failed_when: reverse_zone_result.failed and 'already exists in DNS' not in reverse_zone_result.msg
|
||||
become: true
|
||||
|
||||
- name: Modify or add reverse dns record
|
||||
block:
|
||||
- name: try modifying reverse dns record
|
||||
ipadnsrecord:
|
||||
zone_name: "{{ reverse_record_zone }}"
|
||||
record_name: "{{ reverse_record_name }}"
|
||||
record_type: "PTR"
|
||||
ptr_rec: "{{ record_name }}.{{ zone_name }}."
|
||||
ptr_hostname: ""
|
||||
become: true
|
||||
rescue:
|
||||
- name: add reverse dns record
|
||||
ipadnsrecord:
|
||||
zone_name: "{{ reverse_record_zone }}"
|
||||
record_name: "{{ reverse_record_name }}"
|
||||
record_type: "PTR"
|
||||
record_value: "{{ record_name }}.{{ zone_name }}."
|
||||
register: reverse_record_result
|
||||
failed_when: reverse_zone_result.failed and 'already exists in DNS' not in reverse_zone_result.msg
|
||||
become: true
|
||||
when: zone_name is match("^(|.+\.)" + cloud_domain + "$")
|
@ -20,7 +20,40 @@
|
||||
# - host_entry (host entries string, in a format similar to /etc/hosts)
|
||||
|
||||
|
||||
- name: add dns records
|
||||
include_tasks:
|
||||
file: dns.yaml
|
||||
loop: "{{ hosts_entry }}"
|
||||
- name: get dns zones and entries to add
|
||||
set_fact:
|
||||
dns_zones: "{{ hosts_entry | get_dns_zones(cdomain=cloud_domain) }}"
|
||||
ips_for_reverse: "{{ hosts_entry | get_ips(cdomain=cloud_domain) }}"
|
||||
dns_entries: "{{ hosts_entry | get_dns_entries(cdomain=cloud_domain) }}"
|
||||
no_reverse_ips: []
|
||||
|
||||
- name: add dns zones
|
||||
loop: "{{ dns_zones }}"
|
||||
ipadnszone:
|
||||
name: "{{ item }}"
|
||||
become: true
|
||||
|
||||
- name: add reverse dns zones fixing errors
|
||||
include_tasks: reverse_zones.yml
|
||||
vars:
|
||||
ip: "{{ item }}"
|
||||
loop: "{{ ips_for_reverse }}"
|
||||
|
||||
- name: set create_reverse to false for elements of no_reverse_ips
|
||||
set_fact:
|
||||
u_dns_entries: "{{ u_dns_entries |d([]) + [item|combine({'create_reverse': _rev|from_yaml})] }}"
|
||||
loop: "{{ dns_entries }}"
|
||||
vars:
|
||||
_rev: |
|
||||
{% if (item.record_type == 'A') and (item.a_rec in no_reverse_ips) %}
|
||||
False
|
||||
{% elif (item.record_type == 'AAAA') and (item.aaaa_rec in no_reverse_ips) %}
|
||||
False
|
||||
{% else %}
|
||||
True
|
||||
{% endif %}
|
||||
|
||||
- name: add dns forward and reverse records
|
||||
ipadnsrecord:
|
||||
records: "{{ u_dns_entries }}"
|
||||
become: true
|
||||
|
10
tripleo_ipa/roles/tripleo_ipa_dns/tasks/reverse_zones.yml
Normal file
10
tripleo_ipa/roles/tripleo_ipa_dns/tasks/reverse_zones.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- name: block to add reverse zone
|
||||
block:
|
||||
- name: add reverse zone
|
||||
ipadnszone:
|
||||
name_from_ip: "{{ ip }}"
|
||||
become: true
|
||||
rescue:
|
||||
- name: add ip to no_reverse_ips
|
||||
set_fact:
|
||||
no_reverse_ips: "{{ no_reverse_ips + [ip] }}"
|
Loading…
x
Reference in New Issue
Block a user