bin/rrdweb
changeset 25 9fa9d881fd87
parent 20 86bbabd10ff6
equal deleted inserted replaced
24:29a523db66a8 25:9fa9d881fd87
       
     1 #!/usr/bin/env python
       
     2 
       
     3 import os.path, fnmatch
       
     4 import optparse, logging
       
     5 
       
     6 from rrdweb import graph, html
       
     7 
       
     8 
       
     9 def parse_args (args) :
       
    10     global options
       
    11 
       
    12     parser = optparse.OptionParser(
       
    13         usage   = "%prog [options] <target> [...]"
       
    14     )
       
    15     
       
    16     # generic
       
    17     parser.add_option('-q', "--quiet", help="No output in normal operation",
       
    18         action='store_const', dest="loglvl", const=logging.WARNING,
       
    19     )
       
    20     parser.add_option('-v', "--verbose", help="More output",
       
    21         action='store_const', dest="loglvl", const=logging.INFO,
       
    22     )
       
    23     parser.add_option('-D', "--debug", help="Even more output",
       
    24         action='store_const', dest="loglvl", const=logging.DEBUG,
       
    25     )
       
    26 
       
    27     # options
       
    28     parser.add_option(      "--rrd-type", default="mrtg", help="RRD style to use: mrtg, collectd_ifoctets")
       
    29     
       
    30     # paths
       
    31     parser.add_option('-R', "--rrd-dir", default="rrd", help="Path to directory containing .rrd files")
       
    32     parser.add_option('-I', "--img-dir", default="img", help="Path to directory containing .png files")
       
    33     parser.add_option('-W', "--web-dir", default="web", help="Path to directory containing .html files")
       
    34     parser.add_option('-T', "--tpl-dir", default="templates", help="Path to directory containing .html templates files")
       
    35 
       
    36     # urls
       
    37     parser.add_option('-P', "--url-prefix", default="", help="Prefix for URLs")
       
    38     parser.add_option(      "--img-url", default="img", help="URL to directory containing .png files")
       
    39     parser.add_option(      "--web-url", default="web", help="URL to directory containing .html files")
       
    40     
       
    41     # defaults
       
    42     parser.set_defaults(
       
    43         loglvl      = logging.INFO,
       
    44     )
       
    45     
       
    46     ## parse
       
    47     options, targets = parser.parse_args(args)
       
    48     
       
    49 
       
    50     ## apply
       
    51     logging.basicConfig(
       
    52         format      = "[%(levelname)8s] %(funcName)20s : %(message)s",
       
    53         level       = options.loglvl,
       
    54     )
       
    55     
       
    56     return targets
       
    57 
       
    58 
       
    59 def scan_targets () :
       
    60     """
       
    61         Scan for targets from rrd_dir
       
    62     """
       
    63     
       
    64     # root dir for searching
       
    65     rrd_dir = options.rrd_dir
       
    66     
       
    67     # recurse
       
    68     for dirpath, dirs, files in os.walk(rrd_dir) :
       
    69         for name in files :
       
    70             # full path
       
    71             path = os.path.join(dirpath, name)
       
    72 
       
    73             # relative path from rrd_dir
       
    74             relpath = path[len(os.path.commonprefix([rrd_dir, path])):]
       
    75 
       
    76             # skip dotfiles
       
    77             if name.startswith('.') :
       
    78                 continue
       
    79             
       
    80             # foo/bar, .rrd
       
    81             target, ext = os.path.splitext(relpath)
       
    82             
       
    83             if ext.lower() == '.rrd' :
       
    84                 # as target name
       
    85                 yield target
       
    86 
       
    87 
       
    88 
       
    89 def check_output_file (path) :
       
    90     """
       
    91         Create the directory for the given output path if missing
       
    92     """
       
    93     
       
    94     dir, file = os.path.split(path)
       
    95 
       
    96     if not os.path.exists(dir) :
       
    97         logging.warn("Create directory for output file %s: %s", file, dir)
       
    98 
       
    99         os.makedirs(dir)
       
   100 
       
   101 def target_graph (target, style, interval) : 
       
   102     """
       
   103         Generate .rrd -> .png for given target
       
   104     """
       
   105 
       
   106     # XXX: title..
       
   107     title = target
       
   108 
       
   109     # compose paths
       
   110     rrd_path = os.path.join(options.rrd_dir, target) + '.rrd'
       
   111     out_path = os.path.join(options.img_dir, style, interval, target) + '.png'
       
   112 
       
   113     # create out path if not exists
       
   114     check_output_file(out_path)
       
   115 
       
   116     logging.debug("%s: %s -> %s", target, rrd_path, out_path)
       
   117     
       
   118     # graph function to use
       
   119     graph_func = getattr(graph, options.rrd_type)
       
   120 
       
   121     # graph
       
   122     graph_func(style, interval, title, rrd_path, out_path)
       
   123 
       
   124 
       
   125 def target_html (target, formatter) :
       
   126     """
       
   127         Generate .html for given target
       
   128     """
       
   129 
       
   130     # XXX: title..
       
   131     title = target
       
   132     
       
   133     # build paths
       
   134     html_path = os.path.join(options.web_dir, target + '.html')
       
   135     
       
   136     # create out path if not exists
       
   137     check_output_file(html_path)
       
   138 
       
   139     logging.debug("%s: %s", target, html_path)
       
   140     
       
   141     # render
       
   142     open(html_path, 'w').write(formatter.target(target, title).encode('utf-8'))
       
   143 
       
   144 def overview_html (targets, formatter) :
       
   145     """
       
   146         Generate .html index
       
   147     """
       
   148     
       
   149     # paths
       
   150     overview_path = os.path.join(options.web_dir, "index.html")
       
   151 
       
   152     # create out path if not exists
       
   153     check_output_file(overview_path)
       
   154 
       
   155     logging.debug("%s", overview_path)
       
   156     
       
   157     # as (target, title) pairs
       
   158     open(overview_path, 'w').write(formatter.overview('/', ((target, target) for target in targets)).encode('utf-8'))
       
   159 
       
   160 
       
   161 def generate_target (target, formatter) :
       
   162     
       
   163     # overview
       
   164     target_graph(target, 'overview', 'daily')
       
   165     
       
   166     # details
       
   167     for interval in ('daily', 'weekly', 'yearly') :
       
   168         target_graph(target, 'detail', interval)
       
   169 
       
   170     # html for target
       
   171     target_html(target, formatter)
       
   172 
       
   173 
       
   174 def generate (targets, filters=None):
       
   175     if not targets :
       
   176         # autodetect
       
   177         targets = sorted(list(scan_targets()))
       
   178         
       
   179         logging.info("Autodetected %d targets", len(targets))
       
   180 
       
   181     if filters :
       
   182         # filter targets
       
   183         targets = [target for target in targets if any(fnmatch.fnmatch(target.name, filter) for filter in filters)]
       
   184     
       
   185     logging.info("Updating %d targets", len(targets))
       
   186 
       
   187     # overview
       
   188     formatter = html.Formatter(
       
   189         url_prefix      = options.url_prefix,
       
   190         img_url         = html.urljoin(options.url_prefix, options.img_url, "%(style)s", "%(interval)s", "%(target)s.png"),
       
   191         target_url      = html.urljoin(options.url_prefix, options.web_url, "%(target)s.html"),
       
   192     )
       
   193     
       
   194     # html for overview
       
   195     overview_html(targets, formatter)
       
   196 
       
   197     for target in targets :
       
   198         logging.info("Target: %s", target)
       
   199         
       
   200         # HTML and PNGs
       
   201         generate_target(target, formatter)
       
   202 
       
   203 def main (args) :
       
   204     # parse args
       
   205     targets = parse_args(args)
       
   206     
       
   207     # run
       
   208     generate(targets)
       
   209 
       
   210 if __name__ == '__main__' :
       
   211     from sys import argv
       
   212 
       
   213     main(argv[1:])
       
   214