234 lines
4.7 KiB
Python
234 lines
4.7 KiB
Python
|
|
"""
|
|
host and connection class shared between hbd and
|
|
the websit's heartbeat.py
|
|
|
|
"""
|
|
|
|
import time
|
|
import json
|
|
|
|
# Table of Hosts
|
|
hosts = {}
|
|
# map of addrs to names
|
|
htab = {}
|
|
|
|
|
|
def isIPv4(addr):
|
|
return addr.find('.') > 0
|
|
|
|
|
|
|
|
class Connection:
|
|
def __init__(self, name, cid, addr):
|
|
self.name = name
|
|
self.cid = cid
|
|
self.addr = addr
|
|
self.rtts = [0]
|
|
|
|
def jsons(self):
|
|
return(json.dumps(self.__dict__))
|
|
|
|
|
|
class Host:
|
|
up = "up"
|
|
down = "down"
|
|
overdue = "overdue"
|
|
|
|
|
|
def __init__(self, name):
|
|
global num
|
|
self.name = name
|
|
self.addr4 = None
|
|
self.addr6 = None
|
|
self.num = num
|
|
self.lastbeat = time.time()
|
|
self.upcount = 0
|
|
self.state = Host.up
|
|
self.state = "up"
|
|
self.statetime = self.lastbeat
|
|
self.interval = 0
|
|
self.doesack = -1
|
|
self.cmds = []
|
|
self.cver = 0
|
|
self.connections = {}
|
|
self.latency = 0
|
|
self.hdwcounts = [[0,0],[0,0],[0,0]]
|
|
num += 1
|
|
hosts[name] = self
|
|
|
|
|
|
def jsons(self):
|
|
ddict = {}
|
|
for d in self.__dict__:
|
|
if d == 'connections':
|
|
cl = []
|
|
for c in self.connections:
|
|
cl.append(self.connections[c].__dict__)
|
|
ddict[d] = cl
|
|
else:
|
|
ddict[d] = self.__dict__[d]
|
|
return json.dumps(ddict)
|
|
|
|
|
|
def setcver(self, cver):
|
|
self.cver = cver
|
|
|
|
|
|
def isDynDns(self):
|
|
return self.name in dyndnshosts
|
|
|
|
|
|
def newaddr(self, addr):
|
|
if isIPv4(addr):
|
|
if self.addr4:
|
|
if self.addr4 == addr:
|
|
r = None
|
|
else:
|
|
r = "changed from %s to %s" % (self.addr4, addr)
|
|
del htab[self.addr4]
|
|
self.addr4 = addr
|
|
htab[addr] = self.name
|
|
if self.isDynDns():
|
|
dnsQ.put((self.name, self.addr4))
|
|
else:
|
|
r = "new addr %s" % (addr)
|
|
self.addr4 = addr
|
|
htab[addr] = self.name
|
|
if self.isDynDns():
|
|
dnsQ.put((self.name, self.addr4))
|
|
else:
|
|
if self.addr6:
|
|
if self.addr6 == addr:
|
|
r = None
|
|
else:
|
|
r = "changed from %s to %s" % (self.addr6, addr)
|
|
del htab[self.addr6]
|
|
self.addr6 = addr
|
|
htab[addr] = self.name
|
|
if self.isDynDns():
|
|
dnsQ.put((self.name, self.addr6))
|
|
else:
|
|
r = "new addr %s" % (addr)
|
|
self.addr6 = addr
|
|
htab[addr] = self.name
|
|
if self.isDynDns():
|
|
dnsQ.put((self.name, self.addr6))
|
|
return r
|
|
|
|
|
|
# called when reloading class from pickle, add new fields here
|
|
def fixup(self):
|
|
try:
|
|
a=self.cmds
|
|
except:
|
|
self.cmds=[]
|
|
|
|
try:
|
|
a=self.hdwcounts
|
|
except:
|
|
self.hdwcounts = [[self.doesack,self.upcount],[self.doesack,self.upcount],[self.doesack,self.upcount]]
|
|
|
|
try:
|
|
self.addr=self.addr4
|
|
except:
|
|
pass
|
|
try:
|
|
self.addr=self.addr6
|
|
except:
|
|
pass
|
|
|
|
|
|
try:
|
|
a=self.addr4
|
|
a=self.addr6
|
|
except:
|
|
print "fix %s: addr to addr4/6 fixup" % self.name
|
|
if isIPv4(self.addr):
|
|
self.addr4 = self.addr
|
|
self.addr6 = None
|
|
else:
|
|
self.addr4 = None
|
|
self.addr6 = self.addr
|
|
del self.addr
|
|
|
|
try:
|
|
a=self.latency
|
|
except:
|
|
self.latency = 0
|
|
|
|
try:
|
|
a=self.cver
|
|
except:
|
|
self.cver = 0
|
|
|
|
try:
|
|
a=self.connections
|
|
a.append([])
|
|
except:
|
|
self.connections={}
|
|
|
|
|
|
def getstate(self):
|
|
return self.state
|
|
|
|
|
|
def dispstate(self):
|
|
if self.state in ["down", "overdue"]:
|
|
state = "<b>%s</b>" % self.state
|
|
elif self.state in ["up", "UP"]:
|
|
state = ""
|
|
for x in self.connections.keys():
|
|
try:
|
|
state += " %5.1f" % (self.connections[x].rtts[-1])
|
|
except:
|
|
state += " %5s" % (self.connections[x].rtts[-1])
|
|
else:
|
|
state = "%s" % self.state
|
|
return state
|
|
|
|
|
|
def dispstats(self):
|
|
if self.doesack != -1:
|
|
if self.upcount > 0:
|
|
# return "(%0.1f%%) %s %s %s " % ((self.doesack * 100.0) / self.upcount, self.doesack, self.upcount, self.hdwcounts)
|
|
r = ""
|
|
for v in xrange(3):
|
|
a,u = self.hdwcounts[v]
|
|
if (self.upcount - u) != 0:
|
|
vs = "%0.0f" % (100.0 - (((self.doesack - a) * 100.0) / (self.upcount - u)))
|
|
if vs == "0":
|
|
vs=""
|
|
else:
|
|
vs="-"
|
|
r+= '<td align="right">%s</td>' % vs
|
|
return r
|
|
else:
|
|
return "<td>(%s)</td><td></td><td></td>" % (self.doesack)
|
|
return '<td align="right">N/A</td><td></td<td></td>>'
|
|
|
|
|
|
def htmldisp(self, header=False):
|
|
if header:
|
|
return "<tr><th>Host</th><th>State</th><th>Hr</th><th>Dy</th><th>Wk</th><th>IP4 Addr</th><th>IP6 Addr</th><th>Last change</th><th>Ver</th></tr>\n"
|
|
|
|
else:
|
|
ipv4addr = self.addr4 if self.addr4 else ""
|
|
ipv6addr = self.addr6 if self.addr6 else ""
|
|
lastts = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.statetime))
|
|
return "<tr><td>%-24s</td><td>%-7s</td>%s<td>%-16s</td><td>%-16s</td><td>%-17s</td><td>%s</td></tr>\n" % \
|
|
(self.name, self.dispstate(), self.dispstats(), ipv4addr, ipv6addr, lastts, self.cver)
|
|
|
|
|
|
|
|
# set new state, return number of secs in previous state
|
|
def newstate(self, state, when=0):
|
|
self.state = state
|
|
now = time.time()-when
|
|
s = now-self.statetime
|
|
self.statetime = now
|
|
return s
|
|
|
|
|
|
|