Tutorial¶
This tutorial will provide an introduction and examples for writing Icinga plugins using Pycinga.
Prerequisites¶
Before beginning, make sure that Pycinga is installed. To verify this, the following should run without raising an exception:
>>> import pycinga
Since Icinga plug-ins are simply executable applications, Icinga itself is not required to develop plug-ins.
A Simple Plugin¶
All plugins must inherit from the Plugin
class.
Icinga plug-ins are expected to conform to a standard set of command line
arguments (in addition to any custom arguments that may be added), and the
Pycinga Plugin class already knows how to read and process these arguments.
After inheriting from the class, check()
should be implemented, which should perform whatever check the plugin does,
and return a Response
object.
Here is a basic Icinga script:
import pycinga
from pycinga import Plugin, Response
class MyCheck(Plugin):
def check(self):
return Response(pycinga.OK, "Everything is ok!")
if __name__ == "__main__":
# Instantiate the plugin, check it, and then exit
MyCheck().check().exit()
Save this to a Python file and run it, and you should see the following output:
$ python my_check.py
OK: Everything is ok!
And the exit status will be 0
, meaning everything is good.
This is the most basic Icinga plug-in that can be created. Now, let’s create one that is more feature-complete.
Returning Proper Responses¶
In the first example, we simply returned pycinga.OK
on every
check. Realistically, we would get a value and return OK
, WARNING
,
or CRITICAL
depending on that value. According to the Icinga developer
guidelines, the warning and critical ranges must be able to be set via
the command line via -w
and -c
, respectively. Pycinga plugins
do this for you automatically, as we shall see in this section.
Let’s enhance our check to use a value, and return a proper response status for that value:
import pycinga
from pycinga import Plugin
class MyCheck(Plugin):
def check(self):
# Static for this example, but imagine in a real world plugin
# that this would be calculated.
value = 27
# Return a response for that value
return self.response_for_value(value)
This check now has some numeric value which we’ve set to a static 27
for the purpose of this example. The important piece is that the plugin
calls response_for_value()
to generate
a response based on that value. This method takes into account the warning
and critical ranges set by the plugin and the command line.
Since we didn’t set any defaults for the warning and critical range,
we’ll find that the check will be OK
by default:
$ python my_check.py
OK:
By introducing some ranges, we can see that the plugin automatically
works. In this case, 27 is outside of the warning range, but still not
critical. The plugin properly returns WARN
:
$ python my_check.py -w 10:20 -c 0:30
WARN:
And again, if we modify the ranges slightly, we can get the plugin to consider the value critical:
$ python my_check.py -w 5:10 -c 0:20
CRIT:
Note on ranges: If you’re unfamiliar with Icinga ranges, it may not be
clear how exactly they’re working. Ranges default to exclusive, meaning
a range of 10:20
means that a value is included in this range if the
value is < 10 OR > 20
. For more details on Icinga range format, it is
fully documented in the Range
documentation.
Adding Performance Data¶
Icinga plug-ins can also output metrics which are useful for 3rd party applications and can also be read on the Icinga dashboard. Pycinga provides an easy way to add performance data to responses. Extending our example once again:
import pycinga
from pycinga import Plugin
class MyCheck(Plugin):
def check(self):
# Static for this example, but imagine in a real world plugin
# that this would be calculated.
value = 27
# Return a response for that value
result = self.response_for_value(value)
result.set_perf_data("some_key", value)
result.set_perf_data("zero", 0)
return result
The set_perf_data()
function can be used
to set performance data on the response. If we run the check now, we should
see output similar to the following:
$ python my_check.py
OK:|some_key=27;;;; zero=0;;;;
Note that the extra semicolons are in order to comply with the standard
performance data format and can contain additional information. See
PerfData
for more information.
Custom Command-line Options and Arguments¶
Often checks can require additional command line options. Since Pycinga
plugins parse the command line on their own, you should define additional
options on the plugin itself, rather than attempting to use your own command
line parser. Pycinga uses Python’s built-in argparse
library.
We’ll extend our example to add an option to multiply the value by the given option value::
import pycinga
from pycinga import Plugin, make_option
class MyCheck(Plugin):
multiply_by = make_option("--multiply-by", type="int")
def check(self):
# Static for this example, but imagine in a real world plugin
# that this would be calculated.
value = 27
# Multiply the value if we were given the flag
if self.options.multiply_by:
value = value * self.options.multiply_by
return self.response_for_value(value, str(value))
We’ve added the option multiply_by
. If we run the check without the
option, we see the normal output:
$ python my_check.py
OK: 27
But by adding a number to multiply by, we’ll get different output:
$ python my_check.py --multiply-by 10
OK: 270