--- /dev/null
+#config global_defs
+# option alt_config_file "/etc/keepalived/keepalived.conf"
+# list notification_email "acassen@firewall.loc"
+# list notification_email "failover@firewall.loc"
+# list notification_email "sysadmin@firewall.loc"
+# option notification_email_from "Alexandre.Cassen@firewall.loc"
+# option smtp_server "192.168.200.1"
+# option smtp_connect_timeout "30"
+# option router_id "LVS_DEVEL"
+# option vrrp_mcast_group4 "224.0.0.18" # optional, default 224.0.0.18
+# option vrrp_mcast_group6 "f02::12" # optional, default ff02::12
+# option linkbeat_use_polling "1"
+
+#config ipaddress
+# option name "ipaddress0"
+# option address "192.168.1.1/24"
+# option device "eth0"
+# option scope "global"
+
+#config ipaddress
+# option name "ipaddress1"
+# option address "192.168.1.2/24"
+# option device "eth1"
+# option scope "global"
+
+#config ipaddress
+# option name "ipaddress2"
+# option address "192.168.1.1/24"
+# option device "eth0"
+# option scope "link"
+
+#config ipaddress
+# option name "ipaddress3"
+# option address "192.168.1.2/24"
+# option device "eth2"
+# option scope "site"
+
+#config ipaddress
+# option name "ipaddress4"
+# option address "192.168.1.1/24"
+# option device "eth0"
+# option scope "host"
+
+#config ipaddress
+# option name "ipaddress5"
+# option address "192.168.1.2/24"
+# option device "eth0"
+# option scope "nowhere"
+
+#config route
+# option name "route0"
+# option address "192.168.1.1/24"
+# option gateway "192.168.0.1"
+# option device "eth0"
+
+#config route
+# option name "route1"
+# option address "192.168.2.1/24"
+# option gateway "192.168.0.1"
+# option device "eth0"
+
+#config route
+# option name "route2"
+# option address "127.0.0.1"
+# option blackhole "1"
+
+#config static_ipaddress
+# list address "ipaddress0"
+# list address "ipaddress1"
+
+#config static_routes
+# list route "route0"
+# list route "route1"
+
+#config vrrp_sync_group
+# option name "VI_sync_group_1"
+# list group "VI_1"
+# list group "VI_2"
+# option smtp_alert "1"
+# option notify_backup "<switch-backup-state-script>"
+# option notify_master "<switch-master-state-script>"
+# option notify_fault "<switch-fault-state-script>"
+# option notify "<switch-any-state-script>"
+# option global_tracking 1
+
+#config track_interface
+# option name "track_intf1"
+# option value "eth0"
+# option weight "1"
+
+#config track_interface
+# option name "track_intf2"
+# option value "eth1"
+# option weight "2"
+
+#config track_script
+# option name "track_script1"
+# option value "<script-file1>"
+# option weight "1"
+
+#config track_script
+# option name "track_script2"
+# option value "<script-file2>"
+# option weight "2"
+
+#config vrrp_instance
+# option name "VI_1"
+# option use_vmac "eth0"
+# option native_ipv6 "1"
+# option state "MASTER"
+# option interface "eth0"
+# list track_interface "track_intf1"
+# list track_interface "track_intf2"
+# list track_script "track_script1"
+# list track_script "track_script2"
+# option dont_track_primary "1"
+# list unicast_peer "192.168.0.1"
+# list unicast_peer "192.168.1.1"
+# list virtual_ipaddress "ipaddress2"
+# list virtual_ipaddress "ipaddress3"
+# list virtual_ipaddress_excluded "ipaddress4"
+# list virtual_ipaddress_excluded "ipaddress5"
+# list virtual_routes "route1"
+# list virtual_routes "route2"
+# option mcast_src_ip "224.0.0.1"
+# option unicast_src_ip "192.168.0.1"
+# option virtual_router_id "128"
+# option priority "128"
+# option advert_int "5"
+# option nopreempt "1"
+# option preempt_delay "500"
+# option debug "2"
+# option notify_backup "<switch-backup-state-script>"
+# option notify_master "<switch-master-state-script>"
+# option notify_fault "<switch-fault-state-script>"
+# option notify_stop "<switch-stop-state-script>"
+# option notify "<switch-any-state-script>"
+# option smtp_alert "1"
+# option accept "1"
+
+#config vrrp_script
+# option script "<script-file>"
+# option interval "5"
+# option weight "10"
+# option fall "2"
+# option rise "3"
+
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"
+
+ # 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
+ config_foreach print_track_elem_indent $opt $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_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
+
+ 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_sync_group
+ config_foreach_wrapper vrrp_instance
+ config_foreach_wrapper vrrp_script
+ 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