234 lines
7.1 KiB
Python
Executable file
234 lines
7.1 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Liste les liens à créer pour les plugins munin.
|
|
#
|
|
# Utilise la liste de plugins classiques renvoyée par
|
|
# munin-node-configure, filtrée, et les plugins customisés Cr@ns
|
|
# configurés dans hosts_plugins.py
|
|
#
|
|
# Copyright © 2009 Nicolas Dandrimont <Nicolas.Dandrimont@crans.org>
|
|
#
|
|
# Licence: MIT
|
|
#
|
|
|
|
import optparse
|
|
import os
|
|
import shutil
|
|
import socket
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
from hosts_plugins import hosts_plugins, general_plugins
|
|
|
|
# Plugins munin classiques à ignorer
|
|
IGNORE_PLUGINS = (
|
|
'apt_all',
|
|
'if_',
|
|
'if_err_',
|
|
'multips',
|
|
'nfs4_client',
|
|
'nfsd',
|
|
'nfsd4',
|
|
'exim_mailstats',
|
|
'port_',
|
|
'sensors_',
|
|
'squid_icp',
|
|
'tomcat_',
|
|
'vlan_',
|
|
)
|
|
|
|
# Chemin d'accès aux plugins munin
|
|
MUNIN_PATH = "/usr/share/munin/plugins"
|
|
|
|
# Hacks crades
|
|
QUIRKS = []
|
|
|
|
if sys.version_info < (2, 5):
|
|
def any(genexpr):
|
|
"""Retourne True si quelque chose est vrai dans genexpr"""
|
|
for truc in genexpr:
|
|
if truc:
|
|
return True
|
|
return False
|
|
|
|
def register_quirk(f):
|
|
QUIRKS.append(f)
|
|
|
|
def get_munin_plugins():
|
|
"""Liste les plugins munin créés par le système
|
|
|
|
Retourne un dictionnaire dont la clé est le lien dans
|
|
/etc/munin/plugins, et la valeur le fichier à lier.
|
|
"""
|
|
|
|
# Dictionnaire de sortie
|
|
output = {}
|
|
|
|
# Crée un répertoire vide pour faire croire à Munin qu'on veut
|
|
# créer tous les liens...
|
|
tempdir = tempfile.mkdtemp()
|
|
|
|
# Demande à Munin quels plugins il lui semble bon nous faire
|
|
# utiliser. --families=auto,manual permet de récupérer plus de
|
|
# plugins (qu'il faut ensuite filtrer)
|
|
munin = subprocess.Popen(["/usr/sbin/munin-node-configure",
|
|
"--families=manual",
|
|
"--families=auto",
|
|
"--servicedir", tempdir,
|
|
"--shell"],
|
|
stdout = subprocess.PIPE,
|
|
stderr = subprocess.PIPE
|
|
)
|
|
munin_stdout, munin_stderr = munin.communicate()
|
|
|
|
# if munin.returncode != 0:
|
|
# raise RuntimeError, "munin-node-configure... Stderr:\n%s" % munin_stderr
|
|
|
|
munin_output_lines = munin_stdout.splitlines()
|
|
|
|
for line in munin_output_lines:
|
|
if line.startswith("ln -s"):
|
|
dst, src = line.split()[-2:]
|
|
if dst[0] == "'":
|
|
dst = dst[1:-1]
|
|
src = src[1:-1]
|
|
src = os.path.basename(src)
|
|
# filtrage
|
|
if not os.path.basename(dst) in IGNORE_PLUGINS:
|
|
output[src] = dst
|
|
|
|
os.rmdir(tempdir)
|
|
|
|
# Exécute les hacks sales sur la sortie
|
|
for quirk in QUIRKS:
|
|
quirk(output)
|
|
|
|
return output
|
|
|
|
def get_all_plugins():
|
|
"""Liste les liens de plugins munin à créer
|
|
|
|
Retourne un dictionnaire dont la clé est le lien dans
|
|
/etc/munin/plugins, et la valeur le fichier à lier.
|
|
"""
|
|
|
|
hostname = socket.gethostname()
|
|
result = get_munin_plugins()
|
|
|
|
custom_plugins = hosts_plugins.get(hostname, {})
|
|
custom_plugins.update(general_plugins)
|
|
|
|
for plugin, dest_file in custom_plugins.iteritems():
|
|
if dest_file.startswith('/'):
|
|
result[plugin] = dest_file
|
|
else:
|
|
result[plugin] = os.path.join('/usr/scripts/munin', dest_file)
|
|
|
|
return result
|
|
|
|
def list_plugins(plugins, directory):
|
|
"""Liste les plugins comme s'ils allaient être liés dans
|
|
directory"""
|
|
|
|
for name, path in sorted(plugins.items()):
|
|
print os.path.join(directory, name), '->', path
|
|
|
|
def link_plugins(plugins, directory):
|
|
"""Lie les plugins dans le répertoire directory"""
|
|
|
|
for name, path in plugins.iteritems():
|
|
try:
|
|
os.symlink(path, os.path.join(directory, name))
|
|
if options.verbose:
|
|
print "%s installé avec succès!" % name
|
|
except OSError:
|
|
print "Echec à l'installation de %s (déjà installé?)" % name
|
|
|
|
# Hack propre
|
|
def add_plugin(plugin):
|
|
"""Crée une fonction qui ajoute le plugin à la liste"""
|
|
# Les clôtures en Python, ça fait rêver...
|
|
def f(plugins, plugin=plugin):
|
|
plugins[plugin] = os.path.join(MUNIN_PATH, plugin)
|
|
return f
|
|
|
|
register_quirk(add_plugin("uptime")) # Coucou MoSaN
|
|
register_quirk(add_plugin("netstat"))
|
|
register_quirk(add_plugin("nfs_client"))
|
|
|
|
# Hacks sales
|
|
@register_quirk
|
|
def add_ifaces(plugins):
|
|
"""Ajoute les interfaces à la liste des plugins si munin n'a pas
|
|
trouvé d'interface (ou si elles ont été filtrées)"""
|
|
|
|
if not any(plugin.startswith('if_') for plugin in plugins):
|
|
# Liste les interfaces configurées sur le système
|
|
interfaces_file = None
|
|
interfaces = []
|
|
try:
|
|
interfaces_file = file('/etc/network/interfaces', 'r')
|
|
for line in interfaces_file:
|
|
line = line.split()
|
|
# Recherche d'une ligne type "iface eth0 inet static"
|
|
if line and line[0] == 'iface' and line[-1] == 'static':
|
|
interface_name = line[1]
|
|
# on dégage les interfaces sur vlan spéciaux et
|
|
# aliasées (leur nom contient ':' ou '.')
|
|
if not set('.:') & set(interface_name):
|
|
interfaces.append(interface_name)
|
|
finally:
|
|
if interfaces_file is not None:
|
|
interfaces_file.close()
|
|
|
|
for interface in interfaces:
|
|
plugins['if_%s' % interface] = os.path.join(MUNIN_PATH,'if_')
|
|
plugins['if_err_%s' % interface] = os.path.join(MUNIN_PATH, 'if_err_')
|
|
|
|
@register_quirk
|
|
def use_correct_postfix_mailstats(plugins):
|
|
"""Utilise un postfix_mailstats non buggué sur etch"""
|
|
if "postfix_mailstats" in plugins:
|
|
try:
|
|
debver_file = open('/etc/debian_version')
|
|
except IOError:
|
|
return
|
|
else:
|
|
debver = debver_file.read()
|
|
debver_file.close()
|
|
if debver.startswith('4'):
|
|
plugins["postfix_mailstats"] = "/usr/scripts/munin/postfix_mailstats"
|
|
|
|
if __name__ == "__main__":
|
|
parser = optparse.OptionParser()
|
|
parser.add_option('-d', '--directory',
|
|
help = 'Write plugin symlinks to DIR',
|
|
metavar = 'DIR',
|
|
default = '/etc/munin/plugins'
|
|
)
|
|
parser.add_option('-f', '--force',
|
|
action = 'store_true',
|
|
help = 'Remove destination directory'
|
|
)
|
|
parser.add_option('-p', '--pretend',
|
|
action = 'store_true',
|
|
help = 'Do not actually make links'
|
|
)
|
|
parser.add_option('-v', '--verbose',
|
|
action = 'store_true',
|
|
help = 'Increase verbosity'
|
|
)
|
|
(options, args) = parser.parse_args()
|
|
|
|
plugins = get_all_plugins()
|
|
|
|
if options.pretend:
|
|
list_plugins(plugins, options.directory)
|
|
else:
|
|
if options.force:
|
|
shutil.rmtree(options.directory)
|
|
os.mkdir(options.directory)
|
|
link_plugins(plugins, options.directory)
|
|
|