part 2 of redo: state is in connections
This commit is contained in:
+168
-130
@@ -8,55 +8,159 @@ the websit's heartbeat.py
|
||||
import time
|
||||
import json
|
||||
|
||||
# Table of Hosts
|
||||
hosts = {}
|
||||
# map of addrs to names
|
||||
htab = {}
|
||||
num = 0
|
||||
|
||||
MAXRTTS = 10
|
||||
|
||||
def isIPv4(addr):
|
||||
return addr.find('.') > 0
|
||||
|
||||
|
||||
|
||||
#
|
||||
class Connection:
|
||||
def __init__(self, name, cid, addr):
|
||||
self.name = name
|
||||
# map of addrs to names
|
||||
|
||||
htab = {}
|
||||
up = "up"
|
||||
down = "down"
|
||||
overdue = "overdue"
|
||||
|
||||
def __init__(self, host, cid, addr, afam):
|
||||
self.host = host
|
||||
self.cid = cid
|
||||
self.addr = addr
|
||||
self.afam = afam
|
||||
self.rtts = [0]
|
||||
self.lastbeat = time.time()
|
||||
self.statetime = self.lastbeat
|
||||
self.state = Connection.up
|
||||
|
||||
if host:
|
||||
r = "new addr %s" % (addr)
|
||||
Connection.htab[addr] = self.host.name
|
||||
if self.host.isDynDns():
|
||||
dnsQ.put((self.host.name, self.addr))
|
||||
|
||||
|
||||
def statedict(self, Null=False):
|
||||
d = {}
|
||||
if not Null:
|
||||
d['addr'] = self.addr
|
||||
if self.rtts[-1]:
|
||||
d['rtt'] = "%0.1f" % self.rtts[-1]
|
||||
else:
|
||||
d['rtt'] = ""
|
||||
d['lastbeat'] = self.lastbeat
|
||||
if self.state == Connection.overdue:
|
||||
d['state'] = "<b>%s</b>" % self.state
|
||||
else:
|
||||
d['state'] = self.state
|
||||
d['statetime'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.statetime))
|
||||
|
||||
else:
|
||||
d['addr'] = ''
|
||||
d['rtt'] = ""
|
||||
d['lastbeat'] = ''
|
||||
d['state'] = ''
|
||||
d['statetime'] = ''
|
||||
return d
|
||||
|
||||
|
||||
def headerdict(self, afam):
|
||||
d = {}
|
||||
d['addr'] = '%s Addr' % afam
|
||||
d['rtt'] = 'Latencey'
|
||||
d['lastbeat'] = 'Last Contact'
|
||||
d['state'] = 'State'
|
||||
d['statetime'] = 'Last State'
|
||||
return d
|
||||
|
||||
|
||||
def jsons(self):
|
||||
return(json.dumps(self.__dict__))
|
||||
|
||||
|
||||
class Host:
|
||||
up = "up"
|
||||
down = "down"
|
||||
overdue = "overdue"
|
||||
# set new state, return number of secs in previous state
|
||||
def newstate(self, state, now, when=0):
|
||||
self.state = state
|
||||
delta = now - when
|
||||
s = delta - self.statetime
|
||||
self.statetime = delta
|
||||
return s
|
||||
|
||||
|
||||
def getstate(self):
|
||||
return self.state
|
||||
|
||||
|
||||
def newaddr(self, addr, rtt, now):
|
||||
self.lastbeat = now
|
||||
self.rtts.append(rtt)
|
||||
if len(self.rtts) > MAXRTTS:
|
||||
del self.rtts[0]
|
||||
|
||||
if self.addr == addr:
|
||||
r = None
|
||||
else:
|
||||
r = "changed from %s to %s" % (self.addr, addr)
|
||||
try:
|
||||
del Connection.htab[self.addr]
|
||||
except:
|
||||
pass
|
||||
self.addr = addr
|
||||
Connection.htab[addr] = self.host.name
|
||||
if self.host.isDynDns():
|
||||
dnsQ.put((self.host.name, self.addr))
|
||||
return r
|
||||
|
||||
|
||||
#
|
||||
class Host:
|
||||
# Table of Hosts
|
||||
hosts = {}
|
||||
|
||||
def __init__(self, name):
|
||||
global num
|
||||
self.name = name
|
||||
self.addr4 = None
|
||||
self.addr6 = None
|
||||
self.num = num
|
||||
self.lastbeat = time.time()
|
||||
self.dyn = False
|
||||
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
|
||||
if name:
|
||||
num += 1
|
||||
Host.hosts[name] = self
|
||||
|
||||
|
||||
def statedict(self):
|
||||
d = {}
|
||||
d['name'] = self.name
|
||||
d['dyn'] = str(self.dyn)
|
||||
d['ver'] = str(self.cver)
|
||||
d['num'] = self.num
|
||||
for c in ['IPv4', 'IPv6']:
|
||||
if c in self.connections:
|
||||
cs = self.connections[c].statedict()
|
||||
else:
|
||||
cs = ubConnection.statedict(True)
|
||||
for csv in cs:
|
||||
d['%s.%s' % (c, csv) ] = cs[csv]
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def headerdict(self):
|
||||
d = {}
|
||||
d['name'] = 'Name'
|
||||
d['dyn'] = 'Dyn'
|
||||
d['ver'] = 'Ver'
|
||||
d['num'] = '??'
|
||||
for c in ['IPv4', 'IPv6']:
|
||||
cs = ubConnection.headerdict(c)
|
||||
for csv in cs:
|
||||
d['%s.%s' % (c, csv) ] = cs[csv]
|
||||
return d
|
||||
|
||||
|
||||
|
||||
def jsons(self):
|
||||
@@ -77,101 +181,33 @@ class Host:
|
||||
|
||||
|
||||
def isDynDns(self):
|
||||
return self.name in dyndnshosts
|
||||
return self.dyn
|
||||
|
||||
|
||||
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))
|
||||
def isIPv4(self, addr):
|
||||
if type(addr) == type(()):
|
||||
return addr[0].find('.') > 0
|
||||
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
|
||||
return addr.find('.') > 0
|
||||
|
||||
|
||||
def conndata(self, cid, addr, rtt, now):
|
||||
if self.isIPv4(addr):
|
||||
afam = "IPv4"
|
||||
else:
|
||||
afam = "IPv6"
|
||||
|
||||
if afam not in self.connections:
|
||||
self.connections[afam] = Connection(self, cid, addr, afam)
|
||||
|
||||
conn = self.connections[afam]
|
||||
res = conn.newaddr(addr, rtt, now)
|
||||
return conn, res
|
||||
|
||||
|
||||
# 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
|
||||
pass
|
||||
|
||||
|
||||
def dispstate(self):
|
||||
@@ -209,26 +245,28 @@ class Host:
|
||||
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"
|
||||
hostfields = ['name', 'IPv4.addr', 'IPv4.state', 'IPv4.rtt', 'IPv4.statetime', 'IPv6.addr', 'IPv6.state', 'IPv6.rtt', 'IPv6.statetime', 'ver']
|
||||
def htmlheaders(self):
|
||||
h = []
|
||||
hd = ubHost.headerdict()
|
||||
for f in Host.hostfields:
|
||||
h.append(hd[f])
|
||||
return "<tr><th>"+"</th><th>".join(h)+"</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)
|
||||
|
||||
def htmldisp(self):
|
||||
h = []
|
||||
hd = self.statedict()
|
||||
for f in Host.hostfields:
|
||||
h.append(hd[f])
|
||||
return "<tr><td>"+"</td><td>".join(h)+"</td></tr>\n"
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# create fake "unbound objects", remove in Python 3.0
|
||||
ubHost = Host(None)
|
||||
ubConnection = Connection(None, "", "", "")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user