#!/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("{0}".format(png)) self.wfile.write("") for k in sorted(info): self.wfile.write("\n") self.wfile.write("
" + str(k)) self.wfile.write("" + str(info[k])) 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()