#!/bin/bash
#< Nagios plugin to montior JBoss thread count and JVM Free Memory
# requires jvm_free_mem.sh and thread_count.sh

BASENAME="/bin/basename"
ECHO="/bin/echo"
EGREP="/bin/egrep"
SED="/bin/sed"
SSH="/usr/bin/ssh"

R_JBOSS_HOME="/home/jboss"
R_JBOSS_BIN="${R_JBOSS_HOME}/bin"
R_FREEMEM="${R_JBOSS_BIN}/jvm_free_mem.sh"
R_THREADS="${R_JBOSS_BIN}/thread_count.sh"

SSH_USER="jboss"
THISPROG=$( ${BASENAME} $0 )

CHECK_HOST=""
CHECK_SERVER=""
CHECK_TYPE=""
CRIT=""
WARN=""

E_SUCCESS=0
E_WARNING=1
E_CRITICAL=2
E_UNKNOWN=3

VERBOSE=0

function print_error {
   ${ECHO} "Error: $@" >&2
}

function printv {
   (( VERBOSE )) && {
      ${ECHO} "--> $@"
   }
}

function print_usage {
   {
      ${ECHO} "Usage: ${THISPROG} [-hv] -H <hostname> -s <servername> -C <check_type> -w <warn> -c <crit> [-u <user>]"
      ${ECHO} "       -H   JBoss server hostname"
      ${ECHO} "       -s   JBoss instance"
      ${ECHO} "       -C   Check type - one of the following:"
      ${ECHO} "            jvmfree - Check JVM free memory"
      ${ECHO} "            threads - Check thread count"
      ${ECHO} "       -w   Warning threshold"
      ${ECHO} "       -c   Critical threshold"
      ${ECHO} "       -u   Remote user for ssh checks - default \"jboss\""
      ${ECHO} "       -h   Display this usage message"
      ${ECHO} "       -v   Verbose mode"
   } >&2
}

function check_args {
   # All options are mandatory...
   ERROR_COUNT=0
   for OPTION in CHECK_HOST CHECK_SERVER CHECK_TYPE CRIT WARN; do
      eval VAL=\$$OPTION
      if [ "${VAL}" = "" ]; then
         (( ERROR_COUNT = ERROR_COUNT + 1 ))
      fi
   done
   if [ "${CHECK_TYPE}" != "jvmfree" -a "${CHECK_TYPE}" != "threads" ]; then
      (( ERROR_COUNT = ERROR_COUNT + 1 ))
   fi
   (( ERROR_COUNT )) && { ${ECHO} "UNKNOWN: Argument processing failed"; exit ${E_UNKNOWN}; }
}

function check_thresholds {
   case ${CHECK_TYPE} in
      "jvmfree") ${ECHO} "${WARN}" | ${EGREP} -q '^[0-9]+%$'
                 if [ "$?" -ne "0" ]; then
                    ${ECHO} "UNKNOWN: Invalid format for WARN parameter - expecting 0-100%"
                    exit ${E_UNKNOWN}
                 fi
                 ${ECHO} "${CRIT}" | ${EGREP} -q '^[0-9]+%$'
                 if [ "$?" -ne "0" ]; then
                    ${ECHO} "UNKNOWN: Invalid format for CRIT parameter - expecting 0-100%"
                    exit ${E_UNKNOWN}
                 fi
                 WARN=$( ${ECHO} "${WARN}" | ${SED} 's/%//' )
                 if [ "${WARN}" -lt "0" -o "${WARN}" -gt "100" ]; then
                    ${ECHO} "UNKNOWN: WARN must be between 0 and 100 percent"
                    exit ${E_UNKNOWN}
                 fi
                 CRIT=$( ${ECHO} "${CRIT}" | ${SED} 's/%//' )
                 if [ "${CRIT}" -lt "0" -o "${CRIT}" -gt "100" ]; then
                    ${ECHO} "UNKNOWN: CRIT must be between 0 and 100 percent"
                    exit ${E_UNKNOWN}
                 fi
                 if [ "${CRIT}" -ge "${WARN}" ]; then
                    ${ECHO} "UNKNOWN: CRIT >= WARN"
                    exit ${E_UNKNOWN}
                 fi
                 ;;
      "threads") ${ECHO} "${WARN}" | ${EGREP} -q '^[0-9]+$'
                 if [ "$?" -ne "0" ]; then
                    ${ECHO} "UNKNOWN: Invalid format for WARN parameter - expecting integer"
                    exit ${E_UNKNOWN}
                 fi
                 ${ECHO} "${CRIT}" | ${EGREP} -q '^[0-9]+$'
                 if [ "$?" -ne "0" ]; then
                    ${ECHO} "UNKNOWN: Invalid format for CRIT parameter - expecting integer"
                    exit ${E_UNKNOWN}
                 fi
                 if [ "${CRIT}" -le "${WARN}" ]; then
                    ${ECHO} "UNKNOWN: CRIT <= WARN"
                    exit ${E_UNKNOWN}
                 fi
                 ;;
   esac
}

function check_ssh {
   printv "Checking ssh access to ${CHECK_HOST} as ${SSH_USER}"
   ${SSH} -q -o BatchMode=yes ${SSH_USER}@${CHECK_HOST} "exit"
   if [ "$?" -ne "0" ]; then
      ${ECHO} "UNKNOWN: SSH check failed" && exit ${E_UNKNOWN}
   else
      printv "ssh test OK"
   fi 
}

function perform_checks {
   case ${CHECK_TYPE} in
     "jvmfree") OUTPUT=$( ${SSH} -q -o BatchMode=yes ${SSH_USER}@${CHECK_HOST} "${R_FREEMEM} -s ${CHECK_SERVER}" )
                FREEMEM=$( ${ECHO} "${OUTPUT}" | ${SED} 's/^[^:]*: \([0-9][0-9]\)*%.*$/\1/' )
                if [ "${FREEMEM}" = "" ]; then
                   ${ECHO} "UNKNOWN: Could not obtain JVM free memory for ${CHECK_SERVER}"
                   exit 3
                fi
                if [ "${FREEMEM}" -gt "${WARN}" ]; then
                   ${ECHO} "OK: ${CHECK_SERVER}: ${FREEMEM}% Free JVM Memory" && exit 0
                elif [ "${FREEMEM}" -gt "${CRIT}" ]; then
                   ${ECHO} "WARNING: ${CHECK_SERVER}: ${FREEMEM}% Free JVM Memory" && exit 1
                else 
                   ${ECHO} "CRITICAL: ${CHECK_SERVER}: ${FREEMEM}% Free JVM Memory" && exit 2
                fi
                ;;
     "threads") OUTPUT=$( ${SSH} -q -o BatchMode=yes ${SSH_USER}@${CHECK_HOST} "${R_THREADS} -s ${CHECK_SERVER}" )
                THREADS=$( ${ECHO} "${OUTPUT}" | ${SED} 's/^[^:]*: \([0-9][0-9]*\) .*$/\1/' )
                if [ "${THREADS}" = "" ]; then
                   ${ECHO} "UNKNOWN: Could not obtain JVM free memory for ${CHECK_SERVER}"
                   exit 3
                fi
                if [ "${THREADS}" -ge "${CRIT}" ]; then
                   ${ECHO} "CRITICAL: ${CHECK_SERVER}: ${THREADS} Active Threads" && exit 2
                elif [ "${THREADS}" -ge "${WARN}" ]; then
                   ${ECHO} "WARNING: ${CHECK_SERVER}: ${THREADS} Active Threads" && exit 1
                else 
                   ${ECHO} "OK: ${CHECK_SERVER}: ${THREADS} Active Threads" && exit 0
                fi
                ;;
   esac
}

#
# main()
#
while getopts ":hvH:s:C:w:c:u:" OPTION; do
  case ${OPTION} in
     "C")  CHECK_TYPE="${OPTARG}"   ;;
     "H")  CHECK_HOST="${OPTARG}"   ;;
     "s")  CHECK_SERVER="${OPTARG}" ;;
     "c")  CRIT="${OPTARG}"         ;;
     "w")  WARN="${OPTARG}"         ;;
     "u")  SSH_USER="${OPTARG}"     ;;
     "h")  print_usage && exit 0    ;;
     "v")  VERBOSE=1                ;;
     *  )  print_usage && exit 1    ;;
  esac
done

shift $(( ${OPTIND} - 1 ))

if [ "$#" -ne "0" ]; then
   print_usage && exit 1
fi

check_args
check_thresholds
check_ssh
perform_checks

exit 0