Practically rewrite dnshook
authorDimitris Aragiorgis <dimara@grnet.gr>
Sat, 7 Dec 2013 13:22:07 +0000 (15:22 +0200)
committerDimitris Aragiorgis <dimara@grnet.gr>
Sat, 7 Dec 2013 14:42:49 +0000 (16:42 +0200)
Make it more readable.

Introduce specific methods for getting reverse dns info of an IPv4
or eui64.

Parse every nic info and check for DNS_FLAG network flag

Do not explicitly pass zone statement to nsupdate. Let it determine
the correct zone to update based on the rest of the input.

Signed-off-by: Dimitris Aragiorgis <dimara@grnet.gr>

dnshook
fix-net

diff --git a/dnshook b/dnshook
index 2c71124..4500df7 100755 (executable)
--- a/dnshook
+++ b/dnshook
@@ -1,18 +1,23 @@
-#!/bin/sh
+#!/bin/bash
 
 set -e
 
-# Configuration Fallbacks. All can(must for some of them) be overwritten by /etc/ganeti/dnshook.conf
+# Configuration Fallbacks. All can(must for some of them) be overwritten by /etc/default/snf-network
 TTL=300
+# the bind server IP/FQDN
 SERVER=""
-FZONE="" # Leave empty if only reverse dns management is needed. Don't forget the trailing dot
+# this is the .vm.synnefo.live.
+# Leave empty if only reverse dns management is needed.
+# TODO: make this zone to be instance specific!!!
+FZONE=""
+# the file with dns authorization keys
 KEYFILE=""
 MAC2EUI64="/usr/bin/mac2eui64"
 
-if [ -e /etc/ganeti/dnshook.conf ]; then
-       . /etc/ganeti/dnshook.conf 
-else
-       exit 0
+source /etc/default/snf-network
+
+if [ -z "$SERVER" -o -z "$FZONE" -o -z "$KEYFILE" ]; then
+  exit 0
 fi
 
 update () {
@@ -26,63 +31,229 @@ update () {
 EOF
 }
 
-addremove () {
-       local action=$1
-       local REVZONE=$2
-       local REV6ZONE=$3
-       local REVLPART=$4
-       local REV6LPART=$5
-
-       update $REVZONE "update $action $REVLPART.$REVZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
-       update $REV6ZONE "update $action $REV6LPART$REV6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
-
-       if [ ! -z "$7" ]; then
-               EUI64=$6
-               FORZONE=$7
-               update $FORZONE "update $action $GANETI_INSTANCE_NAME.$FORZONE $TTL A $GANETI_INSTANCE_NIC0_IP"
-               update $FORZONE "update $action $GANETI_INSTANCE_NAME.$FORZONE $TTL AAAA $EUI64" 
-       fi
+
+# ommit zone statement
+# nsupdate  will attempt determine the correct zone to update based on the rest of the input
+send_command () {
+
+       local command="$1"
+       nsupdate -k $KEYFILE > /dev/null << EOF
+       server $SERVER
+       $command
+       send
+EOF
+
 }
 
+
+addremove_arecord () {
+
+  local action=$1
+  local command=
+  if [ -n "$IP" ]; then
+    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL A $IP"
+    send_command "$command"
+  fi
+  if [ -n "$EUI64" ]; then
+    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL AAAA $EUI64"
+    send_command "$command"
+  fi
+
+}
+
+addremove_ptrrecord () {
+
+  local action=$1
+  local command=
+  if [ -n "$IP" ]; then
+         command="update $action $RLPART.$RZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
+    send_command "$command"
+  fi
+  if [ -n "$EUI64" ]; then
+         command="update $action $R6LPART.$R6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
+    send_command "$command"
+  fi
+
+}
+
+
+# first argument is an eui64 (IPv6)
+# sets GLOBAL args R6REC, R6ZONE, R6LPART
+# lets assume eui64=eui64=2001:648:2ffc:1::1
+# the following commands produce:
+# R6REC=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
+# R6ZONE=1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
+# R6LPART=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
+get_rev6_info () {
+
+  local eui64=$1
+  if [ -z "$eui64" ]; then
+    R6REC= ; R6ZONE= ; R6LPART= ;
+  else
+    R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
+    R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
+    R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
+  fi
+
+}
+
+
+# first argument is an ipv4
+# sets args RZONE, RLPART
+# lets assume IP=203.0.113.1
+# RZONE="113.0.203.in-add.arpa"
+# RLPART="1"
+get_rev4_info () {
+
+  local ip=$1
+  if [ -z "$ip" ]; then
+    RZONE= ; RLPART= ;
+  else
+    OLDIFS=$IFS
+    IFS=". "
+    set -- $ip
+    a=$1 ; b=$2; c=$3; d=$4;
+    IFS=$OLDIFS
+    RZONE="$c.$b.$a.in-addr.arpa"
+    RLPART="$d"
+  fi
+
+}
+
+
+update_dns () {
+
+  if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_CREATE" ]; then
+    update_arecord add
+    update_ptrrecord add
+  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REMOVE" ]; then
+    update_arecord delete
+    update_ptrrecord delete
+  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_RENAME" ]; then
+    update_arecord delete
+    update_ptrrecord delete
+    # Let's override a variable and add ourselves
+    GANETI_INSTANCE_NAME=$GANETI_INSTANCE_NEW_NAME
+    update_arecord add
+    update_ptrrecord add
+  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_STARTUP" ]; then
+    update_arecord add
+    update_ptrrecord add
+  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SHUTDOWN" ]; then
+    update_arecord delete
+    update_ptrrecord delete
+  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REBOOT" ]; then
+    update_arecord add
+    update_ptrrecord add
+  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SET_PARAMS" ]; then
+    update_arecord add
+    update_ptrrecord add
+  fi
+
+}
+
+
+# Query nameserver for entries related to the specific instance
+# An example output is the following:
+# www.google.com has address 173.194.113.114
+# www.google.com has address 173.194.113.115
+# www.google.com has address 173.194.113.116
+# www.google.com has address 173.194.113.112
+# www.google.com has address 173.194.113.113
+# www.google.com has IPv6 address 2a00:1450:4001:80b::1012
+query_dns () {
+
+  HOSTQ="host -s -R 3 -W 3"
+  HOST_IP_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has address //p')
+  HOST_IP6_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has IPv6 address //p')
+
+}
+
+
+# Reset all entries related to the specific instance
+# This should be invoced only during instance modification
+# because we do not know which nics have been modify
+reset_dns () {
+
+  if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SET_PARAMS" ]; then
+    query_dns
+    # This should remove the A, AAAA, CNAME entries
+    run_action "update delete $GANETI_INSTANCE_NAME.$FZONE"
+    for ip in $HOST_IP_ALL; do
+      get_rev4_info $ip
+      # This should remove the IPv4 reverse entry
+      run_action "update delete $RLPART.$RZONE"
+    done
+    for ip6 in $HOST_IP6_ALL; do
+      get_rev6_info $ip6
+      # This should remove the IPv6 reverse entry
+      run_action "update delete $R6LPART$R6ZONE."
+    done
+  fi
+
+}
+
+
+# Because we do not have IPv6 value in our environment
+# we caclulate it based on the NIC's MAC and the IPv6 subnet (if any)
+# first argument MAC second IPv6 subnet
+# Changes global value EUI64
+get_eui64 () {
+
+  local mac=$1
+  local prefix=$2
+
+  if [ -z "$prefix" ]; then
+    EUI64=
+  else
+    EUI64=$($MAC2EUI64 $MAC $SUBNET6)
+  fi
+
+}
+
+
 # Main starts here
-if [ "x" = "x$GANETI_INSTANCE_NIC0_IP" ]; then
-       exit 1
-else
-       OLDIFS=$IFS
-       IFS=". "
-       set -- $GANETI_INSTANCE_NIC0_IP
-       a=$1 ; b=$2; c=$3; d=$4;
-       IFS=$OLDIFS
-       RZONE="$c.$b.$a.in-addr.arpa"
-       RLPART="$d"
-
-       # NOTE: We are going to assume one simple thing. /64s ...
-       # A mistake but good enough for alpha and autoconfiguration
-       prefix=$(ip -6 route list table $GANETI_INSTANCE_NIC0_LINK | awk '/\/64/ {print $1; exit}')
-       eui64=$($MAC2EUI64 $GANETI_INSTANCE_NIC0_MAC $prefix)
-       R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
-       R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
-       R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
-fi
 
-if [ "x" = "x$GANETI_INSTANCE_NAME" ]; then
-       exit 1
+# Exit if we do not have instance name.
+# It should be exported to hooks for instance related opcodes.
+if [ -z "$GANETI_INSTNACE_NAME" ]; then
+  exit 0
 fi
 
-if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_CREATE" ]; then
-       addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REMOVE" ]; then
-       addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_RENAME" ]; then
-       addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-       # Let's override a variable and add ourselves
-       GANETI_INSTANCE_NAME=$GANETI_INSTANCE_NEW_NAME
-       addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_STARTUP" ]; then
-       addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SHUTDOWN" ]; then
-       addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REBOOT" ]; then
-       addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-       addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
-fi
+# This runs only for instance modification
+reset_dns
+
+# If GANETI_INSTANCE_NIC_COUNT is not set then nothing happens
+FIRST=0
+LAST=$((GANETI_INSTANCE_NIC_COUNT - 1))
+for idx in $(seq $FIRST $LAST); do
+  ip=GANETI_INSTANCE_NIC${idx}_IP
+  mac=GANETI_INSTANCE_NIC${idx}_MAC
+  mode=GANETI_INSTANCE_NIC${idx}_MODE
+  link=GANETI_INSTANCE_NIC${idx}_LINK
+  subnet=GANETI_INSTANCE_NIC${idx}_NETWORK_SUBNET
+  subnet6=GANETI_INSTANCE_NIC${idx}_NETWORK_SUBNET6
+  tags=GANETI_INSTANCE_NIC${idx}_NETWORK_TAGS
+  eval IP=\$$ip
+  eval MAC=\$$mac
+  eval MODE=\$$mode
+  eval LINK=\$$link
+  eval SUBNET=\$$subnet
+  eval SUBNET6=\$$subnet6
+  eval TAGS=\$$tags
+
+  for tag in $TAGS; do
+    case $tag in
+    $DNS_TAG)
+
+      get_rev4_info "$IP"
+      get_eui64 "$MAC" "$SUBNET6"
+      get_rev6_info "$EUI64"
+      update_dns
+
+      ;;
+    esac
+
+  done
+
+done
diff --git a/fix-net b/fix-net
index b59abdb..d12f67a 100755 (executable)
--- a/fix-net
+++ b/fix-net
@@ -14,7 +14,7 @@ for idx in $(seq $FIRST $LAST); do
   mac=GANETI_INSTANCE_NIC${idx}_MAC
   mode=GANETI_INSTANCE_NIC${idx}_MODE
   link=GANETI_INSTANCE_NIC${idx}_LINK
-  network=GANETI_INSTANCE_NIC${idx}_NETWORK
+  network=GANETI_INSTANCE_NIC${idx}_NETWORK_SUBNET
   subnet6=GANETI_INSTANCE_NIC${idx}_NETWORK_SUBNET6
   tags=GANETI_INSTANCE_NIC${idx}_NETWORK_TAGS
   eval IP=\$$ip