Created
April 12, 2012 20:55
-
-
Save urbans/2370936 to your computer and use it in GitHub Desktop.
Server supervisor on GAE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
application: ****your app name**** | |
version: 1 | |
runtime: python | |
api_version: 1 | |
handlers: | |
- url: /.* | |
script: main.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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