#!/usr/bin/env python import os, sys, time import sets, cgi, shlex import ConfigParser import rrdtool # 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"] # We always have this as our current directory. # It helps when constructing graphs and the like os.chdir(WORKDIR) class GraphDef: filename = None filedata = None title = "" height = 0 width = 0 options = "" commands = "" category = "" name = "" valid = False __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 self.interval = 0 self.valid = False 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.category = cfg.get("general", "category") # Loading graph stuff if cfg.has_section("graph"): if not cfg.has_option("graph", "commands"): raise "Missing commands attribute in: %s" % self.filename self.commands = cfg.get("graph", "commands") 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") self.valid = True # Polling stuff if cfg.has_option("poll", "interval"): self.interval = cfg.get("poll", "interval") def loadGraphs(path = ""): # List files and add appropriate paths graphs = [] for file in os.listdir(CONFDIR + "/" + path): if os.path.isdir(CONFDIR + "/" + path + file): if file != "." and file != "..": graphs.extend(loadGraphs(path + file + "/")) continue graphs.append(GraphDef(path + file)) return graphs def listGraphs(): graphs = loadGraphs() categories = {} for item in graphs: if not item.valid: continue 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, item.interval) 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 os.environ.has_key("PATH_INFO"): path = os.environ["PATH_INFO"].strip("/") else: path = "" 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