Back to index

munin  2.0.1
munin.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 """
00004 Makes it easy to create munin plugins...
00005 
00006     http://munin-monitoring.org/wiki/protocol-config
00007 
00008 Morten Siebuhr
00009 sbhr@sbhr.dk
00010 12/12 2008
00011 """
00012 
00013 def getOptionOrDefault(option, default=None):
00014     from os import environ
00015     return environ.setdefault(option, default)
00016 
00017 class DataSource(object):
00018     """Represents a single data source.
00019 
00020     This class should not be directly created by the user - this is done
00021     transparently by the Plugin-class."""
00022 
00023     __slots__ = ['label', 'cdef', 'draw', 'graph', 'info', 'extinfo', 'max',
00024             'min', 'negative', 'type', 'warning', 'critical', 'colour',
00025             'skipdraw', 'sum', 'stack', 'line', 'value']
00026 
00027     # Allowed draw modes
00028     _draw_modes = ['AREA', 'STACK', \
00029             'LINE1', 'LINE2', 'LINE3', \
00030             'LINESTACK1', 'LINESTACK2', 'LINESTACK3', \
00031             'AREASTACK']
00032 
00033     def get_config(self):
00034         if hasattr(self, "draw"):
00035             assert self.draw in self._draw_modes
00036 
00037         data = dict()
00038 
00039         for attr in self.__slots__:
00040             if attr == 'value':
00041                 continue
00042             if hasattr(self, attr):
00043                 data[attr] = self.__getattribute__(attr)
00044 
00045         return data
00046 
00047     def get_value(self, data_source_name):
00048         assert hasattr(self, "value")
00049 
00050         if callable(self.value):
00051             return self.value(data_source_name)
00052 
00053         return self.value
00054 
00055 class Plugin(object):
00056     """Facilitates OO creation of Munin plugins.
00057 
00058     #!/usr/bin/env python
00059     from munin import Plugin
00060 
00061     p = Plugin("Test measurement", "test/second", category="junk")
00062     p.autoconf = False
00063 
00064     for name, value in {'a': 1, 'b': 2}:
00065         p[ name ].label = name
00066         p[ name ].value = value
00067 
00068     p.run()
00069 
00070     (It will itself detect how the script is called and create the proper
00071     output.)
00072 
00073      * If 'autoconf' is a callable, it will be called when running autoconf.
00074 
00075     """
00076 
00077     def __init__(self, title, vlabel,
00078             category="misc", info="",
00079             args="",
00080             scale=True):
00081         """Sets up the plugin; title, vertical label, category -- all things
00082         that are global for the plugin.
00083         """
00084 
00085         self.title = title
00086         self.vlabel = vlabel
00087         self.category = category
00088         self.info = info
00089         self.args = args
00090         self.scale = scale
00091 
00092         self._values = dict()
00093 
00094         assert type(title) is str
00095         assert type(vlabel) is str
00096         assert type(category) is str
00097 
00098     def __getitem__(self, key):
00099         if not key in self._values:
00100             self._values[ key ] = DataSource()
00101         return self._values[ key ]
00102 
00103     def __setitem__(self, key, value):
00104         self._values[key] = value
00105 
00106     def __delitem__(self, key):
00107         if key in self._values:
00108             del self._values[key]
00109 
00110     def __contains__(self, key):
00111         return key in self._values
00112 
00113     def _print_values(self):
00114         """Print the values for all registered data sources.
00115 
00116         Similar to running with "values"-argument."""
00117         for prefix, line in self._values.items():
00118             value = line.get_value(prefix)
00119             assert type(value) is int
00120             print "%s.value %s" % (prefix, value)
00121 
00122     def _print_config(self):
00123         """Print the output needed for setting up the graph - i.e. when the
00124         plugin is run with "config"-argument."""
00125         # Print graph_-variables
00126 
00127         for prop in ['title', 'category', 'vlabel', 'info', 'args', 'draw']:
00128             if not prop in self.__dict__:
00129                 continue
00130             if not self.__dict__[ prop ]:
00131                 continue
00132             print "graph_%s %s" % (prop, self.__dict__[ prop ])
00133 
00134         # Print setup for individual lines
00135         for prefix, line in self._values.items():
00136 
00137             # The "label" attribute MUST be defined
00138             assert "label" in line.get_config().keys(), "No 'label' defined."
00139 
00140             for attr, value in line.get_config().items():
00141                 print "%s.%s %s" % (prefix, attr, value)
00142 
00143     def _print_autoconf(self):
00144         """Running autoconf-mode."""
00145         aconf = False
00146 
00147         if hasattr(self, "autoconf"):
00148             if callable(self.autoconf):
00149                 aconf = self.autoconf()
00150             else:
00151                 aconf = self.autoconf
00152 
00153         if bool(aconf):
00154             print "YES"
00155         else:
00156             print "NO"
00157 
00158     def run(self, force_mode=None):
00159         """Run the plugin and "do the right thing"^(TM)."""
00160 
00161         mode = force_mode
00162 
00163         if mode == None:
00164             import sys
00165             if len(sys.argv) == 2:
00166                 mode = sys.argv[1]
00167 
00168         if mode == "autoconf":
00169             self._print_autoconf()
00170             return
00171 
00172         if mode == "config":
00173             self._print_config()
00174             return
00175 
00176         self._print_values()