#!/bin/bash

# Copyright (C) 2009-2017:
#    Gabes Jean, naparuba@gmail.com
#    Gerhard Lausser, Gerhard.Lausser@consol.de
#    Gregory Starck, g.starck@gmail.com
#    Hartmut Goebel, h.goebel@goebel-consult.de
#
# This file is part of Shinken Framework
#
# Shinken Framework is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Shinken Framework is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Shinken Framework.  If not, see <http://www.gnu.org/licenses/>.

### BEGIN INIT INFO
# Provides:          shinken
# chkconfig: - 90 15
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: Shinken monitoring daemon
# Description:       Shinken is a monitoring tool composed of many separated modules:
#     - arbiter     : the main one : control everything else.
#     - scheduler   : receives checks/actions from arbiter. Schedules & forwards them to pollers.
#     - poller      : receives the checks from a scheduler. Launch them and returns results
#     - broker      : manage results by looking at scheduler. Like export to flat file or db.
#     - reactionner : manage the failed checks by looking at scheduler.
#     - receiver    : manage all passive data
#     - synchronizer: manage the configuration
#     - gatherer    : (automatically launched) compute system stats
### END INIT INFO

# Deadlink :(
# http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html

# Force colors for our init
BOOTUP=color
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_NOTE="echo -en \\033[1;34m"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"
LOGLEVEL=1
MAINTENANCE_FILE="/var/lib/shinken/MAINTENANCE_MODE_ENABLED"

NAME="shinken"

AVAIL_MODULES="scheduler poller reactionner broker receiver synchronizer arbiter gatherer"

# We only support one mongodb version, because we tested it
MONGODB_VERSION_ASSERTED="3.0.15"

MONGODB_VERSION=$(LANG=C mongod --version | grep "$MONGODB_VERSION_ASSERTED")
if [ $? != 0 ];then
   echo "ERROR: your mongodb version is not the Shinken Enterprise tested one ($MONGODB_VERSION_ASSERTED). Cannot start the daemon."
   exit 2
fi


# Bug SEF-3195: on Centos 7.2 the curl->nss lib have a time race issue with other nss calls, and ssl certificats will raise an error:
#   A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot
# cf https://cohanrobinson.com/php-curl-libcurl-error-on-subsequent-requests/
export NSS_STRICT_NOFORK=DISABLED


## SHINKEN_MODULE_FILE is set by shinken-* if it's one of these that's calling us.
if [ -z "$SHINKEN_MODULE_FILE" ]; then
    SCRIPTNAME=$0
    _usage_mods_="[ <$AVAIL_MODULES> ]"
    _launch_one_module=false
else
    SCRIPTNAME=$SHINKEN_MODULE_FILE
    _launch_one_module=true
fi

#
# Set server.uuid used by the arbiter to identify them to other satellites.
#
SERVER_UUID=/var/lib/shinken/server.uuid
# If we have root privileges
if [ "$(id -u)" == "0" ]; then
    # Set/update the BIOS UUID. It should be unique across vm clones.
    if [ -r /sys/class/dmi/id/product_uuid ] ; then
        cat /sys/class/dmi/id/product_uuid | \
            tr '[:upper:]' '[:lower:]' > ${SERVER_UUID}
    else
        # If there is no BIOS UUID, we get one from shinken-context-manage
        uuid=$(shinken-context-manage --get-server-identity)
        mac_hash=$(echo $uuid | cut -f 2 -d -)

        if [ -r "${SERVER_UUID}" ]; then
            previous_uuid=$(cat "${SERVER_UUID}")
            previous_mac_hash=$(cut -f 2 -d - "${SERVER_UUID}")
            if [ "${previous_mac_hash}" != "${mac_hash}" ] ; then
                rm "${SERVER_UUID}"
            fi
        fi

        if [ ! -r "${SERVER_UUID}" ]; then

            if shinken-addons-has nagvis >/dev/null 2>/dev/null ; then
                shinken-addons-disable nagvis  >/dev/null 2>/dev/null
                nagvis=yes
            fi
            if shinken-addons-has nagvis-shinken-architecture >/dev/null 2>/dev/null ; then
                shinken-addons-disable nagvis-shinken-architecture >/dev/null 2>/dev/null
                nagvis_arch=yes
            fi

            echo $uuid > "${SERVER_UUID}"
            shinken-context-manage --update-nagvis-uuid --old-nagvis-uuid "${previous_uuid}" --new-nagvis-uuid "${uuid}"
            if [ $nagvis = "yes" ] ; then
                shinken-addons-enable nagvis  2>/dev/null > /dev/null
            fi
            if [ $nagvis_arch = "yes" ] ; then
                shinken-addons-enable nagvis-shinken-architecture 2>/dev/null > /dev/null
            fi
        fi
    fi
else
    # Not root, check if /var/lib/shinken/server.uuid is present
    if [ ! -e "${SERVER_UUID}" ]; then
        # If it does not exists, we must create a temporary one
        # He will change the next time this script is run as root
        # (next reboot).
        echo -n "shinken-temporary-uuid-" > "${SERVER_UUID}"
        date +%s%N >> ${SERVER_UUID}
    fi
fi

curpath=$(cd $(dirname "$0") && pwd)
#echo curpath is $curpath filename is $(basename "$0")

## Default paths:
test "$BIN" || BIN=$(cd $curpath/.. && pwd)
test "$VAR" || VAR=$(cd $curpath/../../var && pwd)
test "$ETC" || ETC=$(cd $curpath/../../etc && pwd)

export PATH="${PATH:+$PATH:}/usr/sbin:/bin:/sbin"
export LANG=en_US.UTF8
export LC_ALL=en_US.UTF8
export PYTHONIOENCODING=utf8
export PYTHONUNBUFFERED="1"
unset http_proxy
unset https_proxy
# We forbid some TYPES to be load globaly from flat files, and only import system will be able to
# import them with the synchronizer daemon
export FORBIDDEN_TYPES="host contact service command timeperiod macromodulation hostgroup contactgroup notificationway checkmodulation businessimpactmodulation resultmodulation servicedependency hostdependency escalation serviceescalation hostescalation hostextinfo serviceextinfo"

# Set high limit for open files
ulimit -n 65535 2>/dev/null

# We try to find the LAST possible Python VERSION
pythonver() {
    versions="2.4 2.5 2.6 2.7"
    LASTFOUND=""
    # Is there any python here?
    for v in $versions
    do
        which python$v > /dev/null 2>&1
        if [ $? -eq 0 ]
        then
            LASTFOUND="python$v"
        fi
    done
    if [ -z "$LASTFOUND" ]
    then
        # Finaly try to find a default python
        which python > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            echo "No python interpreter found!"
            exit 2
        else
            echo "python found"
            LASTFOUND=$(which python)
        fi
    fi
    PYTHON=$LASTFOUND
}

# Ok, go search this Python version
pythonver

NO_JE_MALLOC_FLAG='/var/lib/shinken/disable_jemalloc.flag'
JE_MALLOC_PATH="/usr/lib64/libjemalloc.so.1"
check_jemalloc_lib(){
    if [ ! -f $JE_MALLOC_PATH ];then
        echo "Cannot find the libjemalloc at $JE_MALLOC_PATH. Please check your installation. Please create the file $NO_JE_MALLOC_FLAG if you want to disable it."
        if [ ! -f $NO_JE_MALLOC_FLAG ];then
           echo "Exiting on error"
           exit 2
        fi
    fi
}
check_jemalloc_lib

# Uncomment the line below if you got the **lib** shinken installed
# on a non standard place (not in /usr/lib/python*)
#export PYTHONPATH="${PATH:+$PATH:}/opt/shinken"
# Or uncommentif you want to force the Python version
#export PYTHON=python2.7

# default
DEBUG=false
CMD=""
SUBMODULES=""
# if the command should limit to a specific instance id, by default do not limit
SPECIFIC_INSTANCE_ID=""

## This permits to overhidde the default "default shinken cfg file":
[ -z "$SHINKEN_DEFAULT_FILE" ] && SHINKEN_DEFAULT_FILE="/etc/default/$NAME"



usage() {
    cat << END
Usage: $SCRIPTNAME [ -d ]  [ --id X] {start|stop|restart|status|check} $_usage_mods_

 -d  start requested module(s) in debug mode, only useful with start|restart
 --id X : only start/stop/status the instance number X of the daemons

END
}

if [ "$1" = "-d" ]; then
    DEBUG="1"
    shift
fi


if [ "$1" = "--id" ]; then
    shift
    SPECIFIC_INSTANCE_ID="$1"
    shift
fi


if [ $# -eq 0 ]; then
    usage >&2
    exit 2
fi

CMD=$1
shift
SUBMODULES=$*

# Reads configuration variable file if it is present
[ -r "$SHINKEN_DEFAULT_FILE" ] && . "$SHINKEN_DEFAULT_FILE"

if [ -z "$SUBMODULES" ]; then
    SUBMODULES=$AVAIL_MODULES
else
    # check given modules
    for mod1 in $SUBMODULES; do
        found=0
        for mod2 in $AVAIL_MODULES; do
            [ $mod1 = $mod2 ] && found=1;
        done
        [ $found = 0 ] && { usage >&2 ; exit 2 ; }
    done
fi

# Now look if some required variables are pre defined:
if ! test "$SHINKENCFG"
then
    SHINKENCFG="$ETC/shinken.cfg"
fi

# If var or run dir is missing, create them and chown them
[ ! -d $VAR ] && mkdir -p $VAR && chown $SHINKENUSER:$SHINKENGROUP $VAR
[ ! -d $RUN ] && mkdir -p $RUN && chown $SHINKENUSER:$SHINKENGROUP $RUN

# Now place us in our var directory so even our arbiter will be
# happy for opening its pid and cmd files
cd $VAR


#set -xv


echo_success() {
   log_end_msg 0 $*
}

echo_failure() {
    log_end_msg 1 $*
}


# Load the VERBOSE setting and other rcS variables
[ -f /etc/default/rcS ] && . /etc/default/rcS

# Source function library.
[ -f /etc/rc.d/init.d/functions ] && . /etc/rc.d/init.d/functions

[ -f /lib/lsb/init-functions ] && . /lib/lsb/init-functions

# Have a special started output to show that we did launch but it's not currently finished yet
echo_started() {
  RES_COL=60
  MOVE_TO_COL="echo -en \\033[${RES_COL}G"
  SETCOLOR_SUCCESS="echo -en \\033[32m"
  SETCOLOR_NORMAL="echo -en \\033[0;39m"
  $MOVE_TO_COL
  echo -n "["
  $SETCOLOR_SUCCESS
  echo -n $"Started: initialisation ongoing"
  $SETCOLOR_NORMAL
  echo -n "]"
  echo -ne "\r"
  return 0
}


################################################
#
# returns the pid for a submodule
#
GATHERER_PID_FILE="/var/run/shinken/gatherer.pid"

# We have a python tool for this
getpidfile() {
    mod="$1"

    if [ $mod == "gatherer" ];then
       echo $GATHERER_PID_FILE
       return
    fi

    id=${2:-0}
    pidfile=$(shinken-daemons-utils --type $1 --id $id --action get-pid-file)
    echo $pidfile
}


getmodpid() {
    mod=$1
    id=${2:-0}
    pidfile=$(getpidfile "$mod" "$id")
    if [ -s $pidfile ]; then
        cat $pidfile
    fi
}


getpidtree(){
    pid=$1
    res=$(ps --forest -opid,user,cmd -g $(ps -o sid= -p $pid)| grep -v root | grep shinken | awk '{print $1}')
    echo $res;
}


is_process_exists(){    
    if ps -p $1 > /dev/null
    then
	    echo "running"
    else
	    echo "notrunning"
    fi
}


getdebugfile() {
    daemon_type=$1
    daemon_id=${2:-0}
    echo "/var/log/shinken/$daemon_type""d-$daemon_id.debug.log"
    return
    mod="$1"
    modDEBUG=$(echo $mod | tr 'a-z' 'A-Z')"DEBUGFILE"
    debugfile=$(echo $(eval echo \${$modDEBUG}))
    if test "$debugfile"
    then
        echo "$debugfile"
    else
        echo "${VAR}/${mod}-debug.log"
    fi
}


__get_worse_return(){
    if [ $1 -gt $2 ];
    then
        echo $1
    else
        echo $2
    fi
}


# When we are starting a daemon, we MUT have the gatherer script
__assert_gatherer_is_started(){
    gatherer_is_started=$(do_status "gatherer")
    if [ $? -ne 0 ];then
       $SETCOLOR_NOTE
       printf "IMPORTANT:"
       $SETCOLOR_NORMAL
       printf " The shinken-gatherer (computing statistics for other daemon in background) was not started.\n  => Have a look to /var/log/shinken/gatherer.log for troubleshoot.\n"
       echo  "Starting gatherer:"
       do_start "gatherer"
       __print_daemon_label "gatherer" 0
       echo_started
       echo ""
       echo ""
    fi
}

#
# Display status
#
do_status() {
    mod=$1
    daemon_id=${2:-0}


    pidfile=$(getpidfile "$mod" "$daemon_id")
    [ -e "$pidfile" ] || {
        echo -n "NOT RUNNING (pidfile $pidfile not exist)"
        return 3
    }
    [ -r "$pidfile" ] || {
        echo -n "NOT RUNNING (pidfile $pidfile unreadable)"
        return 3
    }
    pid=$(cat "$pidfile")
    if [ -z "$pid" ]; then
        echo -n "NOT RUNNING (pid file empty)"
        return 4
    fi
    ps -p "$pid" >/dev/null 2>&1
    rc=$?
    if [ $rc != 0 ]; then
        log_failure_msg  "NOT RUNNING (process $pid doesn't exist)"
        return 1
    fi
    echo -n "RUNNING (pid $pid)"
    return 0
}


#
# starts our modules
#
do_start() {

    if [ -a ${MAINTENANCE_FILE} ]; then
        output="A maintenance operation is underway on shinken. If this maintenance operation ended badly and you know what you are doing, you can delete the file : ${MAINTENANCE_FILE} to restart shinken."
        resfile="/tmp/bad_start_for_$daemon_type""_instance_$daemon_id"
        echo "$output" > "$resfile" || true
        printf "\033[91m\n\t\tFAILED:\n\t\t$output \n\t\tOutput is in $resfile\033[0m"
        return 1
    fi

    daemon_type=$1
    daemon_id=${2:-0}

    if [ $daemon_type == "gatherer" ];then
       # IMPORTANT: the gatherer is unable to fork() as daemon, so launch with a nohup
       LD_PRELOAD='' nohup $PYTHON /var/lib/shinken/libexec/tools/shinken-gatherer.py >/dev/null 2>/dev/null &
       rc=$?
       if [ $rc != 0 ];then
          gatherer_log=$(tail -n 5 /var/log/shinken/gatherer.log)
          printf "\n\t\tFAILED: Cannot start the Gatherer\n\t\t$gatherer_log \n"
       fi
       return $rc
    fi

    daemon_script="$BIN/shinken-${daemon_type}"

    [ "$DEBUG" = 1 ] && DEBUGCMD="--debug "$(getdebugfile "$daemon_type" "$daemon_id")
    # Be sure the /etc/shinken dir have the valid rights
    chown -R shinken:shinken /etc/shinken  2>/dev/null

    cfg_file=$(shinken-daemons-utils --type $daemon_type --id $daemon_id --action get-configuration-file)

    # Be sure the configuration file is in unix mode, ujust in case
    dos2unix $cfg_file 2>/dev/null

    nice_value=10
    additional_ini=""

    if [ "$daemon_type" == "poller" -o "$daemon_type" == "reactionner" ]; then
        #output=$(nice -n 19 $PYTHON -u "$daemon_script" -d -c "${cfg_file}" $DEBUGCMD 2>&1)
        nice_value=19
    fi

    # Special cases for arbiter and synchronizer
    if [ "$daemon_type" == "arbiter" -o "$daemon_type" == "synchronizer" ]; then
        additional_ini=" -c /etc/shinken/daemons/$daemon_type""d.ini "
    fi

    # If we are allowed (default) then we want to launch our daemons with libjemalloc
    # because libc is leaking memory over time with fragmentation
    if [ ! -f $NO_JE_MALLOC_FLAG  ];then
        export LD_PRELOAD="$JE_MALLOC_PATH"
    else
      export LD_PRELOAD=""
    fi

    output=$(nice -n $nice_value $PYTHON -u "$daemon_script" -d -c "${cfg_file}" $additional_ini $DEBUGCMD --daemon-id=$daemon_id 2>&1)

    rc=$?

    if [ $rc != 0 ]; then
        resfile="/tmp/bad_start_for_$daemon_type""_instance_$daemon_id"
        echo "$output" > "$resfile" || true
        output=$(echo "$output" | grep ERROR | tail -1)
        printf "\n\t\tFAILED:\n\t\t$output \n\t\tFull output is in $resfile"
        return 1
    fi
    echo -n "OK"
    return 0
}


#
# stops modules
#
do_stop() {

    daemon_type=$1
    daemon_id=${2:-0}

    pid=$(getmodpid "$daemon_type" "$daemon_id")

    statusoutput=$(do_status "$daemon_type" "$daemon_id")
#    echo "\nModule state daemon_type  $statusoutput " >> /tmp/out
    [ $? -ne 0 ] && {
        echo -n "$statusoutput"
#        echo "Module state daemon_type exit becaue not launched" >> /tmp/out
        return 0
    }
    if [ ! -z "$pid" ]; then
        # First save the subtree before trying to
        allpids=$(getpidtree $pid)
#        echo "Module daemon_type all pids $allpids" >> /tmp/out
        kill "$pid"
        sleep 0.5
        allok="true"
        for cpid in $allpids; do
             if [ $(is_process_exists $cpid) == "running" ]
             then
               allok="false"
             fi
        done
        if [ $allok == "true" ]
        then
#            echo "ALL daemon_type process are dead in the list $allpids" >> /tmp/out
            echo "OK"
           return 0
        fi
        echo "There are still remaining processes to $daemon_type running.. ; trying to kill them (SIGTERM).."
        #echo "KILLING" daemon_type $pid $allpids
        MAX_COUNTER=30
        if [ "$daemon_type" = "scheduler" ]; then
#            Maybye the retention save take too much time, so get all the pid a new time
            allpids=$(getpidtree $pid)
            MAX_COUNTER=120
        fi
        COUNTER=0
        for cpid in $allpids; do
            if [ $(is_process_exists $cpid) == "running" ]
            then
#                echo "KILLING" $cpid `ps aux | grep $cpid`
                kill $cpid > /dev/null 2>&1
                # wait for the daemon to die or wait 30s and kill it with a -9
                while [ $(is_process_exists $cpid) == "running" ] && [ $COUNTER  -lt $MAX_COUNTER ]; do
                    sleep 1
                    let COUNTER+=1
                done
                if [ $COUNTER -ge $MAX_COUNTER ]; then
                    kill -9 $cpid  > /dev/null 2>&1
                fi
            fi
        done
        # wait a bit for process to manage signal before check and warn about them
        sleep 2
        for cpid in $allpids; do
            if [ $(is_process_exists $cpid) == "running" ]
            then
                echo "FAILED: one or more process for $daemon_type are still running after kill -9!"
                echo "Remaining processes are (pids="$cpid"):"
                ps aux | grep -v grep |grep $cpid
                echo "You should check this."
                return 1
            fi
        done

        echo "OK"
    else
        echo "NOT RUNNING"
    fi
    return 0
}


#
# does the config check
#
do_check() {
    [ "$DEBUG" = 1 ] && DEBUGCMD="--debug $VAR/${mod}-debug.log"
    "$BIN/shinken-arbiter" -v -c "$SHINKENCFG" $DEBUGCMD 2>&1
    return $?
}


__print_daemon_label(){
   daemon_type=$1
   daemon_id=$2

   # TODO: get a real name
   daemon_name=$(shinken-daemons-utils --type $daemon_type --id $daemon_id --action get-instance-name)  #"unnamed "
   str=$(printf "  (id:%s) %s " "$daemon_id" "$daemon_name")
   str2=$(printf "  [ %s " "$str")
   # 54: so we are near the [OK] block from the end
   printf "%-54s ] : " "$str2"
}


# Maybe this daemon_id is not interesting when lookip at the global parameter/filter
__should_skip_daemon_id(){
   daemon_id=$1

   # If the global parameter is not set, do not skip
   if [ "XX$SPECIFIC_INSTANCE_ID" == "XX" ]; then
       return 1  # false
   fi

   # Ok it is set, so it it the same or not?
   if [ "$SPECIFIC_INSTANCE_ID" == "$daemon_id" ]; then
       return 1  # false
   fi

   # not the same
   return 0   # true
}

# If a specific daemon ID is asked, for whe check if it exists
__exists_daemon_id() {
    if [ -n "$SPECIFIC_INSTANCE_ID" ]; then
       is_existing_id=0
       for daemon_id in $mods_enabled ; do
            if [ "$SPECIFIC_INSTANCE_ID" = "$daemon_id" ]; then
                is_existing_id=1
            fi
        done
        if [ $is_existing_id -eq 0 ] ; then
            echo "Daemon $daemon_type with id $SPECIFIC_INSTANCE_ID does not exist."
            return 1
        fi
    fi
    return 0
}

############################
do_start_() {
    daemon_type=$1
    # Maybe this daemon is not enabled at all?
    mods_enabled=$(/usr/sbin/shinken-daemons-has $daemon_type)

    # Do not start/stop the gatherer in a global start, only for specific call
    if [ "$daemon_type" == "gatherer" ] && [ $_launch_one_module == "false" ];then
        return 0
    fi

    if [ "$mods_enabled" == "NO" ]; then
        # skipping this daemon
        if $_launch_one_module; then
            echo "The daemons is disable use shinken-daemons-enable $1 for enable it."
        fi
        return 0
    fi

    # synchronizer and broker need a mongodb
    if [ "$daemon_type" = "broker" ] || [ "$daemon_type" = "synchronizer" ]; then
	    /etc/init.d/mongod  start >/dev/null 2>/dev/null
    fi
    if [ "$daemon_type" = "broker" ]; then
        /etc/init.d/carbon-cache  start >/dev/null 2>/dev/null
    fi

    # We need time synchronisation at start-up
    /etc/init.d/ntpd  restart >/dev/null 2>/dev/null
    
    start_rc=0

    __exists_daemon_id || return 1

    echo  "Starting $1:"

    for daemon_id in $mods_enabled; do
        # Maybe we did ask for a specific daemon_id only, if so, skip it not the good one
        if __should_skip_daemon_id $daemon_id; then
             continue
        fi
        status=$(do_status "$daemon_type" "$daemon_id")
        rc=$?
        if [ $rc -eq 0 ]; then
            log_warning_msg "Already running"
                continue
        fi
            if test "$daemon_type" = "arbiter"
        then
                # arbiter is special it doesn't actually declare a "workdir" properties in its config
            # so we have explicitely to cd to the "VAR" directory.
            cd "$VAR"
        fi

            __print_daemon_label $daemon_type $daemon_id

            startoutput=$(do_start "$daemon_type" "$daemon_id")
        rc=$?
            start_rc=$(__get_worse_return $start_rc $rc)

        if [ $rc -eq 0 ]; then
            echo_started
        echo
        else
            echo_failure
                echo "$startoutput"
        echo
        fi
        #return $rc
    done

    echo

    # In all cases aside gatherer itself, gatherer must be started
    if [ $daemon_type != "gatherer" ];then
        __assert_gatherer_is_started
    fi

    return $start_rc
}


do_stop_() {
    daemon_type=$1
    # Maybe this daemon is not enabled at all?
    mods_enabled=$(/usr/sbin/shinken-daemons-has $daemon_type)
    if [ "$mods_enabled" == "NO" ]; then
	# skipping this daemon
        return 0
    fi

    # Do not start/stop the gatherer in a global start, only for specific call
    if [ "$daemon_type" == "gatherer" ] && [ $_launch_one_module == "false" ];then
        return 0
    fi

    # If a specific daemon ID is asked, for whe check if it exists
    __exists_daemon_id || return 1

    echo  "Stopping $daemon_type: "

    stop_rc=0

    for daemon_id in $mods_enabled; do
        # Maybe we did ask for a specific daemon_id only, if so, skip it not the good one
        if __should_skip_daemon_id $daemon_id; then
             continue
        fi

        __print_daemon_label $daemon_type $daemon_id
        statusoutput=$(do_status "$daemon_type" "$daemon_id")
        rc=$?

        if [ $rc -ne 0 ]; then
            failuremsg="$statusoutput"
        else

                stopoutput=$(do_stop "$daemon_type" "$daemon_id" 2>&1)

            rc=$?
            [ $rc -ne 0 ] && failuremsg="Couldn't stop $1: $stopoutput"
        fi
            stop_rc=$(__get_worse_return $stop_rc $rc)
        if [ $rc -ne 0 ]; then
                log_failure_msg ""
                printf "\t\t$failuremsg"
        echo
        else
            echo_success
        echo
        fi

     done
     echo
     return $stop_rc
}


do_restart_() {
    # Maybe this daemon is not enabled at all?
    mod_enabled=$(/usr/sbin/shinken-daemons-has $1)
    if [ "$mod_enabled" == "NO" ]; then
	# skipping this daemon
	return 0
    fi

    # If a specific daemon ID is asked, for whe check if it exists
    __exists_daemon_id || return 1

    mod="$1"
    echo "Restarting $mod"

    stopoutput=$(do_stop "$mod")
    startoutput=$(do_start "$mod")
    rc=$?
    if [ $rc -eq 0 ]; then
        echo_started
	echo
    else
        log_failure_msg "$startoutput"
        echo_failure
	echo
    fi
    return $rc
}


do_reload_() {
    mod="$1"
    # If a specific daemon ID is asked, for whe check if it exists
    __exists_daemon_id  || return 1

    echo "Reloading $mod"
    if [ "$mod" = "arbiter" ]; then
        do_check_ "$mod"
        checkrc=$?
        if [ $checkrc -ne 0 ]; then
           return 1
        fi
    fi
    stopoutput=$(do_stop "$mod")
    startoutput=$(do_start "$mod")
    rc=$?
    if [ $rc -eq 0 ]; then
        echo_success
	echo
    else
        log_failure_msg "$startoutput"
        echo_failure
	echo
    fi
    return $rc
}


do_status_() {
    # Maybe this daemon is not enabled at all?
    daemon_type="$1"
    mods_enabled=$(/usr/sbin/shinken-daemons-has $daemon_type)
    if [ "$mods_enabled" == "NO" ]; then
	    # skipping this daemon type
	return 0
    fi

    status_rc=0

    # If a specific daemon ID is asked, for whe check if it exists
    __exists_daemon_id || return 1

    mod=$1
    echo "Checking $mod""s: "
    for daemon_id in $mods_enabled; do
        # Maybe we did ask for a specific daemon_id only, if so, skip it not the good one
        if __should_skip_daemon_id $daemon_id; then
             continue
        fi

        __print_daemon_label $1 $daemon_id
        #printf "\t[id:%s] %-15s : " $daemon_id $1
        output=$(do_status "$1" "$daemon_id")
    rc=$?
        status_rc=$(__get_worse_return $status_rc $rc)
    if [ $rc -eq 0 ]; then
            printf "$output"
        echo_success
	echo
	        #return $rc
    else
        echo_failure
	echo
            # In error: show error in the line under
            printf "\t\t$output"
            echo
	        #return $rc
    fi
        done
    echo
    return $status_rc
}


do_check_() {
    echo "Doing config check"
    output=$(do_check "$1" 2>&1)
    rc=$?
    if [ $rc -eq 0 ]; then
        echo_success
	echo
    else
        check_res_file=$(mktemp /tmp/shinken_checkconfig_resultXXXXXXXX)
        echo "$output" > "$check_res_file"
        mv $check_res_file /tmp/shinken_checkconfig_result
        check_res_file="/tmp/shinken_checkconfig_result"
        output=$(echo "$output" | tail -1)
        log_warning_msg "full result is in ${check_res_file}"
        log_failure_msg "ConfigCheck failed: $output"
        echo_failure
	echo
    fi
    return $rc
}
do_checkconfig_() { do_check_ "$1" ; }


############################

do_cmd_on() {
    action=$1
    mods=$2
    do_not_exit_flag=$3
    rc_sum=0
    for mod in $mods
    do
        do_${action}_ "$mod"
	rc=$?
	if [ $rc != 0 ]
	then
	    rc_sum=$rc
	fi
    done
    if [ -z $do_not_exit_flag ]; then
	    exit $rc_sum
    fi
}


############################
## Main:

case "$CMD" in
    start|stop|status)
        do_cmd_on "$CMD" "$SUBMODULES"
        ;;
    restart)
	# note: the -d is already managed by the script, CMD contan only restart here
        do_cmd_on "stop"  "$SUBMODULES" "do-not-exit"
        do_cmd_on "start" "$SUBMODULES"
        ;;    
    check|checkconfig|reload)
        do_cmd_on "$CMD" "arbiter"
        ;;
    *)
        usage >&2
        exit 2
        ;;
esac


