Files
routerstats/routerstats_httpd.py

182 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python3
'''httpd component of routerstats'''
import logging
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
import sys
import os
from functools import partial
import argparse
import configparser
import rrdtool
logging.basicConfig(
format='%(asctime)s %(funcName)20s %(levelname)-8s %(message)s',
level=logging.INFO,
datefmt='%Y-%m-%d %H:%M:%S')
class RequestHandler(SimpleHTTPRequestHandler):
'''Extended SimpleHTTPRequestHandler'''
def serve_png(self):
'''Give a client a png file'''
self.send_response(200)
self.send_header('Content-type', 'image/png')
self.end_headers()
tmp_queries = self.path.split('/')
query = []
for q in tmp_queries:
if q:
query.append(q)
logging.debug(str(query))
retries = 0
while True:
try:
if len(query) > 1:
if query[1] == 'yearly':
title = query[1]
startstr = '--start=end-1Y'
elif query[1] == 'monthly':
title = query[1]
startstr = '--start=end-1M'
elif query[1] == 'weekly':
title = query[1]
startstr = '--start=end-1W'
elif query[1] == 'daily':
title = query[1]
startstr = '--start=end-1d'
else:
title = 'monthly'
startstr = '--start=end-1M'
else:
title = 'monthly'
startstr = '--start=end-1M'
data = rrdtool.graphv(
"-",
startstr,
"--title=" + title,
"DEF:in=" + self.rrdfile + ":net_dnat:AVERAGE", #pylint: disable=no-member
"DEF:out=" + self.rrdfile + ":loc-net:AVERAGE", #pylint: disable=no-member
"CDEF:result_in=in,UN,0,in,IF",
"CDEF:tmp_out=out,UN,0,out,IF",
"CDEF:result_out=tmp_out,-1,*",
"AREA:result_in#00ff00:in",
"AREA:result_out#0000ff:out")
#, "--width", "1024", "--height", "600"
self.wfile.write(data['image'])
break
except rrdtool.OperationalError as error:
retries += 1
if retries > 10:
logging.error('Could not graphv the data: %s', error)
break
def errorpage(self, errorcode, errormsg: str = ''):
'''Give client an errorpage'''
self.send_response(errorcode)
self.send_header('Content-type', 'text/plain')
self.end_headers()
if errormsg:
self.wfile.write(errormsg.encode('utf-8'))
def do_GET(self):
'''Reply to a GET request'''
if self.path == '/':
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.print_page()
elif self.path.startswith('/graph'):
self.serve_png()
elif self.path == '/favicon.ico':
self.send_error(404)
else:
self.send_error(404, str(self.path))
def print_page(self):
'''Print pretty html page'''
self.wfile.write("<html><body>".encode('utf-8'))
self.wfile.write('<img src="/graph/monthly">'.encode('utf-8'))
self.wfile.write('<img src="/graph/weekly">'.encode('utf-8'))
self.wfile.write('<img src="/graph/daily">'.encode('utf-8'))
self.wfile.write("</body></html>".encode('utf-8'))
class CustomHandler(RequestHandler):
'''wrapping the wrapped one, so we can wrap in an init'''
def __init__(self, rrdfile, *args, **kwargs):
self.rrdfile = rrdfile
super().__init__(*args, **kwargs)
def server(rrdfile, port):
'''Start server'''
server_address = ('', port)
server_class = ThreadingHTTPServer
handler_class = partial(CustomHandler, rrdfile)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
def main():
'''This be main'''
config_section = 'httpd'
config = configparser.ConfigParser()
parser = argparse.ArgumentParser(exit_on_error=False)
parser.add_argument('-c', '--config', help='config file to load')
parser.add_argument('-d', '--debug', action='store_true', help='enable debug')
args, _ = parser.parse_known_args()
if args.debug:
logging.root.setLevel(logging.DEBUG)
logging.debug('Starting as PID %s', os.getpid())
found = False
if args.config:
if os.path.isfile(args.config):
config.read(args.config)
found = True
else:
logging.error('Specified config file does not exist: %s', args.config)
else:
logging.debug('Trying to find config')
#Try to find in "usual" places
for directory in ('/etc/routerstats/', '/usr/local/etc/routerstats/', '/opt/routerstats/', './'):
trytoread = directory + 'routerstats.config'
if os.path.isfile(trytoread):
logging.debug('Reading config file %s', trytoread)
config.read(trytoread)
found = True
if not found:
logging.error('No config file found')
sys.exit(0)
parser.add_argument(
'-v',
'--vardir',
help='directory storing rrd file',
default=config[config_section]['var_dir'])
parser.add_argument(
'-p',
'--port',
help='port to bind to',
type=int,
default=config[config_section]['port'])
args = parser.parse_args()
logging.debug(args)
if not os.path.isfile(args.vardir + 'routerstats.rrd'):
logging.error('Cannot find rrd file %s', args.vardir + 'routerstats.rrd' )
sys.exit()
server(rrdfile=args.vardir + 'routerstats.rrd', port=args.port)
if __name__ == '__main__':
logging.debug('Welcome')
main()