summaryrefslogtreecommitdiff
path: root/tools/check-flimsy.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/check-flimsy.py')
-rw-r--r--tools/check-flimsy.py205
1 files changed, 205 insertions, 0 deletions
diff --git a/tools/check-flimsy.py b/tools/check-flimsy.py
new file mode 100644
index 0000000..8d33d9e
--- /dev/null
+++ b/tools/check-flimsy.py
@@ -0,0 +1,205 @@
+#!/usr/bin/python
+
+import urllib2
+import json
+import socket
+import datetime
+import sys
+import time
+import smtplib
+import atexit
+import socket
+import signal
+from email.mime.text import MIMEText
+
+
+def dump(obj):
+ for attr in dir(obj):
+ print "obj.%s = %s" % (attr, getattr(obj, attr))
+
+
+def testurl(url, timeout):
+ """
+ returns a list, which first item is status, and optional second item is extra information, like:
+ ['ok']
+ of
+ ['other', 'overheating']
+ status:
+ 'ok' - check ok
+ 'head too old': arg = time diff in seconds
+ 'connection refused'
+ 'connection timeout'
+ 'response timeout'
+ 'other': arg = error string - other unknown errors
+
+ """
+
+ try:
+ f = urllib2.urlopen(url, timeout=timeout)
+ now = datetime.datetime.utcnow()
+ obj = json.load(f)
+ if 'timestamp' in obj:
+ x = datetime.datetime.utcfromtimestamp(obj['timestamp'] / 1000) + datetime.timedelta(milliseconds = obj['timestamp'] % 1000)
+ secs = (now - x).total_seconds()
+ if secs > 7200:
+ return ['head too old', secs]
+ return ['ok']
+ return ['other', 'no timestamp in reply']
+
+ except urllib2.URLError as e:
+ #print 'except urllib2.URLError'
+ #print repr(e.reason)
+
+ reason_type = type(e.reason).__name__
+
+ if reason_type == 'error':
+ err_str = e.args[0].strerror
+ if err_str == 'Connection refused':
+ return ['connection refused']
+ else:
+ return ['other', str(e)]
+
+ elif reason_type == 'timeout':
+ # timeout when connecting
+ return ['connection timeout']
+
+ else:
+ return ['other', str(e)]
+
+ except IOError as e:
+ #print 'except IOError'
+
+ if type(e).__name__ == 'timeout':
+ # timeout when reading
+ return ['response timeout']
+
+ else:
+ return ['other', str(e)]
+
+ except:
+ return ['other', str(sys.exc_info()[0])]
+
+
+"""
+ print repr(type(e.reason).__name__)
+ print 'repr(e) ', repr(e)
+ print 'e ', e
+ print 'e.args ', e.args
+ print 'e.errno ', e.errno
+ print 'e.strerror ', e.strerror
+ dump(e)
+ print 'repr(e.args[0]) ', repr(e.args[0])
+ dump (e.args[0])
+
+
+"""
+
+myhostname = None
+
+def sendmsg(newstate, state, l, lastchange, adminonly=False):
+ global myhostname
+ if not myhostname:
+ myhostname = socket.gethostname()
+
+ txt = 'checkflimsy on %s\n' % (myhostname)
+ txt += 'state: %s\n' % newstate
+ if newstate == 'head too old':
+ txt += 'head too old: %f seconds\n' % l[1]
+ if newstate == 'other':
+ txt += 'message: %s\n' % str(l[1])
+ txt += 'last state change: %s\n' % lastchange.replace(microsecond=0).isoformat(' ')
+ delta = datetime.datetime.now().replace(microsecond=0) - lastchange.replace(microsecond=0)
+ txt += 'time since last state change: %s\n' % str(delta)
+ txt += '(previous state: %s)\n' % state
+
+ print txt # XXX
+
+ msg = MIMEText(txt)
+
+ fromaddr = 'foo-admin@example.net'
+ toaddrs = ['foo@example.net']
+ if adminonly:
+ toaddrs = ['foo@example.net']
+
+
+ subj = '%s flimsy status: %s' % (myhostname, newstate)
+ if newstate == 'other':
+ subj += ' - %s' % str(l[1])
+ if newstate not in ['ok', 'starting']:
+ subj += ' - WARNING'
+ msg['Subject'] = subj
+ msg['From'] = fromaddr
+ msg['To'] = ', '.join(toaddrs)
+
+ # Send the message via our own SMTP server, but don't include the
+ # envelope header.
+ s = smtplib.SMTP('localhost')
+ s.sendmail(fromaddr, toaddrs, msg.as_string())
+ s.quit()
+
+
+lastchange = None
+state = None
+
+def runloop(url):
+ timeout = 10
+ sleeptime = 30
+ repeattime = 7200
+ lasttold = None
+ global lastchange
+ global state
+
+ while True:
+ #print '.' # XXX
+ l = testurl(url, timeout)
+ newstate = l[0]
+
+ now = datetime.datetime.now()
+
+ if state != newstate:
+ lastchange = now
+ lasttold = now
+ if state == None:
+ # starting
+ print 'check-flimsy started at %s' % (str(now))
+ sendmsg('starting', state, l, lastchange, adminonly=True)
+ else:
+ sendmsg(newstate, state, l, lastchange)
+ state = newstate
+ elif state != 'ok' and (now - lasttold) > datetime.timedelta(seconds=repeattime):
+ lasttold = now
+ sendmsg(newstate, state, l, lastchange)
+
+ time.sleep(sleeptime)
+
+
+"""
+ 'ok' - check ok
+ 'head too old': arg = time diff in seconds
+ 'connection refused'
+ 'connection timeout'
+ 'response timeout'
+ 'other': arg = error string - other unknown errors
+"""
+
+
+def exitproc():
+ sendmsg('EXITING', state, ['-'], lastchange, adminonly=True)
+
+
+def main():
+ url = 'https://flimsy.ct.nordu.net:8080/ct/v1/get-sth'
+ #url = 'http://127.0.0.1:8080'
+
+ while True:
+ try:
+ atexit.register(exitproc)
+ signal.signal(signal.SIGHUP, exitproc)
+
+ runloop(url)
+ except:
+ print "Unexpected error from runloop():", sys.exc_info()[0]
+ raise # XXX
+
+
+main()