Statistics
| Branch: | Tag: | Revision:

root / dnshook @ ad5c908a

History | View | Annotate | Download (6.2 kB)

1
#!/bin/bash
2

    
3
set -e
4

    
5
# Configuration Fallbacks. All can(must for some of them) be overwritten by /etc/default/snf-network
6
TTL=300
7
# the bind server IP/FQDN
8
SERVER=""
9
# this is the .vm.synnefo.live.
10
# Leave empty if only reverse dns management is needed.
11
# TODO: make this zone to be instance specific!!!
12
FZONE=""
13
# the file with dns authorization keys
14
KEYFILE=""
15
MAC2EUI64="/usr/bin/mac2eui64"
16

    
17
source /etc/default/snf-network
18

    
19
if [ -z "$SERVER" -o -z "$FZONE" -o -z "$KEYFILE" ]; then
20
  exit 0
21
fi
22

    
23
update () {
24
	local ZONE=$1
25
	local action="$2"
26
	nsupdate -k $KEYFILE > /dev/null << EOF
27
	server $SERVER
28
	zone $ZONE
29
	$action
30
	send
31
EOF
32
}
33

    
34

    
35
# ommit zone statement
36
# nsupdate  will attempt determine the correct zone to update based on the rest of the input
37
send_command () {
38

    
39
	local command="$1"
40
	nsupdate -k $KEYFILE > /dev/null << EOF
41
	server $SERVER
42
	$command
43
	send
44
EOF
45

    
46
}
47

    
48

    
49
addremove_arecord () {
50

    
51
  local action=$1
52
  local command=
53
  if [ -n "$IP" ]; then
54
    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL A $IP"
55
    send_command "$command"
56
  fi
57
  if [ -n "$EUI64" ]; then
58
    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL AAAA $EUI64"
59
    send_command "$command"
60
  fi
61

    
62
}
63

    
64
addremove_ptrrecord () {
65

    
66
  local action=$1
67
  local command=
68
  if [ -n "$IP" ]; then
69
	  command="update $action $RLPART.$RZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
70
    send_command "$command"
71
  fi
72
  if [ -n "$EUI64" ]; then
73
	  command="update $action $R6LPART.$R6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
74
    send_command "$command"
75
  fi
76

    
77
}
78

    
79

    
80
# first argument is an eui64 (IPv6)
81
# sets GLOBAL args R6REC, R6ZONE, R6LPART
82
# lets assume eui64=eui64=2001:648:2ffc:1::1
83
# the following commands produce:
84
# 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
85
# R6ZONE=1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
86
# R6LPART=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
87
get_rev6_info () {
88

    
89
  local eui64=$1
90
  if [ -z "$eui64" ]; then
91
    R6REC= ; R6ZONE= ; R6LPART= ;
92
  else
93
    R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
94
    R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
95
    R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
96
  fi
97

    
98
}
99

    
100

    
101
# first argument is an ipv4
102
# sets args RZONE, RLPART
103
# lets assume IP=203.0.113.1
104
# RZONE="113.0.203.in-add.arpa"
105
# RLPART="1"
106
get_rev4_info () {
107

    
108
  local ip=$1
109
  if [ -z "$ip" ]; then
110
    RZONE= ; RLPART= ;
111
  else
112
    OLDIFS=$IFS
113
    IFS=". "
114
    set -- $ip
115
    a=$1 ; b=$2; c=$3; d=$4;
116
    IFS=$OLDIFS
117
    RZONE="$c.$b.$a.in-addr.arpa"
118
    RLPART="$d"
119
  fi
120

    
121
}
122

    
123

    
124
update_dns () {
125

    
126
  if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_CREATE" ]; then
127
    update_arecord add
128
    update_ptrrecord add
129
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REMOVE" ]; then
130
    update_arecord delete
131
    update_ptrrecord delete
132
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_RENAME" ]; then
133
    update_arecord delete
134
    update_ptrrecord delete
135
    # Let's override a variable and add ourselves
136
    GANETI_INSTANCE_NAME=$GANETI_INSTANCE_NEW_NAME
137
    update_arecord add
138
    update_ptrrecord add
139
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_STARTUP" ]; then
140
    update_arecord add
141
    update_ptrrecord add
142
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SHUTDOWN" ]; then
143
    update_arecord delete
144
    update_ptrrecord delete
145
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REBOOT" ]; then
146
    update_arecord add
147
    update_ptrrecord add
148
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SET_PARAMS" ]; then
149
    update_arecord add
150
    update_ptrrecord add
151
  fi
152

    
153
}
154

    
155

    
156
# Query nameserver for entries related to the specific instance
157
# An example output is the following:
158
# www.google.com has address 173.194.113.114
159
# www.google.com has address 173.194.113.115
160
# www.google.com has address 173.194.113.116
161
# www.google.com has address 173.194.113.112
162
# www.google.com has address 173.194.113.113
163
# www.google.com has IPv6 address 2a00:1450:4001:80b::1012
164
query_dns () {
165

    
166
  HOSTQ="host -s -R 3 -W 3"
167
  HOST_IP_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has address //p')
168
  HOST_IP6_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has IPv6 address //p')
169

    
170
}
171

    
172

    
173
# Reset all entries related to the specific instance
174
# This should be invoced only during instance modification
175
# because we do not know which nics have been modify
176
reset_dns () {
177

    
178
  if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SET_PARAMS" ]; then
179
    query_dns
180
    # This should remove the A, AAAA, CNAME entries
181
    run_action "update delete $GANETI_INSTANCE_NAME.$FZONE"
182
    for ip in $HOST_IP_ALL; do
183
      get_rev4_info $ip
184
      # This should remove the IPv4 reverse entry
185
      run_action "update delete $RLPART.$RZONE"
186
    done
187
    for ip6 in $HOST_IP6_ALL; do
188
      get_rev6_info $ip6
189
      # This should remove the IPv6 reverse entry
190
      run_action "update delete $R6LPART$R6ZONE."
191
    done
192
  fi
193

    
194
}
195

    
196

    
197
# Because we do not have IPv6 value in our environment
198
# we caclulate it based on the NIC's MAC and the IPv6 subnet (if any)
199
# first argument MAC second IPv6 subnet
200
# Changes global value EUI64
201
get_eui64 () {
202

    
203
  local mac=$1
204
  local prefix=$2
205

    
206
  if [ -z "$prefix" ]; then
207
    EUI64=
208
  else
209
    EUI64=$($MAC2EUI64 $MAC $SUBNET6)
210
  fi
211

    
212
}
213

    
214

    
215
# Main starts here
216

    
217
# Exit if we do not have instance name.
218
# It should be exported to hooks for instance related opcodes.
219
if [ -z "$GANETI_INSTNACE_NAME" ]; then
220
  exit 0
221
fi
222

    
223
# This runs only for instance modification
224
reset_dns
225

    
226
# If GANETI_INSTANCE_NIC_COUNT is not set then nothing happens
227
FIRST=0
228
LAST=$((GANETI_INSTANCE_NIC_COUNT - 1))
229
for idx in $(seq $FIRST $LAST); do
230
  ip=GANETI_INSTANCE_NIC${idx}_IP
231
  mac=GANETI_INSTANCE_NIC${idx}_MAC
232
  mode=GANETI_INSTANCE_NIC${idx}_MODE
233
  link=GANETI_INSTANCE_NIC${idx}_LINK
234
  subnet=GANETI_INSTANCE_NIC${idx}_NETWORK_SUBNET
235
  subnet6=GANETI_INSTANCE_NIC${idx}_NETWORK_SUBNET6
236
  tags=GANETI_INSTANCE_NIC${idx}_NETWORK_TAGS
237
  eval IP=\$$ip
238
  eval MAC=\$$mac
239
  eval MODE=\$$mode
240
  eval LINK=\$$link
241
  eval SUBNET=\$$subnet
242
  eval SUBNET6=\$$subnet6
243
  eval TAGS=\$$tags
244

    
245
  for tag in $TAGS; do
246
    case $tag in
247
    $DNS_TAG)
248

    
249
      get_rev4_info "$IP"
250
      get_eui64 "$MAC" "$SUBNET6"
251
      get_rev6_info "$EUI64"
252
      update_dns
253

    
254
      ;;
255
    esac
256

    
257
  done
258

    
259
done