#! /bin/sh

#
# Helper functions for Arc GC service control (Linux-specific)
#
# This script can be "sourced" (if sourcing with the "functions" qualifer),
# which may be used by the service control scripts. This allows for deeper
# control of the process at a low level.
#
# Otherwise (this is the normal case), invoke this with one of the following
# options:
#
#    start:    Start the Arc GC service via the service control manager
#    stop:     Stop the Arc GC service via the service control manager
#    restart:  Restart the Arc GC service via the service control manager
#

DSC_HOME_PATH="$PWD"
GC_EXE_PATH="$DSC_HOME_PATH/gc_linux_service"
SERVICE_TEMP_FOLDER_PATH="$DSC_HOME_PATH/service_temp"

SERVICE_SCRIPTS_FOLDER_PATH="$DSC_HOME_PATH/service_scripts"
SERVICE_CONTROLLER_PATH="$SERVICE_SCRIPTS_FOLDER_PATH/gca_service_controller"
PID_FILE_PATH="$SERVICE_TEMP_FOLDER_PATH/dsc.pid"

SYSTEM_SERVICE_CONTROLLER=""

verify_privileges()
{
    if [ `id -u` -ne 0 ]; then
        echo "Must have root privileges for this operation" >& 2
        exit 1
    fi
}

get_system_service_controller() {
    if [ ! -z $SYSTEM_SERVICE_CONTROLLER ]; then
        return
    fi

    COMM_OUTPUT=$(cat /proc/1/comm)

    if [[ $COMM_OUTPUT = *"systemd"* ]]; then
        SYSTEM_SERVICE_CONTROLLER="systemd"
    elif [[ $COMM_OUTPUT = *"init"* ]]; then
        SYSTEM_SERVICE_CONTROLLER="upstart"
    else
        print_error "Unexpected system service controller. Expected system service controllers are systemd and upstart."
        exit 1
    fi

    echo "Service controller is $SYSTEM_SERVICE_CONTROLLER."
}

is_dsc_running()
{
    verify_privileges

    # If systemd lives here, then we have a systemd unit file
    if pidof systemd 1> /dev/null 2> /dev/null; then
        echo "Getting status via systemd"
        if /bin/systemctl status gcad 2>/dev/null | grep "Active:.*(running)"; then
            echo "Arc GC service is running"
            return 1
        fi
    elif [ -x /sbin/initctl -a -f /etc/init/gcad.conf ]; then
        echo "Getting status via initctl"
        if /sbin/initctl status gcad 2>/dev/null | grep "start/"; then 
            echo "Arc GC service is running"
            return 1
        fi
    elif [ -x /bin/systemctl ]; then
        echo "Getting status via systemctl"
        if /bin/systemctl status gcad 2>/dev/null | grep "Active:.*(running)"; then 
            echo "Arc GC service is running"
            return 1
        fi
    elif [ -x /sbin/service ]; then
        echo "Getting status via system service"
        if /sbin/service gcad status 2>/dev/null | grep "start/"; then
            echo "Arc GC service is running"
            return 1
        fi
    elif [ -x /usr/sbin/service ]; then
        echo "Getting status via usr system service"
        if /usr/sbin/service gcad status 2>/dev/null | grep "start/"; then
            echo "Arc GC service is running"
            return 1
        fi
    elif [ -x /usr/sbin/invoke-rc.d ]; then
        echo "Getting status via invoke-rc"
        if /usr/sbin/invoke-rc.d gcad status 2>/dev/null | grep "start/"; then
            echo "Arc GC service is running"
            return 1
        fi
    else
        get_system_service_controller
        case "$SYSTEM_SERVICE_CONTROLLER" in
        "systemd")
            echo "Getting status via systemd"
            if /bin/systemctl status gcad 2>/dev/null | grep "Active:.*(running)"; then
                echo "Arc GC service is running"
                return 1
            fi
            ;;
        "upstart")
            echo "Getting status via initctl"
            if /sbin/initctl status gcad 2>/dev/null | grep "start/"; then 
                echo "Arc GC service is running"
                return 1
            fi
            ;;
        *) echo "Unrecognized system service controller to retrieve Arc GC service status."
            ;;
        esac
    fi

    echo "Arc GC service is not running."
    return 0
}

wait_until_dsc_stops()
{
    # Required parameter: Number of seconds to wait for agent to stop
    if [ -z "$1" -o "$1" -le 0 ]; then
        echo "Function \"wait_until_dsc_stops\" called with invalid parameter"
        exit 1
    fi

    COUNTER=$(( $1 * 2 )) # Since we sleep 0.5 seconds, compute number of seconds
    while [ $COUNTER -gt 0 ]; do
        is_dsc_running && return $?
        COUNTER=$(( $COUNTER - 1 ))
        sleep 0.5
    done

    # One final try for accurate return status (just return status from the call)
    is_dsc_running
}

#
# Normal usage functions (used by everything except service control scripts)
#

start_dsc()
{
    is_dsc_running
    if [ $? -ne 0 ]; then
        echo "Arc GC service is already running"
        exit 0 
    fi

    echo "STARTING Arc GC"
    if [ ! -d /lib/systemd/system.conf.d ]; then
        mkdir -p /lib/systemd/system.conf.d
    fi
    if [ -d /lib/systemd/system.conf.d ]; then
        bash -c 'echo -e "[Manager]\nDefaultEnvironment=\"POWERSHELL_DISTRIBUTION_CHANNEL=Azure-GCArcService\"" > /lib/systemd/system.conf.d/gca.conf'
    fi
    # reexecute the process and deserialize the state again, just adding the file doesn't work, we also need systemd to get our new configuration. 
    bash -c 'systemctl daemon-reexec'
    # If systemd lives here, then we have a systemd unit file
    if pidof systemd 1> /dev/null 2> /dev/null; then
        /bin/systemctl start gcad
    else
        if [ -x /sbin/initctl -a -f /etc/init/gcad.conf ]; then
            /sbin/initctl start gcad 
        elif [ -x /bin/systemctl ]; then
            /bin/systemctl start gcad
        elif [ -x /sbin/service ]; then
            /sbin/service gcad start
        elif [ -x /usr/sbin/service ]; then
            /usr/sbin/service gcad start
        elif [ -x /usr/sbin/invoke-rc.d ]; then
            /usr/sbin/invoke-rc.d gcad start
        else
            get_system_service_controller
            case "$SYSTEM_SERVICE_CONTROLLER" in
            "systemd")
                /bin/systemctl start gcad
                ;;
            "upstart")
                /sbin/initctl start gcad
                ;;
            *) echo "Unrecognized system service controller to start Arc GC service." 1>&2
                exit 1
                ;;
            esac
        fi
    fi
}

stop_dsc()
{
    is_dsc_running 
    if [ $? -ne 0 ]; then
        echo "STOPPING Arc GC"
        bash -c 'systemctl unset-environment POWERSHELL_DISTRIBUTION_CHANNEL'
        if [ -e /lib/systemd/system.conf.d/gca.conf ]; then
            bash -c 'rm /lib/systemd/system.conf.d/gca.conf -fr'
        fi
        bash -c 'systemctl daemon-reexec'
        if pidof systemd 1> /dev/null 2> /dev/null; then
            /bin/systemctl stop gcad
        else
            if [ -x /sbin/initctl -a -f /etc/init/gcad.conf ]; then
                /sbin/initctl stop gcad 
            elif [ -x /bin/systemctl ]; then
                /bin/systemctl stop gcad
            elif [ -x /sbin/service ]; then
                /sbin/service gcad stop
            elif [ -x /usr/sbin/service ]; then
                /usr/sbin/service gcad stop
            elif [ -x /usr/sbin/invoke-rc.d ]; then
                /usr/sbin/invoke-rc.d gcad stop
            else
                get_system_service_controller
                case "$SYSTEM_SERVICE_CONTROLLER" in
                "systemd")
                    /bin/systemctl stop gcad
                    ;;
                "upstart")
                    /sbin/initctl stop gcad
                    ;;
                *) echo "Unrecognized system service controller to stop Arc GC service." 1>&2
                    exit 1
                    ;;
                esac
            fi
        fi
    fi
}

restart_dsc()
{
    # Debian 8 and later special handling
    if [ -x /usr/bin/lsb_release -a -x /bin/systemctl ]; then
        distro=`lsb_release -i | awk -F":" '{ print $2 }' | sed -e 's/^[[:space:]]*//'`
        if [ "${distro}" = "Debian" ]; then
            distro_version=`lsb_release -r | awk -F":" '{ print $2 }'`
            version_match=`echo ${distro_version} '>= 8' | bc -l`
            if [ "${version_match}" = "1" ]; then
                /bin/systemctl restart gcad
                return
            fi
        fi
    fi

    is_dsc_running
    if [ $? -eq 0 ]; then
        start_dsc
        return
    fi

    if [ -f $SERVICE_SCRIPTS_FOLDER_PATH/dsc_disable_service_control ]; then
        stop_dsc
        start_dsc
        return 0
    fi

    # If systemd lives here, then we have a systemd unit file
    if pidof systemd 1> /dev/null 2> /dev/null; then
        /bin/systemctl restart gcad
    else
        if [ -x /sbin/initctl -a -f /etc/init/gcad.conf ]; then
            /sbin/initctl restart gcad 
        elif [ -x /bin/systemctl ]; then
            /bin/systemctl restart gcad
        elif [ -x /sbin/service ]; then
            /sbin/service gcad restart
        elif [ -x /usr/sbin/service ]; then
            /usr/sbin/service gcad restart
        elif [ -x /bin/systemctl ]; then
            /bin/systemctl restart gcad
        elif [ -x /usr/sbin/invoke-rc.d ]; then
            /usr/sbin/invoke-rc.d gcad restart
        else
            get_system_service_controller
            case "$SYSTEM_SERVICE_CONTROLLER" in
            "systemd")
                /bin/systemctl restart gcad
                ;;
            "upstart")
                /sbin/initctl restart gcad
                ;;
            *) echo "Unrecognized system service controller to restart Arc GC service." 1>&2
                exit 1
                ;;
            esac
        fi
    fi
}

case "$1" in
    functions)
        ;;

    is-running)
        is_dsc_running
        exit $?
        ;;

    start)
        start_dsc
        ;;

    stop)
        stop_dsc
        ;;

    restart)
        restart_dsc
        ;;

    *)
        echo "Unknown parameter : $1" 1>&2
        exit 1
        ;;
esac
