Statistics
| Branch: | Tag: | Revision:

root / dnshook @ 1bdc9427

History | View | Annotate | Download (6 kB)

1
#!/bin/bash
2

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

    
15
source /etc/default/snf-network
16
source /usr/lib/snf-network/common.sh
17

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

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

    
33

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

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

    
46
}
47

    
48

    
49
update_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

    
58
}
59

    
60

    
61
update_aaaarecord () {
62

    
63
  local action=$1
64
  local command=
65
  if [ -n "$EUI64" ]; then
66
    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL AAAA $EUI64"
67
    send_command "$command"
68
  fi
69

    
70
}
71

    
72

    
73
update_ptrrecord () {
74

    
75
  local action=$1
76
  local command=
77
  if [ -n "$IP" ]; then
78
    command="update $action $RLPART.$RZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
79
    send_command "$command"
80
  fi
81

    
82
}
83

    
84
update_ptr6record () {
85

    
86
  local action=$1
87
  local command=
88
  if [ -n "$EUI64" ]; then
89
    command="update $action $R6LPART$R6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
90
    send_command "$command"
91
  fi
92

    
93
}
94

    
95
update_all () {
96

    
97
  local action=$1
98
  update_arecord $action
99
  update_aaaarecord $action
100
  update_ptrrecord $action
101
  update_ptr6record $action
102

    
103
}
104

    
105

    
106
# first argument is an eui64 (IPv6)
107
# sets GLOBAL args R6REC, R6ZONE, R6LPART
108
# lets assume eui64=2001:648:2ffc:1::1
109
# the following commands produce:
110
# 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
111
# R6ZONE=1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
112
# R6LPART=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
113
get_rev6_info () {
114

    
115
  local eui64=$1
116
  if [ -z "$eui64" ]; then
117
    R6REC= ; R6ZONE= ; R6LPART= ;
118
  else
119
    R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
120
    R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
121
    R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
122
  fi
123

    
124
}
125

    
126

    
127
# first argument is an ipv4
128
# sets args RZONE, RLPART
129
# lets assume IP=203.0.113.1
130
# RZONE="113.0.203.in-add.arpa"
131
# RLPART="1"
132
get_rev4_info () {
133

    
134
  local ip=$1
135
  if [ -z "$ip" ]; then
136
    RZONE= ; RLPART= ;
137
  else
138
    OLDIFS=$IFS
139
    IFS=". "
140
    set -- $ip
141
    a=$1 ; b=$2; c=$3; d=$4;
142
    IFS=$OLDIFS
143
    RZONE="$c.$b.$a.in-addr.arpa"
144
    RLPART="$d"
145
  fi
146

    
147
}
148

    
149

    
150
update_dns () {
151

    
152
  if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_CREATE" ]; then
153
    update_all add
154
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REMOVE" ]; then
155
    update_all delete
156
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_RENAME" ]; then
157
    update_all delete
158
    # Let's override a variable and add ourselves
159
    GANETI_INSTANCE_NAME=$GANETI_INSTANCE_NEW_NAME
160
    update_all add
161
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_STARTUP" ]; then
162
    update_all add
163
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SHUTDOWN" ]; then
164
    update_all delete
165
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REBOOT" ]; then
166
    update_all add
167
  elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SET_PARAMS" ]; then
168
    update_all add
169
  fi
170

    
171
}
172

    
173

    
174
# Query nameserver for entries related to the specific instance
175
# An example output is the following:
176
# www.google.com has address 173.194.113.114
177
# www.google.com has address 173.194.113.115
178
# www.google.com has address 173.194.113.116
179
# www.google.com has address 173.194.113.112
180
# www.google.com has address 173.194.113.113
181
# www.google.com has IPv6 address 2a00:1450:4001:80b::1012
182
query_dns () {
183

    
184
  HOSTQ="host -s -R 3 -W 3"
185
  HOST_IP_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has address //p')
186
  HOST_IP6_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has IPv6 address //p')
187

    
188
}
189

    
190

    
191
# Reset all entries related to the specific instance
192
# This should be invoced only during instance modification
193
# because we do not know which nics have been modify
194
reset_dns () {
195

    
196
  if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SET_PARAMS" ]; then
197
    query_dns
198
    # This should remove the A, AAAA, CNAME entries
199
    send_command "update delete $GANETI_INSTANCE_NAME.$FZONE"
200
    for ip in $HOST_IP_ALL; do
201
      get_rev4_info $ip
202
      # This should remove the IPv4 reverse entry
203
      send_command "update delete $RLPART.$RZONE"
204
    done
205
    for ip6 in $HOST_IP6_ALL; do
206
      get_rev6_info $ip6
207
      # This should remove the IPv6 reverse entry
208
      send_command "update delete $R6LPART$R6ZONE."
209
    done
210
  fi
211

    
212
}
213

    
214

    
215
# Main starts here
216

    
217

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

    
224
# This runs only for instance modification
225
reset_dns
226

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

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

    
250
      get_rev4_info "$IP"
251
      get_eui64 "$MAC" "$SUBNET6"
252
      get_rev6_info "$EUI64"
253
      hooks-log dnshook "update dns for $GANETI_INSTANCE_NAME $IP $EUI64"
254
      update_dns
255

    
256
      ;;
257
    esac
258

    
259
  done
260

    
261
done