keepalived.init (10016B)
1 #!/bin/sh /etc/rc.common 2 # Copyright (C) 2007-2015 OpenWrt.org 3 4 START=70 5 STOP=01 6 7 USE_PROCD=1 8 9 KEEPALIVED_CONF=/tmp/keepalived.conf 10 11 INDENT_1=\\t 12 INDENT_2=$INDENT_1$INDENT_1 13 14 config_section_open() { 15 local tag=$1 16 local name=$2 17 18 printf "$tag" >> $KEEPALIVED_CONF 19 [ -n "$name" ] && printf " $name" >> $KEEPALIVED_CONF 20 printf " {\n" >> $KEEPALIVED_CONF 21 } 22 23 config_section_close() { 24 printf "}\n\n" >> $KEEPALIVED_CONF 25 } 26 27 config_foreach_wrapper() { 28 local section=$1 29 local function=$1 30 31 # Convention is that 'function' and 'section' are the same 32 config_foreach $function $section 33 } 34 35 print_elems_indent() { 36 local config=$1 37 shift 38 local indent=$1 39 shift 40 [ -z "$indent" ] && indent="$INDENT_1" 41 for opt in $*; do 42 local $opt 43 local no_val=0 44 if [ ${opt:0:7} == "no_val_" ]; then 45 opt=${opt:7} 46 no_val=1 47 fi 48 config_get $opt $config $opt 49 eval optval=\$$opt 50 [ -z "$optval" ] && continue 51 printf "$indent$opt" >> $KEEPALIVED_CONF 52 [ "$no_val" == "0" ] && printf " $optval" >> $KEEPALIVED_CONF 53 printf "\n" >> $KEEPALIVED_CONF 54 done 55 unset optval 56 } 57 58 print_list_indent() { 59 local lst=$1 60 local indent=$2 61 local lst_elems 62 [ -z "$indent" ] && indent=$INDENT_1 63 64 eval lst_elems=\$$lst 65 [ -z "$lst_elems" ] && return 0 66 67 printf "$indent$lst {\n" >> $KEEPALIVED_CONF 68 for e in $lst_elems; do 69 [ -n "$eval_item_func" ] 70 printf "$indent$INDENT_1$e\n" >> $KEEPALIVED_CONF 71 done 72 printf "$indent}\n" >> $KEEPALIVED_CONF 73 } 74 75 global_defs() { 76 local linkbeat_use_polling notification_email 77 78 config_get alt_config_file $1 alt_config_file 79 [ -z "$alt_config_file" ] || return 0 80 81 config_get_bool linkbeat_use_polling $1 linkbeat_use_polling 0 82 [ $linkbeat_use_polling -gt 0 ] && printf "linkbeat_use_polling\n\n" >> $KEEPALIVED_CONF 83 84 config_get notification_email $1 notification_email 85 print_list_indent notification_email 86 87 print_elems_indent $1 $INDENT_1 notification_email_from smtp_server smtp_connect_timeout \ 88 router_id vrrp_mcast_group4 vrrp_mcast_group6 89 } 90 91 print_ipaddress_indent() { 92 local section=$1 93 local curr_ipaddr=$2 94 local indent=$3 95 96 local address device scope name 97 config_get name $section name 98 [ "$name" != "$curr_ipaddr" ] && return 0 99 100 config_get address $section address 101 config_get device $section device 102 config_get scope $section scope 103 104 # Default indent 105 [ -z "$indent" ] && indent=$INDENT_1 106 107 # If no address or device exit 108 [ -z "$address" -o -z "$device" ] && return 0 109 110 # Add IP address/netmask and device 111 printf "$indent$address dev $device" >> $KEEPALIVED_CONF 112 # Add scope 113 [ -n "$scope" ] && printf " scope $scope" >> $KEEPALIVED_CONF 114 115 printf "\n" >> $KEEPALIVED_CONF 116 } 117 118 static_ipaddress() { 119 local address 120 config_get address "$1" address 121 for a in $address; do 122 config_foreach print_ipaddress_indent ipaddress $a 123 done 124 } 125 126 print_route_indent() { 127 local section=$1 128 local curr_route=$2 129 local indent=$3 130 131 local name blackhole address src_addr gateway device scope table 132 133 config_get name $section name 134 [ "$name" != "$curr_route" ] && return 0 135 136 config_get_bool blackhole $section blackhole 0 137 config_get address $section address 138 config_get src_addr $section src_addr 139 config_get gateway $section gateway 140 config_get device $section device 141 config_get table $section table 142 143 # If no address exit 144 [ -z "$address" ] && return 0 145 146 # Default indent 147 [ -z "$indent" ] && indent=$INDENT_1 148 149 [ $blackhole -gt 0 ] && { 150 printf "${indent}blackhole $address\n" >> $KEEPALIVED_CONF 151 return 0 152 } 153 # Add src addr or address 154 if [ -n "$src_addr" ]; then 155 printf "${indent}src $src_addr $address" >> $KEEPALIVED_CONF 156 else 157 [ -z "$device" ] && return 0 158 printf "$indent$address" >> $KEEPALIVED_CONF 159 fi 160 # Add route/gateway 161 [ -n "$gateway" ] && printf " via $gateway" >> $KEEPALIVED_CONF 162 # Add device 163 printf " dev $device" >> $KEEPALIVED_CONF 164 # Add scope 165 [ -n "$scope" ] && printf " scope $scope" >> $KEEPALIVED_CONF 166 # Add table 167 [ -n "$table" ] && printf " table $table" >> $KEEPALIVED_CONF 168 printf "\n" >> $KEEPALIVED_CONF 169 170 } 171 172 print_track_elem_indent() { 173 local section=$1 174 local curr_track_elem=$2 175 local indent=$3 176 177 local script name value 178 config_get name $section name 179 [ "$name" != "$curr_track_elem" ] && return 0 180 181 config_get value $section value 182 config_get weight $section weight 183 184 [ -z "$value" ] && return 0 185 186 printf "$indent$value" >> $KEEPALIVED_CONF 187 [ -n "$weight" ] && printf " weight $weight" >> $KEEPALIVED_CONF 188 printf "\n" >> $KEEPALIVED_CONF 189 } 190 191 static_routes() { 192 local route 193 config_get route "$1" route 194 for r in $route; do 195 config_foreach print_route_indent route $r 196 done 197 } 198 199 # Count 'vrrp_instance' with the given name ; called by vrrp_instance_check() 200 vrrp_instance_name_count() { 201 local name 202 config_get name $1 name 203 [ "$name" == "$2" ] && count=$((count + 1)) 204 } 205 206 # Check if there's a 'vrrp_instance' section with the given name 207 vrrp_instance_check() { 208 local count=0 209 local name=$1 210 config_foreach vrrp_instance_name_count vrrp_instance $name 211 [ $count -gt 0 ] && return 0 || return 1 212 } 213 214 vrrp_sync_group() { 215 local group name 216 local valid_group 217 218 # No name for group, exit 219 config_get name $1 name 220 [ -z "$name" ] && return 0 221 222 # No members for group, exit 223 config_get group $1 group 224 [ -z "$group" ] && return 0 225 226 # Check if we have 'vrrp_instance's defined for 227 # each member and remove names with not vrrp_instance defined 228 for m in $group; do 229 vrrp_instance_check $m && valid_group="$valid_group $m" 230 done 231 [ -z "$valid_group" ] && return 0 232 233 config_section_open "vrrp_sync_group" "$name" 234 235 group="$valid_group" 236 print_list_indent group 237 238 print_elems_indent $1 $INDENT_1 notify_backup notify_master notify_fault \ 239 notify no_val_smtp_alert no_val_global_tracking 240 config_section_close 241 } 242 243 vrrp_instance() { 244 local name auth_type auth_pass 245 246 config_get name $1 name 247 [ -z "$name" ] && return 0 248 249 config_section_open "vrrp_instance" "$name" 250 251 config_get auth_type $1 auth_type 252 config_get auth_pass $1 auth_pass 253 [ -n "$auth_type" -a -n "$auth_pass" ] && { 254 printf "${INDENT_1}authentication {\n" >> $KEEPALIVED_CONF 255 printf "${INDENT_2}auth_type $auth_type\n" >> $KEEPALIVED_CONF 256 printf "${INDENT_2}auth_pass $auth_pass\n" >> $KEEPALIVED_CONF 257 printf "$INDENT_1}\n" >> $KEEPALIVED_CONF 258 } 259 260 print_elems_indent $1 $INDENT_1 use_vmac state interface \ 261 mcast_src_ip unicast_src_ip virtual_router_id version priority \ 262 advert_int preempt_delay debug notify_backup \ 263 notify_master notify_fault notify_stop notify \ 264 lvs_sync_daemon_interface garp_master_delay garp_master_refresh \ 265 garp_master_repeat garp_master_refresh_repeat \ 266 no_val_vmac_xmit_base no_val_native_ipv6 no_val_accept \ 267 no_val_dont_track_primary no_val_smtp_alert no_val_nopreempt 268 269 # Handle virtual_ipaddress & virtual_ipaddress_excluded lists 270 for opt in virtual_ipaddress virtual_ipaddress_excluded; do 271 config_get $opt $1 $opt 272 eval optval=\$$opt 273 [ -z "$optval" ] && continue 274 printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF 275 for a in $optval; do 276 config_foreach print_ipaddress_indent ipaddress $a $INDENT_2 277 done 278 printf "$INDENT_1}\n" >> $KEEPALIVED_CONF 279 done 280 281 # Handle virtual_routes 282 for opt in virtual_routes; do 283 config_get $opt $1 $opt 284 eval optval=\$$opt 285 [ -z "$optval" ] && continue 286 printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF 287 for r in $optval; do 288 config_foreach print_route_indent route $r $INDENT_2 289 done 290 printf "$INDENT_1}\n" >> $KEEPALIVED_CONF 291 done 292 293 # Handle track_interface & track_script lists 294 for opt in track_interface track_script; do 295 config_get $opt $1 $opt 296 eval optval=\$$opt 297 [ -z "$optval" ] && continue 298 printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF 299 for t in $optval; do 300 printf "$INDENT_2$optval\n" >> $KEEPALIVED_CONF 301 done 302 printf "$INDENT_1}\n" >> $KEEPALIVED_CONF 303 done 304 305 # Handle simple lists of strings (with no spaces in between) 306 for opt in unicast_peer; do 307 config_get $opt $1 $opt 308 print_list_indent $opt 309 done 310 unset optval 311 312 config_section_close 313 } 314 315 vrrp_script() { 316 local name 317 318 config_get name $1 name 319 [ -z "$name" ] && return 0 320 321 config_section_open "vrrp_script" "$name" 322 323 print_elems_indent $1 $INDENT_1 script interval weight fall rise 324 325 config_section_close 326 } 327 328 process_config() { 329 local alt_config_file 330 331 rm -f $KEEPALIVED_CONF 332 333 # First line 334 printf "! Configuration File for keepalived (autogenerated via init script)\n\n" > $KEEPALIVED_CONF 335 336 [ -f /etc/config/keepalived ] || return 0 337 config_load 'keepalived' 338 339 config_section_open "global_defs" 340 config_foreach_wrapper global_defs 341 config_section_close 342 343 # If "alt_config_file" specified, use that instead 344 [ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && { 345 rm -f $KEEPALIVED_CONF 346 # Symlink "alt_config_file" since it's a bit easier and safer 347 ln -s $alt_config_file $KEEPALIVED_CONF 348 return 0 349 } 350 351 config_section_open "static_ipaddress" 352 config_foreach_wrapper static_ipaddress 353 config_section_close 354 355 config_section_open "static_routes" 356 config_foreach_wrapper static_routes 357 config_section_close 358 359 config_foreach_wrapper vrrp_script 360 config_foreach_wrapper vrrp_sync_group 361 config_foreach_wrapper vrrp_instance 362 return 0 363 } 364 365 service_running() { 366 pgrep -x /usr/sbin/keepalived &> /dev/null 367 } 368 369 conf_md5() { 370 echo "$(md5sum $KEEPALIVED_CONF | awk '{print $1}')" 371 } 372 373 reload_service() { 374 local cur_md5="$(conf_md5)" 375 running && { 376 process_config 377 378 # Return without performing the reload if config 379 # file md5sum has not changed 380 local new_md5="$(conf_md5)" 381 [ "$new_md5" == "$cur_md5" ] && return 0; 382 383 # SIGHUP is used by keepalived to do init.d reload 384 # Get the oldest process (assumption is that it's the parent process) 385 PID=$(pgrep -o /usr/sbin/keepalived) 386 kill -SIGHUP $PID 387 return 0 388 } 389 return 1 390 } 391 392 start_service() { 393 procd_open_instance 394 procd_set_param command /usr/sbin/keepalived 395 procd_append_param command -n # don't daemonize, procd will handle that for us 396 procd_append_param command -f "$KEEPALIVED_CONF" 397 398 process_config 399 400 # set auto respawn behavior 401 procd_set_param respawn 402 procd_close_instance 403 } 404