#!/usr/bin/env python
# $Id: hbc,v 1.3 2005/07/19 20:31:05 andreas Exp $
import sys, time, socket, os, signal, getopt, string

PORT=50003
INTERVAL=10

class NullDevice:
    def write(self, s):
        pass


def handler(signum, frame):
	global up
	if up == 0:
		return
	sys.exit(0)

msgonly=False
helpflag=False
verbose=False
daemon=False
optlist=[]  
args=[]
msgboot=[]
home=os.environ['HOME']
configfile="%s/.hbrc" % home

try:
    optlist, args = getopt.getopt(sys.argv[1:], 'bc:dhm:v')
except:
    helpflag=True

for o,a in optlist:
	if o == '-b':
		msgboot.append("boot=1")
	elif o == '-c':
		configfile=a
	elif o == '-d':
		daemon=True
	elif o == '-h':
		helpflag=True
	elif o == '-m':
		msgboot.append("service=%s" % "service")
		a.replace(';',':')
		msgboot.append("msg=%s" % a)
		msgonly=True
	elif o == '-v':
		verbose=True


if helpflag:
	print "hbc HeartBeatClient"
	print "usage: hbc [-bdhv] [-c configfile] [-m msg][host1 [..]]"
	print
	print "	-b	indicate machine boot"
	print "	-c configfile"
	print "	-d daemonize"
	print "	-h this help"
	print "	-m send a message"
	print "	-v verbose"
	print
	print """ config file can contain 
hb_hosts=('host1', 'host2', ..._
hb_port=50003
interval=20
logfile=...
logfmt={|test|msg}
grace=SECONDS
reportstrict={True|False}
"""

	sys.exit(1)

#
# set defaults

hb_port=PORT
interval=INTERVAL
hb_hosts=[]

try:
	f=open(configfile,"r")	
	if verbose: print "notice: using config file %s" % configfile
except:
	print "warning: running without conifig file: %s" % configfile
	f=None

if f:
	while 1:
		l=f.readline()
		if len(l) == 0:
			break
		r=l[:-1].split('=')
		if r[0] == 'hb_hosts':
			hb_hosts=eval(r[1])
			if verbose:
				print "notice:  cfg hb_hosts: %s" % hb_hosts
		elif r[0] == 'interval':
			interval=eval(r[1])
		elif r[0] == 'hb_port':
			hb_port=eval(r[1])
	f.close()

if len(args) != 0:
	hb_hosts=args

if len(hb_hosts) == 0:
	print "no hb server specified"
	sys.exit(1)


sock=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
iam=socket.gethostname()

if verbose:
	print "notice: hb_hosts: %s" % str(hb_hosts)
	print "notice: hb_port: %s" % hb_port
	print "notice: interval: %s" % interval
	print "notice: iam: %s" % iam

if not msgonly:
	msgboot.append("interval=%s" % interval)

if len(msgboot) > 0:
	msgboot.append("name=%s" % iam)
	msg=string.join(msgboot,";")
	while 1:
		fail=0
		for hb_host in hb_hosts:
			try:
				if verbose: print "sock.send('%s', (%s, %s))" % (msg, hb_host, hb_port)
				sock.sendto(msg, (hb_host, hb_port))
			except:
				fail=1
		if fail:
			time.sleep(10)
		else:
			break
	
if msgonly:
		sys.exit(0)

if daemon:
	pid=os.fork()
	if pid > 0:
		if verbose:
			print "daemoinizing... pid=%d" % pid
		sys.exit(0)


	os.close(0)
	os.close(1)
	os.close(2)
	sys.stdin.close()
	sys.stdout = NullDevice()
	sys.stderr = NullDevice()
	os.chdir("/")
	os.setsid() 
	os.umask(0) 


msg="interval=%s;name=%s" % (interval, iam)
up=1
signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGHUP, handler)

while up:
	try:
		time.sleep(interval)
	except:
		break
	for hb_host in hb_hosts:
		try:
			if verbose: print "sock.send('%s', (%s, %s))" % (msg, hb_host, hb_port)
			sock.sendto(msg, (hb_host, hb_port))
		except:
			pass

up=0
msg="shutdown=1;name=%s" % (iam)
for hb_host in hb_hosts:
	if verbose: print "sock.send('%s', (%s, %s))" % (msg, hb_host, hb_port)
	sock.sendto(msg, (hb_host, hb_port))
time.sleep(1)
sock.close()


