You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

429 lines
10 KiB

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