]> git.proxmox.com Git - mirror_frr.git/commitdiff
initd: initd-mi.patch
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 01:03:41 +0000 (18:03 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 01:03:41 +0000 (18:03 -0700)
Support Multi-Instance protocol daemons initd

OSPFd is the first of the multi-instance daemons. This patch allows the
starting, stopping, restarting and monitoring of multiple instances of
the same protocol daemon.

Multiple instances are specified in the daemons file using a new variable:
ospfd_instances="1,2"

Absence of this variable means ospfd will start in legacy, single instance
mode. The original "ospfd=yes" line is still required.

Daemons are started with the "-n <instance>" option. Each daemon is named
"<daemon>-<instance>", for example "ospfd-1", "ospfd-2" etc. Similarly,
pid files are ospfd-1.pid and vty files are named ospfd-1.vty.

We're also introducing a new file, /etc/default/quagga to store the
default value for the maximum instances associated with a daemon.

watchquagga and others are unmodified and everything else just works once
this code is in place.

The code has been enhanced to support restarting watchquagga with only the
updated daemons when an individual daemon is stopped or started. For example,
without this patch, stopping just bgpd would terminate watchquagga even if
ospfd and zebra are still running. Similarly, starting just bgpd when ospfd
and zebra are running wouldn't update watchquagga to include bgpd. Furthermore,
when the daemons file is modified and a daemon is no longer deemed necessary
and quagga restarted, the daemon is not killed. For example, switching
ospfd=yes to ospfd=no and restarting the quagga will leave ospfd daemon
running. This case is also fixed with this patch.

However, adding a new instance to the ospfd_instances file and starting
just that instance will start just that instance and add it to watchquagga.
Similarly, a single instance maybe stopped or restarted.

Caveat emptor: With multi-instance daemons, stopping a single instance and then
starting a different instance will cause all instances to be monitored by
watchquagga i.e. all instances will be restarted, if necessary.

Signed-off-by: Dinesh G Dutt <ddutt at cumulusnetworks.com>
debian/quagga.default [new file with mode: 0644]
debian/quagga.init.d

diff --git a/debian/quagga.default b/debian/quagga.default
new file mode 100644 (file)
index 0000000..3120a57
--- /dev/null
@@ -0,0 +1 @@
+MAX_INSTANCES=5
index 84f9de7017c8a1e7e74ee98fe76f98117caf4044..c92ffa2ecb27ea1f5abe96af01cc535a865fac7c 100755 (executable)
 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
 
 # Print the name of the pidfile.
 pidfile()
 {
-        echo "/var/run/quagga/$1.pid"
+    echo "$V_PATH/$1.pid"
+}
+
+# Print the name of the vtysh.
+vtyfile()
+{
+    echo "$V_PATH/$1.vty"
 }
 
 # Check if daemon is started by using the pidfile.
@@ -61,9 +69,12 @@ check_daemon()
           # check for daemon binary
           if [ ! -x "$D_PATH/$1" ]; then return 1; fi
                 
-          # check for config file                 
-          if [ ! -r "$C_PATH/$1.conf" ]; then
-            echo -n " (not started without config file)"
+          # check for config file
+          if [ -n "$2" ]; then
+           if [ ! -r "$C_PATH/$1-$2.conf" ]; then
+               return 1
+           fi
+          elif [ ! -r "$C_PATH/$1.conf" ]; then
             return 1
           fi
         fi
@@ -74,36 +85,70 @@ check_daemon()
 # The Quagga daemons creates the pidfile when starting.
 start()
 {
-        echo -n " $1"
-        if ! check_daemon $1; then return; fi
-
         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 " (not started without config file)"
+              return;
+          fi
+
+           start-stop-daemon \
+               --start \
+               --pidfile=`pidfile $1-$2` \
+               --exec "$D_PATH/$1" \
+               -- \
+               `eval echo "$""$1""_options"` -n "$2"
         else
-            start-stop-daemon \
-                --start \
-                --pidfile=`pidfile $1` \
-                --exec "$D_PATH/$1" \
-                -- \
-                `eval echo "$""$1""_options"`
+           echo -n " $1"
+           if ! check_daemon $1; then
+               echo -n " (not started without config file)"
+               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()
 {
-    if ! started "$1" ; then
-        echo -n " ($1)"
+    local inst
+
+    if [ -n "$2" ]; then
+       inst="$1-$2"
+    else
+       inst="$1"
+    fi
+
+    if ! started "$inst" ; then
+        echo -n " ($inst)"
         return 0
     else
-        PIDFILE=`pidfile $1`
+        PIDFILE=`pidfile $inst`
         PID=`cat $PIDFILE 2>/dev/null`
-        start-stop-daemon --stop --quiet --oknodo --exec "$D_PATH/$1"
+        start-stop-daemon --stop --quiet --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
         #
         #       Now we have to wait until $DAEMON has _really_ stopped.
         #
@@ -121,8 +166,9 @@ stop()
                 echo -n "."
                 done
             fi
-        echo -n " $1"
-        rm -f `pidfile $1`
+        echo -n " $inst"
+        rm -f `pidfile $inst`
+        rm -f `vtyfile $inst`
     fi
 }
 
@@ -131,13 +177,15 @@ convert_daemon_prios()
 {
         for name in $DAEMONS zebra vtysh_enable watchquagga_enable; do
           # First, assign the value set by the user to $value 
-          eval value=\$$name
+          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
+          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.
@@ -154,6 +202,7 @@ start_watchquagga()
     local daemon_name
     local daemon_prio
     local found_one
+    local daemon_inst
 
     # Start the monitor daemon only if desired.
     if [ 0 -eq "$watchquagga_enable" ]; then
@@ -173,8 +222,22 @@ start_watchquagga()
     for daemon_name in $DAEMONS; do
         eval daemon_prio=\$$daemon_name
         if [ "$daemon_prio" -gt 0 ]; then
-            watchquagga_options+=($daemon_name)
-            found_one=1
+           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
 
@@ -201,21 +264,65 @@ 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=${2:-$DAEMONS}
+        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
+               eval daemon_prio=\${${daemon_name}:0:3}
+               daemon_inst=""
                 if [ $daemon_prio -eq $prio_i ]; then
-                    stop "$daemon_name"
+                  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.
@@ -225,23 +332,75 @@ 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=${2:-$DAEMONS}
+        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
+               eval daemon_prio=\$${daemon_name}
+               daemon_inst=""
                 if [ $daemon_prio -eq $prio_i ]; then
-                    start "$daemon_name"
+                  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 "."
 }
 
+
 #########################################################
 #               Main program                            #
 #########################################################
@@ -253,13 +412,25 @@ start_prio()
 . "$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 /var/run/quagga ]; then
-    mkdir -p /var/run/quagga
-    chown quagga:quagga /var/run/quagga
-    chmod 755 /var/run/quagga
+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" ]; then
+   dmn="$2"-"$3"
+else
+   dmn="$2"
 fi
 
 case "$1" in
@@ -273,7 +444,7 @@ case "$1" in
         # Start all daemons
         cd $C_PATH/
         if [ "$2" != "watchquagga" ]; then
-          start_prio 10 $2
+          start_prio 10 $dmn
         fi
         vtysh_b
         start_watchquagga
@@ -289,20 +460,24 @@ case "$1" in
     stop|0)
         # Stop all daemons at level '0' or 'stop'
         stop_watchquagga
-        if [ "$2" != "watchquagga" ]; then
-          stop_prio 0 $2
+        if [ "$dmn" != "watchquagga" ]; then
+         [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
+          stop_prio 0 $dmn
         fi
 
-        if [ -z "$2" -o "$2" = "zebra" ]; then
+        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
         ;;
 
     restart|force-reload)
-        $0 stop $2
+        $0 stop $dmn
         sleep 1
-        $0 start $2
+        $0 start $dmn
         ;;
 
     *)