#!/bin/sh
################################################################################
# Name          : zebos                                                        #
# Description   : Helper script to manage zebos daemons                        #
#                 It is simple utility just to start/monitor or stop #
#                 a zebos process or all zebos processes.                      #
# Usage         :                                                              #
#                zebos (start|stop|restart|monitor) {<name>|all}     #
#                arguments:                                                    #
#                        start      start process(s)                           #
#                        stop       stop process(s)                            #
#                        restart    restart process(s)                         #
#                        monitor    monitor process(s)                         #
#                        name       name of the process                        #
#                        all        all zebos processes                        #
################################################################################

#list of zebos processes to be managed
PROCESS_LIST=('imi' 'nsm' 'ribd' 'bgpd' 'mplsd' 'vlogd')

#path for zebos binaries and runit binaries
ZEBOS_PATH="/usr/bin/"
RUNIT_PATH="/usr/bin/"

#variable to store input argument values
ACTION=""
PROCESS=""

#exit codes
EXIT_SUCCESS=0
EXIT_INVALID_ARGS=1

GUARDIAN_CONFIG_FILE="/tmp/guardian_config"

# -----------------------------------------------------------------------------
zebos_print_usage_and_exit()
{
    echo "Description: Utility to manage zebos processes"
    echo
    echo "Usage: $(basename $0) (start|stop|restart|monitor) {<name>|all}";
    echo "arguments:"
    echo -e "\tstart      start process(s)";
    echo -e "\tstop       stop process(s)";
    echo -e "\trestart    restart process(s)";
    echo -e "\tmonitor    monitor process(s)";
    echo -e "\tname       name of the process";
    echo -e "\tall        all zebos processes";
    echo
    exit $EXIT_INVALID_ARGS
}

# -----------------------------------------------------------------------------
validate_process_name()
{
    local is_valid_process=0

    #empty string
    if [ -z "$PROCESS" ] ; then
        echo "The process name is empty";
        zebos_print_usage_and_exit ;
    fi

    #'all'
    if [[ ( "$PROCESS" = "all" ) ]]; then
        return 1;
    fi

    # specific process
    for process_name in "${PROCESS_LIST[@]}" ; do
        if [[ $process_name == $PROCESS ]]; then
            is_valid_process=1
            break
        fi
    done

    if [[ $is_valid_process = 1 ]]; then
        # valid process
        return 1;
    else
        echo "Error: The process name is not valid."
        echo "       The available processes are (${PROCESS_LIST[@]})"
        echo
        exit $EXIT_INVALID_ARGS
    fi
}

# -----------------------------------------------------------------------------
start_process_by_name()
{
    if [ -f "$ZEBOS_PATH$PROCESS" ]; then
        printf "Starting process %s ..." $PROCESS;

        ps -ef |grep "$PROCESS \-d" |grep -v grep &> /dev/null
        if [ $? = 0 ]; then
            printf " (%s is already running)\n" $PROCESS
            return 1;
        fi

        #execute the command
        exec_command="$ZEBOS_PATH$PROCESS -d &> /dev/null"
        $exec_command

        #check whether the process is running
        ps -ef |grep "$PROCESS \-d" |grep -v grep &> /dev/null
        if [ $? = 0 ] ; then
            printf " (succeeded)\n"
        else
            printf " (failed)\n"
        fi
    fi
}

# -----------------------------------------------------------------------------
start_zebos()
{
    if [ "$PROCESS" = "all" ] ; then
        for process_name in "${PROCESS_LIST[@]}" ; do
            PROCESS=$process_name
            start_process_by_name
            sleep 1
        done
    else
        start_process_by_name
    fi

    # Each zebos process creates corresponding linux socket files under /tmp
    # Other users (e.g. gss) also should have permission to access these files
    # Otherwise, non-root users cannot start imish CLI
    chmod -R 777 /tmp/

    exit $EXIT_SUCCESS;
}

# -----------------------------------------------------------------------------
kill_process_by_name()
{
    #check process is running
    ps -ef |grep "$PROCESS \-d" |grep -v grep &> /dev/null
    if [ $? = 0 ]; then
        printf "Stopping process %s ..." $PROCESS;
        ps -ef |grep "$PROCESS \-d" |grep -v grep|awk '{print $2}'|xargs kill -9 &> /dev/null
        printf " (succeeded)\n"
    fi
}

# -----------------------------------------------------------------------------
stop_zebos()
{
    if [ "$PROCESS" = "all" ] ; then
        for process_name in "${PROCESS_LIST[@]}" ; do
            PROCESS=$process_name
            kill_process_by_name;
        done
    else
        kill_process_by_name;
    fi

    exit $EXIT_SUCCESS;
}

# -----------------------------------------------------------------------------
restart_zebos()
{
    #stop the process(s)
    stop_zebos;

    #start the process(s)
    start_zebos;

    exit $EXIT_SUCCESS;
}

# -----------------------------------------------------------------------------
guard_create_entry()
{
    # Give the process a chance to start if necessary
    retries=0;
    until [ $retries -ge 5 ]; do
        found_pid=`ps -C $PROCESS -o pid h`
        rc=$?
        # echo "guard_create_entry: pid of $1 is $found_pid, rc = $rc"
        [ $rc -eq 0 ] && break
        retries=$[$retries+1]
        sleep 1
    done
    if [ $rc -ne 0 ] || [ `echo "${found_pid}" | wc -l` -gt 1 ]  ;
    then
        return 1
    else
        if [[ ( "$MONITOR_ACTION" = "restart" ) ]]; then
            echo "$PROCESS restart $PROCESS pid_only ${found_pid}" >> ${GUARDIAN_CONFIG_FILE}
        else
            echo "$PROCESS reboot $PROCESS pid_only ${found_pid}" >> ${GUARDIAN_CONFIG_FILE}
        fi
    fi

    return 0
}

# -----------------------------------------------------------------------------
monitor_process_by_name()
{
    if [ -f "$ZEBOS_PATH$PROCESS" ]; then
        printf "Start monitoring process %s ..." $PROCESS;

        #check if the entry is already there or not
        if grep -q "$PROCESS pid_only" "$GUARDIAN_CONFIG_FILE"; then
            printf " - updating the entry - "
            sed -i "/$PROCESS pid_only/d" "$GUARDIAN_CONFIG_FILE"
        fi

        ps -ef |grep "$PROCESS \-d" |grep -v grep &> /dev/null

        if [ $? = 0 ]; then
            #process is running, start monitoring by creating an entry 
            #in /tmp/guardian_config 
            guard_create_entry $PROCESS || boot_abort "Failed to find ${PROCESS}"
            printf " (succeeded)\n" 
        fi
    fi
}

# -----------------------------------------------------------------------------
# TODO:
# currently rc.local is updated to call "zebos monitor all".  Since runit is not
# included in build, monitor_process_by name will fail. Hence no process will be
# started during start up process.   For now, let us make this function just 
# to start the process.  Once runit is included, we can update this function 
# to call monitor_process_by_name function.

monitor_zebos()
{
    if [ "$PROCESS" = "all" ] ; then
        for process_name in "${PROCESS_LIST[@]}" ; do
            PROCESS=$process_name
            monitor_process_by_name
        done
    else
        monitor_process_by_name
    fi

    exit $EXIT_SUCCESS;
}

# Main script
#-------------------- ---------------------------------------------------------
#check the number of arguments
if [ "$#" -ne 2 ]; then
    zebos_print_usage_and_exit ;
else
    ACTION="$1"
    PROCESS="$2"
fi

echo
#validate process name argument
validate_process_name

#handle arguments
while :; do
    case "$ACTION" in
        "--help"|"-h"|"-?"|"help") zebos_print_usage_and_exit ;;
        "start") start_zebos ;;
        "stop") stop_zebos;;
        "restart") restart_zebos ;;
        "monitor") monitor_zebos ;;
        *) zebos_print_usage_and_exit ;
        break ;;
    esac
done

exit $EXIT_SUCCESS

