catch up with cvs
This commit is contained in:
@@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user