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.

404 lines
9.8 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" ] && printf " $optval" >> $KEEPALIVED_CONF
  43. printf "\n" >> $KEEPALIVED_CONF
  44. done
  45. unset optval
  46. }
  47. print_list_indent() {
  48. local lst=$1
  49. local indent=$2
  50. local lst_elems
  51. [ -z "$indent" ] && indent=$INDENT_1
  52. eval lst_elems=\$$lst
  53. [ -z "$lst_elems" ] && return 0
  54. printf "$indent$lst {\n" >> $KEEPALIVED_CONF
  55. for e in $lst_elems; do
  56. [ -n "$eval_item_func" ]
  57. printf "$indent$INDENT_1$e\n" >> $KEEPALIVED_CONF
  58. done
  59. printf "$indent}\n" >> $KEEPALIVED_CONF
  60. }
  61. global_defs() {
  62. local linkbeat_use_polling notification_email
  63. config_get alt_config_file $1 alt_config_file
  64. [ -z "$alt_config_file" ] || return 0
  65. config_get_bool linkbeat_use_polling $1 linkbeat_use_polling 0
  66. [ $linkbeat_use_polling -gt 0 ] && printf "linkbeat_use_polling\n\n" >> $KEEPALIVED_CONF
  67. config_get notification_email $1 notification_email
  68. print_list_indent notification_email
  69. print_elems_indent $1 $INDENT_1 notification_email_from smtp_server smtp_connect_timeout \
  70. router_id vrrp_mcast_group4 vrrp_mcast_group6
  71. }
  72. print_ipaddress_indent() {
  73. local section=$1
  74. local curr_ipaddr=$2
  75. local indent=$3
  76. local address device scope name
  77. config_get name $section name
  78. [ "$name" != "$curr_ipaddr" ] && return 0
  79. config_get address $section address
  80. config_get device $section device
  81. config_get scope $section scope
  82. # Default indent
  83. [ -z "$indent" ] && indent=$INDENT_1
  84. # If no address or device exit
  85. [ -z "$address" -o -z "$device" ] && return 0
  86. # Add IP address/netmask and device
  87. printf "$indent$address dev $device" >> $KEEPALIVED_CONF
  88. # Add scope
  89. [ -n "$scope" ] && printf " scope $scope" >> $KEEPALIVED_CONF
  90. printf "\n" >> $KEEPALIVED_CONF
  91. }
  92. static_ipaddress() {
  93. local address
  94. config_get address "$1" address
  95. for a in $address; do
  96. config_foreach print_ipaddress_indent ipaddress $a
  97. done
  98. }
  99. print_route_indent() {
  100. local section=$1
  101. local curr_route=$2
  102. local indent=$3
  103. local name blackhole address src_addr gateway device scope table
  104. config_get name $section name
  105. [ "$name" != "$curr_route" ] && return 0
  106. config_get_bool blackhole $section blackhole 0
  107. config_get address $section address
  108. config_get src_addr $section src_addr
  109. config_get gateway $section gateway
  110. config_get device $section device
  111. config_get table $section table
  112. # If no address exit
  113. [ -z "$address" ] && return 0
  114. # Default indent
  115. [ -z "$indent" ] && indent=$INDENT_1
  116. [ $blackhole -gt 0 ] && {
  117. printf "${indent}blackhole $address\n" >> $KEEPALIVED_CONF
  118. return 0
  119. }
  120. # Add src addr or address
  121. if [ -n "$src_addr" ]; then
  122. printf "${indent}src $src_addr $address" >> $KEEPALIVED_CONF
  123. else
  124. [ -z "$device" ] && return 0
  125. printf "$indent$address" >> $KEEPALIVED_CONF
  126. fi
  127. # Add route/gateway
  128. [ -n "$gateway" ] && printf " via $gateway" >> $KEEPALIVED_CONF
  129. # Add device
  130. printf " dev $device" >> $KEEPALIVED_CONF
  131. # Add scope
  132. [ -n "$scope" ] && printf " scope $scope" >> $KEEPALIVED_CONF
  133. # Add table
  134. [ -n "$table" ] && printf " table $table" >> $KEEPALIVED_CONF
  135. printf "\n" >> $KEEPALIVED_CONF
  136. }
  137. print_track_elem_indent() {
  138. local section=$1
  139. local curr_track_elem=$2
  140. local indent=$3
  141. local script name value
  142. config_get name $section name
  143. [ "$name" != "$curr_track_elem" ] && return 0
  144. config_get value $section value
  145. config_get weight $section weight
  146. [ -z "$value" ] && return 0
  147. printf "$indent$value" >> $KEEPALIVED_CONF
  148. [ -n "$weight" ] && printf " weight $weight" >> $KEEPALIVED_CONF
  149. printf "\n" >> $KEEPALIVED_CONF
  150. }
  151. static_routes() {
  152. local route
  153. config_get route "$1" route
  154. for r in $route; do
  155. config_foreach print_route_indent route $r
  156. done
  157. }
  158. # Count 'vrrp_instance' with the given name ; called by vrrp_instance_check()
  159. vrrp_instance_name_count() {
  160. local name
  161. config_get name $1 name
  162. [ "$name" == "$2" ] && count=$((count + 1))
  163. }
  164. # Check if there's a 'vrrp_instance' section with the given name
  165. vrrp_instance_check() {
  166. local count=0
  167. local name=$1
  168. config_foreach vrrp_instance_name_count vrrp_instance $name
  169. [ $count -gt 0 ] && return 0 || return 1
  170. }
  171. vrrp_sync_group() {
  172. local group name
  173. local valid_group
  174. # No name for group, exit
  175. config_get name $1 name
  176. [ -z "$name" ] && return 0
  177. # No members for group, exit
  178. config_get group $1 group
  179. [ -z "$group" ] && return 0
  180. # Check if we have 'vrrp_instance's defined for
  181. # each member and remove names with not vrrp_instance defined
  182. for m in $group; do
  183. vrrp_instance_check $m && valid_group="$valid_group $m"
  184. done
  185. [ -z "$valid_group" ] && return 0
  186. config_section_open "vrrp_sync_group" "$name"
  187. group="$valid_group"
  188. print_list_indent group
  189. print_elems_indent $1 $INDENT_1 notify_backup notify_master notify_fault \
  190. notify no_val_smtp_alert no_val_global_tracking
  191. config_section_close
  192. }
  193. vrrp_instance() {
  194. local name auth_type auth_pass
  195. config_get name $1 name
  196. [ -z "$name" ] && return 0
  197. config_section_open "vrrp_instance" "$name"
  198. config_get auth_type $1 auth_type
  199. config_get auth_pass $1 auth_pass
  200. [ -n "$auth_type" -a -n "$auth_pass" ] && {
  201. printf "${INDENT_1}authentication {\n" >> $KEEPALIVED_CONF
  202. printf "${INDENT_2}auth_type $auth_type\n" >> $KEEPALIVED_CONF
  203. printf "${INDENT_2}auth_pass $auth_pass\n" >> $KEEPALIVED_CONF
  204. printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
  205. }
  206. print_elems_indent $1 $INDENT_1 use_vmac state interface \
  207. mcast_src_ip unicast_src_ip virtual_router_id version priority \
  208. advert_int preempt_delay debug notify_backup \
  209. notify_master notify_fault notify_stop notify \
  210. lvs_sync_daemon_interface garp_master_delay garp_master_refresh \
  211. garp_master_repeat garp_master_refresh_repeat \
  212. no_val_vmac_xmit_base no_val_native_ipv6 no_val_accept \
  213. no_val_dont_track_primary no_val_smtp_alert no_val_nopreempt
  214. # Handle virtual_ipaddress & virtual_ipaddress_excluded lists
  215. for opt in virtual_ipaddress virtual_ipaddress_excluded; do
  216. config_get $opt $1 $opt
  217. eval optval=\$$opt
  218. [ -z "$optval" ] && continue
  219. printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
  220. for a in $optval; do
  221. config_foreach print_ipaddress_indent ipaddress $a $INDENT_2
  222. done
  223. printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
  224. done
  225. # Handle virtual_routes
  226. for opt in virtual_routes; do
  227. config_get $opt $1 $opt
  228. eval optval=\$$opt
  229. [ -z "$optval" ] && continue
  230. printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
  231. for r in $optval; do
  232. config_foreach print_route_indent route $r $INDENT_2
  233. done
  234. printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
  235. done
  236. # Handle track_interface & track_script lists
  237. for opt in track_interface track_script; do
  238. config_get $opt $1 $opt
  239. eval optval=\$$opt
  240. [ -z "$optval" ] && continue
  241. printf "$INDENT_1$opt {\n" >> $KEEPALIVED_CONF
  242. for t in $optval; do
  243. printf "$INDENT_2$optval\n" >> $KEEPALIVED_CONF
  244. done
  245. printf "$INDENT_1}\n" >> $KEEPALIVED_CONF
  246. done
  247. # Handle simple lists of strings (with no spaces in between)
  248. for opt in unicast_peer; do
  249. config_get $opt $1 $opt
  250. print_list_indent $opt
  251. done
  252. unset optval
  253. config_section_close
  254. }
  255. vrrp_script() {
  256. local name
  257. config_get name $1 name
  258. [ -z "$name" ] && return 0
  259. config_section_open "vrrp_script" "$name"
  260. print_elems_indent $1 $INDENT_1 script interval weight fall rise
  261. config_section_close
  262. }
  263. process_config() {
  264. local alt_config_file
  265. rm -f $KEEPALIVED_CONF
  266. # First line
  267. printf "! Configuration File for keepalived (autogenerated via init script)\n\n" > $KEEPALIVED_CONF
  268. [ -f /etc/config/keepalived ] || return 0
  269. config_load 'keepalived'
  270. config_section_open "global_defs"
  271. config_foreach_wrapper global_defs
  272. config_section_close
  273. # If "alt_config_file" specified, use that instead
  274. [ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && {
  275. rm -f $KEEPALIVED_CONF
  276. # Symlink "alt_config_file" since it's a bit easier and safer
  277. ln -s $alt_config_file $KEEPALIVED_CONF
  278. return 0
  279. }
  280. config_section_open "static_ipaddress"
  281. config_foreach_wrapper static_ipaddress
  282. config_section_close
  283. config_section_open "static_routes"
  284. config_foreach_wrapper static_routes
  285. config_section_close
  286. config_foreach_wrapper vrrp_script
  287. config_foreach_wrapper vrrp_sync_group
  288. config_foreach_wrapper vrrp_instance
  289. return 0
  290. }
  291. service_running() {
  292. pgrep -x /usr/sbin/keepalived &> /dev/null
  293. }
  294. conf_md5() {
  295. echo "$(md5sum $KEEPALIVED_CONF | awk '{print $1}')"
  296. }
  297. reload_service() {
  298. local cur_md5="$(conf_md5)"
  299. running && {
  300. process_config
  301. # Return without performing the reload if config
  302. # file md5sum has not changed
  303. local new_md5="$(conf_md5)"
  304. [ "$new_md5" == "$cur_md5" ] && return 0;
  305. # SIGHUP is used by keepalived to do init.d reload
  306. # Get the oldest process (assumption is that it's the parent process)
  307. PID=$(pgrep -o /usr/sbin/keepalived)
  308. kill -SIGHUP $PID
  309. return 0
  310. }
  311. return 1
  312. }
  313. start_service() {
  314. procd_open_instance
  315. procd_set_param command /usr/sbin/keepalived
  316. procd_append_param command -n # don't daemonize, procd will handle that for us
  317. procd_append_param command -f "$KEEPALIVED_CONF"
  318. process_config
  319. # set auto respawn behavior
  320. procd_set_param respawn
  321. procd_close_instance
  322. }