#!/bin/bash
#######################################################################################################################
#
#  =  PowerMTA Munin multi-monitor  =
#
#  -- developer:	aaron.zauner@emarsys.com
#  -- start date:	11.11.2011
#
#
#  =  LICENSE  =
#
#  Copyright (c) 2011, emarsys eMarketing Systems AG
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without modification, are permitted provided that  
#  the following conditions are met:
#
#      Redistributions of source code must retain the above copyright notice, this list of conditions and the  
#      following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list  
#      of conditions and the following disclaimer in the documentation and/or other materials provided with the  
#      distribution. Neither the name of the emarsys eMarketing Systems AG nor the names of its contributors may  
#      be used to endorse or promote products derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
#  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  
#  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
#######################################################################################################################
#
#  -> "xpath" cli tool required (ships with your linux distribution)
#  -> install:
#
#		o check config (/etc/munin/plugin-conf.d) set "env.REMOTEHOST" and "env.PORT", e.g.:
#		  [pmta*]
#			env.REMOTEHOST 127.0.0.1
#			env.PORT 8080
#
#		o chmod +x pmta_
#
#		o link:
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_traffic_in -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_traffic_out -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_conn_in -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_conn_out -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_queue_domains -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_queue_recipients -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-14 14:52 pmta_queue_megabytes -> pmta_
#		  lrwxrwxrwx 1 root root    5 2011-11-15 16:31 pmta_top_domains -> pmta_
#
#		o alternative multi-host configuration:
#		   you can also link the pmta_ script to various hosts and configure munin to respond 
#		   to multiple REMOTEHOSTs, just link pmta_ in this schema and configure munin
#		   accordingly - DO NOT USE DOTS IN YOUR IDENTIFIER VARIABLE, USE UNDERSCORE INSTEAD!
#		   for example:
#			lrwxrwxrwx 1 root root    5 2011-11-18 12:18 mailhost1_domain_com_pmta_top_domains -> pmta_
#			lrwxrwxrwx 1 root root    5 2011-11-18 12:18 mailhost2_domain_com_pmta_top_domains -> pmta_
#			lrwxrwxrwx 1 root root    5 2011-11-18 12:18 mailhost3_domain_com_pmta_top_domains -> pmta_
#			lrwxrwxrwx 1 root root    5 2011-11-18 12:18 mailhost4_domain_com_pmta_top_domains -> pmta_
#		  [...]
#
#		  conf.: 
#		   [mailhost1_domain_com_pmta*]
#				env.REMOTEHOST somehostORip
#				env.PORT portnumber
#		   [mailhost2_domain_com_pmta*]
#				env.REMOTEHOST someotherhostORip
#				env.PORT portnumber
#		  [...]
#
#		o restart munin.
#
###################################################################################################################
# debug (munin-run --pidebug --debug <script>):
if [ "$MUNIN_DEBUG" = "1" ]; then
	set -vx
fi

NAME_SELF=`basename ${0}`
trap 'echo "\n$NAME_SELF - >> interrupt. \n$NAME_SELF - >> exiting."' 1 2 9 11 15

if [ -z "${REMOTEHOST}" ] || [ -z "${PORT}" ]; then
	echo "\n$NAME_SELF - >> no environment variable set for host and/or port. \n$NAME_SELF - >> exiting."
	exit 1
fi

fetch_xml() {
	#  o arg1 specifies xpath or false
	#  o arg2 specifies sed/regex or false
	#  o arg3 specifies category ('status', 'domains',..) or false	
	HTTPQUERY="GET /${3}?format=xml HTTP/1.1\n\n"
	REMOTE=`echo ${HTTPQUERY} | nc -q 1 -w 5 ${REMOTEHOST} ${PORT} | tail -1`
	XML_DATA=${REMOTE}
	SED="s/.*<$2>\([^<]*\)<\/$2>.*/\1/p"	
	
	if [ "$3" = "status" ]; then
		RET=`echo $XML_DATA | xpath -q -e $1 | sed -n $SED | cut -f1 -d '.'`
	elif [ "$3" = "domains" ]; then
		RET=`echo $XML_DATA | xpath -q -e '//domain/*[self::name or self::rcp]' | sed 's/<[^>]*>//g' | sed 's/\./_/g'`
	fi	
	
	if [ "$RET" ]; then
		echo $RET
		return 0
	else
		echo 'no_result'
		return 1
	fi
}

case $NAME_SELF in
	*pmta_traffic_in | *pmta_traffic_out)
		if [ `expr match "$NAME_SELF" ".*pmta_traffic_in"` != 0 ]; then
			WHAT="in"
		elif [ `expr match "$NAME_SELF" ".*pmta_traffic_out"` != 0 ]; then
			WHAT="out"
		fi
		CONF_TITLE="powermta ${WHAT}bound traffic"
		CONF_LABEL="traffic_${WHAT}"
		CONF_SELF="traffic_${WHAT}bound"
		
		if [ -z $1 ]; then			
			GET=`fetch_xml //traffic//lastMin/${WHAT} kb status`  
			RETURN=`echo $GET / 1024 | bc`
			RCPT=`fetch_xml //traffic//lastMin/${WHAT} rcp status`  
			MSGS=`fetch_xml //traffic//lastMin/${WHAT} msg status`  
			echo "megabytes.value $RETURN"
			echo "recipients.value $RCPT"
			echo "messages.value $MSGS"			
			exit 0
		elif [ $1 = config ]; then
			echo "megabytes.label megabytes"
			echo "megabytes.draw AREA"
			echo "megabytes.colour 0000A0"
			echo "recipients.label recipients"
			echo "recipients.draw STACK"
			echo "recipients.colour FF0000"
			echo "messages.label messages"
			echo "messages.draw STACK"
			echo "messages.colour FF6F00"
			AUTOLABEL="no"
		fi
	;;
	*pmta_conn_in | *pmta_conn_out)
		if [ `expr match "$NAME_SELF" ".*pmta_conn_in"` != 0 ]; then
			WHAT="In"
		elif [ `expr match "$NAME_SELF" ".*pmta_conn_out"` != 0 ]; then
			WHAT="Out"
		fi
		CONF_TITLE=`echo "powermta ${WHAT}bound connections" | tr [:upper:] [:lower:]`
		CONF_LABEL=`echo "conn_${WHAT}" | tr [:upper:] [:lower:]`
		CONF_SELF=`echo "connections_${WHAT}bound" | tr [:upper:] [:lower:]`
		if [ -z $1 ]; then			
			GET=`fetch_xml //conn//smtp${WHAT} cur status`  
			echo "${CONF_SELF}.value $GET"
			exit 0 
		elif [ $1 = config ]; then
			echo "${CONF_SELF}.label ${WHAT}bound connections"
			echo "${CONF_SELF}.draw LINE1"
			echo "${CONF_SELF}.colour FF0000"
			AUTOLABEL="no"
		fi
	;;
	*pmta_queue_domains | *pmta_queue_recipients | *pmta_queue_megabytes)		
		if [ `expr match "$NAME_SELF" ".*pmta_queue_domains"` != 0 ]; then
			WHAT="domains"
		elif [ `expr match "$NAME_SELF" ".*pmta_queue_recipients"` != 0 ]; then
			WHAT="recipients"
		elif [ `expr match "$NAME_SELF" ".*pmta_queue_megabytes"` != 0 ]; then
			WHAT="megabytes"
			UNIT_KB="true"
		fi
		CONF_TITLE="powermta ${WHAT} in queue"
		CONF_LABEL="queue_${WHAT}"	
		CONF_SELF="${WHAT}"		
		
		if [ -z $1 ]; then
			if [ !$UNIT_KB ]; then
				GET=`fetch_xml //queue/smtp dom status`  
				echo "${CONF_SELF}.value $GET"
				exit 0 
			else	
				GET=`fetch_xml //queue/smtp kb status`  
				RETURN=`echo $GET / 1024 | bc`
				echo "${CONF_SELF}.value $RETURN"
				exit 0 
			fi
		fi	
	;;
	*pmta_top_domains)
		CONF_TITLE="powermta top 10 domains by recipients"
		CONF_LABEL="top_domains"
		CONF_SELF="domains"
		AUTOLABEL="no"
		
		GET=`fetch_xml false false domains`
		if [ -z $1 ]; then
			for values in $GET; do
				if [ $values -ge 0 2>/dev/null ]; then
					echo $values
				else
					echo -n "$values.value#"
				fi			
			done | tr ' ' '\n' | tr '#' ' ' # restore newline - replace hashtag with whitespace
			exit 0
		elif [ $1 = config ]; then
			for values in $GET; do
				[ $values -ge 0 2>/dev/null ] || echo "$values.label $values\n$values.draw LINE2"
			done
		fi
	;;
esac

case $1 in
	suggest)
		if [ $NAME_SELF = "pmta_" ]; then
			# suggest plugins to munin:
			echo "traffic_in\ntraffic_out\nconn_in\nconn_out\nqueue_domains\nqueue_recipients\nqueue_megabytes\ntop_domains"
			exit 0
        fi
	;;
	config)
		if [ -n "$CONF_TITLE" ] && [ -n "$CONF_LABEL" ]; then
			echo "graph_category mail"
			echo "graph_title $CONF_TITLE on ${REMOTEHOST}"
			echo "graph_vlabel $CONF_LABEL"
			echo "graph_scale yes"
			echo "graph_width 1400"
			echo "graph_height 450"
			echo "graph_args --step 10 --rigid --base 1000 -l 0"
			if [ "$AUTOLABEL" != "no" ]; then
				echo "${CONF_SELF}.label $CONF_LABEL"
				echo "${CONF_SELF}.draw AREA"
				echo "${CONF_SELF}.colour FF6F00"
			fi
		fi
		exit 0
	;;	
	autoconf)
		# tell munin this script supports autoconfiguration:
		echo "yes"
	;;	
	*)
		exit 1
	;;
esac
#EOF
