mirror of
https://github.com/openwrt/packages.git
synced 2025-12-21 23:34:31 +04:00
keepalived seems to be rather particular about which config parameters come before others. When defining a virtual IP address, keepalived will check to see if the vrrp instance is associated with a valid interface. Previously, the interface parameter was declared after the virtual IP address which caused an error when keepalived tried to run this check. Keepalived tries to fall back to checking if 'eth0' exists. The fix is to re-order the config stanzas so that the interface parameter comes before the virtual IP address definitions. Signed-off-by: Ben Kelly <ben@benjii.net> Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
394 lines
9.5 KiB
Bash
394 lines
9.5 KiB
Bash
#!/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" ] && printf " $optval" >> $KEEPALIVED_CONF
|
|
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
|
|
}
|
|
|
|
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 notify_backup notify_master notify_fault \
|
|
notify no_val_smtp_alert no_val_global_tracking
|
|
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 notify_backup \
|
|
notify_master notify_fault notify_stop notify \
|
|
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
|
|
|
|
# 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_interface & track_script lists
|
|
for opt in track_interface 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 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
|
|
}
|
|
|
|
reload_service() {
|
|
running && {
|
|
process_config
|
|
# 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
|
|
}
|
|
|