catch up with cvs

This commit is contained in:
2013-07-14 14:26:35 -04:00
parent 69d962fdc7
commit ce7a103066
+119 -44
View File
@@ -1,9 +1,14 @@
#!/usr/bin/env python #!/usr/bin/env python
# $Id: hbd,v 1.35 2013/06/03 13:24:26 andreas Exp $ # $Id: hbd,v 1.38 2013/07/14 02:25:05 andreas Exp $
# Wait for heartbeat messages and act on them (or their absence) # Wait for heartbeat messages and act on them (or their absence)
# #
VER = 1.36
import time, os, string, sys, socket, atexit, select, SocketServer, getopt, signal, cPickle, smtplib, traceback import time, os, string, sys, socket, atexit, select, SocketServer, getopt, signal, cPickle, smtplib, traceback
from subprocess import Popen, STDOUT, PIPE
False = 0 False = 0
True = 1 True = 1
LOGFILE = "/home/andreas/public_html/messages/andreas" LOGFILE = "/home/andreas/public_html/messages/andreas"
@@ -37,12 +42,14 @@ msgw=None
msgwB = None msgwB = None
msgwHeight = 10 msgwHeight = 10
def handler(signum, frame): def handler(signum, frame):
global up, sig global up, sig
if up == 0: if up == 0:
return return
sig = signum sig = signum
if verbose: print "signal: %s up: %d" % (sig, up) if verbose:
print "signal: %s up: %d" % (sig, up)
up = 0 up = 0
# sys.exit(0) # sys.exit(0)
@@ -51,10 +58,12 @@ def shortname(name):
r = string.split(name, '.') r = string.split(name, '.')
return r[0] return r[0]
class NullDevice: class NullDevice:
def write(self, s): def write(self, s):
pass pass
class Host: class Host:
up = "up" up = "up"
down = "down" down = "down"
@@ -96,6 +105,7 @@ class Host:
displaystatetime(self.name) displaystatetime(self.name)
return s return s
def email(s, msg): def email(s, msg):
ret = "OK" ret = "OK"
toaddrs = AEMAIL toaddrs = AEMAIL
@@ -105,7 +115,8 @@ def email(s, msg):
body = "To: %s\nFrom: %s\nSubject: %s\nDate: %s\n\n%s" % (toaddrs[0], fromaddr, subj, date, msg) body = "To: %s\nFrom: %s\nSubject: %s\nDate: %s\n\n%s" % (toaddrs[0], fromaddr, subj, date, msg)
try: try:
server = smtplib.SMTP(SMTPSERVER) server = smtplib.SMTP(SMTPSERVER)
if DEBUG: server.set_debuglevel(1) if DEBUG:
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, body) server.sendmail(fromaddr, toaddrs, body)
except smtplib.SMTPRecipientsRefused, errs: except smtplib.SMTPRecipientsRefused, errs:
log("cannot send email: %s\n" % (errs)) log("cannot send email: %s\n" % (errs))
@@ -120,6 +131,39 @@ def email(s, msg):
return ret return ret
#
# nsupdate: set the DNS A record for a fqdn
# return: None if ok, else error text
def nsupdate(hostname, newip):
D = {}
D['domain'] = 'dy.wapanafa.org'
D['fqdn'] = '%s.dy.wapanafa.org' % hostname
D['dnsttl'] = '5'
D['newip'] = newip
D['ts'] = time.strftime('%Y-%m-%d.%H:%M:%S', time.gmtime())
nsup = """update delete %(fqdn)s A
update add %(fqdn)s %(dnsttl)s A %(newip)s
update delete %(fqdn)s TXT
update add %(fqdn)s %(dnsttl)s TXT "Created: %(ts)s"
send
answer
""" % D
# log("DBG: nsup %s" % nsup)
cmd = ["/usr/bin/nsupdate", "-k", "/etc/dhcpc/K%(domain)s.+157+00000." % D, "-v"]
# log("DBG: cmd %s" % cmd)
try:
p = Popen(cmd, shell=False, bufsize=1, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
except OSError, e:
return "nsupdate: execution failed: %s" % e
except:
return "nsupdate: some error occured"
(output, err) = p.communicate(nsup)
if output.find('status: NOERROR') >= 0:
return None
return output
# #
# #
@@ -135,12 +179,11 @@ def dur(sec):
return "0:%02d" % s return "0:%02d" % s
#
# #
# #
def addhost(name, addr): def addhost(name, addr):
sname = shortname(name) sname = shortname(name)
if hosts.has_key(sname): if sname in hosts: # was: hosts.has_key(sname):
del htab[hosts[sname].addr] del htab[hosts[sname].addr]
hosts[sname].addr = addr hosts[sname].addr = addr
if visual: if visual:
@@ -148,8 +191,6 @@ def addhost(name, addr):
htab[addr] = sname htab[addr] = sname
m = "%s, changed address to %s" % (sname, addr) m = "%s, changed address to %s" % (sname, addr)
log(m) log(m)
if name in watchhosts:
email("address change", m)
else: else:
hosts[sname] = Host(sname, addr) hosts[sname] = Host(sname, addr)
s = hosts.keys() s = hosts.keys()
@@ -162,8 +203,7 @@ def addhost(name, addr):
if visual: if visual:
display() display()
#
#
# #
def on_exit(): def on_exit():
if visual: if visual:
@@ -174,7 +214,8 @@ def on_exit():
def initlog(logfile): def initlog(logfile):
return open(logfile, "a") return open(logfile, "a")
#
# #
# #
def initwin(): def initwin():
@@ -185,7 +226,8 @@ def initwin():
begin_x = 0 begin_x = 0
begin_y = 2 begin_y = 2
height = len(htab)+2 height = len(htab)+2
if DEBUG: log("initwin called with %d" % height) if DEBUG:
log("initwin called with %d" % height)
win = curses.newwin(height, maxX, begin_y, begin_x) win = curses.newwin(height, maxX, begin_y, begin_x)
a = win.border(0, 0, 0, 0, 0, 0, curses.ACS_LTEE, curses.ACS_RTEE) a = win.border(0, 0, 0, 0, 0, 0, curses.ACS_LTEE, curses.ACS_RTEE)
@@ -200,8 +242,8 @@ def initwin():
stdscr.addstr(0, 0, "hbd Version 1.0", curses.A_BOLD) stdscr.addstr(0, 0, "hbd Version 1.0", curses.A_BOLD)
stdscr.refresh() stdscr.refresh()
msgwB.refresh() msgwB.refresh()
#
#
# #
def checkoverdue(): def checkoverdue():
@@ -216,7 +258,7 @@ def checkoverdue():
hosts[h].newstate(Host.overdue, grace) hosts[h].newstate(Host.overdue, grace)
log(m) log(m)
#
# #
# #
def displaytime(): def displaytime():
@@ -234,34 +276,35 @@ def displaytime():
win.refresh() win.refresh()
stdscr.refresh() stdscr.refresh()
#
# #
# #
def displaystatetime(h, refresh=1): def displaystatetime(h, refresh=1):
win.addstr(hosts[h].num+1, 60, "%-17s" % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(hosts[h].statetime))) win.addstr(hosts[h].num+1, 60, "%-17s" % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(hosts[h].statetime)))
if refresh: if refresh:
win.refresh() win.refresh()
#
# #
# #
def displayaddr(h, refresh=1): def displayaddr(h, refresh=1):
win.addstr(hosts[h].num+1, 35, "%-16s" % hosts[h].addr) win.addstr(hosts[h].num+1, 35, "%-16s" % hosts[h].addr)
if refresh: if refresh:
win.refresh() win.refresh()
#
# #
# #
def displaybody(): def displaybody():
for h in hosts.keys(): for h in hosts.keys():
win.addstr(hosts[h].num+1, 1, "%-25s" % (h)) win.addstr(hosts[h].num+1, 1, "%-25s" % (h))
if hosts[h].addr != None: if hosts[h].addr is not None:
displayaddr(h, 0) displayaddr(h, 0)
if hosts[h].statetime != None: if hosts[h].statetime is not None:
displaystatetime(h, 0) displaystatetime(h, 0)
win.refresh() win.refresh()
#
# #
# #
def displaymsgs(): def displaymsgs():
@@ -272,7 +315,7 @@ def displaymsgs():
y += 1 y += 1
msgw.refresh() msgw.refresh()
#
# #
# #
def display(): def display():
@@ -282,6 +325,7 @@ def display():
displaybody() displaybody()
displaymsgs() displaymsgs()
def log(m, service="heartbeat"): def log(m, service="heartbeat"):
msg = time.strftime("%b %d %H:%M:%S", time.localtime(time.time()))+": "+m+"\n" msg = time.strftime("%b %d %H:%M:%S", time.localtime(time.time()))+": "+m+"\n"
msgs.append(msg) msgs.append(msg)
@@ -291,7 +335,7 @@ def log(m, service="heartbeat"):
m2 = msg m2 = msg
logf.write(m2) logf.write(m2)
logf.flush() logf.flush()
if msgw != None: if msgw is not None:
y, x = msgw.getyx() y, x = msgw.getyx()
# if y > = msgwHeight-1: # if y > = msgwHeight-1:
# msgw.scroll() # msgw.scroll()
@@ -300,21 +344,31 @@ def log(m, service="heartbeat"):
msgw.refresh() msgw.refresh()
pickleit() pickleit()
# #
# #
def fromaddr(name, addr, boot, interval, acks): def fromaddr(name, addr, boot, interval, acks):
global htab global htab
if not hosts.has_key(name): if not name in hosts: # was: hosts.has_key(name):
addhost(name, addr) addhost(name, addr)
host = hosts[name] host = hosts[name]
host.doesack = acks host.doesack = acks
if host.addr != addr: if host.addr != addr:
log("%s changed address to %s" % (host.name, addr)) if host.addr in htab: # was: htab.has_key(host.addr):
if htab.has_key(host.addr):
del htab[host.addr] del htab[host.addr]
host.addr = addr host.addr = addr
htab[addr] = name htab[addr] = name
m = "%s changed address to %s" % (host.name, addr)
if name in dyndnshosts:
err = nsupdate(name, addr)
if err:
m += ", DNS failed: %s" % err
else:
m += ", DNS updated."
log(m)
if name in watchhosts:
email("address change", m)
host.lastbeat = now host.lastbeat = now
if host.getstate() != Host.up and interval > 0: if host.getstate() != Host.up and interval > 0:
@@ -326,7 +380,7 @@ def fromaddr(name, addr, boot, interval, acks):
email("back", name) email("back", name)
host.upcount += 1 host.upcount += 1
#
# #
# #
def readsock(): def readsock():
@@ -412,16 +466,21 @@ def initcurses():
curses.noecho() curses.noecho()
curses.cbreak() curses.cbreak()
stdscr.keypad(1) stdscr.keypad(1)
if DEBUG: sys.stderr.write("curses init done: %s\n" % stdscr) if DEBUG:
sys.stderr.write("curses init done: %s\n" % stdscr)
def exitcurses(): def exitcurses():
curses.nocbreak(); stdscr.keypad(0); curses.echo() curses.nocbreak()
stdscr.keypad(0)
curses.echo()
curses.endwin() curses.endwin()
#
# #
# #
class HtmlHandler(SocketServer.BaseRequestHandler): class HtmlHandler(SocketServer.BaseRequestHandler):
def handle(self): def handle(self):
f = self.request.makefile() f = self.request.makefile()
@@ -486,12 +545,15 @@ class HtmlHandler(SocketServer.BaseRequestHandler):
except: except:
pass pass
def saveandrestart(): def saveandrestart():
sock.close() sock.close()
serv.shutdown()
serv.socket.close() serv.socket.close()
log("restarting") log("restarting")
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs) os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
def pickleit(): def pickleit():
pickf = open(PICKFILE, 'w') pickf = open(PICKFILE, 'w')
pick = cPickle.Pickler(pickf) pick = cPickle.Pickler(pickf)
@@ -570,11 +632,13 @@ logfmt="text"
interval = INTERVAL interval = INTERVAL
grace = GRACE grace = GRACE
watchhosts = [] watchhosts = []
dyndnshosts = []
drophosts = [] drophosts = []
try: try:
f = open(configfile, "r") f = open(configfile, "r")
if verbose: print "notice: using config file %s" % configfile if verbose:
print "notice: using config file %s" % configfile
except: except:
print "warning: running without conifig file: %s" % configfile print "warning: running without conifig file: %s" % configfile
f = None f = None
@@ -584,7 +648,8 @@ if f:
l = f.readline() l = f.readline()
if len(l) == 0: if len(l) == 0:
break break
if verbose: print " %s" % l[:-1] if verbose:
print " %s" % l[:-1]
r = l[:-1].split('=') r = l[:-1].split('=')
if r[0] == 'interval': if r[0] == 'interval':
interval = eval(r[1]) interval = eval(r[1])
@@ -602,6 +667,8 @@ if f:
logfmt = r[1] logfmt = r[1]
elif r[0] == 'watchhosts': elif r[0] == 'watchhosts':
watchhosts = eval(r[1]) watchhosts = eval(r[1])
elif r[0] == 'dyndnshosts':
dyndnshosts = eval(r[1])
elif r[0] == 'drophosts': elif r[0] == 'drophosts':
drophosts = eval(r[1]) drophosts = eval(r[1])
f.close() f.close()
@@ -611,7 +678,8 @@ if len(args) != 0:
sys.exit(1) sys.exit(1)
if verbose: print "notice: logging to %s" % logfile if verbose:
print "notice: logging to %s" % logfile
logf = initlog(logfile) logf = initlog(logfile)
if os.path.exists(PICKFILE): if os.path.exists(PICKFILE):
@@ -625,7 +693,7 @@ if os.path.exists(PICKFILE):
except: except:
os.unlink(PICKFILE) os.unlink(PICKFILE)
for h in drophosts: for h in drophosts:
if hosts.has_key(h): if h in hosts: # was: hosts.has_key(h):
del hosts[h] del hosts[h]
@@ -638,7 +706,7 @@ if visual:
display() display()
stdscr.nodelay(1) stdscr.nodelay(1)
log("Starting") log("Starting %s" % VER)
atexit.register(on_exit) atexit.register(on_exit)
ilist = [] ilist = []
@@ -655,7 +723,8 @@ ilist.append(serv.fileno())
if not forground: if not forground:
pid = os.fork() pid = os.fork()
if pid > 0: if pid > 0:
if verbose: print "daemoinizing... pid=%d" % pid if verbose:
print "daemoinizing... pid = %d" % pid
sys.exit(0) sys.exit(0)
verbose = False verbose = False
@@ -679,12 +748,19 @@ sleep=next - now
while up: while up:
if visual: if visual:
c = stdscr.getch() c = stdscr.getch()
if c == ord('c'): msgs=[]; display() if c == ord('c'):
elif c == ord('q'): break # Exit the while() msgs = []
elif c == ord('d'): DEBUG=not DEBUG display()
elif c == ord('v'): verbose=not verbose elif c == ord('q'):
# elif c == ord('p'): PrintDocument() break # Exit the while()
# elif c == ord('x'): x = y = 0 elif c == ord('d'):
DEBUG = not DEBUG
elif c == ord('v'):
verbose = not verbose
# elif c == ord('p'):
# PrintDocument()
# elif c == ord('x'):
# x = y = 0
try: try:
sr = select.select(ilist, [], [], sleep) sr = select.select(ilist, [], [], sleep)
@@ -718,10 +794,9 @@ while up:
if sleep < 0: if sleep < 0:
sys.stderr.write("sleep is negaitive! %s next = %s\n" % (sleep, next)) sys.stderr.write("sleep is negaitive! %s next = %s\n" % (sleep, next))
sleep = 0 sleep = 0
if DEBUG: sys.stderr.write("sleep=%s next=%s\n" % (sleep, next)) if DEBUG:
sys.stderr.write("sleep = %s next = %s\n" % (sleep, next))
if sig == signal.SIGHUP: if sig == signal.SIGHUP:
saveandrestart() saveandrestart()