#! /bin/bash
MYFULLNAME=$(readlink -m "$0")
MYNAME=$(basename $0)
MYDIR=$(dirname $0)
MYDIR=$(readlink -m "$MYDIR")
VERSION="0.0.2"
VERBOSE=""
LOGFILE=""
HOST=""
SSH="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet"

if [ -f "$MYDIR/utilityfunctions.sh" ]; then
    source $MYDIR/utilityfunctions.sh
else
    echo "File '$MYDIR/utilityfunctions.sh' was not found." >&2
    exit 5
fi

export LC_ALL=C

# sysv-rc-conf --level 5 piphostc on
# sysv-rc-conf --level 6 piphostc off
# sysv-rc-conf --level 0 piphostc off
# sysv-rc-conf --list | grep pip
# /etc/init.d/piphostc
#


#
# Prints the software version and exits.
#
function printVersionAndExit()
{
    echo "$MYNAME Version $VERSION on $(hostname)" >&2
    exit 0
}

function printHelpAndExit()
{
cat <<EOF
Usage:
  $MYNAME [OPTION]... 

  $MYNAME - Monitors various system properties and reports them through MQTT.

  -h, --help           Print this help and exit.
  -v, --version        Print version information and exit.
  --verbose            Print more messages.
  --log-file=FILE      Store all the messages in the given file too.
  --id=INTEGER         Set the host ID.



EOF
    exit 0
}

ARGS=$(\
    getopt \
        -o hvs:c:l \
        -l "help,verbose,version,log-file:,id:" \
        -- "$@")

if [ $? -ne 0 ]; then
    exit 6
fi

eval set -- "$ARGS"
while true; do
    case "$1" in
        -h|--help)
            shift
            printHelpAndExit
            ;;

        --verbose)
            shift
            VERBOSE="true"
            VERBOSE_OPTION="--verbose"
            ;;

        -v|--version)
            shift
            VERSION_OPTION="--version"
            ;;

        --log-file)
            shift
            LOGFILE=$(readlink -m "$1")
            shift
            ;;

        --id)
            shift
            shift
            ;;

        --)
            shift
            break
            ;;

        *)
            ;;
    esac
done

function mqtt_config_file()
{
    local file_name="$HOME/.pip/mqtt.conf"

    if [ ! -f "$file_name" ]; then
        printVerbose "Creating '$file_name'."

        mkdir -p "$(dirname $file_name)" 2>/dev/null
cat <<EOF >$file_name
#
# Configuration file created by $MYNAME $(date)
#
MQTT_SERVER="192.168.0.5"
MQTT_PORT=1883
MQTT_USER="pipas"
MQTT_PASSWORD="p"
EOF
    fi

    echo "$file_name"
}

#
# Prints detailed memory measurements in JSon format.
#
function get_memory_measurements()
{
    local line=$(free | grep -i '^Mem:')
    local total=$(echo "$line" | awk '{print $2}')
    local available=$(echo "$line" | awk '{print $7}')

    echo "{ \"Total\": $total, \"Available\": $available }"
}

function get_disk_throughput()
{
    local lines=$(sudo iotop -qbokn 4)
    local read_kilo
    local write_kilo

    write_kilo=$(\
        echo "$lines" | grep "Actual DISK WRITE" | tail -n 1 | \
        awk '{print $10}')

    read_kilo=$(\
        echo "$lines" | grep "Actual DISK READ" | tail -n 1 | \
        awk '{print $4}')

    if [ -z "$read_kilo" ]; then
        read_kilo="null"
    fi
    
    if [ -z "$write_kilo" ]; then
        write_kilo="null"
    fi

    echo "{ \"ReadKps\": $read_kilo, \"WriteKps\": $write_kilo }"
}

function get_load()
{
    cat /proc/loadavg | awk '{print $1}'
}

function get_cpu_temp()
{
    local temp
    
    temp=$(which sensors)
    if [ -z "$temp" ]; then
        echo 0
        return 1
    fi

    temp=$(sensors | \
        grep Core | \
        awk -F: '{print $2}' | \
        awk '{print $1}' | \
        tr -d '[+°C]'  | \
        sort | \
        tail -n1)

    if [ -z "$temp" ]; then
        temp='0.0'
    fi

    echo $temp
}

#
# Prints some local resources in JSon format. This is the fast method, this is
# what we execute often.
# 
# This information goes to "stat/${hostname}/resources".
#
# Collecting the following:
#   o hostname
#   o load
#   o memory 
#   o processor threads
#   o number of containers
#   o disk throughtput
#
function get_resources()
{
    local hostname=$(hostname)
    local load=$(get_load)
    local temp=$(get_cpu_temp)
    local memory=$(get_memory_measurements)
    local nproc=$(nproc)
    local n_containers=$(get_number_of_containers 2>/dev/null)
    local throughput=$(get_disk_throughput 2>/dev/null)
    local message

    message="{\
\"hostname\":\"$hostname\", \
\"Load\":$load, \
\"CpuTemp\":$temp, \
\"NProc\": $nproc, \
\"NContainers\": $n_containers, \
\"Memory\": $memory, \
\"DiskThroughput\": $throughput}"
    echo "$message"
}

MQTT_CONFIG_FILE=$(mqtt_config_file)
if [ ! -f "$MQTT_CONFIG_FILE" ]; then
    printError "Config file '$MQTT_CONFIG_FILE' not found."
    exit 5
else
    printVerbose "Loading config file '$MQTT_CONFIG_FILE'."
    source "$MQTT_CONFIG_FILE"
fi

function check_install_mosquitto()
{
    if [ -z "$(which mosquitto_pub)" ]; then
        sudo apt -y --force-yes install mosquitto-clients
    fi
}

#
# Sends the load of the local computer to the mqtt broker.
#
function local_resources_to_mqtt()
{
    local hostname=$(hostname)
    local topic="stat/${hostname}/resources"
    local message=$(get_resources)

    echo "------------------------------------"
    echo "     mqtt: mqtt://$MQTT_SERVER:$MQTT_PORT"
    echo "    topic: $topic"
    echo "  message: $message"
    mosquitto_pub \
        -u "$MQTT_USER" \
        -P "$MQTT_PASSWORD" \
        -h "$MQTT_SERVER" \
        -p "$MQTT_PORT" \
        -t "$topic" \
        -m "$message"
}

function get_disk_stats()
{
    local hostname=$(hostname)
    local line
    local total
    local used
    local available
    local percent
    local sum

    line=$(df --total | grep total)
    total=$(echo "$line" | awk '{print $2}')
    used=$(echo "$line" | awk '{print $3}')
    available=$(echo "$line" | awk '{print $4}')
    percent=$(echo "$line" | awk '{print $5}' | tr -d '%')

    sum="\"Total\": $total, \"Used\": $used, \"Free\": $available, \"Percent\": $percent"

    echo "{\"Sum\": {$sum}, \"hostname\": \"$hostname\"}"
}

function get_hw_info()
{
    local hostname=$(hostname)    
    local model
    local manufacturer
   
    if [ -f "/sys/class/dmi/id/product_name" ]; then
        model=$(cat /sys/class/dmi/id/product_name | head -n1)
    fi

    if [ -f "/sys/class/dmi/id/board_vendor" ]; then
        manufacturer=$(cat /sys/class/dmi/id/board_vendor | head -n1)
    fi

    model=$(echo ${model%%+([[:space:]])})
    manufacturer=$(echo ${manufacturer%%+([[:space:]])})
    cat <<EOF
{ "hostname": "$hostname", "model": "$model", "manufacturer": "$manufacturer"}
EOF
}

#
# 
#
function hw_to_mqtt()
{
    local hostname=$(hostname)
    local topic="stat/${hostname}/hardware"
    local message=$(get_hw_info)
    local retcode

    echo "------------------------------------"
    echo "     mqtt: mqtt://$MQTT_SERVER:$MQTT_PORT"
    echo "    topic: $topic"
    echo "  message: $message"
    mosquitto_pub \
        -u "$MQTT_USER" \
        -P "$MQTT_PASSWORD" \
        -h "$MQTT_SERVER" \
        -p "$MQTT_PORT" \
        -t "$topic" \
        -m "$message"

    retcode=$?
    echo "  retcode: $retcode"
}

#
# 
#
function disks_to_mqtt()
{
    local hostname=$(hostname)
    local topic="stat/${hostname}/disks"
    local message=$(get_disk_stats)
    local retcode

    echo "------------------------------------"
    echo "     mqtt: mqtt://$MQTT_SERVER:$MQTT_PORT"
    echo "    topic: $topic"
    echo "  message: $message"
    mosquitto_pub \
        -u "$MQTT_USER" \
        -P "$MQTT_PASSWORD" \
        -h "$MQTT_SERVER" \
        -p "$MQTT_PORT" \
        -t "$topic" \
        -m "$message"

    retcode=$?
    echo "  retcode: $retcode"
}

# {"StatusSNS":{"Time":"1970-01-16T05:49:55","ENERGY":{"Total":35.640,"Yesterday":0.000,"Today":35.640,"Power":0,"Factor":0.00,"Voltage":218,"Current":0.000}}}"

function get_power()
{
    local pdu_name=$1
    local power=$(pip-pdu-control --power $pdu_name)
    local current=$(pip-pdu-control --current $pdu_name)
    local topic="stat/$pdu_name/STATUS10"
    local message

    [ -z "$power" ] && power="0"
    [ -z "$current" ] && current="0"
    message="{\"StatusSNS\":{\"ENERGY\":{\"Power\":$power,\"Current\":$current}}}"
    
    echo "------------------------------------"
    echo "     mqtt: mqtt://$MQTT_SERVER:$MQTT_PORT"
    echo "    topic: $topic"
    echo "  message: $message"

    mosquitto_pub \
        -u "$MQTT_USER" \
        -P "$MQTT_PASSWORD" \
        -h "$MQTT_SERVER" \
        -p "$MQTT_PORT" \
        -t "$topic" \
        -m "$message"

    retcode=$?
    echo "  retcode: $retcode"
}

#
# 
#
function ping_server()
{
    local hostname=$1
    local topic="stat/${hostname}/state"
    local message=$(pip-server-control --ping --print-json $hostname)
    local retcode

    echo "------------------------------------"
    echo "     mqtt: mqtt://$MQTT_SERVER:$MQTT_PORT"
    echo "    topic: $topic"
    echo "  message: $message"
    mosquitto_pub \
        -u "$MQTT_USER" \
        -P "$MQTT_PASSWORD" \
        -h "$MQTT_SERVER" \
        -p "$MQTT_PORT" \
        -t "$topic" \
        -m "$message"

    retcode=$?
    echo "  retcode: $retcode"
}

function emit_rc_file()
{
    cat <<EOF
#! /bin/bash
# chkconfig: 2345 20 80

### BEGIN INIT INFO
# Provides:          pipscripts
# Required-Start:    
# Required-Stop:     
# Default-Start:     1 2 3 4 5
# Default-Stop:      0 6
# Short-Description: Remote monitoring
# Description:       Remote monitoring and control with pipscripts.
### END INIT INFO


LOCKFILE="/var/lock/subsys/pipscripts"

function start()
{
    # Touch our lock file so that stopping will work correctly
    touch \${LOCKFILE}

    sudo -H -u pipas bash -c 'pip-host-control --idle --status "Started."'

    if [ "\$(hostname)" == "core2" ]; then
        printVerbose "Computer secondary core is on-line."
    elif [ "\$(hostname)" == "core3" ]; then
        printVerbose "Computer tertiary core is on-line."
    elif [ "\$(hostname)" == "core4" ]; then
        printVerbose "Core4 is on-line."
    fi
}

function stop()
{
    # Remove our lock file
    rm \${LOCKFILE}

    # Run that command that we wanted to run
    sudo -H -u pipas bash -c 'pip-host-control --halted --status "Shut down."'
    
    if [ "\$(hostname)" == "core2" ]; then
        printVerbose "Computer secondary core is shutting down."
    elif [ "\$(hostname)" == "core3" ]; then
        printVerbose "Computer tertiary core is shutting down."
    elif [ "\$(hostname)" == "core4" ]; then
        printVerbose "Core4 is shutting down."
    fi
}

case "\$1" in
    start) start;;
    stop) stop;;
    *)
        echo $"Usage: \$0 {start|stop}"
        exit 1
esac

exit 0
EOF


}

function run_checks()
{
    local rc_file="/etc/init.d/pipscripts"
    local check_file="/etc/rc1.d/S20pipscripts"
    local level
    local emit

    check_install_mosquitto

    for f in /etc/rc5.d/S20piphostc /etc/rc3.d/S20piphostc \
        /etc/rc2.d/S20piphostc /etc/rc4.d/S20piphostc \
        /etc/rc1.d/S20piphostc /etc/init.d/piphostc \
        /etc/rc0.d/K80piphostc /etc/rc6.d/K80piphostc; 
    do
        if [ -f $f ]; then
            sudo rm $f
        fi
    done

    emit=""
    if [ ! -f "$rc_file" -o ! -f "$check_file" ]; then
        printVerbose "Not found: $rc_file $check_file"
        emit="true"
    elif [ "$MYFULLNAME" -nt "$rc_file" ]; then
        printVerbose "$MYFULLNAME -nt $rc_file"
        emit="true"
    fi

    if [ -n "$emit" ]; then
        emit_rc_file | sudo tee "$rc_file" >/dev/null
        sudo chmod +x "$rc_file"

        sudo apt -y --force-yes install sysv-rc-conf
        for level in 5 4 3 2 1; do
            sudo sysv-rc-conf --level $level pipscripts on
        done

        sudo sysv-rc-conf --level 0 pipscripts off
        sudo sysv-rc-conf --level 6 pipscripts off 
    fi
    
}

#
# mpt-status 
# ioc0 vol_id 0 type IME, 8 phy, 543 GB, state OPTIMAL, flags ENABLED
# ioc0 phy 7 scsi_id 8 HP       DG146BABCF       HPD5, 136 GB, state ONLINE, flags NONE
# ioc0 phy 6 scsi_id 1 HP       DG146BABCF       HPD5, 136 GB, state ONLINE, flags NONE
#
if [ $VERSION_OPTION ]; then
    printVersionAndExit
else
    run_checks

    hw_to_mqtt
    local_resources_to_mqtt
    disks_to_mqtt
    sleep 15
    
    local_resources_to_mqtt
    sleep 15
    
    local_resources_to_mqtt
    sleep 15
    
    local_resources_to_mqtt
    sleep 15
    
    hostname=$(hostname)
    if [ "$hostname" == "core4" -o "$hostname" == "storage02" ]; then
        for h in core1 core2 core3 t7500 storage01 laptop01 \
            www dns1 dns2 mqtt; 
        do
            ping_server $h
        done
    fi

    if [ "$hostname" == "core4" -o "$hostname" == "storage02"  ]; then
        get_power pdu01
        get_power pdu02
    fi

fi
