#!/bin/bash
#< Nagios Plugin - Check status of a Solaris SMF controlled service

AWK="/usr/bin/awk"
BASENAME="/usr/bin/basename"
ECHO="/bin/echo"
GREP="/usr/xpg4/bin/grep"
SED="/usr/bin/sed"
SUDO="/usr/local/bin/sudo"
SVCS="/usr/bin/svcs"
WC="/usr/bin/wc"
ZLOGIN="/usr/sbin/zlogin"
ZONEADM="/usr/sbin/zoneadm"
ZONECFG="/usr/sbin/zonecfg"

THISPROG=$( ${BASENAME} $0 )

COUNT=0
VERBOSE=0
ZONE="global"

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

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

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

function print_usage {
   {
      ${ECHO} "Usage: ${THISPROG} [-hv] [-z <zonename>] -s <service_fmri> [ -p -w <warn> -c <crit> ]"
      ${ECHO} "       -c   Specify critical threshold for number of processes (use with -p)"
      ${ECHO} "       -h   Display this usage message"
      ${ECHO} "       -p   Check number of processes"
      ${ECHO} "       -s   FMRI of target service"
      ${ECHO} "       -v   Verbose mode"
      ${ECHO} "       -w   Specify warning threshold for number of processes (use with -p)"
      ${ECHO} "       -z   Specify zonename (default is global)"
   } >&2
}

function check_usage {
   if [ -z "${FMRI}" ]; then
      ${ECHO} "UNKNOWN: -s option mandatory"
      exit ${E_UNKNOWN}
   fi
   if [ "${COUNT}" -gt "0" ]; then
      if [ -z "${WARN}" ]; then
         ${ECHO} "UNKNOWN: -w mandatory with -p"
         exit ${E_UNKNOWN}
      fi
      if [ -z "${CRIT}" ]; then
         ${ECHO} "UNKNOWN: -c mandatory with -p"
         exit ${E_UNKNOWN}
      fi
      ${ECHO} "${WARN}" | ${GREP} -E -q '^[0-9]+$'
      if [ "$?" -ne "0" ]; then
         ${ECHO} "UNKNOWN: -w should have an integer value"
         exit ${E_UNKNOWN}
      fi
      ${ECHO} "${CRIT}" | ${GREP} -E -q '^[0-9]+$'
      if [ "$?" -ne "0" ]; then
         ${ECHO} "UNKNOWN: -c should have an integer value"
         exit ${E_UNKNOWN}
      fi
      if [ "${CRIT}" -le "${WARN}" ]; then
         ${ECHO} "UNKNOWN: -c should be >= -w"
         exit ${E_UNKNOWN}
      fi
   fi
}

function check_valid_zone {
   if [ "${ZONE}" = "global" ]; then
      return
   fi
   ZONELIST=$( ${SUDO} ${ZONEADM} list -cp )
   if [ "$?" -ne "0" ]; then
      ${ECHO} "UNKNOWN: Could not get zone list"
      exit ${E_UNKNOWN}
   fi
   ZONESTATE=$( ${ECHO} "${ZONELIST}" | ${GREP} -E "^[0-9-]+:${ZONE}:" )
   if [ "$?" -ne "0" ]; then
      ${ECHO} "UNKNOWN: ${ZONE} is not a valid zone"
      exit ${E_UNKNOWN}
   fi
}

function check_zone_runstate {
   if [ "${ZONE}" = "global" ]; then
      return
   fi
   STATE=$( ${ECHO} "${ZONESTATE}" | ${SED} 's/^[^:]*:[^:]*:\([^:]*\):.*$/\1/' )
   if [ "${STATE}" != "running" ]; then
      # We only output a warning, as the check_zone plugin monitors zone state
      ${ECHO} "WARNING: ${ZONE} in state ${STATE}"
      exit ${E_WARNING}
   fi
}

function check_service {
   if [ "${ZONE}" = "global" ]; then
      RESULT=$( ${SVCS} -H ${FMRI} 2>&1 )
      ${ECHO} "${RESULT}" | ${GREP} -q 'Pattern.*doesn.t match any'
      if [ "$?" -eq "0" ]; then
         ${ECHO} "CRITICAL: Service ${FMRI} not present on global zone"
         exit ${E_CRITICAL}
      fi
   else
      RESULT=$( ${SUDO} ${ZLOGIN} ${ZONE} svcs -H ${FMRI} 2>&1 )
      ${ECHO} "${RESULT}" | ${GREP} -q 'Pattern.*doesn.t match any'
      if [ "$?" -eq "0" ]; then
         ${ECHO} "CRITICAL: Service ${FMRI} not present on ${ZONE}"
         exit ${E_CRITICAL}
      fi
   fi
   if [ "${COUNT}" -eq "0" ]; then
      SVCSTATE=$( ${ECHO} "${RESULT}" | ${AWK} '{print $1}' )
      if [ "${SVCSTATE}" = "online" ]; then
         ${ECHO} "OK: Service ${FMRI} is online [Zone: ${ZONE}]"
         exit ${E_OK}
      elif [ "${SVCSTATE}" = "disabled" ]; then
         ${ECHO} "WARNING: Service ${FMRI} has been disabled [Zone: ${ZONE}]"
         exit ${E_WARNING}
      else
         ${ECHO} "CRITICAL: Service ${FMRI} is in state: ${SVCSTATE} [Zone: ${ZONE}]"
         exit ${E_CRITICAL}
      fi
   else
      if [ "${ZONE}" = "global" ]; then
         SVCPROCS=$( ${SVCS} -H -p ${FMRI} )
         SVCSTATE=$( ${ECHO} "${SVCPROCS}" | ${AWK} 'NR==1 {print $1}' )
         PROCCOUNT=$( ${ECHO} "${SVCPROCS}" | ${SED} '1d' | ${WC} -l | ${AWK} '{print $1}' )
         if [ "${SVCSTATE}" = "online" ]; then
            if [ "${PROCCOUNT}" -ge "${CRIT}" ]; then
               ${ECHO} "CRITICAL: ${PROCCOUNT} ${CRIT} processes for ${FMRI} [Zone: ${ZONE}]"
               exit ${E_CRITICAL}
            elif [ "${PROCCOUNT}" -ge "${WARN}" ]; then
               ${ECHO} "WARNING: ${PROCCOUNT} processes for ${FMRI} [Zone: ${ZONE}]"
               exit ${E_WARNING}
            else
               ${ECHO} "OK: ${PROCCOUNT} processes for ${FMRI} [Zone: ${ZONE}]"
               exit ${E_OK}
            fi
         elif [ "${SVCSTATE}" = "disabled" ]; then
            ${ECHO} "WARNING: Service ${FMRI} has been disabled [Zone: ${ZONE}]"
            exit ${E_WARNING}
         else
            ${ECHO} "CRITICAL: Service ${FMRI} is in state: ${SVCSTATE} [Zone: ${ZONE}]"
            exit ${E_CRITICAL}
         fi
      else
         SVCPROCS=$( ${SUDO} ${ZLOGIN} ${ZONE} svcs -H -p ${FMRI} )
         SVCSTATE=$( ${ECHO} "${SVCPROCS}" | ${AWK} 'NR==1 {print $1}' )
         PROCCOUNT=$( ${ECHO} "${SVCPROCS}" | ${SED} '1d' | ${WC} -l | ${AWK} '{print $1}' )
         if [ "${SVCSTATE}" = "online" ]; then
            if [ "${PROCCOUNT}" -ge "${CRIT}" ]; then
               ${ECHO} "CRITICAL: ${PROCCOUNT} ${CRIT} processes for ${FMRI} [Zone: ${ZONE}]"
               exit ${E_CRITICAL}
            elif [ "${PROCCOUNT}" -ge "${WARN}" ]; then
               ${ECHO} "WARNING: ${PROCCOUNT} processes for ${FMRI} [Zone: ${ZONE}]"
               exit ${E_WARNING}
            else
               ${ECHO} "OK: ${PROCCOUNT} processes for ${FMRI} [Zone: ${ZONE}]"
               exit ${E_OK}
            fi
         elif [ "${SVCSTATE}" = "disabled" ]; then
            ${ECHO} "WARNING: Service ${FMRI} has been disabled [Zone: ${ZONE}]"
            exit ${E_WARNING}
         else
            ${ECHO} "CRITICAL: Service ${FMRI} is in state: ${SVCSTATE} [Zone: ${ZONE}]"
            exit ${E_CRITICAL}
         fi  
      fi
   fi
}

function tmp_warn {
   if [ "${COUNT}" -eq "1" ]; then
      echo "not yet implemented..."
      exit 127
   fi
}

#
# main()
#
while getopts ":c:hps:vw:z:" OPTION; do
  case ${OPTION} in
     "c")  CRIT="${OPTARG}"        ;;
     "h")  print_usage && exit 0   ;;
     "p")  COUNT=1                 ;;
     "s")  FMRI="${OPTARG}"        ;;
     "v")  VERBOSE=1               ;;
     "w")  WARN="${OPTARG}"        ;;
     "z")  ZONE="${OPTARG}"        ;;
     *  )  print_usage && exit 1   ;;
  esac
done

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

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

check_usage
#tmp_warn
check_valid_zone
check_zone_runstate
check_service

${ECHO} "UNKNOWN: Should never be reached"
exit ${E_UNKNOWN}