|
|
- #!/bin/sh /etc/rc.common
- # Copyright (C) 2007-2015 OpenWrt.org
-
- START=70
- STOP=01
-
- USE_PROCD=1
-
- KEEPALIVED_CONF=/tmp/keepalived.conf
-
- INDENT_1=\\t
- INDENT_2=$INDENT_1$INDENT_1
-
- config_section_open() {
- local tag=$1
- local name=$2
-
- printf "$tag" >> $KEEPALIVED_CONF
- [ -n "$name" ] && printf " $name" >> $KEEPALIVED_CONF
- printf " {\n" >> $KEEPALIVED_CONF
- }
-
- config_section_close() {
- printf "}\n\n" >> $KEEPALIVED_CONF
- }
-
- config_foreach_wrapper() {
- local section=$1
- local function=$1
-
- # Convention is that 'function' and 'section' are the same
- config_foreach $function $section
- }
-
- print_elems_indent() {
- local config=$1
- shift
- local indent=$1
- shift
- [ -z "$indent" ] && indent="$INDENT_1"
- for opt in $*; do
- local $opt
- local no_val=0
- if [ ${opt:0:7} == "no_val_" ]; then
- opt=${opt:7}
- no_val=1
- fi
- config_get $opt $config $opt
- eval optval=\$$opt
- [ -z "$optval" ] && continue
- printf "$indent$opt" >> $KEEPALIVED_CONF
- [ "$no_val" == "0" ] && {
- local words=$(echo "$optval" | wc -w)
- if [ $words -gt 1 ]; then
- printf " \"$optval\"" >> $KEEPALIVED_CONF
- else
- printf " $optval" >> $KEEPALIVED_CONF
- fi
- }
- printf "\n" >> $KEEPALIVED_CONF
- done
- unset optval
- }
-
- print_list_indent() {
- local lst=$1
- local indent=$2
- local lst_elems
- [ -z "$indent" ] && indent=$INDENT_1
-
- eval lst_elems=\$$lst
- [ -z "$lst_elems" ] && return 0
-
- printf "$indent$lst {\n" >> $KEEPALIVED_CONF
- for e in $lst_elems; do
- [ -n "$eval_item_func" ]
- printf "$indent$INDENT_1$e\n" >> $KEEPALIVED_CONF
- done
- printf "$indent}\n" >> $KEEPALIVED_CONF
- }
-
- print_notify() {
- local type=$1
- shift
- local name=$1
- shift
- for notify in $*; do
- printf "$INDENT_1$notify" >> $KEEPALIVED_CONF
- notify=$(echo $notify | tr 'a-z' 'A-Z')
- printf " \"/bin/busybox env -i ACTION=$notify TYPE=$type NAME=$name /sbin/hotplug-call keepalived\"\n" >> $KEEPALIVED_CONF
- done
- }
-
- global_defs() {
- local linkbeat_use_polling notification_email
-
- config_get alt_config_file $1 alt_config_file
- [ -z "$alt_config_file" ] || return 0
-
- config_get_bool linkbeat_use_polling $1 linkbeat_use_polling 0
- [ $linkbeat_use_polling -gt 0 ] && printf "linkbeat_use_polling\n\n" >> $KEEPALIVED_CONF
-
- config_get notification_email $1 notification_email
- print_list_indent notification_email
-
- print_elems_indent $1 $INDENT_1 notification_email_from smtp_server smtp_connect_timeout \
- router_id vrrp_mcast_group4 vrrp_mcast_group6
- }
-
- print_ipaddress_indent() {
- local section=$1
- local curr_ipaddr=$2
- local indent=$3
-
- local address device scope name
- config_get name $section name
- [ "$name" != "$curr_ipaddr" ] && return 0
-
- config_get address $section address
- config_get device $section device
- config_get scope $section scope
-
- # Default indent
- [ -z "$indent" ] && indent=$INDENT_1
-
- # If no address or device exit
- [ -z "$address" -o -z "$device" ] && return 0
-
- # Add IP address/netmask and device
- printf "$indent$address dev $device" >> $KEEPALIVED_CONF
- # Add scope
- [ -n "$scope" ] && printf " scope $scope" >> $KEEPALIVED_CONF
-
- printf "\n" >> $KEEPALIVED_CONF
- }
-
- static_ipaddress() {
- local address
- config_get address "$1" address
- for a in $address; do
- config_foreach print_ipaddress_indent ipaddress $a
- done
- }
-
- print_route_indent() {
- local section=$1
- local curr_route=$2
- local indent=$3
-
- local name blackhole address src_addr gateway device scope table
-
- config_get name $section name
- [ "$name" != "$curr_route" ] && return 0
-
- config_get_bool blackhole $section blackhole 0
- config_get address $section address
- config_get src_addr $section src_addr
- config_get gateway $section gateway
- config_get device $section device
- config_get table $section table
-
- # If no address exit
- [ -z "$address" ] && return 0
-
- # Default indent
- [ -z "$indent" ] && indent=$INDENT_1
-
- [ $blackhole -gt 0 ] && {
- printf "${indent}blackhole $address\n" >> $KEEPALIVED_CONF
- return 0
- }
- # Add src addr or address
- if [ -n "$src_addr" ]; then
- printf "${indent}src $src_addr $address" >> $KEEPALIVED_CONF
- else
- [ -z "$device" ] && return 0
- printf "$indent$address" >> $KEEPALIVED_CONF
- fi
- # Add route/gateway
- [ -n "$gateway" ] && printf " via $gateway" >> $KEEPALIVED_CONF
- # Add device
- printf " dev $device" >> $KEEPALIVED_CONF
- # Add scope
- [ -n "$scope" ] && printf " scope $scope" >> $KEEPALIVED_CONF
- # Add table
- [ -n "$table" ] && printf " table $table" >> $KEEPALIVED_CONF
- printf "\n" >> $KEEPALIVED_CONF
-
- }
-
- print_track_elem_indent() {
- local section=$1
- local curr_track_elem=$2
- local indent=$3
-
- local script name value
- config_get name $section name
- [ "$name" != "$curr_track_elem" ] && return 0
-
- config_get value $section value
- config_get weight $section weight
-
- [ -z "$value" ] && return 0
-
- printf "$indent$value" >> $KEEPALIVED_CONF
- [ -n "$weight" ] && printf " weight $weight" >> $KEEPALIVED_CONF
- printf "\n" >> $KEEPALIVED_CONF
- }
-
- static_routes() {
- local route
- config_get route "$1" route
- for r in $route; do
- config_foreach print_route_indent route $r
- done
- }
-
- # Count 'vrrp_instance' with the given name ; called by vrrp_instance_check()
- vrrp_instance_name_count() {
- local name
- config_get name $1 name
- [ "$name" == "$2" ] && count=$((count + 1))
- }
-
- # Check if there's a 'vrrp_instance' section with the given name
- vrrp_instance_check() {
- local count=0
- local name=$1
- config_foreach vrrp_instance_name_count vrrp_instance $name
- [ $count -gt 0 ] && return 0 || return 1
- }
-
- vrrp_sync_group() {
- local group name
- local valid_group
-
- # No name for group, exit
- config_get name $1 name
- [ -z "$name" ] && return 0
-
- # No members for group, exit
- config_get group $1 group
- [ -z "$group" ] && return 0
-
- # Check if we have 'vrrp_instance's defined for
- # each member and remove names with not vrrp_instance defined
- for m in $group; do
- vrrp_instance_check $m && valid_group="$valid_group $m"
- done
- [ -z "$valid_group" ] && return 0
-
- config_section_open "vrrp_sync_group" "$name"
-
- group="$valid_group"
- print_list_indent group
-
- print_elems_indent $1 $INDENT_1 no_val_smtp_alert no_val_global_tracking
-
- print_notify "GROUP" "$name" notify_backup notify_master \
- notify_fault notify
-
- config_section_close
- }
-
- vrrp_instance() {
- local name auth_type auth_pass
-
- config_get name $1 name
- [ -z "$name" ] && return 0
-
- config_section_open "vrrp_instance" "$name"
-
- config_get auth_type $1 auth_type
- config_get auth_pass $1 auth_pass
- [ -n "$auth_type" -a -n "$auth_pass" ] && {
- printf "${INDENT_1}authentication {\n" >> $KEEPALIVED_CONF
- printf "${INDENT_2}auth_type $auth_type\n" >> $KEEPALIVED_CONF
- printf "${INDENT_2}auth_pass $auth_pass\n" >> $KEEPALIVED_CONF
- printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
- }
-
- print_elems_indent $1 $INDENT_1 use_vmac state interface \
- mcast_src_ip unicast_src_ip virtual_router_id version priority \
- advert_int preempt_delay debug \
- lvs_sync_daemon_interface garp_master_delay garp_master_refresh \
- garp_master_repeat garp_master_refresh_repeat \
- no_val_vmac_xmit_base no_val_native_ipv6 no_val_accept \
- no_val_dont_track_primary no_val_smtp_alert no_val_nopreempt
-
- print_notify "INSTANCE" "$name" notify_backup notify_master \
- notify_fault notify_stop notify
-
- # Handle virtual_ipaddress & virtual_ipaddress_excluded lists
- for opt in virtual_ipaddress virtual_ipaddress_excluded; do
- config_get $opt $1 $opt
- eval optval=\$$opt
- [ -z "$optval" ] && continue
- printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
- for a in $optval; do
- config_foreach print_ipaddress_indent ipaddress $a $INDENT_2
- done
- printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
- done
-
- # Handle virtual_routes
- for opt in virtual_routes; do
- config_get $opt $1 $opt
- eval optval=\$$opt
- [ -z "$optval" ] && continue
- printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
- for r in $optval; do
- config_foreach print_route_indent route $r $INDENT_2
- done
- printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
- done
-
- # Handle track_script lists
- for opt in track_script; do
- config_get $opt $1 $opt
- eval optval=\$$opt
- [ -z "$optval" ] && continue
- printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
- for t in $optval; do
- printf "$INDENT_2$optval\n" >> $KEEPALIVED_CONF
- done
- printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
- done
-
- # Handle track_interface lists
- for opt in track_interface; do
- config_get $opt $1 $opt
- eval optval=\$$opt
- [ -z "$optval" ] && continue
- printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
- for t in $optval; do
- config_foreach print_track_elem_indent track_interface $t $INDENT_2
- done
- printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
- done
-
- # Handle simple lists of strings (with no spaces in between)
- for opt in unicast_peer; do
- config_get $opt $1 $opt
- print_list_indent $opt
- done
- unset optval
-
- config_section_close
- }
-
- vrrp_script() {
- local name
-
- config_get name $1 name
- [ -z "$name" ] && return 0
-
- config_section_open "vrrp_script" "$name"
-
- print_elems_indent $1 $INDENT_1 script interval weight fall rise
-
- config_section_close
- }
-
- process_config() {
- local alt_config_file
-
- rm -f $KEEPALIVED_CONF
-
- # First line
- printf "! Configuration File for keepalived (autogenerated via init script)\n\n" > $KEEPALIVED_CONF
-
- [ -f /etc/config/keepalived ] || return 0
- config_load 'keepalived'
-
- config_section_open "global_defs"
- config_foreach_wrapper global_defs
- config_section_close
-
- # If "alt_config_file" specified, use that instead
- [ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && {
- rm -f $KEEPALIVED_CONF
- # Symlink "alt_config_file" since it's a bit easier and safer
- ln -s $alt_config_file $KEEPALIVED_CONF
- return 0
- }
-
- config_section_open "static_ipaddress"
- config_foreach_wrapper static_ipaddress
- config_section_close
-
- config_section_open "static_routes"
- config_foreach_wrapper static_routes
- config_section_close
-
- config_foreach_wrapper vrrp_script
- config_foreach_wrapper vrrp_sync_group
- config_foreach_wrapper vrrp_instance
- return 0
- }
-
- service_running() {
- pgrep -x /usr/sbin/keepalived &> /dev/null
- }
-
- conf_md5() {
- echo "$(md5sum $KEEPALIVED_CONF | awk '{print $1}')"
- }
-
- reload_service() {
- local cur_md5="$(conf_md5)"
- running && {
- process_config
-
- # Return without performing the reload if config
- # file md5sum has not changed
- local new_md5="$(conf_md5)"
- [ "$new_md5" == "$cur_md5" ] && return 0;
-
- # SIGHUP is used by keepalived to do init.d reload
- # Get the oldest process (assumption is that it's the parent process)
- PID=$(pgrep -o /usr/sbin/keepalived)
- kill -SIGHUP $PID
- return 0
- }
- return 1
- }
-
- start_service() {
- procd_open_instance
- procd_set_param command /usr/sbin/keepalived
- procd_append_param command -n # don't daemonize, procd will handle that for us
- procd_append_param command -f "$KEEPALIVED_CONF"
-
- process_config
-
- # set auto respawn behavior
- procd_set_param respawn
- procd_close_instance
- }
-
|