6 [ -z "$CTDB_PER_IP_ROUTING_STATE" ] && {
7 CTDB_PER_IP_ROUTING_STATE="$CTDB_BASE/state/per_ip_routing"
12 case "$CTDB_PER_IP_ROUTING_CONF" in
15 CTDB_PER_IP_ROUTING_CONF="$CTDB_PER_IP_ROUTING_STATE/auto_link_local.conf"
18 [ -z "$CTDB_PER_IP_ROUTING_CONF" ] && {
19 #echo "No config file found. Nothing to do for 13.per_ip_routing"
25 _low=$CTDB_PER_IP_ROUTING_TABLE_ID_LOW
26 _high=$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH
29 echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW not configured";
33 echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_HIGH not configured";
36 test "$_low" -ge "$_high" && {
37 echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$_low] needs to be below CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$_high]";
41 test -z "$CTDB_PER_IP_ROUTING_RULE_PREF" && {
42 echo "$0: CTDB_PER_IP_ROUTING_RULE_PREF not configured";
47 lock_root="$CTDB_PER_IP_ROUTING_STATE"
55 ############################
56 # grab a lock file. Not atomic, but close :)
57 # tries to cope with NFS
59 if [ -z "$lock_root" ]; then
63 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
64 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
66 if [ "$pid" = "$$" ]; then
67 locknesting=`expr $locknesting + 1`
68 lock_debug "lock nesting now $locknesting"
72 if test -f "$lckf"; then
73 test $machine = $host || {
74 lock_debug "lock file $lckf is valid for other machine $machine"
78 /bin/kill -0 $pid && {
79 lock_debug "lock file $lckf is valid for process $pid"
83 lock_debug "stale lock file $lckf for $machine:$pid"
87 echo "$host:$$" > "$lckf"
91 ############################
94 if [ -z "$lock_root" ]; then
97 if [ "$locknesting" != "0" ]; then
98 locknesting=`expr $locknesting - 1`
99 lock_debug "lock nesting now $locknesting"
106 generate_table_id () {
108 local _ipsdir="$CTDB_PER_IP_ROUTING_STATE/ips"
109 local _ipdir="$_ipsdir/$_ip"
113 #echo "generate_table_id $_ip"
115 local _id=`cat $_ipdir/table_id 2>/dev/null| xargs`
117 #echo "IP: $_ip => OLD TABLE: $_id"
122 local _low="$CTDB_PER_IP_ROUTING_TABLE_ID_LOW"
123 local _high="$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH"
126 for _id in `seq $_low $_high | xargs`; do
127 local _table_lck="table_id_$_id.lock"
128 lock_file $_table_lck 2>/dev/null || {
131 local _taken=`grep "^$_id$" $_ipsdir/*/table_id 2>/dev/null| wc -l | xargs`
132 test x"$_taken" != x"0" && {
133 unlock_file $_table_lck
134 #echo "tableid: $_id taken"
138 echo "$_newid" > $_ipdir/table_id
139 unlock_file $_table_lck
143 test -z "$_newid" && {
144 echo "generate_table_id: out of table ids: $_low - $_high"
148 #echo "IP: $_ip => NEW TABLE: $_newid"
153 run_release_script_once()
157 #echo "run_release_script_once[$_script]"
159 test -x "$_script" && {
160 #echo "run it: start"
162 echo "release_script: $_script - failed $?"
168 echo '#!/bin/sh' > $_script
177 generate_auto_link_local()
182 #echo "generate_auto_link_local $_ip $_maskbits"
184 local _netip=`ipv4_host_addr_to_net_addr $_ip $_maskbits`
186 local _line="$_ip $_netip/$_maskbits"
188 local _config=`cat $CTDB_PER_IP_ROUTING_CONF 2>/dev/null`
190 local _exact=`echo -n "$_config" | grep "^$line$" | wc -l | xargs`
192 test x"$_exact" = x"1" && {
196 local _tmp="$CTDB_PER_IP_ROUTING_CONF.$$.tmp"
197 echo -n "$_config" | grep -v "^$_ip " > $_tmp
198 echo "$_line" >> $_tmp
200 mv $_tmp $CTDB_PER_IP_ROUTING_CONF
203 generate_per_ip_routing()
209 local _ipdir="$CTDB_PER_IP_ROUTING_STATE/ips/$_ip"
212 release_script="$_ipdir/per_ip_routing_release.sh"
213 setup_script="$_ipdir/per_ip_routing_setup.sh"
215 test x"$_readonly" = x"yes" && {
222 mkdir -p $_ipdir || {
223 echo "mkdir -p $_ipdir failed"
226 echo "$_ip" > $_ipdir/ip
228 generate_table_id $_ip
230 test x"$AUTO_LINK_LOCAL" = x"yes" && {
231 generate_auto_link_local $_ip $_maskbits
234 run_release_script_once $release_script
236 echo '#!/bin/sh' > $setup_script
237 echo '#' >> $setup_script
238 echo >> $setup_script
239 chmod +x $setup_script
244 setup_per_ip_routing()
249 local _release_script=$4
250 local _setup_script=$5
252 local _config=`cat $CTDB_PER_IP_ROUTING_CONF`
253 local _lines=`echo -n "$_config" | grep -n "^$_ip " | cut -d ':' -f1 | xargs`
255 local _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
257 test -n "$_lines" && {
258 echo "ip rule del from $_ip pref $_pref table $_table_id" >> $_release_script
259 echo "ip route flush table $_table_id 2>/dev/null" >> $_release_script
261 cmd="ip rule del from $_ip pref $_pref 2>/dev/null"
262 echo "$cmd" >> $_setup_script
264 cmd="ip route flush table $_table_id 2>/dev/null"
265 echo "$cmd" >> $_setup_script
267 cmd="ip rule add from $_ip pref $_pref table $_table_id"
268 echo "$cmd || {" >> $_setup_script
269 echo " echo \"$cmd - failed \$ret\"" >> $_setup_script
270 echo " exit \$ret" >> $_setup_script
271 echo "}" >> $_setup_script
274 for _l in $_lines; do
275 local _line=`echo -n "$_config" | head -n $_l | tail -n 1`
276 local _dest=`echo -n "$_line" | cut -d ' ' -f 2`
277 local _gw=`echo -n "$_line" | cut -d ' ' -f 3`
284 cmd="ip route add $_dest $_via dev $_iface table $_table_id"
285 echo "$cmd || {" >> $_setup_script
286 echo " echo \"$cmd - failed \$ret\"" >> $_setup_script
287 echo " exit \$ret" >> $_setup_script
288 echo "}" >> $_setup_script
296 #############################
297 # called when ctdbd starts up
300 pref=$CTDB_PER_IP_ROUTING_RULE_PREF
301 rules=`ip rule show | grep "^$pref:" | sed -e 's/.*from \([^ ][^ ]*\) lookup \([^ ][^ ]*\)/\2;\1/' | xargs`
303 table_id=`echo -n "$r" | cut -d ';' -f1`
304 ip=`echo -n "$r" | cut -d ';' -f2-`
306 echo "Removing ip rule for public address $ip for routing table $table_id"
307 cmd="ip rule del from $ip table $table_id pref $pref"
310 cmd="ip route flush table $table_id"
312 eval $cmd 2>/dev/null
315 # make sure that we only respond to ARP messages from the NIC where
316 # a particular ip address is associated.
317 [ -f /proc/sys/net/ipv4/conf/all/arp_filter ] && {
318 echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
321 mkdir -p $CTDB_PER_IP_ROUTING_STATE
327 for s in $CTDB_PER_IP_ROUTING_STATE/ips/*/per_ip_routing_release.sh; do
328 run_release_script_once "$s"
330 rm -rf $CTDB_PER_IP_ROUTING_STATE
334 ################################################
335 # called when ctdbd wants to claim an IP address
338 echo "must supply interface, IP and maskbits"
345 ipv4_is_valid_addr $ip || {
346 echo "$0: $1 not an ipv4 address skipping IP:$ip"
350 [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
351 echo "$0: $1 No state directory found, waiting for startup."
355 generate_per_ip_routing $ip $maskbits $iface "no" || {
356 echo "$0: $1: generate_per_ip_routing $ip $maskbits $iface no - failed"
360 setup_per_ip_routing $ip $iface $table_id $release_script $setup_script || {
361 echo "$0: $1: setup_per_ip_routing $ip $iface $table_id $release_script $setup_script - failed"
365 setup_iface_ip_readd_script $iface $ip $maskbits $setup_script || {
366 echo "$0: $1: setup_iface_ip_readd_script $iface $ip $maskbits $setup_script - failed"
370 # flush our route cache
371 echo 1 > /proc/sys/net/ipv4/route/flush
372 ctdb gratiousarp $ip $iface
376 ################################################
377 # called when ctdbd wants to claim an IP address
380 echo "must supply old interface, new interface, IP and maskbits"
388 ipv4_is_valid_addr $ip || {
389 echo "$0: $1 not an ipv4 address skipping IP:$ip"
393 [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
394 echo "$0: $1 No state directory found, waiting for startup."
398 generate_per_ip_routing $ip $maskbits $niface "no" || {
399 echo "$0: $1: generate_per_ip_routing $ip $maskbits $niface no - failed"
403 setup_per_ip_routing $ip $niface $table_id $release_script $setup_script || {
404 echo "$0: $1: setup_per_ip_routing $ip $niface $table_id $release_script $setup_script - failed"
408 setup_iface_ip_readd_script $niface $ip $maskbits $setup_script || {
409 echo "$0: $1: setup_iface_ip_readd_script $niface $ip $maskbits $setup_script - failed"
413 # flush our route cache
414 echo 1 > /proc/sys/net/ipv4/route/flush
416 ctdb gratiousarp $ip $niface
417 tickle_tcp_connections $ip
421 ##################################################
422 # called when ctdbd wants to release an IP address
425 echo "must supply interface, IP and maskbits"
433 ipv4_is_valid_addr $ip || {
434 echo "$0: $1 not an ipv4 address skipping IP:$ip"
438 [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
439 echo "$0: $1 No state directory found, waiting for startup."
443 generate_per_ip_routing $ip $maskbits $iface "yes" || {
444 echo "$0: $1: generate_per_ip_routing $ip $maskbits $iface yes - failed"
448 run_release_script_once "$release_script"
453 ###########################################
454 # called when ctdbd has finished a recovery
458 ####################################
459 # called when ctdbd is shutting down
466 ctdb_standard_event_handler "$@"