#!/bin/sh
#set -vx

# SellaNMS Administration Script

# Manual Settings
MYSQL=""
CONFIG="@resolved_sysconfdir@/sella_nms.conf"

# Constants
PROGRAM="admin-sella_nms.sh"
VERSION="0.2.0"

banner() {
	printf "%s v%s by James M. Sella\n" ${PROGRAM} ${VERSION}
}

usage() {
	banner
	printf "Usage: %s [OPTION]\n\n" `basename $0`
	printf " -m,--monitor [CHANNEL] [STATUS]\tMonitor for incoming alarms.\n"
	printf " -s,--summary [LIMIT]\t\t\tDisplay summary information.\n"
	printf " -a,--alarms [LIMIT]\t\t\tDisplay the contents of the alarms table.\n"
	printf " -o,--output [LIMIT]\t\t\tDisplay the contents of the output table.\n"
	printf " -x,--state [LIMIT]\t\t\tDisplay the contents of the state table.\n"
	printf " -d,--discovery [LIMIT]\t\t\tDisplay the contents of all discovery tables.\n"
	printf " -di,--discovery-icmp [LIMIT]\t\tDisplay the contents of the ICMP discovery table.\n"
	printf " -ds,--discovery-snmp [LIMIT]\t\tDisplay the contents of the SNMP discovery table.\n"
	printf " --reset-database\t\t\tResets the contents of the database.\n"
	printf " --clear-alarms\t\t\t\tClears all displayed alarms.\n"
	printf "\n"
	printf "Example: %s --alarms 100\n" `basename $0`
	printf "Example: %s --monitor 'interface-%%' 'failure'\n" `basename $0`
	printf "\n"
}

find_mysql() {
	MYSQL_LIST="${MYSQL} /usr/local/bin/mysql /usr/bin/mysql `which mysql 2> /dev/null`"

	for MYSQL in ${MYSQL_LIST}; do
		if [ -x ${MYSQL} ]; then
			return 0
		fi
	done

	echo "Unable to locate mysql. Please install the MySQL client and/or configure path manually."
	return 1
}

read_config() {
	if [ ! -r ${CONFIG} ];  then
		echo "Failed to read configuration file ${CONFIG}. Exiting."
		return 1
	fi
	
	SERVER=`awk 'BEGIN { depth=0; } { if (depth >= 2) go=1; if (go == 1) { if (/server/) print; if (/}/) depth--; } if (depth < 1) go=0; if (/system.*{/) depth++; if (/storage.*{/) depth++; }' ${CONFIG} | sed 's/.*server[ \t][ \t]*\([a-zA-Z0-9_\.\-][a-zA-Z0-9_\.\-]*\);.*$/\1/'`

	DATABASE=`awk 'BEGIN { depth=0; } { if (depth >= 2) go=1; if (go == 1) { if (/database/) print; if (/}/) depth--; } if (depth < 1) go=0; if (/system.*{/) depth++; if (/storage.*{/) depth++; }' ${CONFIG} | sed 's/.*database[ \t][ \t]*\([a-zA-Z0-9_\.\-][a-zA-Z0-9_\.\-]*\);.*$/\1/'`

	USERNAME=`awk 'BEGIN { depth=0; } { if (depth >= 2) go=1; if (go == 1) { if (/username/) print; if (/}/) depth--; } if (depth < 1) go=0; if (/system.*{/) depth++; if (/storage.*{/) depth++; }' ${CONFIG} | sed 's/.*username[ \t][ \t]*\([a-zA-Z0-9_\.\-][a-zA-Z0-9_\.\-]*\);.*$/\1/'`

	PASSWORD=`awk 'BEGIN { depth=0; } { if (depth >= 2) go=1; if (go == 1) { if (/password/) print; if (/}/) depth--; } if (depth < 1) go=0; if (/system.*{/) depth++; if (/storage.*{/) depth++; }' ${CONFIG} | sed 's/.*password[ \t][ \t]*\([a-zA-Z0-9_\.\-][a-zA-Z0-9_\.\-]*\);.*$/\1/'`
}

test_mysql() {
	COUNT=`echo "SELECT COUNT(id) FROM discovery_icmp" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	if [ $? -ne 0 ]; then
		printf "Failed to connect to the SellaNMS MySQL database.\n\nConfig: %s\nServer: %s\nDatabase: %s\nUsername: %s\nPassword: %s\n\n" ${CONFIG} ${SERVER} ${DATABASE} ${USERNAME} ${PASSWORD}
		exit 1
	fi
}

summary() {
	printf "[Discovery Information]\n"
	discovery_summary $1

	printf "\n[Output Information]\n"
	output_summary $1

	printf "\n[GUI Information]\n"
	gui_summary $1

}

discovery_summary() {
	ICMP_COUNT=`echo "SELECT COUNT(id) FROM discovery_icmp" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	SNMP_COUNT=`echo "SELECT COUNT(id) FROM discovery_snmp" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	NE_COUNT=`echo "SELECT COUNT(id) FROM element" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`
	NEI_COUNT=`echo "SELECT COUNT(id) FROM interface" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`
	NEII_COUNT=`echo "SELECT COUNT(id) FROM ip" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	if [ ${NE_COUNT} -le 2 ]; then # 2 elements are inserted into the db as part of the setup process.
		if [ ${ICMP_COUNT} -eq 0 ]; then
			printf "No discovery information. Please start a discovery process.\n"
		else
			printf "Discovery started; %d ICMP hosts located, %d SNMP OIDs collected.\n" ${ICMP_COUNT} ${SNMP_COUNT}
		fi
		printf "There is no previous discovery information.\n"
	else 
		if [ ${SNMP_COUNT} -eq 0 ]; then
			printf "Last discovery located %d ICMP hosts.\n" ${ICMP_COUNT}
		else
			printf "Discovery started; %d ICMP hosts located, %d SNMP OIDs collected.\n" ${ICMP_COUNT} ${SNMP_COUNT}
		fi
		printf "Previously completed discovery containts %d elements, %d interfaces and %d IPs\n" ${NE_COUNT} ${NEI_COUNT} ${NEII_COUNT}
	fi
}

output_summary() {
	test -z "$1" && LAST=2 || LAST=$1

	OUTPUT_COUNT=`echo "SELECT COUNT(id) AS output_table_record_count FROM output" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "Pending output records: %d\nDisplaying last %d records:\n" ${OUTPUT_COUNT} ${LAST}

	echo "SELECT * FROM output ORDER BY timestamp DESC LIMIT ${LAST}\G" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}
}

gui_summary() {
	test -z "$1" && LAST=2 || LAST=$1

	EVENT_COUNT=`echo "SELECT COUNT(id) FROM gui_event" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "gui_event records: %d\nDisplaying last %d records:\n" ${EVENT_COUNT} ${LAST}

	echo "SELECT * FROM gui_event ORDER BY timestamp DESC LIMIT ${LAST}\G" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}
}

output() {
	test -z "$1" && LAST=25 || LAST=$1

	COUNT=`echo "SELECT COUNT(id) AS output_table_record_count FROM output" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "Displaying the last %d records (out of %d) from table output (descending order).\n\n" ${LAST} ${COUNT}

	echo "SELECT * FROM output ORDER BY timestamp DESC LIMIT ${LAST}\G" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}
}

alarms() {
	test -z "$1" && LAST=25 || LAST=$1

	COUNT=`echo "SELECT COUNT(id) FROM gui_event" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "Displaying the last %d records (out of %d) from table gui_event (descending order).\n\n" ${LAST} ${COUNT}

	echo "SELECT * FROM gui_event ORDER BY timestamp DESC LIMIT ${LAST}\G" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}
}

discoveryicmp() {
	test -z "$1" && LAST=25 || LAST=$1

	COUNT=`echo "SELECT COUNT(id) FROM discovery_icmp" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "Displaying the last %d records (out of %d) from table discovery_icmp (descending order).\n\n" ${LAST} ${COUNT}

	echo "SELECT * FROM discovery_icmp ORDER BY timestamp DESC LIMIT ${LAST}\G" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}
}

discoverysnmp() {
	test -z "$1" && LAST=25 || LAST=$1

	COUNT=`echo "SELECT COUNT(id) FROM discovery_snmp" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "Displaying the last %d records (out of %d) from table discovery_snmp (descending order).\n\n" ${LAST} ${COUNT}

	echo "SELECT * FROM discovery_snmp ORDER BY timestamp DESC LIMIT ${LAST}\G" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}
}

monitor() {
	LAST_ID=0
	TMPFILE="/tmp/${PROGRAM}-monitor.$$"

	test -z "$1" && CHANNEL="%" || CHANNEL=$1
	test -z "$2" && STATUS="%" || STATUS=$2

	if [ -e "${TMPFILE}" ]; then
		echo "Temporary file ${TMPFILE} already exists. Aborting."
		return 1
	fi

	EVENT_COUNT=`echo "SELECT COUNT(id) FROM gui_event" | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}`

	printf "%d existing gui_event records. Monitoring for incoming gui_event records...\n" ${EVENT_COUNT}

	trap "rm -f ${TMPFILE};echo;break" INT

	while [ 1 ]; do
		SQL="SELECT gui_event.id AS event_id, MIN(gui_event.timestamp) AS stamp, gui_event.channel AS channel, gui_event.state AS state, element_data.value AS element, interface_data.value AS interface, gui_event.brief AS brief, gui_event.detail AS detail FROM gui_event LEFT JOIN element_data ON ( element_data.element = element AND element_data.variable = '.1.3.6.1.2.1.1.5.0' ) LEFT JOIN interface_data ON ( interface_data.interface = interface AND (interface_data.variable = '.1.3.6.1.2.1.2.2.1.2')) WHERE gui_event.id > \"${LAST_ID}\" AND channel LIKE \"${CHANNEL}\" AND state LIKE \"${STATUS}\" AND element IS NOT NULL GROUP BY address, interface, element, brief ORDER BY gui_event.id, gui_event.timestamp DESC, element, interface, address"

		echo $SQL | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER} > ${TMPFILE}
		NEXT_ID="`tail -1 ${TMPFILE} | awk -F '	' '{ print $1; }'`"
		STAMP="`tail -1 ${TMPFILE} | awk -F '	' '{ print $3; }'`"

		if [ -n "${NEXT_ID}" ]; then
				  awk -F '	' '{
						printf("Timestamp: %s\tElement: %s\tInterface: %s\nStatus: %s  Channel: %s\nBrief: %s\nDetail: %s\n\n", $2, $5, $6, $4, $3, $7, $8);
					}' ${TMPFILE}

				  LAST_ID=${NEXT_ID}
		fi

		sleep 5
	done

	trap - INT
}

clear() {
	if [ `id -u` -ne 0 ]; then
		printf "Root privileges are required for this function.\n"

		return
	fi

	if [ "$1" != "force" ]; then
		trap "echo 'aborted';return" INT

		printf "Will clear all currently displayed alarms in 5 seconds.\nUse Ctrl-C to abort. To avoid this delay, use the 'force' argument.\n"
		sleep 5

		trap - INT
	fi

	printf "\nClearing alarms..."

	SQL="DELETE FROM gui_event"
	echo $SQL | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}

	printf "done\n"
}

reset() {
	if [ `id -u` -ne 0 ]; then
		printf "Root privileges are required for this function.\n"

		return
	fi

	printf "The SellaNMS daemons should be shutdown prior to running this.\n\n"
	if [ "$1" != "force" ]; then
		trap "echo 'aborted';return" INT

		printf "Will clear all contents of database in 10 seconds.\nUse Ctrl-C to abort. To avoid this delay, use the 'force' argument.\n"
		sleep 10

		trap - INT
	fi

	printf "\nReseting database contents..."
	echo
	SQL="
		DELETE FROM connection;
		DELETE FROM connection_data;
		DELETE FROM connection_point;
		DELETE FROM discovery_icmp;
		DELETE FROM discovery_snmp;
		DELETE FROM gui_channel;
		DELETE FROM gui_channel_assoc;
		DELETE FROM gui_chat_data;
		DELETE FROM gui_chat_login;
		DELETE FROM gui_event;
		DELETE FROM gui_event_message;
		DELETE FROM gui_history;
		DELETE FROM gui_login;
		DELETE FROM gui_login_security;
		DELETE FROM gui_security;
		DELETE FROM gui_user;
		DELETE FROM gui_user_prefs;
		DELETE FROM gui_view;
		DELETE FROM element;
		DELETE FROM element_attr;
		DELETE FROM element_data;
		DELETE FROM interface;
		DELETE FROM interface_attr;
		DELETE FROM interface_data;
		DELETE FROM ip;
		DELETE FROM ip_attr;
		DELETE FROM ip_data;
		DELETE FROM output;
	"

	echo $SQL | ${MYSQL} -s -u ${USERNAME} -p"${PASSWORD}" ${DATABASE} -h ${SERVER}

	printf "done\n"
}

# Start Main
find_mysql && test $? -ne 0 && exit 1
read_config && test $? -ne 0 && exit 1
test_mysql

case "$1" in
	-m|--monitor)
		monitor $2 $3
		;;
	-s|--summary)
		summary $2
		;;
	-a|--alarms)
		alarms $2
		;;
	-o|--output)
		output $2
		;;
	-d|--discovery)
		discoveryicmp $2
		discoverysnmp $2
		;;
	-di|--discovery-icmp)
		discoveryicmp $2
		;;
	-ds|--discovery-snmp)
		discoverysnmp $2
		;;
	--reset-database)
		reset $2
		;;
	--clear-alarms)
		clear $2
		;;
	*)
		usage
		;;
esac
