#!/usr/bin/env python2.7
import os
import rrdtool # Stupid thing can't do Python 3 yet.
import time
import urllib
import urlparse
import SimpleHTTPServer
import SocketServer
ROOT_PATH = "/var/lib/collectd"
GRAPH_ARGS = ['--imgformat', 'PNG', '--width', '2560', '--height', '1440']
COLOURS = ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#009933", "#990033", "#FF00FF", "#00FFFF", "#AAAA00", "#678993"]
REDRAW_TIMEOUT = 300
HOW_FAR_BACK = 86400/2
DIR_ALL_OF_THEM = ['ethstat', 'fscache', 'hddtemp', 'irq', 'protocols']
DIR_BREAKDOWN = ['cpu', 'df', 'memory']
class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""See if you can spot all the holes in this."""
def do_GET(self):
self._params = urlparse.urlparse(self.path)
self._query = urlparse.parse_qs(self._params.query)
self._url = urllib.url2pathname(self._params.path)
if self._url.endswith('/'):
self.directory()
elif self._url.endswith('.rrd'):
self.info()
elif self._url.endswith('.png'):
self.graph_file()
elif self.path != "/favicon.ico":
print(self.path)
self.serve("/etc/passwd")
def directory(self):
last = self._url[:-1].rpartition("/")[2]
cat = last.partition('-')[0]
real = ROOT_PATH + self._url
files = [os.path.join(real, f)
for f in os.listdir(real)
if os.path.isfile(os.path.join(real, f))]
if cat in DIR_BREAKDOWN:
self.graph_breakdown(files)
elif cat in DIR_ALL_OF_THEM:
self.graph_allofthem(files)
else:
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
def info(self):
info = rrdtool.info(ROOT_PATH + self._url)
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.send_header('Refresh', str(HOW_FAR_BACK))
self.end_headers()
self.wfile.write("
")
png = self._url[:-4] + ".png"
self.wfile.write("
".format(png))
self.wfile.write("")
for k in sorted(info):
self.wfile.write("" + str(k))
self.wfile.write(" | " + str(info[k]))
self.wfile.write(" |
\n")
self.wfile.write("
")
self.wfile.close()
def graph_file(self):
img = os.path.join("/tmp", self._url[1:])
if os.path.exists(img) and \
os.path.getmtime(img) > time.time() - REDRAW_TIMEOUT:
print("PNG cached, serving", img)
self.serve(img, 'image/png')
return
rrd = ROOT_PATH + self._url[:-4] + ".rrd"
args = GRAPH_ARGS + ['--start', '-%i' % HOW_FAR_BACK, '--end', '-1']
args += ['--title', self._url]
ds = {}
info = rrdtool.info(rrd)
for k in info:
if k.startswith('ds['):
ds[k.split(']')[0][3:]] = 1
print(ds)
col = 0
rrd = rrd.replace(":", "\\:")
for src in ds:
args += ['DEF:{0}={1}:{0}:AVERAGE'.format(src, rrd)]
args += ['LINE2:{0}{1}:{0}'.format(src, COLOURS[col])]
col = (col + 1) % len(COLOURS)
print(args)
try: os.makedirs(os.path.dirname(img))
except Exception: pass
rrdtool.graph(img, *args)
print("PNG generated, serving", img)
self.serve(img, 'image/png')
def graph_breakdown(self, files):
self.graph_many(files, 'AREA:{0}{1}:{0}:STACK')
def graph_allofthem(self, files):
self.graph_many(files, 'LINE2:{0}{1}:{0}')
def graph_many(self, files, fmt):
img = os.path.join("/tmp", self._url[1:-1] + ".png")
if os.path.exists(img) and \
os.path.getmtime(img) > time.time() - REDRAW_TIMEOUT:
print("PNG cached, serving", img)
self.serve(img, 'image/png')
return
args = GRAPH_ARGS + ['--start', str(-HOW_FAR_BACK), '--end', '-1']
args += ['--title', self._url]
col = 0
for rrd in files:
rrd = rrd.replace(":", "\\:")
_, _, name = rrd.rpartition("/")
name, _, _ = name.partition(".")
args += ['DEF:{0}={1}:value:AVERAGE'.format(name, rrd)]
args += [fmt.format(name, COLOURS[col])]
col = (col + 1) % len(COLOURS)
print(args)
try: os.makedirs(os.path.dirname(img))
except Exception: pass
rrdtool.graph(img, *args)
print("PNG generated, serving", img)
self.serve(img, 'image/png')
def serve(self, f, content_type='text/plain'):
self.send_response(200)
self.send_header('Content-Type', content_type)
self.end_headers()
with open(f) as fd:
self.wfile.write(fd.read())
self.wfile.close()
if __name__ == '__main__':
os.chdir(ROOT_PATH)
address = '', 8000
SocketServer.TCPServer(address, MyHandler).serve_forever()