1 |
|
#!/bin/sh
|
|
1 |
#!/bin/bash
|
2 |
2 |
|
3 |
3 |
set -e
|
4 |
4 |
|
5 |
|
# Configuration Fallbacks. All can(must for some of them) be overwritten by /etc/ganeti/dnshook.conf
|
|
5 |
# Configuration Fallbacks. All can(must for some of them) be overwritten by /etc/default/snf-network
|
6 |
6 |
TTL=300
|
|
7 |
# the bind server IP/FQDN
|
7 |
8 |
SERVER=""
|
8 |
|
FZONE="" # Leave empty if only reverse dns management is needed. Don't forget the trailing dot
|
|
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
|
9 |
14 |
KEYFILE=""
|
10 |
15 |
MAC2EUI64="/usr/bin/mac2eui64"
|
11 |
16 |
|
12 |
|
if [ -e /etc/ganeti/dnshook.conf ]; then
|
13 |
|
. /etc/ganeti/dnshook.conf
|
14 |
|
else
|
15 |
|
exit 0
|
|
17 |
source /etc/default/snf-network
|
|
18 |
|
|
19 |
if [ -z "$SERVER" -o -z "$FZONE" -o -z "$KEYFILE" ]; then
|
|
20 |
exit 0
|
16 |
21 |
fi
|
17 |
22 |
|
18 |
23 |
update () {
|
... | ... | |
26 |
31 |
EOF
|
27 |
32 |
}
|
28 |
33 |
|
29 |
|
addremove () {
|
30 |
|
local action=$1
|
31 |
|
local REVZONE=$2
|
32 |
|
local REV6ZONE=$3
|
33 |
|
local REVLPART=$4
|
34 |
|
local REV6LPART=$5
|
35 |
|
|
36 |
|
update $REVZONE "update $action $REVLPART.$REVZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
|
37 |
|
update $REV6ZONE "update $action $REV6LPART$REV6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
|
38 |
|
|
39 |
|
if [ ! -z "$7" ]; then
|
40 |
|
EUI64=$6
|
41 |
|
FORZONE=$7
|
42 |
|
update $FORZONE "update $action $GANETI_INSTANCE_NAME.$FORZONE $TTL A $GANETI_INSTANCE_NIC0_IP"
|
43 |
|
update $FORZONE "update $action $GANETI_INSTANCE_NAME.$FORZONE $TTL AAAA $EUI64"
|
44 |
|
fi
|
|
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 |
|
45 |
46 |
}
|
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 |
|
47 |
215 |
# Main starts here
|
48 |
|
if [ "x" = "x$GANETI_INSTANCE_NIC0_IP" ]; then
|
49 |
|
exit 1
|
50 |
|
else
|
51 |
|
OLDIFS=$IFS
|
52 |
|
IFS=". "
|
53 |
|
set -- $GANETI_INSTANCE_NIC0_IP
|
54 |
|
a=$1 ; b=$2; c=$3; d=$4;
|
55 |
|
IFS=$OLDIFS
|
56 |
|
RZONE="$c.$b.$a.in-addr.arpa"
|
57 |
|
RLPART="$d"
|
58 |
|
|
59 |
|
# NOTE: We are going to assume one simple thing. /64s ...
|
60 |
|
# A mistake but good enough for alpha and autoconfiguration
|
61 |
|
prefix=$(ip -6 route list table $GANETI_INSTANCE_NIC0_LINK | awk '/\/64/ {print $1; exit}')
|
62 |
|
eui64=$($MAC2EUI64 $GANETI_INSTANCE_NIC0_MAC $prefix)
|
63 |
|
R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
|
64 |
|
R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
|
65 |
|
R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
|
66 |
|
fi
|
67 |
216 |
|
68 |
|
if [ "x" = "x$GANETI_INSTANCE_NAME" ]; then
|
69 |
|
exit 1
|
|
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
|
70 |
221 |
fi
|
71 |
222 |
|
72 |
|
if [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_CREATE" ]; then
|
73 |
|
addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
74 |
|
elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REMOVE" ]; then
|
75 |
|
addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
76 |
|
elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_RENAME" ]; then
|
77 |
|
addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
78 |
|
# Let's override a variable and add ourselves
|
79 |
|
GANETI_INSTANCE_NAME=$GANETI_INSTANCE_NEW_NAME
|
80 |
|
addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
81 |
|
elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_STARTUP" ]; then
|
82 |
|
addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
83 |
|
elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_SHUTDOWN" ]; then
|
84 |
|
addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
85 |
|
elif [ "x$GANETI_OP_CODE" = "xOP_INSTANCE_REBOOT" ]; then
|
86 |
|
addremove delete $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
87 |
|
addremove add $RZONE $R6ZONE $RLPART $R6LPART $eui64 $FZONE
|
88 |
|
fi
|
|
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
|