fwknop: init script improvements
[feed/packages.git] / net / keepalived / files / keepalived.init
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 INDENT_3="${INDENT_1}${INDENT_1}${INDENT_1}"
14 INDENT_4="${INDENT_1}${INDENT_1}${INDENT_1}${INDENT_1}"
15
16 config_section_open() {
17 local tag="$1"
18 local name="$2"
19
20 printf '%s' "$tag" >> "$KEEPALIVED_CONF"
21 [ -n "$name" ] && printf ' %s' "$name" >> "$KEEPALIVED_CONF"
22 printf ' {\n' >> "$KEEPALIVED_CONF"
23 }
24
25 config_section_close() {
26 printf '}\n\n' >> "$KEEPALIVED_CONF"
27 }
28
29 config_foreach_wrapper() {
30 local section="$1"
31 local function="$1"
32
33 # Convention is that 'function' and 'section' are the same
34 config_foreach "$function" "$section"
35 }
36
37 print_elems_indent() {
38 local config="$1"
39 shift
40 local indent="$1"
41 shift
42
43 [ -z "$indent" ] && indent="$INDENT_1"
44 for opt in "$@"; do
45 local "$opt"
46 local optval
47 local no_val=0
48 if [ "${opt:0:7}" = "no_val_" ]; then
49 opt="${opt:7}"
50 no_val=1
51 fi
52 config_get "$opt" "$config" "$opt"
53 eval optval=\$"$opt"
54 [ -z "$optval" ] && continue
55 printf '%b%s' "$indent" "$opt" >> "$KEEPALIVED_CONF"
56 [ "$no_val" = "0" ] && {
57 local words=0
58 words="$(echo "$optval" | wc -w)"
59 if [ "$words" -gt 1 ]; then
60 printf ' "%s"' "$optval" >> "$KEEPALIVED_CONF"
61 else
62 printf ' %s' "$optval" >> "$KEEPALIVED_CONF"
63 fi
64 }
65 printf '\n' >> "$KEEPALIVED_CONF"
66 done
67 unset optval
68 }
69
70 print_list_indent() {
71 local lst="$1"
72 local indent="$2"
73 local lst_elems
74 [ -z "$indent" ] && indent="$INDENT_1"
75
76 eval lst_elems=\$"$lst"
77 [ -z "$lst_elems" ] && return 0
78
79 printf '%b%s {\n' "$indent" "$lst" >> "$KEEPALIVED_CONF"
80 for e in $lst_elems; do
81 printf '%b%s\n' "${indent}${INDENT_1}" "$e">> "$KEEPALIVED_CONF"
82 done
83 printf '%b}\n' "$indent" >> "$KEEPALIVED_CONF"
84 }
85
86 print_notify() {
87 local type="$1"
88 shift
89 local name="$1"
90 shift
91 for notify in "$@"; do
92 printf '%b%s' "${INDENT_1}" "$notify">> "$KEEPALIVED_CONF"
93 notify="$(echo "$notify" | tr 'a-z' 'A-Z')"
94 printf ' "/bin/busybox env -i ACTION=%s TYPE=%s NAME=%s /sbin/hotplug-call keepalived"\n' "$notify" "$type" "$name" >> "$KEEPALIVED_CONF"
95 done
96 }
97
98 global_defs() {
99 local linkbeat_use_polling notification_email
100
101 config_get alt_config_file "$1" alt_config_file
102 [ -z "$alt_config_file" ] || return 0
103
104 config_get_bool linkbeat_use_polling "$1" linkbeat_use_polling 0
105 [ "$linkbeat_use_polling" -gt 0 ] && printf 'linkbeat_use_polling\n\n' >> "$KEEPALIVED_CONF"
106
107 config_get notification_email "$1" notification_email
108 print_list_indent notification_email
109
110 print_elems_indent "$1" "$INDENT_1" \
111 notification_email_from \
112 smtp_server \
113 smtp_connect_timeout \
114 router_id \
115 vrrp_mcast_group4 \
116 vrrp_mcast_group6 \
117 vrrp_startup_delay
118 }
119
120 print_ipaddress_indent() {
121 local section="$1"
122 local curr_ipaddr="$2"
123 local indent="$3"
124
125 local address device scope name
126 config_get name "$section" name
127 [ "$name" != "$curr_ipaddr" ] && return 0
128
129 config_get address "$section" address
130 config_get device "$section" device
131 config_get scope "$section" scope
132
133 # Default indent
134 [ -z "$indent" ] && indent="$INDENT_1"
135
136 # If no address exit
137 [ -z "$address" ] && return 0
138
139 if [ -z "$device" ]; then
140 printf '%b%s' "$indent" "$address" >> "$KEEPALIVED_CONF"
141 else
142 # Add IP address/netmask and device
143 printf '%b%s dev %s' "$indent" "$address" "$device">> "$KEEPALIVED_CONF"
144 # Add scope
145 [ -n "$scope" ] && printf ' scope %s' "$scope" >> "$KEEPALIVED_CONF"
146 fi
147
148 printf '\n' >> "$KEEPALIVED_CONF"
149 }
150
151 static_ipaddress() {
152 local address
153 config_get address "$1" address
154 for a in $address; do
155 config_foreach print_ipaddress_indent ipaddress "$a"
156 done
157 }
158
159 print_route_indent() {
160 local section="$1"
161 local curr_route="$2"
162 local indent="$3"
163
164 local name blackhole address src_addr gateway device scope table
165
166 config_get name "$section" name
167 [ "$name" != "$curr_route" ] && return 0
168
169 config_get_bool blackhole "$section" blackhole 0
170 config_get address "$section" address
171 config_get src_addr "$section" src_addr
172 config_get gateway "$section" gateway
173 config_get device "$section" device
174 config_get table "$section" table
175
176 # If no address exit
177 [ -z "$address" ] && return 0
178
179 # Default indent
180 [ -z "$indent" ] && indent="$INDENT_1"
181
182 [ "$blackhole" -gt 0 ] && {
183 printf '%bblackhole %s\n' "$indent" "$address" >> "$KEEPALIVED_CONF"
184 return 0
185 }
186 # Add src addr or address
187 if [ -n "$src_addr" ]; then
188 printf '%bsrc %s %s' "$indent" "$src_addr" "$address" >> "$KEEPALIVED_CONF"
189 else
190 [ -z "$device" ] && return 0
191 printf '%b%s' "$indent" "$address" >> "$KEEPALIVED_CONF"
192 fi
193 # Add route/gateway
194 [ -n "$gateway" ] && printf ' via %s' "$gateway" >> "$KEEPALIVED_CONF"
195 # Add device
196 printf ' dev %s' "$device" >> "$KEEPALIVED_CONF"
197 # Add scope
198 [ -n "$scope" ] && printf ' scope %s' "$scope" >> "$KEEPALIVED_CONF"
199 # Add table
200 [ -n "$table" ] && printf ' table %s' "$table" >> "$KEEPALIVED_CONF"
201 printf '\n' >> "$KEEPALIVED_CONF"
202
203 }
204
205 print_track_elem_indent() {
206 local section="$1"
207 local curr_track_elem="$2"
208 local indent="$3"
209
210 local name value
211 config_get name "$section" name
212 [ "$name" != "$curr_track_elem" ] && return 0
213
214 config_get value "$section" value
215 config_get weight "$section" weight
216
217 [ -z "$value" ] && return 0
218
219 printf '%b%s' "$indent" "$value" >> "$KEEPALIVED_CONF"
220 [ -n "$weight" ] && printf ' weight %s' "$weight" >> "$KEEPALIVED_CONF"
221 printf '\n' >> "$KEEPALIVED_CONF"
222 }
223
224 static_routes() {
225 local route
226 config_get route "$1" route
227 for r in $route; do
228 config_foreach print_route_indent route "$r"
229 done
230 }
231
232 # Count 'vrrp_instance' with the given name ; called by vrrp_instance_check()
233 vrrp_instance_name_count() {
234 local name
235 config_get name "$1" name
236 [ "$name" = "$2" ] && count="$((count + 1))"
237 }
238
239 # Check if there's a 'vrrp_instance' section with the given name
240 vrrp_instance_check() {
241 local count="0"
242 local name="$1"
243 config_foreach vrrp_instance_name_count vrrp_instance "$name"
244 [ $count -gt 0 ] && return 0 || return 1
245 }
246
247 vrrp_sync_group() {
248 local group name
249 local valid_group
250
251 # No name for group, exit
252 config_get name "$1" name
253 [ -z "$name" ] && return 0
254
255 # No members for group, exit
256 config_get group "$1" group
257 [ -z "$group" ] && return 0
258
259 # Check if we have 'vrrp_instance's defined for
260 # each member and remove names with not vrrp_instance defined
261 for m in $group; do
262 vrrp_instance_check "$m" && valid_group="$valid_group $m"
263 done
264 [ -z "$valid_group" ] && return 0
265
266 config_section_open "vrrp_sync_group" "$name"
267
268 group="$valid_group"
269 print_list_indent group
270
271 print_elems_indent "$1" "$INDENT_1" no_val_smtp_alert no_val_global_tracking
272
273 print_notify "GROUP" "$name" notify_backup notify_master \
274 notify_fault notify
275
276 config_section_close
277 }
278
279 vrrp_instance() {
280 local name auth_type auth_pass
281
282 config_get name "$1" name
283 [ -z "$name" ] && return 0
284
285 config_section_open "vrrp_instance" "$name"
286
287 config_get auth_type "$1" auth_type
288 config_get auth_pass "$1" auth_pass
289 [ -n "$auth_type" ] && [ -n "$auth_pass" ] && {
290 printf '%bauthentication {\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
291 printf '%bauth_type %s\n' "${INDENT_2}" "$auth_type" >> "$KEEPALIVED_CONF"
292 printf '%bauth_pass %s\n' "${INDENT_2}" "$auth_pass" >> "$KEEPALIVED_CONF"
293 printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
294 }
295
296 print_elems_indent "$1" "$INDENT_1" state interface \
297 mcast_src_ip unicast_src_ip virtual_router_id version priority \
298 advert_int preempt_delay debug \
299 lvs_sync_daemon_interface garp_master_delay garp_master_refresh \
300 garp_master_repeat garp_master_refresh_repeat \
301 no_val_vmac_xmit_base no_val_native_ipv6 no_val_accept \
302 no_val_dont_track_primary no_val_smtp_alert no_val_nopreempt \
303 no_val_use_vmac
304
305 print_notify "INSTANCE" "$name" notify_backup notify_master \
306 notify_fault notify_stop
307
308 # Handle virtual_ipaddress & virtual_ipaddress_excluded lists
309 for opt in virtual_ipaddress virtual_ipaddress_excluded; do
310 config_get "$opt" "$1" "$opt"
311 eval optval=\$$opt
312 [ -z "$optval" ] && continue
313 printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
314 for a in $optval; do
315 config_foreach print_ipaddress_indent ipaddress "$a" "$INDENT_2"
316 done
317 printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
318 done
319
320 # Handle virtual_routes
321 for opt in virtual_routes; do
322 config_get "$opt" "$1" "$opt"
323 eval optval=\$$opt
324 [ -z "$optval" ] && continue
325 printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
326 for r in $optval; do
327 config_foreach print_route_indent route "$r" "$INDENT_2"
328 done
329 printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
330 done
331
332 # Handle track_script lists
333 for opt in track_script; do
334 config_get "$opt" "$1" "$opt"
335 eval optval=\$$opt
336 [ -z "$optval" ] && continue
337 printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
338 for t in $optval; do
339 printf '%b%s\n' "${INDENT_2}" "$optval" >> "$KEEPALIVED_CONF"
340 done
341 printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
342 done
343
344 # Handle track_interface lists
345 for opt in track_interface; do
346 config_get "$opt" "$1" "$opt"
347 eval optval=\$$opt
348 [ -z "$optval" ] && continue
349 printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
350 for t in $optval; do
351 config_foreach print_track_elem_indent track_interface "$t" "$INDENT_2"
352 done
353 printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
354 done
355
356 # Handle simple lists of strings (with no spaces in between)
357 for opt in unicast_peer; do
358 config_get "$opt" "$1" "$opt"
359 print_list_indent "$opt"
360 done
361 unset optval
362
363 config_section_close
364 }
365
366 vrrp_script() {
367 local name
368
369 config_get name "$1" name
370 [ -z "$name" ] && return 0
371
372 config_section_open "vrrp_script" "$name"
373
374 print_elems_indent "$1" "$INDENT_1" script interval weight fall rise
375
376 config_section_close
377 }
378
379 url() {
380 local url="$2"
381
382 local name path digest
383
384 config_get name "$1" name
385 [ "$url" = "$name" ] || return 0
386
387 config_get path "$1" path
388 config_get digest "$1" digest
389
390 [ -n "$digest" ] && [ -n "$path" ] && {
391 printf '%burl {\n' "${INDENT_3}" >> "$KEEPALIVED_CONF"
392 printf '%bpath %s\n' "${INDENT_4}" "$path" >> "$KEEPALIVED_CONF"
393 printf '%bdigest %s\n' "${INDENT_4}" "$digest" >> "$KEEPALIVED_CONF"
394 printf '%b}\n' "${INDENT_3}" >> "$KEEPALIVED_CONF"
395 }
396 }
397
398 url_list() {
399 config_foreach url url "$1"
400 }
401
402 real_server() {
403 local server="$2"
404
405 local enabled name weight ipaddr port check
406
407 config_get_bool enabled "$1" enabled 1
408 [ "$enabled" -eq 1 ] || return 0
409
410 config_get name "$1" name
411 [ "$server" = "$name" ] || return 0
412
413 config_get weight "$1" weight
414 [ -n "$weight" ] || return 0
415
416 config_get ipaddr "$1" ipaddr
417 config_get port "$1" port
418 config_get check "$1" check
419
420 [ -n "$ipaddr" ] && [ -n "$port" ] && {
421 printf '%breal_server %s %d {\n' "${INDENT_1}" "$ipaddr" "$port" >> "$KEEPALIVED_CONF"
422 printf '%bweight %d\n' "${INDENT_2}" "$weight" >> "$KEEPALIVED_CONF"
423 case "$check" in
424 TCP_CHECK)
425 printf '%b%s {\n' "${INDENT_2}" "$check" >> "$KEEPALIVED_CONF"
426 print_elems_indent "$1" "$INDENT_3" connect_timeout \
427 connect_port
428 printf '%b}\n' "${INDENT_2}" >> "$KEEPALIVED_CONF"
429 ;;
430 MISC_CHECK)
431 printf '%b%s {\n' "${INDENT_2}" "$check" >> "$KEEPALIVED_CONF"
432 print_elems_indent "$1" "$INDENT_3" misc_path
433 printf '%b}\n' "${INDENT_2}" >> "$KEEPALIVED_CONF"
434 ;;
435 HTTP_GET | SSL_GET)
436 printf '%b%s {\n' "${INDENT_2}" "$check" >> "$KEEPALIVED_CONF"
437 print_elems_indent "$1" "$INDENT_3" connect_timeout \
438 connect_port nb_get_retry delay_before_retry
439 # Handle url list
440 config_list_foreach "$1" url url_list
441 printf '%b}\n' "${INDENT_2}" >> "$KEEPALIVED_CONF"
442 ;;
443 esac
444 printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
445 }
446 }
447
448 real_server_list() {
449 config_foreach real_server real_server "$1"
450 }
451
452 virtual_server() {
453 local enabled ipaddr port lb_algo sorry_server_ip sorry_server_port
454
455 config_get_bool enabled "$1" enabled 1
456 [ "$enabled" -eq 1 ] || return 0
457
458 config_get ipaddr "$1" ipaddr
459 [ -z "$ipaddr" ] && return 0
460 config_get port "$1" port
461 [ -z "$port" ] && return 0
462
463 config_section_open "virtual_server" "$ipaddr $port"
464
465 print_elems_indent "$1" "$INDENT_1" fwmark delay_loop \
466 lb_kind persistence_timeout persistence_granularity \
467 virtualhost protocol
468
469 config_get lb_algo "$1" lb_algo
470 [ -z "$lb_algo" ] && lb_algo="rr"
471 modprobe ip_vs_${lb_algo} 1>/dev/null 2>&1
472 printf '%blb_algo %s\n' "${INDENT_1}" "${lb_algo}" >> "$KEEPALIVED_CONF"
473
474 config_get sorry_server_ip "$1" sorry_server_ip
475 config_get sorry_server_port "$1" sorry_server_port
476 [ -n "$sorry_server_ip" ] && [ -n "$sorry_server_port" ] && {
477 printf '%bsorry_server %s %s\n' "${INDENT_1}" "$sorry_server_ip" "$sorry_server_port" >> "$KEEPALIVED_CONF"
478 }
479
480 # Handle real_server list
481 config_list_foreach "$1" real_server real_server_list
482
483 config_section_close
484 }
485
486 process_config() {
487 local alt_config_file
488
489 rm -f "$KEEPALIVED_CONF"
490
491 # First line
492 printf '! Configuration file for keepalived (autogenerated via init script)\n' > "$KEEPALIVED_CONF"
493 printf '! Written %s\n\n' "$(date +'%c')" >> "$KEEPALIVED_CONF"
494
495 [ -f /etc/config/keepalived ] || return 0
496 config_load 'keepalived'
497
498 config_section_open "global_defs"
499 config_foreach_wrapper global_defs
500 config_section_close
501
502 # If "alt_config_file" specified, use that instead
503 [ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && {
504 rm -f "$KEEPALIVED_CONF"
505 # Symlink "alt_config_file" since it's a bit easier and safer
506 ln -s "$alt_config_file" "$KEEPALIVED_CONF"
507 return 0
508 }
509
510 config_section_open "static_ipaddress"
511 config_foreach_wrapper static_ipaddress
512 config_section_close
513
514 config_section_open "static_routes"
515 config_foreach_wrapper static_routes
516 config_section_close
517
518 config_foreach_wrapper vrrp_script
519 config_foreach_wrapper vrrp_sync_group
520 config_foreach_wrapper vrrp_instance
521 config_foreach_wrapper virtual_server
522 return 0
523 }
524
525 service_triggers() {
526 procd_add_reload_trigger "keepalived"
527 }
528
529 reload_service() {
530 process_config
531 #SIGHUP is used by keepalived to do init.d reload
532 procd_send_signal keepalived
533 }
534
535 start_service() {
536 procd_open_instance
537 procd_set_param command /usr/sbin/keepalived
538 procd_append_param command -n # don't daemonize, procd will handle that for us
539 procd_append_param command -f "$KEEPALIVED_CONF"
540
541 process_config
542
543 # set auto respawn behavior
544 procd_set_param respawn
545 procd_close_instance
546 }
547