6 ctdb_setup_service_state_dir "per_ip_routing"
8 [ -z "$CTDB_PER_IP_ROUTING_STATE" ] && {
9 CTDB_PER_IP_ROUTING_STATE="$service_state_dir"
14 case "$CTDB_PER_IP_ROUTING_CONF" in
17 CTDB_PER_IP_ROUTING_CONF="$CTDB_PER_IP_ROUTING_STATE/auto_link_local.conf"
20 [ -z "$CTDB_PER_IP_ROUTING_CONF" ] && {
21 #echo "No config file found. Nothing to do for 13.per_ip_routing"
27 _low=$CTDB_PER_IP_ROUTING_TABLE_ID_LOW
28 _high=$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH
31 echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW not configured";
35 echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_HIGH not configured";
38 test "$_low" -ge "$_high" && {
39 echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$_low] needs to be below CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$_high]";
43 test -z "$CTDB_PER_IP_ROUTING_RULE_PREF" && {
44 echo "$0: CTDB_PER_IP_ROUTING_RULE_PREF not configured";
49 lock_root="$CTDB_PER_IP_ROUTING_STATE"
57 ############################
58 # grab a lock file. Not atomic, but close :)
59 # tries to cope with NFS
61 if [ -z "$lock_root" ]; then
65 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
66 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
68 if [ "$pid" = "$$" ]; then
69 locknesting=`expr $locknesting + 1`
70 lock_debug "lock nesting now $locknesting"
74 if test -f "$lckf"; then
75 test $machine = $host || {
76 lock_debug "lock file $lckf is valid for other machine $machine"
81 lock_debug "lock file $lckf is valid for process $pid"
85 lock_debug "stale lock file $lckf for $machine:$pid"
89 echo "$host:$$" > "$lckf"
93 ############################
96 if [ -z "$lock_root" ]; then
99 if [ "$locknesting" != "0" ]; then
100 locknesting=`expr $locknesting - 1`
101 lock_debug "lock nesting now $locknesting"
108 generate_table_id () {
110 local _ipsdir="$CTDB_PER_IP_ROUTING_STATE/ips"
111 local _ipdir="$_ipsdir/$_ip"
115 #echo "generate_table_id $_ip"
117 local _id=`cat $_ipdir/table_id 2>/dev/null| xargs`
119 #echo "IP: $_ip => OLD TABLE: $_id"
124 local _low="$CTDB_PER_IP_ROUTING_TABLE_ID_LOW"
125 local _high="$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH"
128 for _id in `seq $_low $_high | xargs`; do
129 local _table_lck="table_id_$_id.lock"
130 lock_file $_table_lck 2>/dev/null || {
133 local _taken=`grep "^$_id$" $_ipsdir/*/table_id 2>/dev/null| wc -l | xargs`
134 test x"$_taken" != x"0" && {
135 unlock_file $_table_lck
136 #echo "tableid: $_id taken"
140 echo "$_newid" > $_ipdir/table_id
141 unlock_file $_table_lck
145 test -z "$_newid" && {
146 echo "generate_table_id: out of table ids: $_low - $_high"
150 #echo "IP: $_ip => NEW TABLE: $_newid"
155 run_release_script_once()
159 #echo "run_release_script_once[$_script]"
161 test -x "$_script" && {
162 #echo "run it: start"
164 echo "release_script: $_script - failed $?"
170 echo '#!/bin/sh' > $_script
179 generate_auto_link_local()
184 #echo "generate_auto_link_local $_ip $_maskbits"
186 local _netip=`ipv4_host_addr_to_net_addr $_ip $_maskbits`
188 local _line="$_ip $_netip/$_maskbits"
190 local _lockfile="$CTDB_PER_IP_ROUTING_CONF.lock"
191 local _script="$CTDB_PER_IP_ROUTING_CONF.$$.sh"
193 echo "#!/bin/sh" > $_script
196 echo "_config=\`cat $CTDB_PER_IP_ROUTING_CONF 2>/dev/null\`" >> $_script
197 echo "_exact=\`echo -n \"\$_config\" | grep \"^$_line\$\" | wc -l | xargs\`" >> $_script
200 echo "test x\"\$_exact\" = x\"1\" && {" >> $_script
201 echo " exit 0;" >> $_script
205 echo "_tmp=\"$CTDB_PER_IP_ROUTING_CONF.$$.tmp\"" >> $_script
206 echo "echo -n \"\$_config\" | grep -v \"^$_ip \" | cat > \$_tmp || {" >> $_script
207 echo " echo \"echo -n \\\"\$_config\\\" | grep -v \\\"^$_ip \\\" > \$_tmp - failed\"" >> $_script
208 echo " exit 1;" >> $_script
210 echo "echo \"$_line\" >> \$_tmp || {" >> $_script
211 echo " echo \"echo \\\"$_line\\\" >> \$_tmp - failed\"" >> $_script
212 echo " exit 1;" >> $_script
216 echo "mv \$_tmp $CTDB_PER_IP_ROUTING_CONF || {" >> $_script
217 echo " echo \"mv \$_tmp $CTDB_PER_IP_ROUTING_CONF - failed\"" >> $_script
218 echo " exit 1;" >> $_script
222 echo "echo \"Added '$_line' to $CTDB_PER_IP_ROUTING_CONF\"">> $_script
223 echo "exit 0" >> $_script
227 test -f $_lockfile || {
231 flock --timeout 30 $_lockfile $_script
237 generate_per_ip_routing()
243 local _ipdir="$CTDB_PER_IP_ROUTING_STATE/ips/$_ip"
246 release_script="$_ipdir/per_ip_routing_release.sh"
247 setup_script="$_ipdir/per_ip_routing_setup.sh"
249 test x"$_readonly" = x"yes" && {
256 mkdir -p $_ipdir || {
257 echo "mkdir -p $_ipdir failed"
260 echo "$_ip" > $_ipdir/ip
262 generate_table_id $_ip
264 test x"$AUTO_LINK_LOCAL" = x"yes" && {
265 generate_auto_link_local $_ip $_maskbits
268 run_release_script_once $release_script
270 echo '#!/bin/sh' > $setup_script
271 echo '#' >> $setup_script
272 echo >> $setup_script
273 chmod +x $setup_script
278 setup_per_ip_routing()
283 local _release_script=$4
284 local _setup_script=$5
286 local _config=`cat $CTDB_PER_IP_ROUTING_CONF`
287 local _lines=`echo -n "$_config" | grep -n "^$_ip " | cut -d ':' -f1 | xargs`
289 local _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
291 test -n "$_lines" && {
292 echo "ip rule del from $_ip pref $_pref table $_table_id" >> $_release_script
293 echo "ip route flush table $_table_id 2>/dev/null" >> $_release_script
295 cmd="ip rule del from $_ip pref $_pref 2>/dev/null"
296 echo "$cmd" >> $_setup_script
298 cmd="ip route flush table $_table_id 2>/dev/null"
299 echo "$cmd" >> $_setup_script
301 cmd="ip rule add from $_ip pref $_pref table $_table_id"
302 echo "$cmd || {" >> $_setup_script
303 echo " echo \"$cmd - failed \$ret\"" >> $_setup_script
304 echo " exit \$ret" >> $_setup_script
305 echo "}" >> $_setup_script
308 for _l in $_lines; do
309 local _line=`echo -n "$_config" | head -n $_l | tail -n 1`
310 local _dest=`echo -n "$_line" | cut -d ' ' -f 2`
311 local _gw=`echo -n "$_line" | cut -d ' ' -f 3`
318 cmd="ip route add $_dest $_via dev $_iface table $_table_id"
319 echo "$cmd || {" >> $_setup_script
320 echo " echo \"$cmd - failed \$ret\"" >> $_setup_script
321 echo " exit \$ret" >> $_setup_script
322 echo "}" >> $_setup_script
332 #############################
333 # called when ctdbd starts up
336 pref=$CTDB_PER_IP_ROUTING_RULE_PREF
337 rules=`ip rule show | grep "^$pref:" | sed -e 's/.*from \([^ ][^ ]*\) lookup \([^ ][^ ]*\)/\2;\1/' | xargs`
339 table_id=`echo -n "$r" | cut -d ';' -f1`
340 ip=`echo -n "$r" | cut -d ';' -f2-`
342 echo "Removing ip rule for public address $ip for routing table $table_id"
343 cmd="ip rule del from $ip table $table_id pref $pref"
346 cmd="ip route flush table $table_id"
348 eval $cmd 2>/dev/null
351 # make sure that we only respond to ARP messages from the NIC where
352 # a particular ip address is associated.
353 [ -f /proc/sys/net/ipv4/conf/all/arp_filter ] && {
354 echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
357 mkdir -p $CTDB_PER_IP_ROUTING_STATE
363 for s in $CTDB_PER_IP_ROUTING_STATE/ips/*/per_ip_routing_release.sh; do
364 run_release_script_once "$s"
366 rm -rf $CTDB_PER_IP_ROUTING_STATE
370 ################################################
371 # called when ctdbd wants to claim an IP address
377 ipv4_is_valid_addr $ip || {
378 echo "$0: $1 not an ipv4 address skipping IP:$ip"
382 [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
383 echo "$0: $1 No state directory found, waiting for startup."
387 generate_per_ip_routing $ip $maskbits $iface "no" || {
388 echo "$0: $1: generate_per_ip_routing $ip $maskbits $iface no - failed"
392 setup_per_ip_routing $ip $iface $table_id $release_script $setup_script || {
393 echo "$0: $1: setup_per_ip_routing $ip $iface $table_id $release_script $setup_script - failed"
397 setup_iface_ip_readd_script $iface $ip $maskbits $setup_script || {
398 echo "$0: $1: setup_iface_ip_readd_script $iface $ip $maskbits $setup_script - failed"
402 # flush our route cache
403 echo 1 > /proc/sys/net/ipv4/route/flush
404 ctdb gratiousarp $ip $iface
408 ################################################
409 # called when ctdbd wants to claim an IP address
416 ipv4_is_valid_addr $ip || {
417 echo "$0: $1 not an ipv4 address skipping IP:$ip"
421 [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
422 echo "$0: $1 No state directory found, waiting for startup."
426 generate_per_ip_routing $ip $maskbits $niface "no" || {
427 echo "$0: $1: generate_per_ip_routing $ip $maskbits $niface no - failed"
431 setup_per_ip_routing $ip $niface $table_id $release_script $setup_script || {
432 echo "$0: $1: setup_per_ip_routing $ip $niface $table_id $release_script $setup_script - failed"
436 setup_iface_ip_readd_script $niface $ip $maskbits $setup_script || {
437 echo "$0: $1: setup_iface_ip_readd_script $niface $ip $maskbits $setup_script - failed"
441 # flush our route cache
442 echo 1 > /proc/sys/net/ipv4/route/flush
444 ctdb gratiousarp $ip $niface
445 tickle_tcp_connections $ip
449 ##################################################
450 # called when ctdbd wants to release an IP address
456 ipv4_is_valid_addr $ip || {
457 echo "$0: $1 not an ipv4 address skipping IP:$ip"
461 [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
462 echo "$0: $1 No state directory found, waiting for startup."
466 generate_per_ip_routing $ip $maskbits $iface "yes" || {
467 echo "$0: $1: generate_per_ip_routing $ip $maskbits $iface yes - failed"
471 run_release_script_once "$release_script"
476 ###########################################
477 # called when ctdbd has finished a recovery
481 ####################################
482 # called when ctdbd is shutting down
489 ctdb_standard_event_handler "$@"