part 2 of redo: state is in connections

This commit is contained in:
2016-04-26 21:59:15 +02:00
parent b1fef35d03
commit 21f8fe8842
2 changed files with 278 additions and 229 deletions
+109 -98
View File
@@ -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 = []
continue for c in Host.hosts[h].connections:
timeout = hosts[h].interval+grace conn = Host.hosts[h].connections[c]
if hosts[h].state == Host.up and now-hosts[h].lastbeat > timeout: if conn.state == Connection.down:
continue
timeout = Host.hosts[h].interval + grace
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.sort() hosts_sorted = Host.hosts.keys()
res.append(hosts[hosts_sorted[0]].htmldisp(True)) if len(hosts_sorted):
for h in hosts_sorted: hosts_sorted.sort()
res.append(hosts[h].htmldisp()) for h in hosts_sorted:
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
+168 -130
View File
@@ -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]]
num += 1 if name:
hosts[name] = self 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): 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:
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: else:
if self.addr6: return addr.find('.') > 0
if self.addr6 == addr:
r = None
else: def conndata(self, cid, addr, rtt, now):
r = "changed from %s to %s" % (self.addr6, addr) if self.isIPv4(addr):
del htab[self.addr6] afam = "IPv4"
self.addr6 = addr else:
htab[addr] = self.name afam = "IPv6"
if self.isDynDns():
dnsQ.put((self.name, self.addr6)) if afam not in self.connections:
else: self.connections[afam] = Connection(self, cid, addr, afam)
r = "new addr %s" % (addr)
self.addr6 = addr conn = self.connections[afam]
htab[addr] = self.name res = conn.newaddr(addr, rtt, now)
if self.isDynDns(): return conn, res
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: pass
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): 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