]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-cm-ansible.git/commitdiff
nameserver: Let records tasks coexist with DDNS 375/head
authorDavid Galloway <dgallowa@redhat.com>
Thu, 1 Feb 2018 20:42:36 +0000 (15:42 -0500)
committerDavid Galloway <dgallowa@redhat.com>
Thu, 1 Feb 2018 20:48:21 +0000 (15:48 -0500)
It takes about 3 minutes for ansible to compile all the zone files.
That was causing nsupdate/DDNS to overwrite any new records we wanted to
add or change before named could be reloaded.

This PR:
  - Writes zone files to a temporary location
  - Dumps pending DDNS changes into zone files
  - Freezes DDNS zone files from updates
  - Moves temporary zone files into place all at once
  - Unfreezes DDNS zone files

This results in about a 3 second window where DDNS updates will be
refused which isn't great but we can at least update records while OVH
jobs are running now.

Signed-off-by: David Galloway <dgallowa@redhat.com>
roles/nameserver/tasks/records.yml

index de154c567b4c1bb9a321fb29cce7e0bcce73b0b4..948dfab2bd1bb934241fe9cec5ed36e88ada8f99 100644 (file)
   notify: reload named
   when: item.value.dynamic == true
 
-# This makes sure dynamic DNS records in the journal files are in sync with the
-# actual zone files so we can store them in the next step.
-- name: Sync Dynamic DNS journals with zone files
-  command: "rndc sync -clean {{ item.key }}"
-  with_dict: "{{ named_domains }}"
-  when: item.value.dynamic == true and
-        item.value.ddns_hostname_prefixes is defined
-  # Don't fail if there is no journal file
-  failed_when: false
-
-- name: Create temporary directory for dynamic A records
+# We store new zone files in a temp directory because it takes ansible minutes
+# to write all the files.  If we prevented DDNS updates while they were
+# getting written, there's a good chance some updates would get refused.
+# We copy these to named_conf_zones_path at the end.
+- name: Create temporary directory for zone files
   command: "mktemp -d"
   register: named_tempdir
 
-# We need to store existing DNS records in a temp file so we can spit
-# them back out into the zone file after static records are written.
-# Given hostname prefix(es) to expect, this task greps for those records
-# and stores them in a temporary file named after the domain.
-- name: Store existing dynamic A records
-  shell: "grep -E '^({% for prefix in item.value.ddns_hostname_prefixes %}{{ prefix }}{% if not loop.last %}|{% endif %}{% endfor %})[0-9]+\\s+A' {{ named_conf_zones_path }}/{{ item.key }} > {{ named_tempdir.stdout }}/{{ item.key }}"
-  with_dict: "{{ named_domains }}"
-  when: item.value.dynamic == true and
-        item.value.ddns_hostname_prefixes is defined
-  # Don't fail if there are no records to store
-  failed_when: false
-
-- name: Write forward zone files
+- name: Write forward zone files to tempdir
   template:
     src: forward.j2
-    dest: "{{ named_conf_zones_path }}/{{ item.key }}"
+    dest: "{{ named_tempdir.stdout }}/{{ item.key }}"
     validate: named-checkzone {{ item.key }} %s
   with_dict: "{{ named_domains }}"
   notify: reload named
   when: (item.value.dynamic != true) or
         (item.value.dynamic == true and item.value.ddns_hostname_prefixes is defined)
 
-- name: Write reverse zone files
+- name: Write reverse zone files to tempdir
   template:
     src: reverse.j2
-    dest: "{{ named_conf_zones_path }}/{{ item.1 }}"
+    dest: "{{ named_tempdir.stdout }}/{{ item.1 }}"
     validate: named-checkzone {{ item.1 }} %s
   with_subelements:
     - "{{ named_domains }}"
       skip_missing: True
   notify: reload named
 
-- name: Restore dynamic A records from temp file(s)
-  shell: "cat {{ named_tempdir.stdout }}/{{ item.key }} >> {{ named_conf_zones_path }}/{{ item.key }}"
+# This makes sure dynamic DNS records in the journal files are in sync with the
+# actual zone files so we can store them in the next 2 steps.
+- name: Sync Dynamic DNS journals with zone files
+  command: "rndc sync -clean {{ item.key }}"
   with_dict: "{{ named_domains }}"
   when: item.value.dynamic == true and
         item.value.ddns_hostname_prefixes is defined
-  # Don't fail if there are no records to restore
+  # Don't fail if there is no journal file
   failed_when: false
 
-# This gets rid of any cached dynamic records that we didn't just restore
-- name: Freeze, reload, thaw dynamic zone files
-  shell: "rndc freeze; rndc reload; rndc thaw"
+# Prevents dynamic DNS record updates so we can capture current DDNS records
+# and move our new zone files into place without them getting overwritten.
+- name: Freeze Dynamic DNS zones to prevent updates
+  command: "rndc freeze {{ item.key }}"
+  with_dict: "{{ named_domains }}"
+  when: item.value.dynamic == true and
+        item.value.ddns_hostname_prefixes is defined
+
+- name: Spit existing dynamic A records into new/temp forward zone file
+  shell: "grep -E '^({% for prefix in item.value.ddns_hostname_prefixes %}{{ prefix }}{% if not loop.last %}|{% endif %}{% endfor %})[0-9]+\\s+A' {{ named_conf_zones_path }}/{{ item.key }} >> {{ named_tempdir.stdout }}/{{ item.key }}"
+  with_dict: "{{ named_domains }}"
+  when: item.value.dynamic == true and
+        item.value.ddns_hostname_prefixes is defined
+  # Don't fail if there are no records to store
+  failed_when: false
+
+- name: Move all new/temp zone files to actual zone file dir
+  shell: "mv -vf {{ named_tempdir.stdout }}/* {{ named_conf_zones_path }}/"
+
+# Re-run setup module to update ansible_date_time.epoch
+- name:
+  setup:
+
+- name: Set new_named_serial variable
+  set_fact:
+    new_named_serial: "{{ ansible_date_time.epoch }}"
+
+# Since ansible takes a while to write the new/temp zone files, it is likely
+# a DDNS record update incremented the serial so the original named_serial is
+# too old.  We replace it here to be safe.
+- name: Overwrite zone file serial number
+  shell: "sed -i 's/{{ named_serial }}/{{ new_named_serial }}/g' {{ named_conf_zones_path }}/*"
+
+# Context is incorrect due to the files being written to a temp directory first
+- name: Restore SELinux context on zone files
+  command: "restorecon -r {{ named_conf_zones_path }}"
+
+# This re-enables dynamic DNS record updates
+- name: Thaw frozen zone files
+  shell: "rndc thaw {{ item.key }}"
+  with_dict: "{{ named_domains }}"
+  when: item.value.dynamic == true and
+        item.value.ddns_hostname_prefixes is defined
 
-- name: Clean up dynamic A records temp dir
+- name: Clean up temp dir
   file:
     path: "{{ named_tempdir.stdout }}"
     state: absent