#!/bin/sh
-. $CTDB_BASE/functions
+[ -n "$CTDB_BASE" ] || \
+ CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; dirname "$PWD")
+
+. "${CTDB_BASE}/functions"
+
loadconfig
-[ -z "$CTDB_PER_IP_ROUTING_STATE" ] && {
- CTDB_PER_IP_ROUTING_STATE="$CTDB_BASE/state/per_ip_routing"
-}
+service_name=per_ip_routing
-AUTO_LINK_LOCAL="no"
-
-case "$CTDB_PER_IP_ROUTING_CONF" in
- __auto_link_local__)
- AUTO_LINK_LOCAL="yes"
- CTDB_PER_IP_ROUTING_CONF="$CTDB_PER_IP_ROUTING_STATE/auto_link_local.conf"
- ;;
- *)
- [ -z "$CTDB_PER_IP_ROUTING_CONF" ] && {
- #echo "No config file found. Nothing to do for 13.per_ip_routing"
- exit 0;
- }
- ;;
-esac
+# Do nothing if unconfigured
+[ -n "$CTDB_PER_IP_ROUTING_CONF" ] || exit 0
-_low=$CTDB_PER_IP_ROUTING_TABLE_ID_LOW
-_high=$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH
+table_id_prefix="ctdb."
-test -z "$_low" && {
- echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW not configured";
- exit 1;
-}
-test -z "$_high" && {
- echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_HIGH not configured";
- exit 1;
-}
-test "$_low" -ge "$_high" && {
- echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$_low] needs to be below CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$_high]";
- exit 1;
-}
+[ -n "$CTDB_PER_IP_ROUTING_RULE_PREF" ] || \
+ die "error: CTDB_PER_IP_ROUTING_RULE_PREF not configured"
-test -z "$CTDB_PER_IP_ROUTING_RULE_PREF" && {
- echo "$0: CTDB_PER_IP_ROUTING_RULE_PREF not configured";
- exit 1;
-}
+[ "$CTDB_PER_IP_ROUTING_TABLE_ID_LOW" -lt "$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH" ] 2>/dev/null || \
+ die "error: CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$CTDB_PER_IP_ROUTING_TABLE_ID_LOW] and/or CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH] improperly configured"
-locknesting=0
-lock_root="$CTDB_PER_IP_ROUTING_STATE"
-host=`hostname`
+if [ "$CTDB_PER_IP_ROUTING_TABLE_ID_LOW" -le 253 -a \
+ 255 -le "$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH" ] ; then
+ die "error: range CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$CTDB_PER_IP_ROUTING_TABLE_ID_LOW]..CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH] must not include 253-255"
+fi
-lock_debug()
+have_link_local_config ()
{
- echo -n ""
+ [ "$CTDB_PER_IP_ROUTING_CONF" = "__auto_link_local__" ]
}
-############################
-# grab a lock file. Not atomic, but close :)
-# tries to cope with NFS
-lock_file() {
- if [ -z "$lock_root" ]; then
- lock_root=`pwd`;
- fi
- lckf="$lock_root/$1"
- machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
- pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
+if ! have_link_local_config && [ ! -r "$CTDB_PER_IP_ROUTING_CONF" ] ; then
+ die "error: CTDB_PER_IP_ROUTING_CONF=$CTDB_PER_IP_ROUTING_CONF file not found"
+fi
- if [ "$pid" = "$$" ]; then
- locknesting=`expr $locknesting + 1`
- lock_debug "lock nesting now $locknesting"
- return 0
- fi
+######################################################################
- if test -f "$lckf"; then
- test $machine = $host || {
- lock_debug "lock file $lckf is valid for other machine $machine"
- stat -c%y "$lckf"
- return 1
- }
- kill -0 $pid && {
- lock_debug "lock file $lckf is valid for process $pid"
- stat -c%y "$lckf"
- return 1
- }
- lock_debug "stale lock file $lckf for $machine:$pid"
- cat "$lckf"
- /bin/rm -f "$lckf"
+ipv4_is_valid_addr()
+{
+ _ip="$1"
+
+ _count=0
+ # Get the shell to break up the address into 1 word per octet
+ for _o in $(export IFS="." ; echo $_ip) ; do
+ # The 2>/dev/null stops output from failures where an "octet"
+ # is not numeric. The test will still fail.
+ if ! [ 0 -le $_o -a $_o -le 255 ] 2>/dev/null ; then
+ return 1
fi
- echo "$host:$$" > "$lckf"
- return 0
-}
+ _count=$(($_count + 1))
+ done
-############################
-# unlock a lock file
-unlock_file() {
- if [ -z "$lock_root" ]; then
- lock_root=`pwd`;
- fi
- if [ "$locknesting" != "0" ]; then
- locknesting=`expr $locknesting - 1`
- lock_debug "lock nesting now $locknesting"
- else
- lckf="$lock_root/$1"
- /bin/rm -f "$lckf"
- fi
+ # A valid IPv4 address has 4 octets
+ [ $_count -eq 4 ]
}
-generate_table_id () {
- local _ip=$1
- local _ipsdir="$CTDB_PER_IP_ROUTING_STATE/ips"
- local _ipdir="$_ipsdir/$_ip"
+ensure_ipv4_is_valid_addr ()
+{
+ _event="$1"
+ _ip="$2"
- mkdir -p $_ipdir
+ ipv4_is_valid_addr "$_ip" || {
+ echo "$0: $_event not an ipv4 address skipping IP:$_ip"
+ exit 0
+ }
+}
- #echo "generate_table_id $_ip"
+ipv4_host_addr_to_net ()
+{
+ _host="$1"
+ _maskbits="$2"
+
+ # Convert the host address to an unsigned long by splitting out
+ # the octets and doing the math.
+ _host_ul=0
+ for _o in $(export IFS="." ; echo $_host) ; do
+ _host_ul=$(( ($_host_ul << 8) + $_o)) # work around Emacs color bug
+ done
+
+ # Calculate the mask and apply it.
+ _mask_ul=$(( 0xffffffff << (32 - $_maskbits) ))
+ _net_ul=$(( $_host_ul & $_mask_ul ))
+
+ # Now convert to a network address one byte at a time.
+ _net=""
+ for _o in $(seq 1 4) ; do
+ _net="$(($_net_ul & 255))${_net:+.}${_net}"
+ _net_ul=$(($_net_ul >> 8))
+ done
+
+ echo "${_net}/${_maskbits}"
+}
- local _id=`cat $_ipdir/table_id 2>/dev/null| xargs`
- test -n "$_id" && {
- #echo "IP: $_ip => OLD TABLE: $_id"
- table_id=$_id
- return 0;
- }
+######################################################################
- local _low="$CTDB_PER_IP_ROUTING_TABLE_ID_LOW"
- local _high="$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH"
-
- local _newid=""
- for _id in `seq $_low $_high | xargs`; do
- local _table_lck="table_id_$_id.lock"
- lock_file $_table_lck 2>/dev/null || {
- continue;
- }
- local _taken=`grep "^$_id$" $_ipsdir/*/table_id 2>/dev/null| wc -l | xargs`
- test x"$_taken" != x"0" && {
- unlock_file $_table_lck
- #echo "tableid: $_id taken"
- continue
- }
- _newid=$_id;
- echo "$_newid" > $_ipdir/table_id
- unlock_file $_table_lck
- break;
- done
+ensure_rt_tables ()
+{
+ rt_tables="$CTDB_SYS_ETCDIR/iproute2/rt_tables"
+
+ # This file should always exist. Even if this didn't exist on the
+ # system, adding a route will have created it. What if we startup
+ # and immediately shutdown? Let's be sure.
+ if [ ! -f "$rt_tables" ] ; then
+ mkdir -p "${rt_tables%/*}" # dirname
+ touch "$rt_tables"
+ fi
+}
- test -z "$_newid" && {
- echo "generate_table_id: out of table ids: $_low - $_high"
- exit 1;
- }
+# Setup a table id to use for the given IP. We don't need to know it,
+# it just needs to exist in /etc/iproute2/rt_tables. Fail if no free
+# table id could be found in the configured range.
+ensure_table_id_for_ip ()
+{
+ _ip=$1
+
+ ensure_rt_tables
+
+ # Maintain a table id for each IP address we've ever seen in
+ # rt_tables. We use a "ctdb." prefix on the label.
+ _label="${table_id_prefix}${_ip}"
+
+ # This finds either the table id corresponding to the label or a
+ # new unused one (that is greater than all the used ones in the
+ # range).
+ (
+ # Note that die() just gets us out of the subshell...
+ flock --timeout 30 0 || \
+ die "ensure_table_id_for_ip: failed to lock file $rt_tables"
+
+ _new=$CTDB_PER_IP_ROUTING_TABLE_ID_LOW
+ while read _t _l ; do
+ # Skip comments
+ case "$_t" in
+ \#*) continue ;;
+ esac
+ # Found existing: done
+ if [ "$_l" = "$_label" ] ; then
+ return 0
+ fi
+ # Potentially update the new table id to be used. The
+ # redirect stops error spam for a non-numeric value.
+ if [ $_new -le $_t -a \
+ $_t -le $CTDB_PER_IP_ROUTING_TABLE_ID_HIGH ] 2>/dev/null ; then
+ _new=$(($_t + 1))
+ fi
+ done
- #echo "IP: $_ip => NEW TABLE: $_newid"
- table_id=$_newid
- return 0;
+ # If the new table id is legal then add it to the file and
+ # print it.
+ if [ $_new -le $CTDB_PER_IP_ROUTING_TABLE_ID_HIGH ] ; then
+ printf "%d\t%s\n" "$_new" "$_label" >>"$rt_tables"
+ return 0
+ else
+ return 1
+ fi
+ ) <"$rt_tables"
}
-run_release_script_once()
+# Clean up all the table ids that we might own.
+clean_up_table_ids ()
{
- local _script=$1
+ ensure_rt_tables
+
+ (
+ # Note that die() just gets us out of the subshell...
+ flock --timeout 30 0 || \
+ die "clean_up_table_ids: failed to lock file $rt_tables"
+
+ # Delete any items from the file that have a table id in our
+ # range or a label matching our label. Preserve comments.
+ _tmp="${rt_tables}.$$.ctdb"
+ awk -v min="$CTDB_PER_IP_ROUTING_TABLE_ID_LOW" \
+ -v max="$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH" \
+ -v pre="$table_id_prefix" \
+ '/^#/ || \
+ !(min <= $1 && $1 <= max) && \
+ !(index($2, pre) == 1) \
+ { print $0 }' "$rt_tables" >"$_tmp"
+
+ mv "$_tmp" "$rt_tables"
+ # The lock is gone - don't do anything else here
+ ) <"$rt_tables"
+}
- #echo "run_release_script_once[$_script]"
+######################################################################
- test -x "$_script" && {
- #echo "run it: start"
- $_script || {
- echo "release_script: $_script - failed $?"
- return $?;
- }
- #echo "run it: end"
- }
+# This prints the config for an IP, which is either relevant entries
+# from the config file or, if set to the magic link local value, some
+# link local routing config for the IP.
+get_config_for_ip ()
+{
+ _ip="$1"
+
+ if have_link_local_config ; then
+ # When parsing public_addresses also split on '/'. This means
+ # that we get the maskbits as item #2 without further parsing.
+ while IFS="/$IFS" read _i _maskbits _x ; do
+ if [ "$_ip" = "$_i" ] ; then
+ echo -n "$_ip "; ipv4_host_addr_to_net "$_ip" "$_maskbits"
+ fi
+ done <"${CTDB_PUBLIC_ADDRESSES:-/dev/null}"
+ else
+ while read _i _rest ; do
+ if [ "$_ip" = "$_i" ] ; then
+ printf "%s\t%s\n" "$_ip" "$_rest"
+ fi
+ done <"$CTDB_PER_IP_ROUTING_CONF"
+ fi
+}
- echo -e "#!/bin/sh\n#\n" > $_script
- chmod +x $_script
+ip_has_configuration ()
+{
+ _ip="$1"
- return 0;
+ [ -n "$(get_config_for_ip $_ip)" ]
}
-generate_auto_link_local()
+add_routing_for_ip ()
{
- local _ip=$1
- local _maskbits=$2
-
- #echo "generate_auto_link_local $_ip $_maskbits"
+ _iface="$1"
+ _ip="$2"
- local _netip=`ipv4_host_addr_to_net_addr $_ip $_maskbits`
+ # Do nothing if no config for this IP.
+ ip_has_configuration "$_ip" || return 0
- local _line="$_ip $_netip/$_maskbits"
+ ensure_table_id_for_ip "$_ip" || \
+ die "add_routing_for_ip: out of table ids in range $CTDB_PER_IP_ROUTING_TABLE_ID_LOW - $CTDB_PER_IP_ROUTING_TABLE_ID_HIGH"
- local _config=`cat $CTDB_PER_IP_ROUTING_CONF 2>/dev/null`
+ _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
+ _table_id="${table_id_prefix}${_ip}"
- local _exact=`echo -n "$_config" | grep "^$line$" | wc -l | xargs`
+ del_routing_for_ip "$_ip" >/dev/null 2>&1
- test x"$_exact" = x"1" && {
- return 0;
- }
+ ip rule add from "$_ip" pref "$_pref" table "$_table_id" || \
+ die "add_routing_for_ip: failed to add rule for $_ip"
- local _tmp="$CTDB_PER_IP_ROUTING_CONF.$$.tmp"
- echo -n "$_config" | grep -v "^$_ip " > $_tmp
- echo "$_line" >> $_tmp
+ # Add routes to table for any lines matching the IP.
+ get_config_for_ip "$_ip" |
+ while read _i _dest _gw ; do
+ _r="$_dest ${_gw:+via} $_gw dev $_iface table $_table_id"
+ ip route add $_r || \
+ die "add_routing_for_ip: failed to add route: $_r"
+ done
+}
- mv $_tmp $CTDB_PER_IP_ROUTING_CONF
+del_routing_for_ip ()
+{
+ _ip="$1"
+
+ _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
+ _table_id="${table_id_prefix}${_ip}"
+
+ # Do this unconditionally since we own any matching table ids.
+ # However, print a meaningful message if something goes wrong.
+ _cmd="ip rule del from $_ip pref $_pref table $_table_id"
+ _out=$($_cmd 2>&1) || \
+ cat <<EOF
+WARNING: Failed to delete policy routing rule
+ Command "$_cmd" failed:
+ $_out
+EOF
+ # This should never usually fail, so don't redirect output.
+ # However, it can fail when deleting a rogue IP, since there will
+ # be no routes for that IP. In this case it should only fail when
+ # the rule deletion above has already failed because the table id
+ # is invalid. Therefore, go to a little bit of trouble to indent
+ # the failure message so that it is associated with the above
+ # warning message and doesn't look too nasty.
+ ip route flush table "$_table_id" 2>&1 | sed -e 's@^.@ &@'
}
-generate_per_ip_routing()
+######################################################################
+
+flush_rules_and_routes ()
{
- local _ip=$1
- local _maskbits=$2
- local _iface=$3
- local _readonly=$4
- local _ipdir="$CTDB_PER_IP_ROUTING_STATE/ips/$_ip"
-
- table_id=""
- release_script="$_ipdir/release_script.sh"
-
- test x"$_readonly" = x"yes" && {
- test -d $_ipdir || {
- return 1;
- }
- return 0;
- }
+ ip rule show |
+ while read _p _x _i _x _t ; do
+ # Remove trailing colon after priority/preference.
+ _p="${_p%:}"
+ # Only remove rules that match our priority/preference.
+ [ "$CTDB_PER_IP_ROUTING_RULE_PREF" = "$_p" ] || continue
+
+ echo "Removing ip rule for public address $_i for routing table $_t"
+ ip rule del from "$_i" table "$_t" pref "$_p"
+ ip route flush table "$_t" 2>/dev/null
+ done
+}
- mkdir -p $_ipdir || {
- echo "mkdir -p $_ipdir failed"
- return 1;
- }
- echo "$_ip" > $_ipdir/ip
+# Add any missing routes. Some might have gone missing if, for
+# example, all IPs on the network were removed (possibly if the
+# primary was removed). If $1 is "force" then (re-)add all the
+# routes.
+add_missing_routes ()
+{
+ $CTDB ip -v -X | {
+ read _x # skip header line
+
+ # Read the rest of the lines. We're only interested in the
+ # "IP" and "ActiveInterface" columns. The latter is only set
+ # for addresses local to this node, making it easy to skip
+ # non-local addresses. For each IP local address we check if
+ # the relevant routing table is populated and populate it if
+ # not.
+ while IFS="|" read _x _ip _x _iface _x ; do
+ [ -n "$_iface" ] || continue
+
+ _table_id="${table_id_prefix}${_ip}"
+ if [ -z "$(ip route show table $_table_id 2>/dev/null)" -o \
+ "$1" = "force" ] ; then
+ add_routing_for_ip "$_iface" "$_ip"
+ fi
+ done
+ } || exit $?
+}
- generate_table_id $_ip
+# Remove rules/routes for addresses that we're not hosting. If a
+# releaseip event failed in an earlier script then we might not have
+# had a chance to remove the corresponding rules/routes.
+remove_bogus_routes ()
+{
+ # Get a IPs current hosted by this node, each anchored with '@'.
+ _ips=$($CTDB ip -v -X | awk -F'|' 'NR > 1 && $4 != "" {printf "@%s@\n", $2}')
+
+ ip rule show |
+ while read _p _x _i _x _t ; do
+ # Remove trailing colon after priority/preference.
+ _p="${_p%:}"
+ # Only remove rules that match our priority/preference.
+ [ "$CTDB_PER_IP_ROUTING_RULE_PREF" = "$_p" ] || continue
+ # Only remove rules for which we don't have an IP. This could
+ # be done with grep, but let's do it with shell prefix removal
+ # to avoid unnecessary processes. This falls through if
+ # "@${_i}@" isn't present in $_ips.
+ [ "$_ips" = "${_ips#*@${_i}@}" ] || continue
+
+ echo "Removing ip rule/routes for unhosted public address $_i"
+ del_routing_for_ip "$_i"
+ done
+}
- test x"$AUTO_LINK_LOCAL" = x"yes" && {
- generate_auto_link_local $_ip $_maskbits
- }
+######################################################################
- release_script="$_ipdir/release_script.sh"
- run_release_script_once $release_script
+service_reconfigure ()
+{
+ add_missing_routes "force"
+ remove_bogus_routes
- return 0;
+ # flush our route cache
+ set_proc sys/net/ipv4/route/flush 1
}
-case "$1" in
- #############################
- # called when ctdbd starts up
- startup)
- # cleanup old rules
- pref=$CTDB_PER_IP_ROUTING_RULE_PREF
- rules=`ip rule show | grep "^$pref:" | sed -e 's/.*from \([^ ][^ ]*\) lookup \([^ ][^ ]*\)/\2;\1/' | xargs`
- for r in $rules; do
- table_id=`echo -n "$r" | cut -d ';' -f1`
- ip=`echo -n "$r" | cut -d ';' -f2-`
-
- echo "Removing ip rule for public address $ip for routing table $table_id"
- cmd="ip rule del from $ip table $table_id pref $pref"
- #echo $cmd
- eval $cmd
- cmd="ip route flush table $table_id"
- #echo $cmd
- eval $cmd 2>/dev/null
- done
-
- # make sure that we only respond to ARP messages from the NIC where
- # a particular ip address is associated.
- [ -f /proc/sys/net/ipv4/conf/all/arp_filter ] && {
- echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
- }
+######################################################################
- mkdir -p $CTDB_PER_IP_ROUTING_STATE
+ctdb_check_args "$@"
- ;;
+ctdb_service_check_reconfigure
- shutdown)
+case "$1" in
+ startup)
+ flush_rules_and_routes
- for s in $CTDB_PER_IP_ROUTING_STATE/ips/*/release_script.sh; do
- run_release_script_once "$s"
- done
- rm -rf $CTDB_PER_IP_ROUTING_STATE
+ # make sure that we only respond to ARP messages from the NIC
+ # where a particular ip address is associated.
+ get_proc sys/net/ipv4/conf/all/arp_filter >/dev/null 2>&1 && {
+ set_proc sys/net/ipv4/conf/all/arp_filter 1
+ }
+ ;;
+ shutdown)
+ flush_rules_and_routes
+ clean_up_table_ids
;;
- ################################################
- # called when ctdbd wants to claim an IP address
- takeip)
- if [ $# != 4 ]; then
- echo "must supply interface, IP and maskbits"
- exit 1
- fi
+ takeip)
iface=$2
ip=$3
maskbits=$4
- ipv4_is_valid_addr $ip || {
- echo "$0: $1 not an ipv4 address skipping IP:$ip"
- exit 0;
- }
-
- [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
- echo "$0: $1 No state directory found, waiting for startup."
- exit 0;
- }
-
- generate_per_ip_routing $ip $maskbits $iface "no" || {
- echo "$0: $1: generate_per_ip_routing $ip $maskbits $iface no - failed"
- exit 1;
- }
-
- config=`cat $CTDB_PER_IP_ROUTING_CONF`
- lines=`echo -n "$config" | grep -n "^$ip " | cut -d ':' -f1 | xargs`
-
- pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
-
- test -n "$lines" && {
- echo "ip rule del from $ip pref $pref table $table_id" >> $release_script
- echo "ip route flush table $table_id 2>/dev/null" >> $release_script
-
- ip rule del from $ip pref $pref 2>/dev/null
- ip rule add from $ip pref $pref table $table_id
- ip route flush table $table_id 2>/dev/null
- }
- for l in $lines; do
- line=`echo -n "$config" | head -n $l | tail -n 1`
- dest=`echo -n "$line" | cut -d ' ' -f 2`
- gw=`echo -n "$line" | cut -d ' ' -f 3`
-
- via=""
- test -n "$gw" && {
- via="via $gw"
- }
-
- ip route add $dest $via dev $iface table $table_id
- done
+ ensure_ipv4_is_valid_addr "$1" "$ip"
+ add_routing_for_ip "$iface" "$ip"
# flush our route cache
- echo 1 > /proc/sys/net/ipv4/route/flush
- ctdb gratiousarp $ip $iface
+ set_proc sys/net/ipv4/route/flush 1
+ $CTDB gratiousarp "$ip" "$iface"
;;
- ################################################
- # called when ctdbd wants to claim an IP address
- updateip)
- if [ $# != 5 ]; then
- echo "must supply old interface, new interface, IP and maskbits"
- exit 1
- fi
+ updateip)
oiface=$2
niface=$3
ip=$4
maskbits=$5
- ipv4_is_valid_addr $ip || {
- echo "$0: $1 not an ipv4 address skipping IP:$ip"
- exit 0;
- }
-
- [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
- echo "$0: $1 No state directory found, waiting for startup."
- exit 0;
- }
-
- generate_per_ip_routing $ip $maskbits $niface "no" || {
- echo "$0: $1: generate_per_ip_routing $ip $maskbits $niface no - failed"
- exit 1;
- }
-
- config=`cat $CTDB_PER_IP_ROUTING_CONF`
- lines=`echo -n "$config" | grep -n "^$ip " | cut -d ':' -f1 | xargs`
-
- pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
-
- test -n "$lines" && {
- echo "ip rule del from $ip pref $pref table $table_id" >> $release_script
- echo "ip route flush table $table_id 2>/dev/null" >> $release_script
-
- ip rule del from $ip pref $pref 2>/dev/null
- ip rule add from $ip pref $pref table $table_id
- ip route flush table $table_id 2>/dev/null
- }
- for l in $lines; do
- line=`echo -n "$config" | head -n $l | tail -n 1`
- dest=`echo -n "$line" | cut -d ' ' -f 2`
- gw=`echo -n "$line" | cut -d ' ' -f 3`
-
- via=""
- test -n "$gw" && {
- via="via $gw"
- }
-
- ip route add $dest $via dev $niface table $table_id
- done
+ ensure_ipv4_is_valid_addr "$1" "$ip"
+ add_routing_for_ip "$niface" "$ip"
# flush our route cache
- echo 1 > /proc/sys/net/ipv4/route/flush
-
- ctdb gratiousarp $ip $niface
- tickle_tcp_connections $ip
+ set_proc sys/net/ipv4/route/flush 1
+ $CTDB gratiousarp "$ip" "$niface"
+ tickle_tcp_connections "$ip"
;;
- ##################################################
- # called when ctdbd wants to release an IP address
- releaseip)
- if [ $# != 4 ]; then
- echo "must supply interface, IP and maskbits"
- exit 1
- fi
-
+ releaseip)
iface=$2
ip=$3
maskbits=$4
- ipv4_is_valid_addr $ip || {
- echo "$0: $1 not an ipv4 address skipping IP:$ip"
- exit 0;
- }
-
- [ ! -d "$CTDB_PER_IP_ROUTING_STATE" ] && {
- echo "$0: $1 No state directory found, waiting for startup."
- exit 0;
- }
-
- generate_per_ip_routing $ip $maskbits $iface "yes" || {
- echo "$0: $1: generate_per_ip_routing $ip $maskbits $iface yes - failed"
- exit 1;
- }
-
- run_release_script_once "$release_script"
-
- ;;
-
-
- ###########################################
- # called when ctdbd has finished a recovery
- recovered)
+ ensure_ipv4_is_valid_addr "$1" "$ip"
+ del_routing_for_ip "$ip"
;;
- ####################################
- # called when ctdbd is shutting down
- shutdown)
+ ipreallocated)
+ add_missing_routes
+ remove_bogus_routes
;;
- monitor)
- ;;
*)
ctdb_standard_event_handler "$@"
;;
esac
exit 0
-