]> git.proxmox.com Git - mirror_frr.git/blame - tools/frrcommon.sh.in
mgmtd: Bringup MGMTD daemon and datastore module support
[mirror_frr.git] / tools / frrcommon.sh.in
CommitLineData
3ec95567 1#!/bin/bash
ea4d91bf
DL
2#
3# This is a "library" of sorts for use by the other FRR shell scripts. It
4# has most of the daemon start/stop logic, but expects the following shell
5# functions/commands to be provided by the "calling" script:
6#
7# log_success_msg
8# log_warning_msg
9# log_failure_msg
10#
11# (coincidentally, these are LSB standard functions.)
12#
13# Sourcing this file in a shell script will load FRR config variables but
14# not perform any action. Note there is an "exit 1" if the main config
15# file does not exist.
16#
17# This script should be installed in @CFG_SBIN@/frrcommon.sh
18
33606a15
DL
19# FRR_PATHSPACE is passed in from watchfrr
20suffix="${FRR_PATHSPACE:+/${FRR_PATHSPACE}}"
21nsopt="${FRR_PATHSPACE:+-N ${FRR_PATHSPACE}}"
22
ea4d91bf
DL
23PATH=/bin:/usr/bin:/sbin:/usr/sbin
24D_PATH="@CFG_SBIN@" # /usr/lib/frr
33606a15
DL
25C_PATH="@CFG_SYSCONF@${suffix}" # /etc/frr
26V_PATH="@CFG_STATE@${suffix}" # /var/run/frr
ea4d91bf
DL
27VTYSH="@vtysh_bin@" # /usr/bin/vtysh
28FRR_USER="@enable_user@" # frr
29FRR_GROUP="@enable_group@" # frr
30FRR_VTY_GROUP="@enable_vty_group@" # frrvty
5c906377 31FRR_CONFIG_MODE="@enable_configfile_mask@" # 0600
68495906 32FRR_DEFAULT_PROFILE="@DFLT_NAME@" # traditional / datacenter
ea4d91bf
DL
33
34# ORDER MATTERS FOR $DAEMONS!
35# - keep zebra first
36# - watchfrr does NOT belong in this list
37
1c84efe4 38DAEMONS="zebra mgmtd bgpd ripd ripngd ospfd ospf6d isisd babeld pimd pim6d ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
ea4d91bf
DL
39RELOAD_SCRIPT="$D_PATH/frr-reload.py"
40
41#
42# general helpers
43#
44
0f65c560 45is_user_root () {
1d42fb94
MR
46 if [[ ! -z $FRR_NO_ROOT && "${FRR_NO_ROOT}" == "yes" ]]; then
47 return 0
48 fi
49
0f65c560
DA
50 [ "${EUID:-$(id -u)}" -eq 0 ] || {
51 log_failure_msg "Only users having EUID=0 can start/stop daemons"
52 return 1
53 }
54}
55
ea4d91bf
DL
56debug() {
57 [ -n "$watchfrr_debug" ] || return 0
58
da960122 59 printf '%s %s(%s):' "$(date +%Y-%m-%dT%H:%M:%S.%N)" "$0" $$ >&2
ea4d91bf
DL
60 # this is to show how arguments are split regarding whitespace & co.
61 # (e.g. for use with `debug "message" "$@"`)
62 while [ $# -gt 0 ]; do
63 printf ' "%s"' "$1" >&2
64 shift
65 done
66 printf '\n' >&2
67}
68
ea4d91bf
DL
69vtysh_b () {
70 [ "$1" = "watchfrr" ] && return 0
63b46c8f 71 if [ ! -r "$C_PATH/frr.conf" ]; then
2469a37f
QY
72 log_warning_msg "$C_PATH/frr.conf does not exist; skipping config apply"
73 return 0
ea4d91bf 74 fi
2469a37f 75
da960122
QY
76 cmd="$VTYSH $nsopt -b"
77 [ -n "$1" ] && cmd="${cmd} -d $1"
2469a37f
QY
78
79 log_success_msg "Sending config with '$cmd'"
80 eval "$cmd"
ea4d91bf
DL
81}
82
83daemon_inst() {
84 # note this sets global variables ($dmninst, $daemon, $inst)
85 dmninst="$1"
195f215c 86 daemon="${dmninst%-*}"
ea4d91bf 87 inst=""
195f215c 88 [ "$daemon" != "$dmninst" ] && inst="${dmninst#*-}"
ea4d91bf
DL
89}
90
91daemon_list() {
92 # note $1 and $2 specify names for global variables to be set
93 local enabled disabled evar dvar
94 enabled=""
95 disabled=""
96 evar="$1"
97 dvar="$2"
98
99 for daemon in $DAEMONS; do
100 eval cfg=\$$daemon
101 eval inst=\$${daemon}_instances
1c84efe4 102 [ "$daemon" = zebra -o "$daemon" = staticd -o "$daemon" = mgmtd ] && cfg=yes
ea4d91bf 103 if [ -n "$cfg" -a "$cfg" != "no" -a "$cfg" != "0" ]; then
380fe10b
DL
104 if ! daemon_prep "$daemon" "$inst"; then
105 continue
106 fi
ea4d91bf 107 debug "$daemon enabled"
b82ad4c0 108
ea4d91bf
DL
109 if [ -n "$inst" ]; then
110 debug "$daemon multi-instance $inst"
195f215c
DL
111 oldifs="${IFS}"
112 IFS="${IFS},"
ea4d91bf 113 for i in $inst; do
195f215c 114 enabled="$enabled $daemon-$i"
ea4d91bf 115 done
195f215c 116 IFS="${oldifs}"
b82ad4c0
DS
117 else
118 enabled="$enabled $daemon"
ea4d91bf
DL
119 fi
120 else
121 debug "$daemon disabled"
122 disabled="$disabled $daemon"
123 fi
124 done
125
126 enabled="${enabled# }"
127 disabled="${disabled# }"
128 [ -z "$evar" ] && echo "$enabled"
129 [ -n "$evar" ] && eval $evar="\"$enabled\""
130 [ -n "$dvar" ] && eval $dvar="\"$disabled\""
131}
132
133#
134# individual daemon management
135#
136
137daemon_prep() {
138 local daemon inst cfg
139 daemon="$1"
140 inst="$2"
141 [ "$daemon" = "watchfrr" ] && return 0
142 [ -x "$D_PATH/$daemon" ] || {
195f215c 143 log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed"
ea4d91bf
DL
144 return 1
145 }
146 [ -r "$C_PATH/frr.conf" ] && return 0
147
148 cfg="$C_PATH/$daemon${inst:+-$inst}.conf"
149 if [ ! -r "$cfg" ]; then
972cdc56 150 install -g "$FRR_GROUP" -o "$FRR_USER" -m "$FRR_CONFIG_MODE" /dev/null "$cfg"
ea4d91bf
DL
151 fi
152 return 0
153}
154
155daemon_start() {
156 local dmninst daemon inst args instopt wrap bin
5493cdf5 157
0f65c560
DA
158 is_user_root || exit 1
159
5493cdf5
DL
160 all=false
161 [ "$1" = "--all" ] && { all=true; shift; }
162
ea4d91bf
DL
163 daemon_inst "$1"
164
da960122 165 [ "$MAX_FDS" != "" ] && ulimit -n "$MAX_FDS" > /dev/null 2> /dev/null
ea4d91bf 166 daemon_prep "$daemon" "$inst" || return 1
b7d492f2 167 if test ! -d "$V_PATH"; then
6f26cc24 168 install -g "$FRR_GROUP" -o "$FRR_USER" -m "$FRR_CONFIG_MODE" -d "$V_PATH"
972cdc56 169 chmod gu+x "${V_PATH}"
b7d492f2 170 fi
ea4d91bf
DL
171
172 eval wrap="\$${daemon}_wrap"
173 bin="$D_PATH/$daemon"
174 instopt="${inst:+-n $inst}"
175 eval args="\$${daemon}_options"
176
2469a37f
QY
177 cmd="$all_wrap $wrap $bin $nsopt -d $frr_global_options $instopt $args"
178 log_success_msg "Starting $daemon with command: '$cmd'"
179 if eval "$cmd"; then
ea4d91bf 180 log_success_msg "Started $dmninst"
5493cdf5
DL
181 if $all; then
182 debug "Skipping startup of vtysh until all have started"
183 else
184 vtysh_b "$daemon"
185 fi
ea4d91bf
DL
186 else
187 log_failure_msg "Failed to start $dmninst!"
188 fi
189}
190
191daemon_stop() {
192 local dmninst daemon inst pidfile vtyfile pid cnt fail
193 daemon_inst "$1"
194
0f65c560
DA
195 is_user_root || exit 1
196
f0cccaa6 197 all=false
c594796d 198 [ "$2" = "--reallyall" ] && all=true
f0cccaa6 199
ea4d91bf
DL
200 pidfile="$V_PATH/$daemon${inst:+-$inst}.pid"
201 vtyfile="$V_PATH/$daemon${inst:+-$inst}.vty"
202
203 [ -r "$pidfile" ] || fail="pid file not found"
f0cccaa6 204 $all && [ -n "$fail" ] && return 0
9dedc9eb 205 [ -z "$fail" ] && pid="$(cat "$pidfile")"
ea4d91bf
DL
206 [ -z "$fail" -a -z "$pid" ] && fail="pid file is empty"
207 [ -n "$fail" ] || kill -0 "$pid" 2>/dev/null || fail="pid $pid not running"
208
19a99d89 209 if [ -n "$fail" ] && [ "$2" != "--quiet" ]; then
ea4d91bf
DL
210 log_failure_msg "Cannot stop $dmninst: $fail"
211 return 1
212 fi
213
214 debug "kill -2 $pid"
215 kill -2 "$pid"
216 cnt=1200
217 while kill -0 "$pid" 2>/dev/null; do
218 sleep .1
219 [ $(( cnt -= 1 )) -gt 0 ] || break
220 done
221 if kill -0 "$pid" 2>/dev/null; then
222 log_failure_msg "Failed to stop $dmninst, pid $pid still running"
223 still_running=1
224 return 1
225 else
226 log_success_msg "Stopped $dmninst"
227 rm -f "$pidfile"
228 return 0
229 fi
230}
231
232daemon_status() {
233 local dmninst daemon inst pidfile pid fail
234 daemon_inst "$1"
235
236 pidfile="$V_PATH/$daemon${inst:+-$inst}.pid"
237
238 [ -r "$pidfile" ] || return 3
9dedc9eb 239 pid="$(cat "$pidfile")"
ea4d91bf
DL
240 [ -z "$pid" ] && return 1
241 kill -0 "$pid" 2>/dev/null || return 1
242 return 0
243}
244
245print_status() {
246 daemon_status "$1"
247 rv=$?
248 if [ "$rv" -eq 0 ]; then
249 log_success_msg "Status of $1: running"
250 else
251 log_failure_msg "Status of $1: FAILED"
252 fi
253 return $rv
254}
255
256#
257# all-daemon commands
258#
259
260all_start() {
261 daemon_list daemons
262 for dmninst in $daemons; do
5493cdf5 263 daemon_start --all "$dmninst"
ea4d91bf 264 done
5493cdf5 265 vtysh_b
ea4d91bf
DL
266}
267
268all_stop() {
828ac454 269 local pids reversed
ea4d91bf 270
1686b1d4
DS
271 daemon_list enabled_daemons disabled_daemons
272 [ "$1" = "--reallyall" ] && enabled_daemons="$enabled_daemons $disabled_daemons"
ea4d91bf
DL
273
274 reversed=""
1686b1d4 275 for dmninst in $enabled_daemons; do
ea4d91bf
DL
276 reversed="$dmninst $reversed"
277 done
278
279 for dmninst in $reversed; do
c594796d 280 daemon_stop "$dmninst" "$1" &
ea4d91bf
DL
281 pids="$pids $!"
282 done
283 for pid in $pids; do
284 wait $pid
285 done
286}
287
288all_status() {
289 local fail
290
291 daemon_list daemons
292 fail=0
293 for dmninst in $daemons; do
294 print_status "$dmninst" || fail=1
295 done
296 return $fail
297}
298
299#
300# config sourcing
301#
302
303load_old_config() {
304 oldcfg="$1"
305 [ -r "$oldcfg" ] || return 0
306 [ -s "$oldcfg" ] || return 0
307 grep -v '^[[:blank:]]*\(#\|$\)' "$oldcfg" > /dev/null || return 0
308
309 log_warning_msg "Reading deprecated $oldcfg. Please move its settings to $C_PATH/daemons and remove it."
310
311 # save off settings from daemons for the OR below
312 for dmn in $DAEMONS; do eval "_new_$dmn=\${$dmn:-no}"; done
313
314 . "$oldcfg"
315
316 # OR together the daemon enabling options between config files
317 for dmn in $DAEMONS; do eval "test \$_new_$dmn != no && $dmn=\$_new_$dmn; unset _new_$dmn"; done
318}
319
320[ -r "$C_PATH/daemons" ] || {
195f215c 321 log_failure_msg "cannot run $@: $C_PATH/daemons does not exist"
ea4d91bf
DL
322 exit 1
323}
324. "$C_PATH/daemons"
325
33606a15
DL
326if [ -z "$FRR_PATHSPACE" ]; then
327 load_old_config "$C_PATH/daemons.conf"
328 load_old_config "/etc/default/frr"
329 load_old_config "/etc/sysconfig/frr"
330fi
ea4d91bf 331
5216a05b 332if { declare -p watchfrr_options 2>/dev/null || true; } | grep -q '^declare -a'; then
3ec95567
DL
333 log_warning_msg "watchfrr_options contains a bash array value." \
334 "The configured value is intentionally ignored since it is likely wrong." \
335 "Please remove or fix the setting."
336 unset watchfrr_options
337fi
338
68495906
DL
339if test -z "$frr_profile"; then
340 # try to autodetect config profile
341 if test -d /etc/cumulus; then
342 frr_profile=datacenter
343 # elif test ...; then
344 # -- add your distro/system here
345 elif test -n "$FRR_DEFAULT_PROFILE"; then
346 frr_profile="$FRR_DEFAULT_PROFILE"
347 fi
348fi
349test -n "$frr_profile" && frr_global_options="$frr_global_options -F $frr_profile"
350
ea4d91bf
DL
351#
352# other defaults and dispatch
353#
354
355frrcommon_main() {
356 local cmd
357
358 debug "frrcommon_main" "$@"
359
360 cmd="$1"
361 shift
362
da960122 363 if [ "$1" = "all" ] || [ -z "$1" ]; then
ea4d91bf
DL
364 case "$cmd" in
365 start) all_start;;
366 stop) all_stop;;
367 restart)
19a99d89 368 all_stop --quiet
ea4d91bf
DL
369 all_start
370 ;;
371 *) $cmd "$@";;
372 esac
373 else
374 case "$cmd" in
375 start) daemon_start "$@";;
376 stop) daemon_stop "$@";;
377 restart)
378 daemon_stop "$@"
379 daemon_start "$@"
380 ;;
381 *) $cmd "$@";;
382 esac
383 fi
384}