#!/usr/bin/env python import os, sys, time import sets, cgi, shlex import ConfigParser import rrdtool from rrdui import * # TODO: Temporary if not os.environ.has_key("CONFDIR") or not os.environ.has_key("WORKDIR"): raise "not setup properly. CONFDIR and WORKDIR env variables must be set" CONFDIR = os.environ["CONFDIR"] WORKDIR = os.environ["WORKDIR"] class GraphDef: filename = None filedata = None title = "" height = 0 width = 0 options = "" commands = "" category = "" name = "" __config = None def __init__(self, name): self.filename = "%s/%s" % (CONFDIR, name) self.filedata = "%s/%s.rrd" % (WORKDIR, name) self.category = "All" self.name = name cfg = self.__config = ConfigParser.RawConfigParser() cfg.read(self.filename) # Loading general stuff if cfg.has_option("general", "title"): self.title = cfg.get("general", "title") if cfg.has_option("general", "category"): self.title = cfg.get("general", "category") # Loading graph stuff if cfg.has_option("graph", "width"): self.width = int(cfg.get("graph", "width")) if cfg.has_option("graph", "height"): self.height = int(cfg.get("graph", "height")) if cfg.has_option("graph", "options"): self.options = cfg.get("graph", "options") if not cfg.has_option("graph", "commands"): raise "Missing commands attribute in: %s" % self.filename self.commands = cfg.get("graph", "commands") def getCreateInfo(self): cfg = self.__config rra = None fields = {} # The RRA info if cfg.has_option("create", "rra"): rra = cfg.get("create", "rra").split() # The various fields for field in cfg.options("create"): if not field.startswith("field."): continue fieldname = field[6:] fields[fieldname] = cfg.get("create", field) return (fields, rra) def getPollingInfo(self): cfg = self.__config interval = 300 fields = {} # The interval if cfg.has_option("poll", "interval"): interval = int(cfg.get("poll", "interval")) # The various fields for field in cfg.options("poll"): if not field.startswith("field."): continue fieldname = field[6:] fields[fieldname] = cfg.get("poll", field) return (fields, interval) def loadGraphs(): # List files and add appropriate paths graphs = [] for file in os.listdir(CONFDIR): if os.path.isdir(file): continue graphs.append(GraphDef(file)) return graphs def listGraphs(): graphs = loadGraphs() categories = {} for item in graphs: if not categories.has_key(item.category): categories[item.category] = [] categories[item.category].append(item) groups = categories.keys() groups.sort() print "Content-Type: text/xml\n" print "" print "" for group in groups: print " " % group categories[group].sort() for item in categories[group]: print " " % \ (item.name, item.width, item.height, item.title) print " " print "" def displayGraph(): # print "Content-Type: text/plain" print "Content-Type: image/png" print "" form = cgi.FieldStorage() if not form.has_key("category") or not form.has_key("name"): raise "Required arguments not specified" name = form["name"].value item = GraphDef(name) # Default to one day display end = int(time.time()) start = end - 86400 if form.has_key("start"): start = int(form["start"].value) if form.has_key("end"): end = int(form["end"].value) # Default to Height and Width in graph height = item.height width = item.width if form.has_key("width"): width = int(form["width"].value) if form.has_key("height"): height = int(form["height"].value) args = ["-", "--imgformat=PNG", "--rigid", "--start=%d" % start, "--end=%d" % end, "--title=%s" % item.title, "--height=%d" % height, "--width=%d" % width ] # TODO Check color syntax if form.has_key("color"): colors = form.getlist("color"); for color in colors: args.append("--color") args.append(color.replace(":", "#")) commands = item.commands.replace("{START}", time.strftime("%Y-%m-%d %H\\:%M", time.localtime(start))) commands = commands.replace("{END}", time.strftime("%Y-%m-%d %H\\:%M", time.localtime(end))) commands = commands.replace("{RRD}", item.filedata) args.extend(shlex.split(commands)) args.extend(shlex.split(item.options)) print >> sys.stderr, str(args) rrdtool.graph(*args) if not os.environ.has_key("PATH_INFO"): raise "PATH_INFO not set" path = os.environ["PATH_INFO"].strip("/") parts = path.split("/") method = parts[0] del parts[0] if not method: method = "list" if method == "list": listGraphs() elif method == "graph": displayGraph() else: raise "Invalid request: %s" % method