#!/usr/bin/python
"""
Setup symlinks for pvl.verkko-rrd -> collectd based on define host/interface names
"""
__version__ = '0.1'
import os
import pvl.args
import pvl.rrd.hosts
from pvl.rrd.hosts import hostreverse
import optparse
import logging; log = logging.getLogger('main')
COLLECTD_RRD = '/var/lib/collectd/rrd'
COLLECTD_PLUGIN = 'interfaces'
COLLECTD_TYPE = 'if_octets'
def parse_argv (argv, doc = __doc__) :
"""
Parse command-line argv, returning (options, args).
"""
prog = argv.pop(0)
args = argv
# optparse
parser = optparse.OptionParser(
prog = prog,
usage = '%prog: [options] [<input.txt> [...]]',
version = __version__,
description = doc,
)
# common
parser.add_option_group(pvl.args.parser(parser))
# options
parser.add_option('--collectd-rrd', metavar='PATH', default=COLLECTD_RRD,
help="Path to collectd rrd: %default")
parser.add_option('--collectd-plugin', metavar='PLUGIN', default=None,
help="Collectd plugin to use: <input>-<plugin>.txt")
parser.add_option('--collectd-type', metavar='TYPE', default=COLLECTD_TYPE,
help="Collectd type to use: %default")
# interface is by plugin, snmp is by type...
parser.add_option('--collectd-instance-plugin', action='store_const', dest='collectd_instance', const='plugin',
help="Collectd by plugin instance")
parser.add_option('--collectd-instance-type', action='store_const', dest='collectd_instance', const='type',
help="Collectd by type instance")
# hostnames
parser.add_option('--reverse-host', action='store_true',
help="Flip host.domain -> domain.host (default)")
parser.add_option('--no-reverse-host', action='store_false', dest='reverse_host',
help="Keep host.domain as host.domain")
parser.add_option('--domain', metavar='DOMAIN',
help="Append domain to collectd hostnames: <input>.txt -> <input>")
# output
parser.add_option('--rrd', metavar='PATH',
help="Output directory for .rrd symlinks: <input>.txt -> <input>/")
parser.add_option('--noop', action='store_true',
help="Scan symlinks, but do not update")
parser.set_defaults(
collectd_instance = 'type',
reverse_host = True,
)
# parse
options, args = parser.parse_args(args)
# apply
pvl.args.apply(options)
return options, args
def sync_links (options, links, rrddir) :
"""
Sync given (collectd, name) symlinks in given dir.
"""
log.info("%s", rrddir)
for rrdpath, (domain, host, port) in links :
linkpath = os.path.join(rrddir,
hostreverse(domain) if options.reverse_host else domain,
hostreverse(host) if options.reverse_host else host,
port + '.rrd'
)
# sync
if os.path.exists(linkpath) and os.readlink(linkpath) == rrdpath :
continue
log.info("%s: %s", linkpath, rrdpath)
yield linkpath, rrdpath
def apply_links (options, links) :
"""
Apply given symlinks
"""
for link, path in links :
linkdir = os.path.dirname(link)
# do
if not os.path.exists(linkdir) :
log.warn("makedirs: %s", linkdir)
os.makedirs(linkdir)
os.symlink(path, link)
def main (argv) :
options, args = parse_argv(argv)
for path in args :
# <path>/<domain>-<plugin>.txt -> <path>/<domain>-<plugin>
if '.txt' in path:
basepath, _ = os.path.splitext(path)
else:
basepath = path
# <path>/<domain> -> <domain>
_, basename = os.path.split(basepath)
# <path>/<domain>-<plugin> -> <path>/<domain>, <plugin>
if '-' in basename :
basename, collectd_plugin = basename.rsplit('-', 1)
else :
collectd_plugin = None
# domain?
if options.domain is None :
# reverse-order hostname
domain = hostreverse(basename)
else :
# may be ''
domain = options.domain
# output dir?
if not options.rrd:
log.error("no --rrd output dir given")
return 1
rrddir = options.rrd
# generate links from spec
links = list(pvl.rrd.hosts.collectd_interfaces(options, open(path),
collectd_domain = domain,
collectd_plugin = options.collectd_plugin or collectd_plugin or COLLECTD_PLUGIN,
))
if not os.path.exists(rrddir) :
log.error("given --rrd must already exist: %s", rrddir)
return 1
# sync missing links
links = list(sync_links(options, links,
rrddir = rrddir,
))
# verbose
if not options.quiet :
for link, path in links :
print link, '->', path
# apply
if not options.noop :
apply_links(options, links)
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))