Iptables lives in iptables/planetlab-config
[myplc.git] / host.init
index 6e38c9d..63dd1d6 100755 (executable)
--- a/host.init
+++ b/host.init
 #
 # description: Manages all PLC services on this machine
 #
-# $Id: host.init,v 1.1.1.1 2006/03/27 17:36:46 mlhuang Exp $
+# $Id$
 #
 
 PATH=/sbin:/bin:/usr/bin:/usr/sbin
 
 # Source function library.
-. /etc/init.d/functions
+if [ -f /etc/init.d/functions ] ; then
+    . /etc/init.d/functions
+fi
+
+# If success() or failure() are not defined
+if ! type -type success >/dev/null || ! type -type failure >/dev/null ; then
+    success() {
+       echo -ne "[  OK  ]\r"
+       return 0
+    }
+    failure() {
+       echo -ne "[FAILED]\r"
+       return 1
+    }
+fi
 
 # Source configuration
-if [ -f /etc/sysconfig/plc -a -z "${PLC_ROOT}${PLC_DATA}" ] ; then
-    . /etc/sysconfig/plc
+SERVICE=$(basename $0)
+if [ ! -f /etc/sysconfig/$SERVICE ] ; then
+    SERVICE=plc
+fi
+if [ -f /etc/sysconfig/$SERVICE -a -z "${PLC_ROOT}${PLC_DATA}" ] ; then
+    . /etc/sysconfig/$SERVICE
 fi
 
-RETVAL=0
+# Total number of errors
+ERRORS=0
 
-start ()
+# Count the exit status of the last command
+check ()
+{
+    ERRORS=$(($ERRORS+$?))
+}
+
+mounted ()
+{
+    if cut -d' ' -f2 /proc/mounts | grep -q "$1" ; then
+       return 0
+    else
+       return 1
+    fi
+}
+
+mount_plc ()
 {
     echo -n $"Mounting PLC: "
 
-    if ! cut -d' ' -f2 /proc/mounts | grep -q $PLC_ROOT ; then
+    if ! mounted $PLC_ROOT ; then
        if ! e2fsck -a $PLC_ROOT.img | logger -t "PLC" ; then
            e2fsck $PLC_ROOT.img
        fi
        mount -o loop $PLC_ROOT.img $PLC_ROOT
-       RETVAL=$(($RETVAL+$?))
+       check
     fi
-    if ! cut -d' ' -f2 /proc/mounts | grep -q $PLC_ROOT/data ; then
+    if ! mounted $PLC_ROOT/data ; then
        mount -t none -o bind,rw $PLC_DATA $PLC_ROOT/data
-       RETVAL=$(($RETVAL+$?))
+       check
     fi
-    if ! cut -d' ' -f2 /proc/mounts | grep -q $PLC_ROOT/proc ; then
+    if ! mounted $PLC_ROOT/proc ; then
        mount -t proc none $PLC_ROOT/proc
-       RETVAL=$(($RETVAL+$?))
+       check
     fi
 
-    if [ $RETVAL -eq 0 ]; then
-       success $"PLC mount"
-    else
-       failure $"PLC mount"
-    fi
+    [ $ERRORS -eq 0 ] && success $"PLC unmount" || failure $"PLC unmount"      
     echo
 
-    chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS start
-    RETVAL=$?
 }
 
-stop ()
+start ()
 {
-    chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS stop
+    # Starting everything
+    if [ -z "$1" ] ; then
+       mount_plc 
+    fi
+
+    chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS start $*
+    check
+}
 
+umount_plc ()
+{
     echo -n $"Unmounting PLC: "
 
-    umount $PLC_ROOT/proc
-    RETVAL=$(($RETVAL+$?))
-    umount $PLC_ROOT/data
-    RETVAL=$(($RETVAL+$?))
-    umount $PLC_ROOT
-    RETVAL=$(($RETVAL+$?))
+    for dir in $PLC_ROOT/proc $PLC_ROOT/data $PLC_ROOT ; do
+       if mounted $dir ; then
+           umount $dir
+           check
+       fi
+    done
 
-    if [ $RETVAL -eq 0 ]; then
-       success $"PLC unmount"
-    else
-       failure $"PLC unmount"  
-    fi
+    [ $ERRORS -eq 0 ] && success $"PLC unmount" || failure $"PLC unmount"      
     echo
 }
 
-case "$1" in
+stop ()
+{
+    if mounted $PLC_ROOT ; then
+       chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS stop $*
+       check
+    fi
+
+    # Stopped everything
+    if [ -z "$1" ] ; then
+       umount_plc
+    fi
+}
+
+mountstatus_plc ()
+{
+    for dir in $PLC_ROOT/proc $PLC_ROOT/data $PLC_ROOT ; do
+       if mounted $dir ; then
+           echo $dir
+       fi
+    done
+}
+
+# safestop : tries to stop normally; if that fails, kills processes that are still using /plc 
+# needs the lsof rpm in the root context (should be a dependency of the myplc spec)
+function check_command ()
+{
+    command=$1; shift
+    found=$(type -p $command)
+    if [ -z "$found" ] ; then
+        echo "$COMMAND : requires command $command, was not found - exiting"
+       exit 1
+    fi
+}
+
+
+### when process stil use /plc/root, we cannot umount it
+function kill_all ()
+{
+    [ -n "$DEBUG" ] && set -x
+    check_command lsof
+    
+    echo -n "Killing processes using $PLC_ROOT and $PLC_DATA: "
+    # initialize process list
+    former_process_list="unlikely"
+      
+    # we ignore unknown uids for now, since we run in the chroot jail anyway
+    # not too sure about that though, 
+    while true; do
+        # get the list of processes - collapse and remove empty lines
+       process_list=$(lsof -t +D $PLC_ROOT +D $PLC_DATA)
+       if [ -z "$process_list" ] ; then
+           # we are done, let's bail out
+           success "$PLC_ROOT clear" ; echo ; return
+       fi
+       if [ "$process_list" = "$former_process_list" ] ; then
+           # we are stuck, no progress since last time : exit on error
+           failure "$PLC_ROOT locked" ; echo ; return
+       fi
+       # record for next loop
+       former_process_list="$process_list"
+       # kill them
+       kill $process_list
+       sleep 2
+       # check there are dead
+       for pid in $process_list ; do
+           ps -o pid $pid &> /dev/null 
+           if [ "$?" = 0 ] ; then
+               [ -n "$DEBUG" ] && echo "$pid survived kill - forcing kill -9"
+               kill -9 $pid
+           fi
+       done
+    done
+}
+
+# Get command
+shift $(($OPTIND - 1))
+command=$1
+
+# Get step(s)
+shift 1
+
+case "$command" in
     start|stop)
-       $1
+       $command $*
        ;;
 
     restart)
-       stop
-       start
+       stop $*
+       ERRORS=0
+       start $*
+       ;;
+
+    reload)
+       chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS reload $*
+       ;;      
+
+    mount|umount|mountstatus)
+        ${command}_plc
        ;;
 
+   kill)
+        kill_all
+        ;;
+
+   safestop)
+        stop
+       ### Checking : we might need to run kill
+       mounted=$(mountstatus_plc)
+       if [ -n "$mounted" ] ; then
+           echo "Umount failed : killing remaining processes and trying again"
+           ERRORS=0
+           kill_all
+           ERRORS=0
+           stop
+       fi
+       ;;
+  
     *)
-       echo "Usage: $0 {start|stop|restart}"
+       echo "Usage: $0 {start|stop|restart|reload|mount|umount|mountstatus|kill|safestop}"
        RETVAL=1
        ;;
 esac
 
-exit $RETVAL
+exit $ERRORS