#!/usr/bin/env python

from time import time
start = time()

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'mymontools.settings'

import django
django.setup()

##############################################################################

import optparse
import re
import sys
import syslog

from django.core.validators import validate_ipv46_address, ValidationError
from django.utils import timezone

from traps.models import *
from traps.tools import *
from traps.translate import translate_trapoid_to_name

##############################################################################

parser = optparse.OptionParser()

parser.add_option('', '--no-syslog', dest='syslog', action='store_false', default=True, help='Dissable syslog')

parser.add_option('-v', '--verbose', dest='verb', action='count', default=0, help='Be verbose')

(opts, args) = parser.parse_args()

#####

opts.verb = min( opts.verb, 3 )

if opts.syslog:
	syslog.openlog(ident='MyMonTools_Traphandler', logoption=syslog.LOG_PID, facility=syslog.LOG_DAEMON)

##############################################################################

verbose2syslog = [syslog.LOG_ERR, syslog.LOG_WARNING, syslog.LOG_NOTICE, syslog.LOG_INFO]

def logit(prio, msg):
	if prio <= opts.verb:
		if opts.syslog:
			syslog.syslog(verbose2syslog[prio], msg)
		else:
			print u'>>> V%1d: %s' % (prio, msg)

##############################################################################

logit(1, 'Traphandler started')

lines = sys.stdin.readlines()

if len(lines) < 3:
	logit(0, 'Trap is incomplete, exiting...')
	sys.exit(1)

trap = Trap()
# FIXME: Strip DNS-Domain
trap.hostname = lines[0].replace('.treuchtlingen.stadt', '').replace('.treuchtlingen.de', '').lstrip().rstrip()
trap.agent = lines[1].lstrip().rstrip()
trap.traptime = timezone.make_aware( datetime.datetime.now() , timezone.get_current_timezone() )

ip = re.search(r'\[([\d\.:a-fA-F]+)\]', trap.agent)
if ip:
	try:
		ip = ip.groups()[0]
		validate_ipv46_address( ip )
		trap.agentip = ip
	except (ValidationError, IndexError):
		pass

varbinds = {}
for line in lines[2:]:
	try:
		(oid, value) = line.split(' ',1)
	except ValueError:
		logit(0, 'Read data is corrupt, exiting...')
		sys.exit(1)
	varbinds[oid] = value


# SNMPv2-MIB::snmpTrapOID.0
try:
	trap.trapoid = varbinds.pop('.1.3.6.1.6.3.1.1.4.1.0').lstrip().rstrip()
except KeyError:
	logit(0, 'Trap does not contain snmpTrapOID, exiting...')
	sys.exit(1)

# SNMP-COMMUNITY-MIB::snmpTrapAddress.0
#try:
#	trap.agentip = varbinds.pop('.1.3.6.1.6.3.18.1.3.0').lstrip().rstrip()
#except KeyError:
#	pass

# SNMP-COMMUNITY-MIB::snmpTrapCommunity.0
try:
	trap.community = varbinds.pop('.1.3.6.1.6.3.18.1.4.0').lstrip().rstrip()
except KeyError:
	logit(3, 'Trap does not contain snmpTrapCommunity (SNMPv1 only - not fatal)')

# SNMPv2-MIB::snmpTrapEnterprise.0
try:
	trap.enterprise = varbinds.pop('.1.3.6.1.6.3.1.1.4.3.0').lstrip().rstrip()
except KeyError:
	 logit(3, 'Trap does not contain snmpTrapEnterprise (SNMPv1 only - not fatal)')

try:
	trap.save()
except:
	logit(0, u'Could not save trap, exiting...')
	sys.exit(1)

logit(2, u'Trap saved: %s (runtime: %-.3fs)' % (trap,  (time() - start),) )

# Save VarBindings
for (oid, value) in varbinds.iteritems():
	tvb = TrapVarbind()
	tvb.trap = trap
	tvb.oid = oid.lstrip().rstrip()
	tvb.value = value.lstrip().rstrip()
	try:
		tvb.save()
	except:
		logit(0, u'Could not save one VarBinding')

logit(2, u'VarBindings saved (runtime: %-.3fs)' % (time() - start) )

##############################################################################

# Translate TrapOID to TrapName
oidname = translate_trapoid_to_name(trap.trapoid)
if oidname:
	trap.trapname = oidname
	trap.save()
	logit(3, u'Trap-OID translated (runtime: %-.3fs)' % (time() - start) )
else:
	logit(2, u'Trap-OID could not be translated')

##############################################################################

# FIXME:#56 Auch je nach VarBinding unterschiedliche Configs/Category/Severity
try:
	cfgtrap = CfgTrap.objects.get(trapoid=trap.trapoid)
except CfgTrap.DoesNotExist:
	cfgtrap = None

if cfgtrap:
	trap.category = cfgtrap.category
	trap.severity = cfgtrap.severity
	trap.save()
	logit(3, u'Trap config found, trap categorized (runtime: %-.3fs)' % (time() - start) )
else:
	logit(2, u'No Trap config found for trap %s (runtime: %-.3fs)' % (trap.trapoid, (time() - start),) )

logit(1, u'Traphandler finished (runtime: %-.3fs)' % (time() - start) )