Server supervisor on GAE
import cgi | |
import datetime | |
import urllib | |
import wsgiref.handlers | |
from google.appengine.ext import db | |
from google.appengine.api import users | |
from google.appengine.ext import webapp | |
from google.appengine.ext.webapp.util import run_wsgi_app | |
from datetime import datetime | |
######################################### functions ########################################### | |
def xstr(s): | |
"""NUll stringifying function""" | |
if s is None: | |
return '' | |
return str(s).encode("iso-8859-15", "xmlcharrefreplace") | |
def pretty_date(time=False): | |
""" | |
Get a datetime object or a int() Epoch timestamp and return a | |
pretty string like 'an hour ago', 'Yesterday', '3 months ago', | |
'just now', etc | |
""" | |
now = datetime.now() | |
if type(time) is int: | |
diff = now - datetime.fromtimestamp(time) | |
elif isinstance(time,datetime): | |
diff = now - time | |
elif not time: | |
diff = now - now | |
second_diff = diff.seconds | |
day_diff = diff.days | |
if day_diff < 0: | |
return '' | |
if day_diff == 0: | |
if second_diff < 10: | |
return "just now" | |
if second_diff < 60: | |
return str(second_diff) + " sec ago" | |
if second_diff < 120: | |
return "min ago" | |
if second_diff < 3600: | |
return str( second_diff / 60 ) + " mins ago" | |
if second_diff < 7200: | |
return "hour ago" | |
if second_diff < 86400: | |
return str( second_diff / 3600 ) + " hrs ago" | |
if day_diff == 1: | |
return "Yesterday" | |
if day_diff < 7: | |
return str(day_diff) + " days ago" | |
if day_diff < 31: | |
return str(day_diff/7) + " weeks ago" | |
if day_diff < 365: | |
return str(day_diff/30) + " months ago" | |
return str(day_diff/365) + " years ago" | |
def dfColorizer(s): | |
"""colorizes df output""" | |
elements = s.split() | |
outarr = [] | |
color="#000" | |
hasDfPercent = None | |
for el in elements: | |
if el == None: | |
pass | |
elif el.find("%") != -1: | |
percent = float(el.split("%")[0]) | |
hasDfPercent = percent | |
if percent > 95: | |
color="FF0000" | |
elif percent > 90: | |
color="FF6600" | |
elif percent > 70: | |
color="996600" | |
else: | |
color="006600" | |
outarr.append("<span style='font-size:1.7em;font-weight:bold;'><br>%s<br></span>" % (el)) | |
else: | |
outarr.append("<span style='font-size:0.9em'>" + el + "</span>") | |
out = ("<font color='#%s'>%s</font>") % (color," ".join(outarr)) | |
if hasDfPercent >= 0 and hasDfPercent <=100: | |
out = out + "<br>" | |
out = out + "<img src='http://chart.apis.google.com/chart?chbh=a,0&chs=150x20&cht=bhs&chco=%s,ffffff&chd=t:%s|100&chf=bg,s,00000000'>" % (color,percent) | |
return out | |
def timeToColor(time=False): | |
"""color for _last seen_ time""" | |
now = datetime.now() | |
if type(time) is int: | |
diff = now - datetime.fromtimestamp(time) | |
elif isinstance(time,datetime): | |
diff = now - time | |
elif not time: | |
diff = now - now | |
second_diff = diff.seconds | |
day_diff = diff.days | |
if day_diff < 0: | |
return '' | |
if day_diff == 0: | |
if second_diff < 600: | |
return "#00ca00" | |
if second_diff < 3600: | |
return "#006600" | |
if second_diff < 7200: | |
return "#bd7400" | |
if second_diff < 86400: | |
return "#ff0000" | |
if day_diff == 1: | |
return "#ff0000" | |
if day_diff < 7: | |
return "#ff0000" | |
if day_diff < 31: | |
return "#000" | |
#if day_diff < 365: | |
# return str(day_diff/30) + " months ago" | |
return "#000" | |
######################################### model ########################################### | |
class Status(db.Model): | |
"""Models an individual Guestbook entry with an author, content, and date.""" | |
reportdate = db.DateTimeProperty(auto_now_add=True) | |
servername = db.StringProperty() | |
uptime = db.StringProperty(indexed=False) | |
freesysdisk = db.StringProperty(multiline=True,indexed=False) | |
freedatadisk1 = db.StringProperty(multiline=True,indexed=False) | |
freedatadisk2 = db.StringProperty(multiline=True,indexed=False) | |
pyserverdate = db.DateTimeProperty(indexed=False) | |
serverdate = db.StringProperty(indexed=False) | |
freemem = db.StringProperty(multiline=True, indexed=False) | |
apache = db.StringProperty(indexed=False) | |
php = db.StringProperty(indexed=False) | |
mysql = db.StringProperty(indexed=False) | |
load = db.StringProperty(indexed=False) | |
fullreport = db.TextProperty(indexed=False) | |
class UniqueServer(db.Model): | |
servername = db.StringProperty() | |
######################################### Index ########################################### | |
class Index(webapp.RequestHandler): | |
def get(self): | |
self.response.out.write('Coming soon') | |
######################################### Showing status ########################################### | |
class ListStatuses(webapp.RequestHandler): | |
def get(self): | |
self.response.out.write("<html><head>" | |
"<style>body{font-family:arial,helvetica;background-color:#444;}" | |
"th{color:#bbb;background-color:black;}" | |
"td{background-color:#ccc;}" | |
"h1{color:#ccc;}" | |
"</style>" | |
"</head>" | |
"<body>" | |
"<h1>Dashboard</h1><br />"); | |
self.response.out.write("<table border=1 cellspacing=0 cellpadding=4><tr>" | |
"<th>Name</th>" | |
"<th>Last seen</th>" | |
"<th>Sys disk</th>" | |
"<th>Data disk 1</th>" | |
"<th>Data disk 2</th>" | |
"<th>Uptime</th>" | |
"<th>Time lag</th>" | |
"<th>Load</th>" | |
"<th>Free mem</th>" | |
"<th>Apache</th>" | |
"<th>PHP</th>" | |
"<th>MySql</th>" | |
"<th>Full report</th>" | |
"</tr>"); | |
#find all servers ====================================== | |
servers = db.GqlQuery("SELECT * FROM UniqueServer ORDER BY servername ASC") | |
for server in servers: | |
#find last status ===================================== | |
statuses = db.GqlQuery("SELECT * FROM Status WHERE servername = '%s'" | |
"ORDER BY reportdate DESC LIMIT 1" % server.servername) | |
for s in statuses: | |
#get delta t ======================================= | |
if s.pyserverdate == None or s.reportdate == None: | |
lag = "-" | |
else: | |
t1 = s.pyserverdate | |
t2 = s.reportdate | |
if t1 > t2: | |
delta = -(t1-t2).seconds | |
else: | |
delta = (t2-t1).seconds | |
lag = str(delta) + " s" | |
#print table row =================================== | |
self.response.out.write("<tr>" | |
"<td style='background-color:%s;'>%s </td>" #name | |
"<td title='%s' style='background-color:%s;'>%s </td>" #last seen | |
"<td>%s </td>" #free sys disk | |
"<td>%s </td>" #free data disk1 | |
"<td>%s </td>" #free data disk2 | |
"<td>%s </td>" #uptime | |
"<td title='%s'>%s </td>" #system date lag | |
"<td>%s </td>" #load | |
"<td>%s </td>" #free mem | |
"<td>%s </td>" #apache | |
"<td>%s </td>" #PHP | |
"<td>%s </td>" #Mysql | |
"<td title='%s'>...</td>" #Full report | |
"</tr>" % ( | |
timeToColor(s.reportdate), xstr(s.servername), | |
xstr(s.reportdate), timeToColor(s.reportdate) ,pretty_date(s.reportdate), | |
dfColorizer(xstr(s.freesysdisk)), | |
dfColorizer(xstr(s.freedatadisk1)), | |
dfColorizer(xstr(s.freedatadisk2)), | |
xstr(s.uptime), | |
xstr(s.serverdate), | |
xstr(lag), | |
xstr(s.load), | |
xstr(s.freemem), | |
xstr(s.apache), | |
xstr(s.php), | |
xstr(s.mysql), | |
xstr(s.fullreport).replace("'",'"')) | |
); | |
#close table ============================================= | |
self.response.out.write('</table></body></html>'); | |
######################################### POSTING DATA ########################################### | |
class PostStatus(webapp.RequestHandler): | |
"""Handle incoming requests and save to database""" | |
def post(self): | |
#get and validate server name ================== | |
cursrvname = self.request.get('servername') | |
if cursrvname == None: | |
return | |
#store server to table of servers ============== | |
result = db.GqlQuery("SELECT * FROM UniqueServer WHERE servername = '%s'" % cursrvname) | |
if result.count() == 0: | |
newsrv = UniqueServer() | |
newsrv.servername = cursrvname | |
newsrv.put() | |
#store status ================================== | |
s = Status() | |
s.servername = cursrvname | |
s.freesysdisk = self.request.get('freesysdisk') or None | |
s.freedatadisk1 = self.request.get('freedatadisk1') or None | |
s.freedatadisk2 = self.request.get('freedatadisk2') or None | |
s.uptime = self.request.get('uptime') or None | |
s.serverdate = self.request.get('serverdate') or None | |
s.freemem = self.request.get('freemem') or None | |
s.apache = self.request.get('apache') or None | |
s.php = self.request.get('php') or None | |
s.mysql = self.request.get('mysql') or None | |
s.load = self.request.get('load') or None | |
s.fullreport = self.request.get('fullreport') or None | |
if self.request.get('pyserverdate'): | |
s.pyserverdate = datetime.strptime(self.request.get('pyserverdate'),"%Y-%m-%d %H:%M:%S") | |
s.put() | |
self.response.out.write('ok') | |
def get(self): | |
self.post() | |
######################################### Housekeeping ########################################### | |
application = webapp.WSGIApplication([ | |
('/', Index), | |
('/showstatus', ListStatuses), | |
('/post', PostStatus) | |
], debug=True) | |
def main(): | |
run_wsgi_app(application) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment