#!/bin/bash

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific


MONITOR_CONF_DIR=/etc/ambari-metrics-monitor/conf/
METRIC_MONITOR=ambari-metrics-monitor

RESOURCE_MONITORING_DIR=/usr/lib/python2.6/site-packages/resource_monitoring
METRIC_MONITOR_PY_SCRIPT=${RESOURCE_MONITORING_DIR}/main.py

PIDFILE=/var/run/ambari-metrics-monitor/ambari-metrics-monitor.pid
OUTFILE=/var/log/ambari-metrics-monitor/ambari-metrics-monitor.out

STOP_TIMEOUT=5

OK=0
NOTOK=1

if [ -a /usr/bin/python2.7 ] && [ -z "${PYTHON}" ]; then
  PYTHON=/usr/bin/python2.7
fi

if [ -a /usr/bin/python2.6 ] && [ -z "${PYTHON}" ]; then
  PYTHON=/usr/bin/python2.6
fi

if [ "x$PYTHON" == "x" ]; then
  PYTHON=/usr/bin/python
fi

export PYTHON=${PYTHON}

check_python_version ()
{
  echo "Verifying Python version compatibility..."
  majversion=`${PYTHON} -V 2>&1 | awk '{print $2}' | cut -d'.' -f1`
  minversion=`${PYTHON} -V 2>&1 | awk '{print $2}' | cut -d'.' -f2`
  numversion=$(( 10 * $majversion + $minversion))
  if (( $numversion < 26 )); then
    echo "ERROR: Found Python version $majversion.$minversion. Ambari Metric Monitor requires Python version > 2.6"
    return ${NOTOK}
  fi
  echo "Using python " ${PYTHON}
  return ${OK}
}

function write_pidfile
{
    local pidfile="$1"
    echo $! > "${pidfile}" 2>/dev/null
    if [[ $? -gt 0 ]]; then
      echo "ERROR:  Cannot write pid ${pidfile}."
      exit 1;
    fi
}

#locate config dir
while [[ -z "${_ams_configs_done}" ]]; do
  case $1 in
    --config)
      shift
      confdir=$1
      shift
      if [[ -d "${confdir}" ]]; then
        MONITOR_CONF_DIR="${confdir}"
      elif [[ -z "${confdir}" ]]; then
        echo "ERROR: No parameter provided for --config "
        exit 1
      else
        echo "ERROR: Cannot find configuration directory \"${confdir}\""
        exit 1
      fi
    ;;
    *)
      _ams_configs_done=true
    ;;
  esac
done

#execute ams-env.sh
if [[ -f "${MONITOR_CONF_DIR}/ams-env.sh" ]]; then
  . "${MONITOR_CONF_DIR}/ams-env.sh"
else
  echo "ERROR: Cannot execute ${MONITOR_CONF_DIR}/ams-env.sh." 2>&1
  exit 1
fi

# Set log directory path
if [[ -n "${AMS_MONITOR_LOG_DIR}" ]]; then
  OUTFILE=${AMS_MONITOR_LOG_DIR}/ambari-metrics-monitor.out
fi

#TODO decide if rebuild on each start (pretty quickly) to tolerate major node changes (like kernel update)
#build psutil
if [ ! "$(ls -A ${RESOURCE_MONITORING_DIR}/psutil/build)" ]; then
  echo "Building psutil..."
  dir=$(pwd)
  cd "${RESOURCE_MONITORING_DIR}/psutil"
  # build psutil and redirect output to log file
  echo "--------------------------Building psutil--------------------------" >> ${OUTFILE}
  ${PYTHON} "setup.py" "build" >> ${OUTFILE}
  echo "----------------------Finished building psutil---------------------" >> ${OUTFILE}
  cd "${dir}"
else
  echo "psutil build directory is not empty, continuing..."
fi

# Set pid directory path
if [[ -n "${AMS_MONITOR_PID_DIR}" ]]; then
  PIDFILE=${AMS_MONITOR_PID_DIR}/ambari-metrics-monitor.pid
fi

case "$1" in

  start)
    check_python_version
    if [ "$?" -eq "${NOTOK}" ]; then
          exit -1
    fi

    echo "Checking for previously running Metric Monitor..."
    if [ -f ${PIDFILE} ]; then
      PID=`cat ${PIDFILE}`
      if [ -z "`ps ax -o pid | grep -w ${PID}`" ]; then
        echo "${PIDFILE} found with no process. Removing ${PID}..."
        rm -f ${PIDFILE}
      else
        tput bold
        echo "WARN: ${METRIC_MONITOR} already running with PID: ${PID}"
        tput sgr0
        echo "Exiting."
        exit 0
      fi
    fi

    echo "Starting ${METRIC_MONITOR}"

    nohup ${PYTHON} ${METRIC_MONITOR_PY_SCRIPT} "$@" >> ${OUTFILE} 2>&1 &
    PID=$!
    write_pidfile ${PIDFILE}

    sleep 2

    echo "Verifying ${METRIC_MONITOR} process status with PID : ${PID}"
    if [ -z "`ps ax -o pid | grep -w ${PID}`" ]; then
      echo "Output of PID check : `ps ax -o pid | grep -w ${PID}`"
      if [ -s ${OUTFILE} ]; then
        echo "ERROR: ${METRIC_MONITOR} start failed. For more details, see ${OUTFILE}:"
        echo "===================="
        tail -n 10 ${OUTFILE}
        echo "===================="
      else
        echo "ERROR: ${METRIC_MONITOR} start failed"
        rm -f ${PIDFILE}
      fi
      echo "Monitor out at: ${OUTFILE}"
      exit -1
    fi

    echo "Metric Monitor successfully started"
    echo "Server log at: ${OUTFILE}"
  ;;
  status)
    if [ -f ${PIDFILE} ]; then
      PID=`cat ${PIDFILE}`
      echo "Found ${METRIC_MONITOR} PID: $PID"
      if [ -z "`ps ax -o pid | grep -w ${PID}`" ]; then
        echo "${METRIC_MONITOR} not running. Stale PID File at: $PIDFILE"
        retcode=2
      else
        tput bold
        echo "${METRIC_MONITOR} running."
        tput sgr0
        echo "Monitor PID at: ${PIDFILE}"
        echo "Monitor out at: ${OUTFILE}"
      fi
    else
      tput bold
      echo "${METRIC_MONITOR} currently not running"
      tput sgr0
      echo "Usage: /usr/sbin/${METRIC_MONITOR} {start|stop|restart|status}"
      retcode=3
    fi
  ;;
  stop)
    pidfile=${PIDFILE}

    if [[ -f "${pidfile}" ]]; then
        pid=$(cat "$pidfile")

        kill "${pid}" >/dev/null 2>&1
        sleep "${STOP_TIMEOUT}"

        if kill -0 "${pid}" > /dev/null 2>&1; then
          echo "WARNING: ${METRIC_MONITOR} did not stop gracefully after ${STOP_TIMEOUT} seconds: Trying to kill with kill -9"
          kill -9 "${pid}" >/dev/null 2>&1
        fi

        if ps -p "${pid}" > /dev/null 2>&1; then
          echo "ERROR: Unable to kill ${pid}"
        else
          rm -f "${pidfile}" >/dev/null 2>&1
        fi
    fi

  ;;
  restart)
    echo -e "Restarting ${METRIC_MONITOR}"
    $0 stop
    $0 start "$@"
    retcode=$?
  ;;
esac
