add http support
This commit is contained in:
+165
-58
@@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# $Id: watcharnsberg,v 1.3 2005/05/06 14:33:30 andreas Exp $
|
# $Id: watcharnsberg,v 1.4 2005/05/06 14:34:00 andreas Exp $
|
||||||
# Wait for heartbeat messages and act on them (or their absence)
|
# Wait for heartbeat messages and act on them (or their absence)
|
||||||
#
|
#
|
||||||
import time, os, string, sys, socket, curses, atexit, select
|
import time, os, string, sys, socket, curses, atexit, select, SocketServer
|
||||||
|
|
||||||
|
|
||||||
LOGF="/home/andreas/public_html/messages/andreas"
|
LOGF="/home/andreas/public_html/messages/andreas"
|
||||||
@@ -11,6 +11,8 @@ hosts={}
|
|||||||
num=0
|
num=0
|
||||||
upcount=0
|
upcount=0
|
||||||
PORT=50003
|
PORT=50003
|
||||||
|
TPORT=50004
|
||||||
|
THOST="10.99.1.4"
|
||||||
DEBUG=False
|
DEBUG=False
|
||||||
verbose=False
|
verbose=False
|
||||||
|
|
||||||
@@ -28,17 +30,22 @@ msgwB=None
|
|||||||
msgwHeight=10
|
msgwHeight=10
|
||||||
|
|
||||||
class Host:
|
class Host:
|
||||||
|
up="up"
|
||||||
|
down="down"
|
||||||
|
overdue="overdue"
|
||||||
|
OVERDUE="OVERDUE"
|
||||||
|
|
||||||
def __init__(self, name, addr):
|
def __init__(self, name, addr):
|
||||||
global num
|
global num
|
||||||
self.name=name
|
self.name=name
|
||||||
self.addr=addr
|
self.addr=addr
|
||||||
self.num=num
|
self.num=num
|
||||||
self.last=time.time()
|
self.lastbeat=time.time()
|
||||||
self.upcount=0
|
self.upcount=0
|
||||||
self.up=1
|
self.state=Host.up
|
||||||
self.uppercent="n/a"
|
self.uppercent="n/a"
|
||||||
self.state="up"
|
self.state="up"
|
||||||
self.statetime=self.last
|
self.statetime=self.lastbeat
|
||||||
self.interval=INTERVAL
|
self.interval=INTERVAL
|
||||||
num+=1
|
num+=1
|
||||||
|
|
||||||
@@ -50,10 +57,6 @@ class Host:
|
|||||||
now=time.time()
|
now=time.time()
|
||||||
s=now-self.statetime
|
s=now-self.statetime
|
||||||
self.statetime=now
|
self.statetime=now
|
||||||
if state == "up":
|
|
||||||
self.up=1
|
|
||||||
elif state == "down":
|
|
||||||
self.up=0
|
|
||||||
if visual:
|
if visual:
|
||||||
displaystatetime(self.name)
|
displaystatetime(self.name)
|
||||||
return s
|
return s
|
||||||
@@ -138,36 +141,36 @@ def initwin():
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
def displaytime():
|
def checkoverdue():
|
||||||
if visual:
|
|
||||||
maxY,maxX=stdscr.getmaxyx()
|
|
||||||
stdscr.addstr(0,maxX-8, time.strftime("%H:%M:%S", time.localtime(now)), curses.A_BOLD)
|
|
||||||
# stdscr.addstr(0,67,"%s.%04d" % (time.strftime("%H:%M:%S", time.localtime(now)),int((now-int(now))*10000) ), curses.A_BOLD)
|
|
||||||
|
|
||||||
for h in hosts:
|
for h in hosts:
|
||||||
if hosts[h].last != 0:
|
if hosts[h].state == Host.down:
|
||||||
attr=0
|
continue
|
||||||
if verbose:
|
if hosts[h].state == Host.up and now-hosts[h].lastbeat > hosts[h].interval+GRACE:
|
||||||
d=dur(now-hosts[h].last)
|
hosts[h].newstate(Host.overdue)
|
||||||
else:
|
elif hosts[h].state == Host.overdue and now-hosts[h].lastbeat > hosts[h].interval*5+GRACE:
|
||||||
d=hosts[h].getstate()
|
log("%s is overdue" % h)
|
||||||
if not hosts[h].up:
|
hosts[h].newstate(Host.OVERDUE)
|
||||||
d=hosts[h].getstate()
|
|
||||||
elif now-hosts[h].last > hosts[h].interval+GRACE:
|
#
|
||||||
d="overdue"
|
#
|
||||||
if now-hosts[h].last > hosts[h].interval*5+GRACE:
|
#
|
||||||
d="OVERDUE"
|
#
|
||||||
if hosts[h].getstate() != "overdue":
|
def displaytime():
|
||||||
log("%s is overdue" % h)
|
maxY,maxX=stdscr.getmaxyx()
|
||||||
hosts[h].newstate("overdue")
|
stdscr.addstr(0,maxX-8, time.strftime("%H:%M:%S", time.localtime(now)), curses.A_BOLD)
|
||||||
if now-hosts[h].last > hosts[h].interval*60+GRACE:
|
|
||||||
attr=curses.A_BOLD
|
for h in hosts:
|
||||||
if visual:
|
d=hosts[h].getstate()
|
||||||
win.addstr(hosts[h].num+1, 25, "%8s" % d, attr)
|
attr=0
|
||||||
win.addstr(hosts[h].num+1, 53, "%3s" % hosts[h].uppercent )
|
if verbose and hosts[h].state != Host.down:
|
||||||
if visual:
|
d=dur(now-hosts[h].lastbeat)
|
||||||
win.refresh()
|
if hosts[h].state == Host.OVERDUE:
|
||||||
stdscr.refresh()
|
attr=curses.A_BOLD
|
||||||
|
win.addstr(hosts[h].num+1, 25, "%8s" % d, attr)
|
||||||
|
win.addstr(hosts[h].num+1, 53, "%3s" % hosts[h].uppercent )
|
||||||
|
win.refresh()
|
||||||
|
stdscr.refresh()
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@@ -195,6 +198,7 @@ def displaybody():
|
|||||||
displaystatetime(h, 0)
|
displaystatetime(h, 0)
|
||||||
win.refresh()
|
win.refresh()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@@ -212,8 +216,7 @@ def displaymsgs():
|
|||||||
def display():
|
def display():
|
||||||
if visual:
|
if visual:
|
||||||
initwin()
|
initwin()
|
||||||
displaytime()
|
displaytime()
|
||||||
if visual:
|
|
||||||
displaybody()
|
displaybody()
|
||||||
displaymsgs()
|
displaymsgs()
|
||||||
|
|
||||||
@@ -239,10 +242,10 @@ def fromaddr(name, addr, boot):
|
|||||||
if not htab.has_key(addr):
|
if not htab.has_key(addr):
|
||||||
addhost(name, addr)
|
addhost(name, addr)
|
||||||
host=hosts[htab[addr]]
|
host=hosts[htab[addr]]
|
||||||
host.last=now
|
host.lastbeat=now
|
||||||
if host.getstate() != "up":
|
if host.getstate() != Host.up:
|
||||||
lasts=host.state
|
lasts=host.state
|
||||||
d=host.newstate("up")
|
d=host.newstate(Host.up)
|
||||||
log("%s, back after being %s for %s" % (host.name, lasts, dur(d)))
|
log("%s, back after being %s for %s" % (host.name, lasts, dur(d)))
|
||||||
host.upcount+=1
|
host.upcount+=1
|
||||||
|
|
||||||
@@ -280,24 +283,52 @@ def readsock():
|
|||||||
if boot:
|
if boot:
|
||||||
log("%s booted" % name)
|
log("%s booted" % name)
|
||||||
if msg:
|
if msg:
|
||||||
log("%s %s" % (name, msg),service=service)
|
log("%s msg: %s" % (name, msg),service=service)
|
||||||
fromaddr(name, addr[0], boot)
|
fromaddr(name, addr[0], boot)
|
||||||
if shutdown:
|
if shutdown:
|
||||||
log("%s shutdown" % name)
|
log("%s shutdown" % name)
|
||||||
hosts[name].newstate("down")
|
hosts[name].newstate(Host.down)
|
||||||
hosts[name].interval=interval
|
hosts[name].interval=interval
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
def dominute():
|
def updatestats():
|
||||||
global upcount
|
global upcount
|
||||||
upcount+=1
|
upcount+=1
|
||||||
|
|
||||||
for h in hosts:
|
for h in hosts:
|
||||||
if upcount > 0:
|
if upcount > 0:
|
||||||
hosts[h].uppercent="%3.0f" % ((hosts[h].upcount*hosts[h].interval*100.0)/(upcount*INTERVAL))
|
hosts[h].uppercent="%3.0f" % ((hosts[h].upcount*hosts[h].interval*100.0)/(upcount*INTERVAL))
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
def genhtml(now):
|
||||||
|
f=open("/home/andreas/public_html/private/watcharnsberg.html","w")
|
||||||
|
f.write("<html>")
|
||||||
|
f.write("<head>")
|
||||||
|
f.write("<meta http-equiv=Refresh content=%d>\n" % 10)
|
||||||
|
f.write("</head>")
|
||||||
|
f.write('<body BGCOLOR="#FFFFFF" LINK="#008000" VLINK="#008000" BACKGROUND="/~andreas/images/tile.marble.gif">')
|
||||||
|
f.write("<H2>Heartbeat status at %s</H2>" % time.strftime("%H:%M:%S", time.localtime(now)))
|
||||||
|
f.write("<table>")
|
||||||
|
f.write("<tr><th>Host</th><th>State</th><th>IP Addr</th><th>Res</th><th>Last change</th></tr>\n" )
|
||||||
|
for h in hosts:
|
||||||
|
f.write("<tr><td>%-24s</td><td>%-7s</td><td>%-16s</td><td>%-3s</td><td>%-17s</td></tr>\n" % (h, hosts[h].state, hosts[h].addr, hosts[h].uppercent, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(hosts[h].statetime))))
|
||||||
|
f.write("</table>")
|
||||||
|
f.write("<P>")
|
||||||
|
for m in msgs[len(msgs)-30:]:
|
||||||
|
f.write("%s<BR>" % m)
|
||||||
|
os.environ['SCRIPT_FILENAME']="/home/andreas/bin/watcharnsberg"
|
||||||
|
g=os.popen("/home/andreas/cgi-bin/trailer.py", "r")
|
||||||
|
o=g.readlines()
|
||||||
|
g.close()
|
||||||
|
f.write(string.join(o,""))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
def initcurses():
|
def initcurses():
|
||||||
@@ -312,12 +343,79 @@ def exitcurses():
|
|||||||
curses.nocbreak(); stdscr.keypad(0); curses.echo()
|
curses.nocbreak(); stdscr.keypad(0); curses.echo()
|
||||||
curses.endwin()
|
curses.endwin()
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
class HtmlHandler(SocketServer.BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
f=self.request.makefile()
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
line=string.strip(f.readline())
|
||||||
|
if len(line) == 0:
|
||||||
|
break
|
||||||
|
r=line.split()
|
||||||
|
if r[0] == "GET":
|
||||||
|
uri=r[1]
|
||||||
|
html=r[2]
|
||||||
|
if uri != "/":
|
||||||
|
code=404
|
||||||
|
cause="Not Found"
|
||||||
|
else:
|
||||||
|
code=200
|
||||||
|
cause="OK"
|
||||||
|
self.request.send("HTTP/1.0 %s %s\r\n" % (code, cause))
|
||||||
|
self.request.send("Date: %s\r\n" % time.strftime("%a, %d %b %Y %H:%M:%S GMT",time.gmtime(now)))
|
||||||
|
self.request.send("Server: WatchArnsberg\r\n")
|
||||||
|
self.request.send("Last-Modified: %s\r\n" % time.strftime("%a, %d %b %Y %H:%M:%S GMT",time.gmtime(now)))
|
||||||
|
self.request.send("Accept-Ranges: bytes\r\n")
|
||||||
|
self.request.send("Connection: close\r\n")
|
||||||
|
self.request.send("Content-Type: text/html; charset=ISO-8859-1\r\n\r\n")
|
||||||
|
res=[]
|
||||||
|
if code != 200:
|
||||||
|
res.append('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">')
|
||||||
|
res.append('<html><head>')
|
||||||
|
res.append('<title>%s %s</title>' % (code, cause))
|
||||||
|
res.append('</head><body>')
|
||||||
|
res.append('<h1>%s</h1>' % (cause))
|
||||||
|
res.append('<p>The requested URL %s was not found on this server.</p>' % uri)
|
||||||
|
res.append('<hr>')
|
||||||
|
res.append('<address>WatchArnsberg (Unix) Server at somewhere.planix.com Port %d</address>' % TPORT)
|
||||||
|
res.append('</body></html>')
|
||||||
|
|
||||||
|
else:
|
||||||
|
res.append('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">')
|
||||||
|
res.append("<html>")
|
||||||
|
res.append("<head>")
|
||||||
|
res.append("<meta http-equiv=Refresh content=%d>\n" % 60)
|
||||||
|
res.append("</head>")
|
||||||
|
res.append('<body BGCOLOR="#FFFFFF" LINK="#008000" VLINK="#008000" BACKGROUND="/~andreas/images/tile.marble.gif">')
|
||||||
|
res.append("<H2>Heartbeat status at %s</H2>" % time.strftime("%H:%M:%S", time.localtime(now)))
|
||||||
|
res.append("<table>")
|
||||||
|
res.append("<tr><th>Host</th><th>State</th><th>IP Addr</th><th>Res</th><th>Last change</th></tr>\n" )
|
||||||
|
for h in hosts:
|
||||||
|
res.append("<tr><td>%-24s</td><td>%-7s</td><td>%-16s</td><td>%-3s</td><td>%-17s</td></tr>\n" % (h, hosts[h].state, hosts[h].addr, hosts[h].uppercent, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(hosts[h].statetime))))
|
||||||
|
res.append("</table>")
|
||||||
|
res.append("<P>")
|
||||||
|
for m in msgs[len(msgs)-30:]:
|
||||||
|
res.append("%s<BR>" % m)
|
||||||
|
# os.environ['SCRIPT_FILENAME']="/home/andreas/bin/watcharnsberg"
|
||||||
|
# g=os.popen("/home/andreas/cgi-bin/trailer.py", "r")
|
||||||
|
# o=g.readlines()
|
||||||
|
# g.close()
|
||||||
|
# res.append(string.join(o,""))
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.request.send(string.join(res,"\n"))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Main
|
# Main
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
initlog()
|
initlog()
|
||||||
|
|
||||||
now=time.time()
|
now=time.time()
|
||||||
@@ -336,9 +434,11 @@ ilist=[]
|
|||||||
|
|
||||||
sock=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
sock.bind(("",PORT))
|
sock.bind(("",PORT))
|
||||||
|
|
||||||
ilist.append(sock)
|
ilist.append(sock)
|
||||||
|
|
||||||
|
serv=SocketServer.TCPServer((THOST,TPORT),HtmlHandler)
|
||||||
|
ilist.append(serv.fileno())
|
||||||
|
|
||||||
next=int(now)+1
|
next=int(now)+1
|
||||||
sleep=next - now
|
sleep=next - now
|
||||||
while 1:
|
while 1:
|
||||||
@@ -358,7 +458,9 @@ while 1:
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except select.error, value:
|
except select.error, value:
|
||||||
if value[0] != 4: # interrupted system call
|
if value[0] != 4: # interrupted system call
|
||||||
raise os.error, value
|
print select.error, value
|
||||||
|
#raise os.error, value
|
||||||
|
continue
|
||||||
if visual:
|
if visual:
|
||||||
exitcurses()
|
exitcurses()
|
||||||
initcurses()
|
initcurses()
|
||||||
@@ -367,18 +469,23 @@ while 1:
|
|||||||
for fh in sr[0]:
|
for fh in sr[0]:
|
||||||
if fh == sock:
|
if fh == sock:
|
||||||
readsock()
|
readsock()
|
||||||
|
if fh == serv.fileno():
|
||||||
|
serv.handle_request()
|
||||||
if now >= next:
|
if now >= next:
|
||||||
next+=1
|
next=now+1
|
||||||
if int(now) % INTERVAL == startsec:
|
if int(now) % INTERVAL == startsec:
|
||||||
dominute()
|
updatestats()
|
||||||
|
## if int(now) % 60 == 0:
|
||||||
|
## genhtml(now)
|
||||||
|
checkoverdue()
|
||||||
if visual:
|
if visual:
|
||||||
# stdscr.addstr(1 , 0, "Now is %s, Next is %s" % (now, next))
|
stdscr.move(1 , 0)
|
||||||
if DEBUG:
|
stdscr.clrtoeol()
|
||||||
stdscr.addstr(1 , 0, "len(htab) is %s, Next is %s" % (len(htab), next))
|
displaytime()
|
||||||
else:
|
|
||||||
stdscr.move(1 , 0)
|
|
||||||
stdscr.clrtoeol()
|
|
||||||
displaytime()
|
|
||||||
sleep=next-now
|
sleep=next-now
|
||||||
|
if sleep < 0:
|
||||||
|
sys.stderr.write("sleep is negaitive! %s next=%s\n" % (sleep, next))
|
||||||
|
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))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user