#!/usr/bin/env python

import os
import sys
import glob
import subprocess
import signal

from os import path


class Alarm(Exception):
	pass

def alarm_handler(signum, frame):
	raise Alarm()

def main ():
	location = path.realpath(__file__)

	exabgp = path.abspath(path.join(location,'..','..','..','sbin','exabgp'))
	if not path.isfile(exabgp):
		print "could not find exabgp"

	runtest = path.abspath(path.join(location,'..','..','runtest'))
	if not path.isdir(runtest):
		sys.exit('could not find test folder')

	sequence_daemon = path.abspath(path.join(location,'..','..','sbin','ibgp-check'))
	if not path.isfile(sequence_daemon):
		sys.exit('could not find the sequence daemon')

	match = '*' if len(sys.argv) < 2 else sys.argv[1].split('/')[-1].split('.')[0]
	if match == 'all': match = '*'

	if len(sys.argv) >= 3:
		reverse = reversed if sys.argv[2].startswith('rev') else lambda _:_
		skip = 0 if not sys.argv[2].isdigit() else int(sys.argv[2])
		show = True if sys.argv[2] == 'show' else False
	else:
		reverse = lambda _:_
		skip = 0
		show = False

	confs = glob.glob(path.join(runtest,'%s.conf' % match.replace('all','*')))
	confs = reverse(confs)

	for configuration in confs:
		if skip:
			print 'skiped ',configuration
			skip -= 1
			continue

		sequence_file = configuration.replace('.conf','.sequence')
		if path.isfile(sequence_file):
			check_sequence(exabgp,configuration,sequence_daemon,sequence_file,show)
		else:
			print "sequence check for", configuration
			print "skip (no sequence data)\n"
			continue

def check_sequence(exabgp,configuration,daemon,fname,show):
	os.environ['exabgp.tcp.once'] = 'true'
	os.environ['exabgp.debug.defensive'] = 'true'

	timeout = 30  # seconds

	class Exit (Exception): pass

	try:
		command_daemon = [daemon,fname]
		command_exabgp = [exabgp, configuration]

		if show:
			raise Exit()

		signal.signal(signal.SIGALRM, alarm_handler)
		signal.alarm(timeout)

		print "sequence check for", configuration
		print "will wait for completion for %d seconds" % timeout

		print "starting daemon,",
		daemon = subprocess.Popen(command_daemon, stdout=subprocess.PIPE)

		print "exabgp"
		exabgp = subprocess.Popen(command_exabgp, stdout=subprocess.PIPE)

		exabgp_output = exabgp.communicate()[0]
		daemon_output = daemon.communicate()[0]
	except Alarm:
		exabgp_output = '(killed) exabgp was still running\n'
		daemon_output = '(killed) still waiting for data after %d seconds\n' % timeout

		for pid in [daemon.pid, exabgp.pid]:
			try:
				os.kill(pid,signal.SIGTERM)
			except OSError:
				pass
	except Exit:
		exabgp_output = ''
		daemon_output = ''

	def commands (command_exabgp,command_daemon):
		r = ""
		r += "command lines are:\n\n"
		r += "> env exabgp.tcp.port=1790 exabgp.debug.defensive=true exabgp.tcp.once=true exabgp.tcp.bind='' " + ' '.join(command_exabgp) + '\n\n'
		r += '> env exabgp.tcp.port=1790 ' + ' '.join(command_daemon)
		return r

	if show:
		print commands(command_exabgp,command_daemon)
	elif 'successful' in daemon_output:
		print "successful\n"
	else:
		print "\n"*4
		print "failure\n"
		print
		print commands(command_exabgp,command_daemon)
		print
		print 'exabgp:\n', exabgp_output
		print 'daemon:\n', daemon_output
		print "\n"*4

def check (main):
	os.environ['exabgp.tcp.bind'] = ''
	if not os.environ.get('exabgp.tcp.port',None):
		os.environ['exabgp.tcp.port'] = '1790'

	uid = os.getuid()
	gid = os.getgid()

	port = os.environ['exabgp.tcp.port']
	if not port.isdigit():
		print 'invalid port value %s' % port

	if uid and gid and int(port) <= 1024:
		print 'you need to have root privileges to bind to port 79'
		sys.exit(1)
	main()

check(main)
