Make our dynamic dns update system for compute nodes more generic.
authorWard Vandewege <ward@curoverse.com>
Sun, 16 Nov 2014 18:54:47 +0000 (13:54 -0500)
committerWard Vandewege <ward@curoverse.com>
Sun, 16 Nov 2014 18:54:47 +0000 (13:54 -0500)
refs #4461

services/api/app/models/node.rb
services/api/config/application.default.yml
services/api/config/unbound.template [new file with mode: 0644]
services/api/script/restart-dns-server [new file with mode: 0755]
services/api/script/restart-dnsmasq [deleted file]

index db39ab658d9b1ad7c3c9a2263349ea3e0cfa6869..40b78e90808e3534d8468a808fd2ef24310765a9 100644 (file)
@@ -5,7 +5,7 @@ class Node < ArvadosModel
   serialize :info, Hash
   serialize :properties, Hash
   before_validation :ensure_ping_secret
-  after_update :dnsmasq_update
+  after_update :dns_server_update
 
   # Only a controller can figure out whether or not the current API tokens
   # have access to the associated Job.  They're expected to set
@@ -15,7 +15,10 @@ class Node < ArvadosModel
 
   MAX_SLOTS = 64
 
-  @@confdir = Rails.configuration.dnsmasq_conf_dir
+  @@dns_server_conf_dir = Rails.configuration.dns_server_conf_dir
+  @@dns_server_conf_template = Rails.configuration.dns_server_conf_template
+  @@dns_server_reload_command = Rails.configuration.dns_server_reload_command
+  @@uuid_prefix = Rails.configuration.uuid_prefix
   @@domain = Rails.configuration.compute_node_domain rescue `hostname --domain`.strip
   @@nameservers = Rails.configuration.compute_node_nameservers
 
@@ -132,26 +135,44 @@ class Node < ArvadosModel
     self.info['ping_secret'] ||= rand(2**256).to_s(36)
   end
 
-  def dnsmasq_update
+  def dns_server_update
     if self.hostname_changed? or self.ip_address_changed?
       if self.hostname and self.ip_address
-        self.class.dnsmasq_update(self.hostname, self.ip_address)
+        self.class.dns_server_update(self.hostname, self.ip_address)
       end
     end
   end
 
-  def self.dnsmasq_update(hostname, ip_address)
-    return unless @@confdir
+  def self.dns_server_update(hostname, ip_address)
+    return unless @@dns_server_conf_dir and @@dns_server_conf_template
     ptr_domain = ip_address.
       split('.').reverse.join('.').concat('.in-addr.arpa')
-    hostfile = File.join @@confdir, hostname
-    File.open hostfile, 'w' do |f|
-      f.puts "address=/#{hostname}/#{ip_address}"
-      f.puts "address=/#{hostname}.#{@@domain}/#{ip_address}" if @@domain
-      f.puts "ptr-record=#{ptr_domain},#{hostname}"
+    hostfile = File.join @@dns_server_conf_dir, "#{hostname}.conf"
+
+    begin
+      template = IO.read(@@dns_server_conf_template)
+    rescue => e
+      STDERR.puts "Unable to read dns_server_conf_template #{@@dns_server_conf_template}: #{e.message}"
+      return
+    end
+
+    populated = template % {hostname:hostname, uuid_prefix:@@uuid_prefix, ip_address:ip_address, ptr_domain:ptr_domain}
+
+    begin
+      File.open hostfile, 'w' do |f|
+        f.puts populated
+      end
+    rescue => e
+      STDERR.puts "Unable to write #{hostfile}: #{e.message}"
+      return
     end
-    File.open(File.join(@@confdir, 'restart.txt'), 'w') do |f|
-      # this should trigger a dnsmasq restart
+    #  f.puts "address=/#{hostname}/#{ip_address}"
+    #  f.puts "address=/#{hostname}.#{@@domain}/#{ip_address}" if @@domain
+    #  f.puts "ptr-record=#{ptr_domain},#{hostname}"
+    #end
+    File.open(File.join(@@dns_server_conf_dir, 'restart.txt'), 'w') do |f|
+      # this will trigger a dns server restart
+      f.puts @@dns_server_reload_command
     end
   end
 
@@ -161,13 +182,13 @@ class Node < ArvadosModel
 
   # At startup, make sure all DNS entries exist.  Otherwise, slurmctld
   # will refuse to start.
-  if @@confdir and
-      !File.exists? (File.join(@@confdir, hostname_for_slot(MAX_SLOTS-1)))
+  if @@dns_server_conf_dir and @@dns_server_conf_template and
+      !File.exists? (File.join(@@dns_server_conf_dir, hostname_for_slot(MAX_SLOTS-1)))
     (0..MAX_SLOTS-1).each do |slot_number|
       hostname = hostname_for_slot(slot_number)
-      hostfile = File.join @@confdir, hostname
+      hostfile = File.join @@dns_server_conf_dir, hostname
       if !File.exists? hostfile
-        dnsmasq_update(hostname, '127.40.4.0')
+        dns_server_update(hostname, '127.40.4.0')
       end
     end
   end
index be1f157eb048923ad533e3f54c4ad03841c0417d..1da510222299c458d58522f302094afaf88c908f 100644 (file)
@@ -100,8 +100,21 @@ common:
   # silenced by throttling are not counted against this total.
   crunch_limit_log_bytes_per_job: 67108864
 
-  # Path to /etc/dnsmasq.d, or false = do not update dnsmasq data.
-  dnsmasq_conf_dir: false
+  # Path to dns server configuration directory (e.g. /etc/unbound.d/conf.d), 
+  # or false = do not update dns server data.
+  dns_server_conf_dir: false
+
+  # Template for the dns server host snippets. See unbound.template in this directory for
+  # an example. Set to false to disable.
+  dns_server_conf_template: false
+
+  # Dns server reload command, or false = do not reload dns server after data change
+  dns_server_reload_command: false
+
+  # Example for unbound
+  #dns_server_conf_dir: /etc/unbound/conf.d
+  #dns_server_conf_template: /path/to/your/api/server/config/unbound.template
+  #dns_server_reload_command: /etc/init.d/unbound reload
 
   compute_node_domain: false
   compute_node_nameservers:
diff --git a/services/api/config/unbound.template b/services/api/config/unbound.template
new file mode 100644 (file)
index 0000000..0c67700
--- /dev/null
@@ -0,0 +1,4 @@
+  local-data: "%{hostname} IN A %{ip_address}"
+  local-data: "%{hostname}.%{uuid_prefix} IN A %{ip_address}"
+  local-data: "%{hostname}.%{uuid_prefix}.arvadosapi.com. IN A %{ip_address}"
+  local-data: "%{ptr_domain}. IN PTR %{hostname}.%{uuid_prefix}.arvadosapi.com"
diff --git a/services/api/script/restart-dns-server b/services/api/script/restart-dns-server
new file mode 100755 (executable)
index 0000000..061856c
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+# usage:
+# "restart-dns-server <path-to-restart.txt>" (restart now if needed)
+# or
+# "restart-dns-server <path-to-restart.txt> -d" (wait for restart to be needed, restart, repeat)
+
+RESTART_TXT_PATH=$1
+
+if [[ "$RESTART_TXT_PATH" == "" ]]; then
+  echo
+  echo "Usage: "
+  echo "   $0 <path-to-restart.txt>      # restart now if needed"
+  echo "   $0 <path-to-restart.txt> -d   # wait for restart to be needed, restart, repeat"
+  echo
+  exit 1
+fi
+
+while :
+do
+  if [ -e $RESTART_TXT_PATH ]; then
+    RESTART_COMMAND=`cat $RESTART_TXT_PATH`
+    echo "restart command: $RESTART_COMMAND"
+    rm -f "$RESTART_TXT_PATH"
+    echo restarting
+    $RESTART_COMMAND
+  fi
+  if [ "-d" = "$2" ]
+  then
+    sleep 2
+  else
+    exit 0
+  fi
+done
diff --git a/services/api/script/restart-dnsmasq b/services/api/script/restart-dnsmasq
deleted file mode 100755 (executable)
index d0443a5..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-# usage:
-# "restart-dnsmasq" (restart now if needed)
-# or
-# "restart-dnsmasq -d" (wait for restart to be needed, restart, repeat)
-
-while :
-do
-  if [ -e /etc/dnsmasq.d/restart.txt ] && rm /etc/dnsmasq.d/restart.txt
-  then
-    echo restarting
-    /etc/init.d/dnsmasq restart
-  fi
-  if [ "-d" = "$1" ]
-  then
-    sleep 2
-  else
-    exit
-  fi
-done