quagga: Fixup startup to allow consistency between sysV and systemd

We want the ability to start up quagga in a varied set of
environments.  This needs to be done in SysV and systemd
startups.  As such refactor the code to allow us to
allow end users to easily switch between the two

sysV:
edit the /etc/quagga/daemons file
service quagga [start|stop|reload|restart]

Systemd:
edit the /etc/quagga/daemons file
systemctl [start|stop|reload|restart] quagga

Ticket: CM-10634
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2016-04-25 11:34:35 -04:00
parent e2dd9485cb
commit 651415bd61
25 changed files with 638 additions and 285 deletions

View File

@ -38,7 +38,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "stream.h"
#include "queue.h"
#include "vrf.h"
#include "systemd.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@ -286,7 +285,6 @@ bgp_exit (int status)
if (zlog_default)
closezlog (zlog_default);
systemd_send_stopping ();
exit (status);
}
@ -504,7 +502,6 @@ main (int argc, char **argv)
/* Process ID file creation. */
pid_output (pid_file);
systemd_send_started (bm->master);
/* Make bgp vty socket. */
vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);

24
debian/isisd.service vendored
View File

@ -1,24 +0,0 @@
[Unit]
Description=IS-IS routing daemon
After=syslog.target networking.service zebra.service
Requires=zebra.service
OnFailure=heartbeat-failed@%n.service
[Service]
Nice=-5
Type=notify
EnvironmentFile=/etc/default/quagga
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/isisd $ISISD_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/isisd.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/isisd.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

31
debian/my/daemons vendored Normal file
View File

@ -0,0 +1,31 @@
# This file tells the quagga package which daemons to start.
#
# Entries are in the format: <daemon>=(yes|no|priority)
# 0, "no" = disabled
# 1, "yes" = highest priority
# 2 .. 10 = lower priorities
# Read /usr/share/doc/quagga/README.Debian for details.
#
# Sample configurations for these daemons can be found in
# /usr/share/doc/quagga/examples/.
#
# ATTENTION:
#
# When activation a daemon at the first time, a config file, even if it is
# empty, has to be present *and* be owned by the user and group "quagga", else
# the daemon will not be started by /etc/init.d/quagga. The permissions should
# be u=rw,g=r,o=.
# When using "vtysh" such a config file is also needed. It should be owned by
# group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too.
#
# The watchquagga daemon is always started. Per default in monitoring-only but
# that can be changed via /etc/quagga/debian.conf.
#
zebra=no
bgpd=no
ospfd=no
ospf6d=no
ripd=no
ripngd=no
isisd=no

24
debian/my/debian.conf vendored Normal file
View File

@ -0,0 +1,24 @@
#
# If this option is set the /etc/init.d/quagga script automatically loads
# the config via "vtysh -b" when the servers are started.
# Check /etc/pam.d/quagga if you intend to use "vtysh"!
#
vtysh_enable=yes
zebra_options=" --daemon -A 127.0.0.1"
bgpd_options=" --daemon -A 127.0.0.1"
ospfd_options=" --daemon -A 127.0.0.1"
ospf6d_options=" --daemon -A ::1"
ripd_options=" --daemon -A 127.0.0.1"
ripngd_options=" --daemon -A ::1"
isisd_options=" --daemon -A 127.0.0.1"
#
# Please note that watchquagga_options is an array and not a string so that
# quotes can be used.
#
# The list of daemons to watch is automatically generated by the init script
# from daemons.conf and appended to the watchquagga_options.
# Example:
# watchquagga_options=("-Adz" "-r" '/sbin/service %s restart' -s '/sbin/service %s start' -k '/s
watchquagga_enable=yes
watchquagga_options=(--daemon)

23
debian/ospf6d.service vendored
View File

@ -1,23 +0,0 @@
[Unit]
Description=OSPF routing daemon for IPv6
After=syslog.target networking.service zebra.service
Requires=zebra.service
OnFailure=heartbeat-failed@%n.service
[Service]
Nice=-5
Type=notify
EnvironmentFile=/etc/default/quagga
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
ExecStart=/usr/lib/quagga/ospf6d $OSPF6D_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/ospf6d.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/ospf6d.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

24
debian/ospfd.service vendored
View File

@ -1,24 +0,0 @@
[Unit]
Description=OSPF routing daemon
After=syslog.target networking.service zebra.service
Requires=zebra.service
OnFailure=heartbeat-failed@%n.service
[Service]
Type=notify
Nice=-5
EnvironmentFile=/etc/default/quagga
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/ospfd $OSPFD_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/ospfd.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/ospfd.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

24
debian/ospfd@.service vendored
View File

@ -1,24 +0,0 @@
[Unit]
Description=OSPF routing daemon %I
After=syslog.target networking.service zebra.service
Requires=zebra.service
OnFailure=heartbeat-failed@%n.service
[Service]
Type=notify
Nice=-5
EnvironmentFile=/etc/default/quagga
StartLimitInterval=3m
StartLimitBurst=10
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/ospfd $OSPFD_OPTIONS -n %I
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/ospfd@%I.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/ospfd@%I.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

View File

@ -3,6 +3,7 @@ usr/bin/vtysh
usr/include/quagga/
usr/lib/
tools/quagga-reload.py usr/lib/quagga/
tools/quagga usr/lib/quagga
usr/share/doc/quagga/
usr/share/man/man1/vtysh.1
usr/share/man/man1/quagga.1
@ -17,6 +18,5 @@ usr/share/man/man8/isisd.8
usr/share/man/man8/watchquagga.8
usr/share/snmp/mibs/
cumulus/etc/* etc/
debian/watchquagga.rc etc/cumulus/ssmonitor.d
debian/*.service lib/systemd/system
debian/quagga.conf usr/lib/tmpfiles.d

View File

@ -1,13 +1,13 @@
[Unit]
Description=Cumulus Linux Quagga BGP Daemon
After=syslog.target networking.service zebra.service
Requires=zebra.service
After=syslog.target networking.service
OnFailure=heartbeat-failed@%n.service
[Service]
Nice=-5
EnvironmentFile=/etc/default/quagga
Type=notify
Type=forking
NotifyAccess=all
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
@ -15,10 +15,8 @@ WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/bgpd $BGPD_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/bgpd.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/bgpd.vty
ExecStart=/usr/lib/quagga/quagga start
ExecStop=/usr/lib/quagga/quagga stop
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

24
debian/ripd.service vendored
View File

@ -1,24 +0,0 @@
[Unit]
Description=RIP routing daemon
After=syslog.target networking.service zebra.service
Requires=zebra.service
OnFailure=heartbeat-failed@%n.service
[Service]
Nice=-5
Type=notify
EnvironmentFile=/etc/default/quagga
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/ripd $RIPD_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/ripd.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/ripd.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

24
debian/ripngd.service vendored
View File

@ -1,24 +0,0 @@
[Unit]
Description=RIP routing daemon for IPv6
After=syslog.target networking.service zebra.service
Requires=zebra.service
OnFailure=heartbeat-failed@%n.service
[Service]
Nice=-5
Type=notify
EnvironmentFile=/etc/default/quagga
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/ripngd $RIPNGD_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/ripngd.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/ripngd.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

24
debian/rules vendored
View File

@ -12,11 +12,11 @@ else
endif
%:
dh $@ --parallel --with autoreconf --dbg-package=quagga-dbg --list-missing
dh $@ --with=systemd --parallel --with autoreconf --dbg-package=quagga-dbg --list-missing
if [ -e config.status ]; then \
dh $@ --parallel --dbg-package=quagga-dbg --list-missing; \
dh $@ --with=systemd --parallel --dbg-package=quagga-dbg --list-missing; \
else \
dh $@ --parallel --with autoreconf --dbg-package=quagga-dbg --list-missing; \
dh $@ --with=systemd --parallel --with autoreconf --dbg-package=quagga-dbg --list-missing; \
fi
override_dh_auto_clean:
@ -102,6 +102,8 @@ override_dh_auto_install:
# install config files
mkdir -p debian/tmp/etc/quagga/
cp debian/my/debian.conf debian/tmp/etc/quagga/
cp debian/my/daemons debian/tmp/etc/quagga/
perl -pi -e 's#^!log file #!log file /var/log/quagga/#' debian/tmp/usr/share/doc/quagga/examples/*sample*
# installing the Quagga specific SNMP MIB
@ -111,20 +113,8 @@ override_dh_auto_install:
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
override_dh_systemd_start:
dh_systemd_start bgpd.service
dh_systemd_start isisd.service
dh_systemd_start ospfd.service
dh_systemd_start ospf6d.service
dh_systemd_start ripd.service
dh_systemd_start ripngd.service
dh_systemd_start zebra.service
dh_systemd_start quagga.service
override_dh_systemd_enable:
dh_systemd_enable --no-enable bgpd.service
dh_systemd_enable --no-enable isisd.service
dh_systemd_enable --no-enable ospfd.service
dh_systemd_enable --no-enable ospf6d.service
dh_systemd_enable --no-enable ripd.service
dh_systemd_enable --no-enable ripngd.service
dh_systemd_enable --no-enable zebra.service
dh_systemd_enable quagga.service

23
debian/zebra.service vendored
View File

@ -1,23 +0,0 @@
[Unit]
Description=Cumulus Linux Quagga Zebra Daemon
After=networking.service syslog.service
OnFailure=heartbeat-failed@%n.service
[Service]
Nice=-5
EnvironmentFile=/etc/default/quagga
Type=notify
StartLimitInterval=3m
StartLimitBurst=3
TimeoutSec=1m
WatchdogSec=60s
RestartSec=5
Restart=on-abnormal
LimitNOFILE=1024
ExecStart=/usr/lib/quagga/zebra $ZEBRA_OPTIONS
ExecStartPost=/usr/bin/vtysh -b -n
ExecStopPost=-/bin/rm -f /var/run/quagga/zebra.pid
ExecStopPost=-/bin/rm -f /var/run/quagga/zebra.vty
ExecReload=/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
[Install]
WantedBy=network-online.target

View File

@ -37,7 +37,6 @@
#include "plist.h"
#include "zclient.h"
#include "vrf.h"
#include "systemd.h"
#include "isisd/dict.h"
#include "include-netbsd/iso.h"
@ -170,7 +169,6 @@ reload ()
static __attribute__((__noreturn__)) void
terminate (int i)
{
systemd_send_stopping ();
exit (i);
}
@ -372,8 +370,6 @@ main (int argc, char **argv, char **envp)
if (pid_file[0] != '\0')
pid_output (pid_file);
systemd_send_started (master);
/* Make isis vty socket. */
vty_serv_sock (vty_addr, vty_port, ISIS_VTYSH_PATH);

View File

@ -46,10 +46,11 @@ systemd_send_information (const char *info)
* A return of 0 means that we are not watchdoged
*/
static int
systemd_get_watchdog_time (void)
systemd_get_watchdog_time (int the_process)
{
#if defined HAVE_SYSTEMD
uint64_t usec;
char *watchdog = NULL;
int ret;
ret = sd_watchdog_enabled (0, &usec);
@ -58,9 +59,28 @@ systemd_get_watchdog_time (void)
* If return is 0 -> we don't want watchdog
* if return is < 0, some sort of failure occurred
*/
if (ret <= 0)
if (ret < 0)
return 0;
/*
* systemd can return that this process
* is not the expected sender of the watchdog timer
* If we set the_process = 0 then we expect to
* be able to send the watchdog to systemd
* irrelevant of the pid of this process.
*/
if (ret == 0 && the_process)
return 0;
if (ret == 0 && !the_process)
{
watchdog = getenv ("WATCHDOG_USEC");
if (!watchdog)
return 0;
usec = atol (watchdog);
}
return (usec / 1000000)/ 3;
#else
return 0;
@ -90,11 +110,11 @@ systemd_send_watchdog (struct thread *t)
}
void
systemd_send_started (struct thread_master *m)
systemd_send_started (struct thread_master *m, int the_process)
{
assert (m != NULL);
wsecs = systemd_get_watchdog_time();
wsecs = systemd_get_watchdog_time(the_process);
systemd_master = m;
systemd_send_information ("READY=1");

View File

@ -30,5 +30,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
*/
void systemd_send_information (const char *info);
void systemd_send_stopping (void);
void systemd_send_started (struct thread_master *);
/*
* master - The struct thread_master * to use to schedule ourself
* the_process - Should we send watchdog if we are not the requested
* process?
*/
void systemd_send_started (struct thread_master *master, int the_process);

View File

@ -37,7 +37,6 @@
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
#include "systemd.h"
#include "ospf6d.h"
#include "ospf6_top.h"
@ -166,7 +165,6 @@ ospf6_exit (int status)
if (zlog_default)
closezlog (zlog_default);
systemd_send_stopping ();
exit (status);
}
@ -348,8 +346,6 @@ main (int argc, char *argv[], char *envp[])
/* pid file create */
pid_output (pid_file);
systemd_send_started (master);
/* Make ospf6 vty socket. */
if (!vty_port)
vty_port = OSPF6_VTY_PORT;

View File

@ -40,7 +40,6 @@
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
#include "systemd.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@ -368,7 +367,6 @@ main (int argc, char **argv)
/* Process id file create. */
pid_output (pid_file);
systemd_send_started (master);
vty_serv_sock (vty_addr, vty_port, vty_path);
/* Print banner. */

View File

@ -34,7 +34,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "zclient.h"
#include "plist.h"
#include "sockopt.h"
#include "systemd.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
@ -397,7 +396,6 @@ ospf_deferred_shutdown_finish (struct ospf *ospf)
if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
&& (listcount (om->ospf) == 0))
{
systemd_send_stopping ();
exit (0);
}
@ -466,7 +464,6 @@ ospf_terminate (void)
SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
systemd_send_stopping ();
/* exit immediately if OSPF not actually running */
if (listcount(om->ospf) == 0)
exit(0);

View File

@ -34,7 +34,6 @@
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
#include "systemd.h"
#include "ripd/ripd.h"
@ -156,7 +155,6 @@ sigint (void)
if (! retain_mode)
rip_clean ();
systemd_send_stopping ();
exit (0);
}
@ -305,8 +303,6 @@ main (int argc, char **argv)
exit (1);
}
systemd_send_started (master);
/* Pid file create. */
pid_output (pid_file);

View File

@ -35,7 +35,6 @@
#include "privs.h"
#include "sigevent.h"
#include "vrf.h"
#include "systemd.h"
#include "ripngd/ripngd.h"
@ -155,7 +154,6 @@ sigint (void)
if (! retain_mode)
ripng_clean ();
systemd_send_stopping ();
exit (0);
}
@ -300,8 +298,6 @@ main (int argc, char **argv)
exit (1);
}
systemd_send_started (master);
/* Create VTY socket */
vty_serv_sock (vty_addr, vty_port, RIPNG_VTYSH_PATH);

View File

@ -1,84 +1,558 @@
#!/bin/bash
#
### BEGIN INIT INFO
# Provides: quagga
# Required-Start: $local_fs $network $remote_fs $syslog
# Required-Stop: $local_fs $network $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop the Quagga routing suite
# Description: Quagga is a routing suite for IP routing protocols like
# BGP, OSPF, RIP and others. This script contols the main
# daemon "quagga" as well as the individual protocol daemons.
### END INIT INFO
#
startup()
PATH=/bin:/usr/bin:/sbin:/usr/sbin
D_PATH=/usr/lib/quagga
C_PATH=/etc/quagga
V_PATH=/var/run/quagga
# Local Daemon selection may be done by using /etc/quagga/daemons.
# See /usr/share/doc/quagga/README.Debian.gz for further information.
# Keep zebra first and do not list watchquagga!
DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld"
MAX_INSTANCES=5
RELOAD_SCRIPT=/usr/lib/quagga/quagga-reload.py
. /lib/lsb/init-functions
# Print the name of the pidfile.
pidfile()
{
FILE="/var/run/quagga/$1.was_running"
echo "$V_PATH/$1.pid"
}
/bin/systemctl reset-failed $1 > /dev/null 2>&1
# Print the name of the vtysh.
vtyfile()
{
echo "$V_PATH/$1.vty"
}
if [ -e $FILE ]
then
rm $FILE
/bin/systemctl start $1 > /dev/null 2>&1
# Check if daemon is started by using the pidfile.
started()
{
[ ! -e `pidfile $1` ] && return 3
if [ -n "$2" ] && [ "$2" == "log" ]; then
status_of_proc -p `pidfile $1` $1 $1 && return 0 || return $?
else
kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
return 0
fi
}
# Loads the config via vtysh -b if configured to do so.
vtysh_b ()
{
# Rember, that all variables have been incremented by 1 in convert_daemon_prios()
if [ "$vtysh_enable" = 2 -a -f $C_PATH/Quagga.conf ]; then
/usr/bin/vtysh -b -n
fi
}
# Check if the daemon is activated and if its executable and config files
# are in place.
# params: daemon name
# returns: 0=ok, 1=error
check_daemon()
{
# If the integrated config file is used the others are not checked.
if [ -r "$C_PATH/Quagga.conf" ]; then
return 0
fi
# vtysh_enable has no config file nor binary so skip check.
# (Not sure why vtysh_enable is in this list but does not hurt)
if [ $1 != "watchquagga" -a $1 != "vtysh_enable" ]; then
# check for daemon binary
if [ ! -x "$D_PATH/$1" ]; then return 1; fi
# check for config file
if [ -n "$2" ]; then
if [ ! -r "$C_PATH/$1-$2.conf" ]; then
touch "$C_PATH/$1-$2.conf"
chown quagga:quagga "$C_PATH/$1-$2.conf"
fi
elif [ ! -r "$C_PATH/$1.conf" ]; then
touch "$C_PATH/$1.conf"
chown quagga:quagga "$C_PATH/$1.conf"
fi
fi
return 0
}
# Starts the server if it's not alrady running according to the pid file.
# The Quagga daemons creates the pidfile when starting.
start()
{
ulimit -n $MAX_FDS
if [ "$1" = "watchquagga" ]; then
# We may need to restart watchquagga if new daemons are added and/or
# removed
if started "$1" ; then
stop watchquagga
else
# Echo only once. watchquagga is printed in the stop above
echo -n " $1"
fi
start-stop-daemon \
--start \
--pidfile=`pidfile $1` \
--exec "$D_PATH/$1" \
-- \
"${watchquagga_options[@]}"
elif [ -n "$2" ]; then
echo -n " $1-$2"
if ! check_daemon $1 $2 ; then
echo -n " (binary does not exist)"
return;
fi
start-stop-daemon \
--start \
--pidfile=`pidfile $1-$2` \
--exec "$D_PATH/$1" \
-- \
`eval echo "$""$1""_options"` -n "$2"
else
echo -n " $1"
if ! check_daemon $1; then
echo -n " (binary does not exist)"
return;
fi
start-stop-daemon \
--start \
--pidfile=`pidfile $1` \
--exec "$D_PATH/$1" \
-- \
`eval echo "$""$1""_options"`
fi
}
# Stop the daemon given in the parameter, printing its name to the terminal.
stop()
{
local inst
if [ -n "$2" ]; then
inst="$1-$2"
else
inst="$1"
fi
/bin/systemctl is-enabled $1 > /dev/null 2>&1
if [ $? -eq 0 ]
then
/bin/systemctl start $1 > /dev/null 2>&1
if ! started "$inst" ; then
echo -n " ($inst)"
return 0
else
PIDFILE=`pidfile $inst`
PID=`cat $PIDFILE 2>/dev/null`
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
#
# Now we have to wait until $DAEMON has _really_ stopped.
#
if test -n "$PID" && kill -0 $PID 2>/dev/null; then
echo -n " (waiting) ."
cnt=0
while kill -0 $PID 2>/dev/null; do
cnt=`expr $cnt + 1`
if [ $cnt -gt 60 ]; then
# Waited 120 secs now, fail.
echo -n "Failed.. "
break
fi
sleep 2
echo -n "."
done
fi
echo -n " $inst"
rm -f `pidfile $inst`
rm -f `vtyfile $inst`
fi
}
start_ospfd_multiinstance()
# Converts values from /etc/quagga/daemons to all-numeric values.
convert_daemon_prios()
{
for instance in $MI; do
startup ospfd@$instance
done
for name in $DAEMONS zebra vtysh_enable watchquagga_enable; do
# First, assign the value set by the user to $value
eval value=\${${name}:0:3}
# Daemon not activated or entry missing?
if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
# These strings parsed for backwards compatibility.
if [ "$value" = "yes" -o "$value" = "true" ]; then
value=1;
fi
# Zebra is threatened special. It must be between 0=off and the first
# user assigned value "1" so we increase all other enabled daemons' values.
if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
# If e.g. name is zebra then we set "zebra=yes".
eval $name=$value
done
}
start_daemons()
# Starts watchquagga for all wanted daemons.
start_watchquagga()
{
startup zebra
startup bgpd
startup ospfd
startup ospf6d
startup ripd
startup ripngd
startup isisd
start_ospfd_multiinstance
}
local daemon_name
local daemon_prio
local found_one
local daemon_inst
stop_ospfd_multiinstance()
{
for instance in $MI; do
/bin/systemctl stop ospfd@$instance > /dev/null 2>&1
# Start the monitor daemon only if desired.
if [ 0 -eq "$watchquagga_enable" ]; then
return
fi
# Check variable type
if ! declare -p watchquagga_options | grep -q '^declare \-a'; then
echo
echo "ERROR: The variable watchquagga_options from /etc/quagga/debian.cnf must be a BASH array!"
echo "ERROR: Please convert config file and restart!"
exit 1
fi
# Which daemons have been started?
found_one=0
for daemon_name in $DAEMONS; do
eval daemon_prio=\$$daemon_name
if [ "$daemon_prio" -gt 0 ]; then
eval "daemon_inst=\${${daemon_name}_instances//,/ }"
if [ -n "$daemon_inst" ]; then
for inst in ${daemon_inst}; do
eval "inst_disable=\${${daemon_name}_${inst}}"
if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
if check_daemon $daemon_name $inst; then
watchquagga_options+=("${daemon_name}-${inst}")
fi
fi
done
else
if check_daemon $daemon_name; then
watchquagga_options+=($daemon_name)
fi
fi
found_one=1
fi
done
# Start if at least one daemon is activated.
if [ $found_one -eq 1 ]; then
echo -n "Starting Quagga monitor daemon:"
start watchquagga
echo "."
fi
}
stop_daemons()
# Stopps watchquagga.
stop_watchquagga()
{
stop_ospfd_multiinstance
/bin/systemctl stop bgpd ospfd ospf6d ripd ripngd isisd zebra > /dev/null 2>&1
echo -n "Stopping Quagga monitor daemon:"
stop watchquagga
echo "."
}
MI=`systemctl list-units 'ospfd@*'| sed -n -e '/@/s/\..*//' -e 's/.*@//p'`
# Stops all daemons that have a lower level of priority than the given.
# (technically if daemon_prio >= wanted_prio)
stop_prio()
{
local wanted_prio
local daemon_prio
local daemon_list
local daemon_inst
local inst
if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
daemon=${BASH_REMATCH[1]}
inst=${BASH_REMATCH[2]}
else
daemon="$2"
fi
wanted_prio=$1
daemon_list=${daemon:-$DAEMONS}
echo -n "Stopping Quagga daemons (prio:$wanted_prio):"
for prio_i in `seq 10 -1 $wanted_prio`; do
for daemon_name in $daemon_list; do
eval daemon_prio=\${${daemon_name}:0:3}
daemon_inst=""
if [ $daemon_prio -eq $prio_i ]; then
eval "daemon_inst=\${${daemon_name}_instances//,/ }"
if [ -n "$daemon_inst" ]; then
for i in ${daemon_inst}; do
if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
stop "$daemon_name" "$inst"
elif [ x"$inst" == x ]; then
stop "$daemon_name" "$i"
fi
done
else
stop "$daemon_name"
fi
fi
done
done
echo "."
if [ -z "$inst" ]; then
# Now stop other daemons that're prowling, coz the daemons file changed
echo -n "Stopping other quagga daemons"
if [ -n "$daemon" ]; then
eval "file_list_suffix="$V_PATH"/"$daemon*""
else
eval "file_list_suffix="$V_PATH/*""
fi
for pidfile in $file_list_suffix.pid; do
PID=`cat $pidfile 2>/dev/null`
start-stop-daemon --stop --quiet --oknodo --pidfile "$pidfile"
echo -n "."
rm -rf "$pidfile"
done
echo "."
echo -n "Removing remaining .vty files"
for vtyfile in $file_list_suffix.vty; do
rm -rf "$vtyfile"
done
echo "."
fi
}
# Starts all daemons that have a higher level of priority than the given.
# (technically if daemon_prio <= wanted_prio)
start_prio()
{
local wanted_prio
local daemon_prio
local daemon_list
local daemon_name
local daemon_inst
local inst
if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
daemon=${BASH_REMATCH[1]}
inst=${BASH_REMATCH[2]}
else
daemon="$2"
fi
wanted_prio=$1
daemon_list=${daemon:-$DAEMONS}
echo -n "Starting Quagga daemons (prio:$wanted_prio):"
for prio_i in `seq 1 $wanted_prio`; do
for daemon_name in $daemon_list; do
eval daemon_prio=\$${daemon_name}
daemon_inst=""
if [ $daemon_prio -eq $prio_i ]; then
eval "daemon_inst=\${${daemon_name}_instances//,/ }"
if [ -n "$daemon_inst" ]; then
if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
exit 1
fi
# Check if we're starting again by switching from single instance
# to MI version
if started "$daemon_name"; then
PIDFILE=`pidfile $daemon_name`
start-stop-daemon \
--stop --quiet --oknodo \
--pidfile "$PIDFILE" \
--exec "$D_PATH/$daemon_name"
rm -f `pidfile $1`
rm -f `vtyfile $1`
fi
for i in ${daemon_inst}; do
if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
start "$daemon_name" "$inst"
elif [ x"$inst" == x ]; then
start "$daemon_name" "$i"
fi
done
else
# Check if we're starting again by switching from
# single instance to MI version
eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
for pidfile in $file_list_suffix.pid; do
start-stop-daemon --stop --quiet --oknodo --pidfile "$pidfile"
echo -n "."
rm -rf "$pidfile"
done
for vtyfile in $file_list_suffix.vty; do
rm -rf "$vtyfile"
done
start "$daemon_name"
fi
fi
done
done
echo "."
}
check_status()
{
local daemon_name
local daemon_prio
local daemon_inst
local failed_status=0
if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
daemon=${BASH_REMATCH[1]}
inst=${BASH_REMATCH[2]}
else
daemon="$1"
fi
daemon_list=${daemon:-$DAEMONS}
# Which daemons have been started?
for daemon_name in $daemon_list; do
eval daemon_prio=\$$daemon_name
if [ "$daemon_prio" -gt 0 ]; then
eval "daemon_inst=\${${daemon_name}_instances//,/ }"
if [ -n "$daemon_inst" ]; then
for i in ${daemon_inst}; do
if [ -n "$inst" -a "$inst" = "$i" ]; then
started "$1" "log" || failed_status=$?
elif [ -z "$inst" ]; then
started "$daemon_name-$i" "log" || failed_status=$?
fi
done
else
started "$daemon_name" "log" || failed_status=$?
fi
fi
done
# All daemons that need to have been started are up and running
return $failed_status
}
#########################################################
# Main program #
#########################################################
# Config broken but script must exit silently.
[ ! -r "$C_PATH/daemons" ] && exit 0
# Load configuration
. "$C_PATH/daemons"
. "$C_PATH/debian.conf"
# Read configuration variable file if it is present
[ -r /etc/default/quagga ] && . /etc/default/quagga
MAX_INSTANCES=${MAX_INSTANCES:=5}
# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
convert_daemon_prios
if [ ! -d $V_PATH ]; then
echo "Creating $V_PATH"
mkdir -p $V_PATH
chown quagga:quagga $V_PATH
chmod 755 /$V_PATH
fi
if [ -n "$3" ] && [ "$3" != "all" ]; then
dmn="$2"-"$3"
elif [ -n "$2" ] && [ "$2" != "all" ]; then
dmn="$2"
fi
case "$1" in
start)
start_daemons
;;
stop)
stop_daemons
;;
restart)
stop_daemons
start_daemons
;;
reload)
/usr/lib/quagga/quagga-reload.py --reload /etc/quagga/Quagga.conf
exit $?
;;
status)
systemctl -l -o cat -n0 status zebra bgpd ospfd ospf6d ripd ripngd isisd
exit $?
;;
help)
man -s 1 quagga
;;
*)
echo "Unknown option entered"
man -s 1 quagga
exit -1
;;
start)
# Try to load this necessary (at least for 2.6) module.
if [ -d /lib/modules/`uname -r` ] ; then
echo "Loading capability module if not yet done."
set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e
fi
# Start all daemons
cd $C_PATH/
if [ "$2" != "watchquagga" ]; then
start_prio 10 $dmn
fi
vtysh_b
start_watchquagga
;;
1|2|3|4|5|6|7|8|9|10)
# Stop/start daemons for the appropriate priority level
stop_prio $1
start_prio $1
vtysh_b
;;
stop|0)
# Stop all daemons at level '0' or 'stop'
stop_watchquagga
if [ "$dmn" != "watchquagga" ]; then
[ -n "${dmn}" ] && eval "${dmn/-/_}=0"
stop_prio 0 $dmn
fi
if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
echo "Removing all routes made by zebra."
ip route flush proto zebra
else
[ -n "$dmn" ] && eval "${dmn/-/_}=0"
start_watchquagga
fi
;;
reload)
# Just apply the commands that have changed, no restart necessary
[ ! -x "$RELOAD_SCRIPT" ] && echo "quagga-reload script not available" && exit 0
NEW_CONFIG_FILE="${2:-$C_PATH/Quagga.conf}"
[ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
echo "Applying only incremental changes to running configuration from Quagga.conf"
"$RELOAD_SCRIPT" --reload /etc/quagga/Quagga.conf
exit $?
;;
status)
check_status $dmn
exit $?
;;
restart|force-reload)
$0 stop $dmn
sleep 1
$0 start $dmn
;;
*)
echo "Usage: /etc/init.d/quagga {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
echo " E.g. '/etc/init.d/quagga 5' would start all daemons with a prio 1-5."
echo " reload applies only modifications from the running config to all daemons."
echo " reload neither restarts starts any daemon nor starts any new ones."
echo " Read /usr/share/doc/quagga/README.Debian for details."
exit 1
;;
esac
echo "Exiting from the script"
exit 0

View File

@ -767,5 +767,5 @@ if __name__ == '__main__':
os.unlink(filename)
if restart_bgp:
subprocess.call(['sudo', 'systemctl', 'reset-failed', 'bgpd'])
subprocess.call(['sudo', 'systemctl', '--no-block', 'restart', 'bgpd'])
subprocess.call(['sudo', 'systemctl', 'reset-failed', 'quagga'])
subprocess.call(['sudo', 'systemctl', '--no-block', 'restart', 'quagga'])

View File

@ -28,6 +28,7 @@
#include <sys/un.h>
#include <sys/wait.h>
#include <memory.h>
#include <systemd.h>
#ifndef MIN
#define MIN(X,Y) (((X) <= (Y)) ? (X) : (Y))
@ -985,6 +986,7 @@ static void
sigint(void)
{
zlog_notice("Terminating on signal");
systemd_send_stopping ();
exit(0);
}
@ -1275,6 +1277,7 @@ main(int argc, char **argv)
gs.restart.interval = gs.min_restart_interval;
master = thread_master_create();
systemd_send_started (master, 0);
signal_init (master, array_size(my_signals), my_signals);
srandom(time(NULL));
@ -1374,6 +1377,7 @@ main(int argc, char **argv)
thread_call (&thread);
}
systemd_send_stopping ();
/* Not reached. */
return 0;
}

View File

@ -33,7 +33,6 @@
#include "privs.h"
#include "sigevent.h"
#include "vrf.h"
#include "systemd.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
@ -192,7 +191,6 @@ sigint (void)
zns = zebra_ns_lookup (NS_DEFAULT);
zebra_ns_disable (0, (void **)&zns);
systemd_send_stopping();
exit (0);
}
@ -401,14 +399,12 @@ main (int argc, char **argv)
if (daemon_mode && daemon (0, 0) < 0)
{
zlog_err("Zebra daemon failed: %s", strerror(errno));
systemd_send_stopping ();
exit (1);
}
/* Output pid of zebra. */
pid_output (pid_file);
systemd_send_started (zebrad.master);
/* After we have successfully acquired the pidfile, we can be sure
* about being the only copy of zebra process, which is submitting
* changes to the FIB.