part 2 of redo: state is in connections
This commit is contained in:
@@ -37,7 +37,6 @@ SEND_PUSHOVER=True
|
|||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
|
|
||||||
MAXRECV = 32767
|
MAXRECV = 32767
|
||||||
MAXRTTS = 10
|
|
||||||
LOGFILE = "/home/andreas/public_html/messages/andreas"
|
LOGFILE = "/home/andreas/public_html/messages/andreas"
|
||||||
PICKFILE = "/var/tmp/hbd.pick"
|
PICKFILE = "/var/tmp/hbd.pick"
|
||||||
AEMAIL = ["andreas@wrede.ca"]
|
AEMAIL = ["andreas@wrede.ca"]
|
||||||
@@ -66,6 +65,10 @@ tcss = """<script src="https://home.wrede.ca/pr/sorttable.js"></script>
|
|||||||
<style>
|
<style>
|
||||||
#ntable {
|
#ntable {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wide-ntable {
|
||||||
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,11 +265,11 @@ def dur(sec):
|
|||||||
|
|
||||||
|
|
||||||
def fixsort():
|
def fixsort():
|
||||||
s = hosts.keys()
|
s = Host.hosts.keys()
|
||||||
s.sort()
|
s.sort()
|
||||||
x = 0
|
x = 0
|
||||||
for n in s:
|
for n in s:
|
||||||
hosts[n].num = x
|
Host.hosts[n].num = x
|
||||||
x += 1
|
x += 1
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -290,17 +293,22 @@ def initlog(logfile):
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
def checkoverdue():
|
def checkoverdue():
|
||||||
|
now = time.time()
|
||||||
for h in hosts.keys():
|
for h in Host.hosts.keys():
|
||||||
if hosts[h].state == Host.down:
|
pmsg = []
|
||||||
|
for c in Host.hosts[h].connections:
|
||||||
|
conn = Host.hosts[h].connections[c]
|
||||||
|
if conn.state == Connection.down:
|
||||||
continue
|
continue
|
||||||
timeout = hosts[h].interval+grace
|
timeout = Host.hosts[h].interval + grace
|
||||||
if hosts[h].state == Host.up and now-hosts[h].lastbeat > timeout:
|
if conn.state == Connection.up and (now - conn.lastbeat) > timeout:
|
||||||
|
conn.newstate(Connection.overdue, now, grace)
|
||||||
|
pmsg.append(conn.afam)
|
||||||
|
if pmsg != []:
|
||||||
if h in watchhosts:
|
if h in watchhosts:
|
||||||
email("overdue", "%s is overdue" % h)
|
email("overdue", "%s overdue" % ",".join(pmsg))
|
||||||
pushover("%s is overdue" % h)
|
pushover("%s %s overdue" % (h, join(pmsg)))
|
||||||
hosts[h].newstate(Host.overdue, grace)
|
lof(h, "%s overdue" % join(pmsg))
|
||||||
log(h, "overdue")
|
|
||||||
|
|
||||||
|
|
||||||
def log(host, m, service=None):
|
def log(host, m, service=None):
|
||||||
@@ -344,10 +352,11 @@ def dnsupdatethread():
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
def readsock(sock):
|
def readsock(sock):
|
||||||
|
global now
|
||||||
if DEBUG > 3: sys.stderr.write("readsock recfrom start")
|
if DEBUG > 3: sys.stderr.write("readsock recfrom start")
|
||||||
data, addr = sock.recvfrom(MAXRECV)
|
data, addrp = sock.recvfrom(MAXRECV)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if DEBUG > 2: sys.stderr.write("readsock = %s, %s\n" % (data,addr))
|
if DEBUG > 2: sys.stderr.write("readsock = %s, %s\n" % (data,addrp))
|
||||||
msg = stodict(data)
|
msg = stodict(data)
|
||||||
if not msg: # Old hbc client
|
if not msg: # Old hbc client
|
||||||
if verbose: print "old hbc:", data
|
if verbose: print "old hbc:", data
|
||||||
@@ -355,35 +364,30 @@ def readsock(sock):
|
|||||||
msg = oldmtodict(data)
|
msg = oldmtodict(data)
|
||||||
else:
|
else:
|
||||||
oldclient = False
|
oldclient = False
|
||||||
if verbose: print "readsock = %s, %s" % (msg,addr)
|
if verbose: print "readsock = %s, %s" % (msg,addrp)
|
||||||
|
|
||||||
|
addr = addrp[0:2]
|
||||||
name = shortname(msg.get('name', "unknown"))
|
name = shortname(msg.get('name', "unknown"))
|
||||||
if not name in hosts: # was: hosts.has_key(name):
|
if not name in Host.hosts: # was: hosts.has_key(name):
|
||||||
host = Host(name)
|
host = Host(name)
|
||||||
|
if verbose: print "XX: New host, num now %s" % (len(Host.hosts))
|
||||||
newh=True
|
newh=True
|
||||||
else:
|
else:
|
||||||
host = hosts[name]
|
host = Host.hosts[name]
|
||||||
newh=False
|
newh=False
|
||||||
|
|
||||||
cid = msg.get('id', 0)
|
cid = msg.get('id', 0)
|
||||||
if cid not in host.connections:
|
rtt = msg.get('rtt',None)
|
||||||
host.connections[cid] = Connection(name, cid, addr)
|
|
||||||
conn = host.connections[cid]
|
|
||||||
|
|
||||||
if msg['ID'] == 'HTB':
|
if msg['ID'] == 'HTB':
|
||||||
host.doesack = msg.get('acks', -1)
|
host.doesack = msg.get('acks', -1)
|
||||||
host.lastbeat = now
|
|
||||||
host.setcver(msg.get('ver', 0))
|
host.setcver(msg.get('ver', 0))
|
||||||
|
|
||||||
interval = msg.get('interval', 0)
|
interval = int(msg.get('interval', 0))
|
||||||
shutdown = msg.get('shutdown', 0)
|
shutdown = msg.get('shutdown', 0)
|
||||||
service = msg.get('service', "unknown")
|
service = msg.get('service', "unknown")
|
||||||
message = msg.get('msg', None)
|
message = msg.get('msg', None)
|
||||||
boot = msg.get('boot', 0)
|
boot = msg.get('boot', 0)
|
||||||
host.latency = now - msg.get('time', 0)
|
|
||||||
rtt = msg.get('rtt',"up")
|
|
||||||
conn.rtts.append(rtt)
|
|
||||||
if len(conn.rtts) > MAXRTTS:
|
|
||||||
del conn.rtts[0]
|
|
||||||
|
|
||||||
if boot:
|
if boot:
|
||||||
log(name, "booted")
|
log(name, "booted")
|
||||||
@@ -396,21 +400,22 @@ def readsock(sock):
|
|||||||
email("msg", message)
|
email("msg", message)
|
||||||
pushover(message)
|
pushover(message)
|
||||||
|
|
||||||
res = host.newaddr(addr[0])
|
conn, res = host.conndata(cid, addr[0], rtt, now)
|
||||||
if res:
|
if res:
|
||||||
log(name, res)
|
log(name, res)
|
||||||
if name in watchhosts:
|
if name in watchhosts:
|
||||||
email("address change", "%s %s" % (host.name, res))
|
email("address change", "%s %s" % (host.name, res))
|
||||||
pushover("%s %s" % (host.name, res))
|
pushover("%s %s" % (host.name, res))
|
||||||
|
|
||||||
if host.getstate() != Host.up and interval > 0:
|
if conn.getstate() != Connection.up and interval > 0:
|
||||||
lasts = host.state
|
lasts = conn.state
|
||||||
d = host.newstate(Host.up)
|
d = conn.newstate(Connection.up, now)
|
||||||
m = "back after being %s for %s" % (lasts, dur(d))
|
m = "%s back after being %s for %s" % (conn.afam, lasts, dur(d))
|
||||||
log(name, m)
|
log(name, m)
|
||||||
if name in watchhosts:
|
if name in watchhosts:
|
||||||
email("back", name)
|
email("%s back" % conn.afam, name)
|
||||||
pushover("%s is back" % name)
|
pushover("%s %s is back" % (name, conn.afam))
|
||||||
|
|
||||||
if boot or newh:
|
if boot or newh:
|
||||||
host.upcount = host.doesack
|
host.upcount = host.doesack
|
||||||
else:
|
else:
|
||||||
@@ -418,19 +423,14 @@ def readsock(sock):
|
|||||||
|
|
||||||
|
|
||||||
if shutdown:
|
if shutdown:
|
||||||
log(name, "shutdown")
|
log(name, "%s shutdown" % conn.afam)
|
||||||
if name in watchhosts:
|
if name in watchhosts:
|
||||||
email("shutdown", "%s shutdown" % name)
|
email("shutdown", "%s %s shutdown" % (name, conn.afam))
|
||||||
pushover("%s hbc shutdown" % name)
|
pushover("%s %s shutdown" % (name, conn.afam))
|
||||||
try:
|
conn.newstate(Connection.down, now)
|
||||||
host.newstate(Host.down)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if interval > 0:
|
if interval > 0:
|
||||||
try:
|
|
||||||
host.interval = interval
|
host.interval = interval
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
rmsg = {'time': time.time()}
|
rmsg = {'time': time.time()}
|
||||||
op = 'ACK'
|
op = 'ACK'
|
||||||
@@ -487,7 +487,7 @@ def updatecode(ucode, uname):
|
|||||||
m.update(new_code)
|
m.update(new_code)
|
||||||
icsum = m.hexdigest()
|
icsum = m.hexdigest()
|
||||||
rmsg = {'csum': icsum, 'code': new_code.encode('base64','strict') }
|
rmsg = {'csum': icsum, 'code': new_code.encode('base64','strict') }
|
||||||
hosts[uname].cmds.append(('UPD',rmsg))
|
Host.hosts[uname].cmds.append(('UPD',rmsg))
|
||||||
return fail
|
return fail
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@@ -535,20 +535,22 @@ class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
def buildpage(self):
|
def buildpage(self):
|
||||||
res=self.buildhead(refresh=60, extras=tcss)
|
res=self.buildhead(refresh=60, extras=tcss)
|
||||||
res.append("<H2>Heartbeat status %s</h2><h4> %s (%s)</H4>" % (VER, time.strftime("%H:%M:%S", time.localtime(now)), os.environ.get('TZ', 'CET-1CDT')))
|
res.append("<H2>Heartbeat status %s</h2>" % VER)
|
||||||
|
|
||||||
res.append('<table id="ntable" class="sortable">')
|
res.append('<table id="ntable" class="sortable">')
|
||||||
hosts_sorted = hosts.keys()
|
res.append(ubHost.htmlheaders())
|
||||||
|
hosts_sorted = Host.hosts.keys()
|
||||||
|
if len(hosts_sorted):
|
||||||
hosts_sorted.sort()
|
hosts_sorted.sort()
|
||||||
res.append(hosts[hosts_sorted[0]].htmldisp(True))
|
|
||||||
for h in hosts_sorted:
|
for h in hosts_sorted:
|
||||||
res.append(hosts[h].htmldisp())
|
res.append(Host.hosts[h].htmldisp())
|
||||||
res.append("</table>")
|
res.append("</table>")
|
||||||
|
|
||||||
le = max(40 - len(hosts), 3)
|
le = max(40 - len(Host.hosts), 3)
|
||||||
res.append("<h4>Log of Events</h4>")
|
res.append("<h4>Log of Events</h4>")
|
||||||
for m in msgs[len(msgs)-le:]:
|
for m in msgs[len(msgs)-le:]:
|
||||||
res.append("%s<BR>" % m)
|
res.append("%s<BR>" % m)
|
||||||
|
res.append('<p> %s (%s)</p>' % (time.strftime("%H:%M:%S", time.localtime(now)), os.environ.get('TZ', 'CET-1CDT')))
|
||||||
res.append("</body></html>")
|
res.append("</body></html>")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -597,9 +599,9 @@ class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
uname=uarg[0][2:]
|
uname=uarg[0][2:]
|
||||||
if uarg[1][:2] == "c=":
|
if uarg[1][:2] == "c=":
|
||||||
ucmd=uarg[1][2:]
|
ucmd=uarg[1][2:]
|
||||||
if ucmd != "" and uname != "" and hosts.has_key(uname):
|
if ucmd != "" and uname != "" and Host.hosts.has_key(uname):
|
||||||
rmsg = {'cmd': urllib.unquote(ucmd)}
|
rmsg = {'cmd': urllib.unquote(ucmd)}
|
||||||
hosts[uname].cmds.append(('CMD', rmsg))
|
Host.hosts[uname].cmds.append(('CMD', rmsg))
|
||||||
res=self.buildhead()
|
res=self.buildhead()
|
||||||
res.append("2Done")
|
res.append("2Done")
|
||||||
else:
|
else:
|
||||||
@@ -615,9 +617,9 @@ class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
else:
|
else:
|
||||||
if uarg[0][:2] == "h=":
|
if uarg[0][:2] == "h=":
|
||||||
uname=uarg[0][2:]
|
uname=uarg[0][2:]
|
||||||
if uname != "" and hosts.has_key(uname):
|
if uname != "" and Host.hosts.has_key(uname):
|
||||||
log(uname, "dropped")
|
log(uname, "dropped")
|
||||||
del hosts[uname]
|
del Host.hosts[uname]
|
||||||
res=self.buildhead()
|
res=self.buildhead()
|
||||||
res.append("Done")
|
res.append("Done")
|
||||||
|
|
||||||
@@ -630,8 +632,8 @@ class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
res=self.buildhead()
|
res=self.buildhead()
|
||||||
if uarg[0][:2] == "h=":
|
if uarg[0][:2] == "h=":
|
||||||
uname=uarg[0][2:]
|
uname=uarg[0][2:]
|
||||||
if uname != "" and hosts.has_key(uname):
|
if uname != "" and Host.hosts.has_key(uname):
|
||||||
err = nsupdate(uname, hosts[uname].addr)
|
err = nsupdate(uname, Host.hosts[uname].addr)
|
||||||
ll="nsupdate request: %s" % err
|
ll="nsupdate request: %s" % err
|
||||||
else:
|
else:
|
||||||
ll="name %s not found" % uname
|
ll="name %s not found" % uname
|
||||||
@@ -650,7 +652,7 @@ class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
uname=uarg[0][2:]
|
uname=uarg[0][2:]
|
||||||
if uarg[1][:2] == "c=":
|
if uarg[1][:2] == "c=":
|
||||||
ucode=uarg[1][2:]
|
ucode=uarg[1][2:]
|
||||||
if ucode != "" and uname != "" and hosts.has_key(uname):
|
if ucode != "" and uname != "" and Host.hosts.has_key(uname):
|
||||||
err = updatecode(ucode, urllib.unquote(uname))
|
err = updatecode(ucode, urllib.unquote(uname))
|
||||||
res=self.buildhead()
|
res=self.buildhead()
|
||||||
res.append("3 Done: %s" % err if err else "OK")
|
res.append("3 Done: %s" % err if err else "OK")
|
||||||
@@ -664,8 +666,8 @@ class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
elif upar[0] == "/api/0/hosts": # api access to host table
|
elif upar[0] == "/api/0/hosts": # api access to host table
|
||||||
headerdict = {"Content-Type": "application/json; charset=utf-8" }
|
headerdict = {"Content-Type": "application/json; charset=utf-8" }
|
||||||
l=[]
|
l=[]
|
||||||
for h in hosts:
|
for h in Host.hosts:
|
||||||
l.append(hosts[h].jsons())
|
l.append(Host.hosts[h].jsons())
|
||||||
res=["[",",".join(l),"]"]
|
res=["[",",".join(l),"]"]
|
||||||
elif upar[0] == "/api/0/messages": # api access to host table
|
elif upar[0] == "/api/0/messages": # api access to host table
|
||||||
headerdict = {"Content-Type": "application/json; charset=utf-8" }
|
headerdict = {"Content-Type": "application/json; charset=utf-8" }
|
||||||
@@ -739,7 +741,7 @@ def closeup():
|
|||||||
|
|
||||||
|
|
||||||
def restart():
|
def restart():
|
||||||
print "execv %s %s" % (sys.argv[0], [sys.argv[0]]+cmdargs)
|
if verbose: print "execv %s %s" % (sys.argv[0], [sys.argv[0]]+cmdargs)
|
||||||
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
|
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
|
||||||
print "should not be here"
|
print "should not be here"
|
||||||
|
|
||||||
@@ -749,10 +751,9 @@ def saveandrestart():
|
|||||||
|
|
||||||
|
|
||||||
def pickleit():
|
def pickleit():
|
||||||
pickf = open(PICKFILE, 'w')
|
pickf = open(pickfile, 'w')
|
||||||
pick = cPickle.Pickler(pickf)
|
pick = cPickle.Pickler(pickf)
|
||||||
pick.dump(hosts)
|
pick.dump(Host.hosts)
|
||||||
pick.dump(htab)
|
|
||||||
pick.dump(msgs)
|
pick.dump(msgs)
|
||||||
pick.dump(lastfm)
|
pick.dump(lastfm)
|
||||||
pickf.close()
|
pickf.close()
|
||||||
@@ -820,6 +821,7 @@ grace = 2
|
|||||||
hb_port = PORT
|
hb_port = PORT
|
||||||
hbd_host = THOST
|
hbd_host = THOST
|
||||||
hbd_port = TPORT
|
hbd_port = TPORT
|
||||||
|
pickfile = PICKFILE
|
||||||
logfile = LOGFILE
|
logfile = LOGFILE
|
||||||
logfmt = "text"
|
logfmt = "text"
|
||||||
interval = INTERVAL
|
interval = INTERVAL
|
||||||
@@ -844,26 +846,30 @@ if f:
|
|||||||
if verbose:
|
if verbose:
|
||||||
print " %s" % l[:-1]
|
print " %s" % l[:-1]
|
||||||
r = l[:-1].split('=')
|
r = l[:-1].split('=')
|
||||||
if r[0] == 'interval':
|
o = r[0].strip()
|
||||||
interval = eval(r[1])
|
a = eval(r[1].strip())
|
||||||
elif r[0] == 'grace':
|
if o == 'interval':
|
||||||
grace = eval(r[1])
|
interval = a
|
||||||
elif r[0] == 'hbd_port':
|
elif o == 'grace':
|
||||||
hbd_port = eval(r[1])
|
grace = a
|
||||||
elif r[0] == 'hbd_host':
|
elif o == 'hbd_port':
|
||||||
hbd_host = eval(r[1])
|
hbd_port = a
|
||||||
elif r[0] == 'hb_port':
|
elif o == 'hbd_host':
|
||||||
hb_port = eval(r[1])
|
hbd_host = a
|
||||||
elif r[0] == 'logfile':
|
elif o == 'pickfile':
|
||||||
logfile = eval(r[1])
|
pickfile = a
|
||||||
elif r[0] == 'logfmt':
|
elif o == 'hb_port':
|
||||||
logfmt = eval(r[1])
|
hb_port = a
|
||||||
elif r[0] == 'watchhosts':
|
elif o == 'logfile':
|
||||||
watchhosts = eval(r[1])
|
logfile = a
|
||||||
elif r[0] == 'dyndnshosts':
|
elif o == 'logfmt':
|
||||||
dyndnshosts = eval(r[1])
|
logfmt = a
|
||||||
elif r[0] == 'drophosts':
|
elif o == 'watchhosts':
|
||||||
drophosts = eval(r[1])
|
watchhosts = a
|
||||||
|
elif o == 'dyndnshosts':
|
||||||
|
dyndnshosts = a
|
||||||
|
elif o == 'drophosts':
|
||||||
|
drophosts = a
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
if len(args) != 0:
|
if len(args) != 0:
|
||||||
@@ -875,12 +881,12 @@ if verbose:
|
|||||||
print "notice: logging to %s" % logfile
|
print "notice: logging to %s" % logfile
|
||||||
logf = initlog(logfile)
|
logf = initlog(logfile)
|
||||||
|
|
||||||
if os.path.exists(PICKFILE):
|
if 1 and os.path.exists(pickfile):
|
||||||
pickf = open(PICKFILE, 'r')
|
if verbose: print "opening pickls %s" % pickfile
|
||||||
|
pickf = open(pickfile, 'r')
|
||||||
pick = cPickle.Unpickler(pickf)
|
pick = cPickle.Unpickler(pickf)
|
||||||
try:
|
try:
|
||||||
hosts = pick.load()
|
Host.hosts = pick.load()
|
||||||
htab = pick.load()
|
|
||||||
msgs = pick.load()
|
msgs = pick.load()
|
||||||
try:
|
try:
|
||||||
lastfm = pick.load()
|
lastfm = pick.load()
|
||||||
@@ -888,12 +894,17 @@ if os.path.exists(PICKFILE):
|
|||||||
lastfm = ["","",""]
|
lastfm = ["","",""]
|
||||||
pickf.close()
|
pickf.close()
|
||||||
except:
|
except:
|
||||||
os.unlink(PICKFILE)
|
os.unlink(pickfile)
|
||||||
for h in hosts.keys():
|
Connection.htab = {}
|
||||||
hosts[h].fixup()
|
for h in Host.hosts.keys():
|
||||||
|
Host.hosts[h].dyn = h in dyndnshosts
|
||||||
|
Host.hosts[h].fixup()
|
||||||
for h in drophosts:
|
for h in drophosts:
|
||||||
if h in hosts:
|
if h in Host.hosts:
|
||||||
del hosts[h]
|
del Host.hosts[h]
|
||||||
|
if verbose: print "%s pickled hosts loaded" % len(Host.hosts)
|
||||||
|
else:
|
||||||
|
if verbose: print "no pickled data"
|
||||||
|
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -999,8 +1010,8 @@ while running:
|
|||||||
ts=time.strftime(tsfm[v], time.localtime(now))
|
ts=time.strftime(tsfm[v], time.localtime(now))
|
||||||
if ts != lastfm[v]:
|
if ts != lastfm[v]:
|
||||||
lastfm[v]=ts
|
lastfm[v]=ts
|
||||||
for h in hosts.keys():
|
for h in Host.hosts.keys():
|
||||||
hosts[h].hdwcounts[v] = [hosts[h].doesack, hosts[h].upcount]
|
Host.hosts[h].hdwcounts[v] = [Host.hosts[h].doesack, Host.hosts[h].upcount]
|
||||||
|
|
||||||
if now >= next and now >= firstcheck:
|
if now >= next and now >= firstcheck:
|
||||||
next = now+1
|
next = now+1
|
||||||
|
|||||||
+165
-127
@@ -8,55 +8,159 @@ the websit's heartbeat.py
|
|||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# Table of Hosts
|
|
||||||
hosts = {}
|
|
||||||
# map of addrs to names
|
|
||||||
htab = {}
|
|
||||||
num = 0
|
num = 0
|
||||||
|
|
||||||
|
MAXRTTS = 10
|
||||||
|
|
||||||
def isIPv4(addr):
|
#
|
||||||
return addr.find('.') > 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Connection:
|
class Connection:
|
||||||
def __init__(self, name, cid, addr):
|
# map of addrs to names
|
||||||
self.name = name
|
|
||||||
|
htab = {}
|
||||||
|
up = "up"
|
||||||
|
down = "down"
|
||||||
|
overdue = "overdue"
|
||||||
|
|
||||||
|
def __init__(self, host, cid, addr, afam):
|
||||||
|
self.host = host
|
||||||
self.cid = cid
|
self.cid = cid
|
||||||
self.addr = addr
|
self.addr = addr
|
||||||
|
self.afam = afam
|
||||||
self.rtts = [0]
|
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):
|
def jsons(self):
|
||||||
return(json.dumps(self.__dict__))
|
return(json.dumps(self.__dict__))
|
||||||
|
|
||||||
|
|
||||||
class Host:
|
# set new state, return number of secs in previous state
|
||||||
up = "up"
|
def newstate(self, state, now, when=0):
|
||||||
down = "down"
|
self.state = state
|
||||||
overdue = "overdue"
|
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):
|
def __init__(self, name):
|
||||||
global num
|
global num
|
||||||
self.name = name
|
self.name = name
|
||||||
self.addr4 = None
|
|
||||||
self.addr6 = None
|
|
||||||
self.num = num
|
self.num = num
|
||||||
self.lastbeat = time.time()
|
self.dyn = False
|
||||||
self.upcount = 0
|
self.upcount = 0
|
||||||
self.state = Host.up
|
|
||||||
self.state = "up"
|
|
||||||
self.statetime = self.lastbeat
|
|
||||||
self.interval = 0
|
self.interval = 0
|
||||||
self.doesack = -1
|
self.doesack = -1
|
||||||
self.cmds = []
|
self.cmds = []
|
||||||
self.cver = 0
|
self.cver = 0
|
||||||
self.connections = {}
|
self.connections = {}
|
||||||
self.latency = 0
|
|
||||||
self.hdwcounts = [[0,0],[0,0],[0,0]]
|
self.hdwcounts = [[0,0],[0,0],[0,0]]
|
||||||
|
if name:
|
||||||
num += 1
|
num += 1
|
||||||
hosts[name] = self
|
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):
|
def jsons(self):
|
||||||
@@ -77,101 +181,33 @@ class Host:
|
|||||||
|
|
||||||
|
|
||||||
def isDynDns(self):
|
def isDynDns(self):
|
||||||
return self.name in dyndnshosts
|
return self.dyn
|
||||||
|
|
||||||
|
|
||||||
def newaddr(self, addr):
|
def isIPv4(self, addr):
|
||||||
if isIPv4(addr):
|
if type(addr) == type(()):
|
||||||
if self.addr4:
|
return addr[0].find('.') > 0
|
||||||
if self.addr4 == addr:
|
|
||||||
r = None
|
|
||||||
else:
|
else:
|
||||||
r = "changed from %s to %s" % (self.addr4, addr)
|
return addr.find('.') > 0
|
||||||
del htab[self.addr4]
|
|
||||||
self.addr4 = addr
|
|
||||||
htab[addr] = self.name
|
def conndata(self, cid, addr, rtt, now):
|
||||||
if self.isDynDns():
|
if self.isIPv4(addr):
|
||||||
dnsQ.put((self.name, self.addr4))
|
afam = "IPv4"
|
||||||
else:
|
else:
|
||||||
r = "new addr %s" % (addr)
|
afam = "IPv6"
|
||||||
self.addr4 = addr
|
|
||||||
htab[addr] = self.name
|
if afam not in self.connections:
|
||||||
if self.isDynDns():
|
self.connections[afam] = Connection(self, cid, addr, afam)
|
||||||
dnsQ.put((self.name, self.addr4))
|
|
||||||
else:
|
conn = self.connections[afam]
|
||||||
if self.addr6:
|
res = conn.newaddr(addr, rtt, now)
|
||||||
if self.addr6 == addr:
|
return conn, res
|
||||||
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
|
# called when reloading class from pickle, add new fields here
|
||||||
def fixup(self):
|
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
|
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):
|
def dispstate(self):
|
||||||
@@ -209,26 +245,28 @@ class Host:
|
|||||||
return '<td align="right">N/A</td><td></td<td></td>>'
|
return '<td align="right">N/A</td><td></td<td></td>>'
|
||||||
|
|
||||||
|
|
||||||
def htmldisp(self, header=False):
|
hostfields = ['name', 'IPv4.addr', 'IPv4.state', 'IPv4.rtt', 'IPv4.statetime', 'IPv6.addr', 'IPv6.state', 'IPv6.rtt', 'IPv6.statetime', 'ver']
|
||||||
if header:
|
def htmlheaders(self):
|
||||||
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"
|
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 ""
|
def htmldisp(self):
|
||||||
ipv6addr = self.addr6 if self.addr6 else ""
|
h = []
|
||||||
lastts = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.statetime))
|
hd = self.statedict()
|
||||||
return "<tr><td>%-24s</td><td>%-7s</td>%s<td>%-16s</td><td>%-16s</td><td>%-17s</td><td>%s</td></tr>\n" % \
|
for f in Host.hostfields:
|
||||||
(self.name, self.dispstate(), self.dispstats(), ipv4addr, ipv6addr, lastts, self.cver)
|
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
|
# create fake "unbound objects", remove in Python 3.0
|
||||||
def newstate(self, state, when=0):
|
ubHost = Host(None)
|
||||||
self.state = state
|
ubConnection = Connection(None, "", "", "")
|
||||||
now = time.time()-when
|
|
||||||
s = now-self.statetime
|
|
||||||
self.statetime = now
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user