Through this tutorial we will refer to a very simple application that computes two random number between 1 and 100. Next we will add the ability to check through Nagios the number values and return a warning or critical if the random number falls inside a given range using a command similar to
./check_nrpe -n -H 127.0.0.1 -c runTest -a random1 33:66 67:
Follows the example application:
public class Example { private int m_iRandom1 = 0; private int m_iRandom2 = 0; private Random m_random = new Random(); /** * This method updates the variables with the next random number */ public void updateVariables() { m_iRandom1 = m_random.nextInt(100); // We want to values to be between 0 and 100 m_iRandom2 = m_random.nextInt(100); } /** * The main method */ public static void main(String[] args) throws Exception { Example example = new Example(); example.updateVariables(); // Change variable values every 5 seconds while(true) { Thread.sleep(5000); example.updateVariables(); } } }
As you can see, the application is very simple: every 5 seconds generates a new pair of random numbers. In the next section, we will add to the application the ability to answer to check_nrpe queries; to be able to perform such task, we must create a JNRPE plugin.
Every JNRPE plugin must implement the IPluginInterface interface:
public class ExamplePlugin implements IPluginInterface { private final Example m_instanceToCheck; public ExamplePlugin(Example ex) { m_instanceToCheck = ex; } @Override public ReturnValue execute(ICommandLine cl) { String sVariable = cl.getOptionValue("get"); // (1) if (sVariable.equalsIgnoreCase("random1")) return new ReturnValue("RANDOM1: " + m_instanceToCheck.getRandom1()); // (2) if (sVariable.equalsIgnoreCase("random2")) return new ReturnValue("RANDOM2: " + m_instanceToCheck.getRandom2()); // (3) return new ReturnValue(IJNRPEConstants.STATE_UNKNOWN, sVariable + " is unknown"); } }
This first version of the plugin always returns an OK state and, as text, the variable name and it's value. It will accept a 'get' command that will need as argument the variable name ("--get variable").
The code line identified by (1) means that we want the value of the 'get' option: the argument. That means that if the plugin can be invoked with a command line like :
--get random1
The line identified by (2) and by (3) are very simple: they returns an OK return value that has in the text the name of the requested variable and its value and, as return code, the OK status.
As far as we are, we created a plugin that is able to receive a single option (get) with a single argument (the variable name).
Now we have to describe this plugin to JNRPE. To describe the plugin we have to instantiate a PluginDefinition object:
IPluginInterface tp = new ExamplePlugin(example); PluginDefinition pluginDef = new PluginDefinition("TestPlugin", "Simple Test Plugin description", tp) // (1) .addOption(new PluginOption() // (2) .setOption("g") // The plugin accept the short form parameter 'g' // (3) .setLongOpt("get") // The long form parameter // (4) .setArgName("variable") // The paramater has an argument called 'variable' // (5) .setArgsOptional(false) // The parameter argument is mandatory // (6) .setRequired(true) // The parameter is mandatory // (7) );
Lets analyze the code:
Now that we have created the plugin, we have to register it inside the JNRPE plugins repository.
PluginRepository pluginRepository = new PluginRepository(); // Creates the repository pluginRepository.addPluginDefinition(pluginDef); // Adds our plugin to the repository
Now the plugin is ready and JNRPE is aware of its existence. Since a plugin can be used to execute different tasks, now we have to tell JNRPE how to use the plugin. We will accomplish that by creating a 'command' based on this plugin, much like as you would do configuring NRPE or JNRPE.
As with plugins, all commands are described through a 'command definition' object. In the following example we will define a command based on the 'TestPlugin' that will pass the 'get' parameter with the argument received by check_nrpe (or jCheckNRPE).
CommandDefinition commandDef = new CommandDefinition("runTest", "TestPlugin") // CommandName : runTest, plugin : TestPlugin .addArgument( new CommandOption("get", "$ARG1$")); // The command will pass a parameter called get to the plugi // The argument will the argument received from check_nrpe
Again, as with plugins, now we have to register the command inside the command repository:
CommandRepository commandRepository = new CommandRepository(); // Creates the command repository commandRepository.addCommandDefinition(commandDef); // register the command inside the repository
We are almost done: now we have to instantiate JNRPE and start listening for requests.
JNRPE engine = new JNRPE(pluginRepository, commandRepository); // JNRPE must be aware of both plugins and // commands repository engine.addAcceptedHost("127.0.0.1"); // Will accept requests from localhost engine.listen("127.0.0.1", 5666); // Will listen on 127.0.0.1 on port 5666
Follows the whole main method, completed with the code we discussed above.
public static void main(String[] args) throws InterruptedException { Example example = new Example(); example.updateVariables(); // Instantiate the plugin IPluginInterface tp = new ExamplePlugin(example); // Describe the plugin PluginDefinition pluginDef = new PluginDefinition("TestPlugin", "Simple Test Plugin description", tp) // PluginName : TestPlugin, .addOption(new PluginOption() .setOption("g") // The plugin accept the short form parameter 'g' .setLongOpt("get") // The long form parameter .setArgName("variable") // The paramater has an argument called 'variable' .setArgsOptional(false) // The parameter argument is mandatory .setRequired(true) // The parameter is mandatory ); PluginRepository pluginRepository = new PluginRepository(); // Creates the repository pluginRepository.addPluginDefinition(pluginDef); // Adds our plugin to the repository // Describes the command CommandDefinition commandDef = new CommandDefinition("runTest", "TestPlugin") // CommandName : runTest, plugin : TestPlugin .addArgument(new CommandOption("get", "$ARG1$")); // The command will take a parameter called get that asks for an argument // The argument will be replaced with what will be received by check_nrpe CommandRepository commandRepository = new CommandRepository(); // Creates the command repository commandRepository.addCommandDefinition(commandDef); // register the command inside the repository JNRPE engine = new JNRPE(pluginRepository, commandRepository); // JNRPE must know both plugin and command repository engine.addAcceptedHost("127.0.0.1"); // Will accept requests from localhost engine.listen("127.0.0.1", 5666); // Will listen on 127.0.0.1 on port 5666 // This is just to update the variable values of the example and is // not mandatory at all while(true) { Thread.sleep(5000); example.updateVariables(); } }
Run your java application, than try the following command:
check_nrpe -n -H 127.0.0.1 -c runTest -a random1
You just executed your first JNRPE embedded plugin!
The plugin we've created in the previous paragraph always returns OK. In this chapter we will change it so that it will be able to return WARNING or CRITICAL depending on the value of the random variables.
To perform such checks, we will add a '-w|--warning' and a '-c|--critical' parameter to our plugin. Both the -w and -c parameter will have an argument describing the waning/critical thresholds.
If the value will fall inside the warning or the critical threshold, the plugin will return a return status accordingly to the value.
Checking thresholds is very easy through the use of the ThresholdUtil class.
Below the plugin with the threshold handling code.
public class ExamplePlugin implements IPluginInterface { private final Example m_instanceToCheck; public ExamplePlugin(Example ex) { m_instanceToCheck = ex; } @Override public ReturnValue execute(ICommandLine cl) { String sVariable = cl.getOptionValue("get"); int iValue; if (sVariable.equalsIgnoreCase("random1")) iValue = m_instanceToCheck.getRandom1(); else if (sVariable.equalsIgnoreCase("random2")) iValue = m_instanceToCheck.getRandom2(); else return new ReturnValue(IJNRPEConstants.STATE_UNKNOWN, sVariable + " is unknown"); //(1) String sCriticalThreshold = cl.getOptionValue("critical"); //(2) String sWarningThreshold = cl.getOptionValue("warning"); //(3) if (ThresholdUtil.isValueInRange(sCriticalThreshold, iValue)) //(4) return new ReturnValue("CRITICAL - " + sVariable + " : " + iValue); if (ThresholdUtil.isValueInRange(sWarningThreshold, iValue)) //(5) return new ReturnValue("WARNING - " + sVariable + " : " +iValue); return new ReturnValue("OK - " + sVariable + " : " +iValue); //(6) } }
The line identified by (1) returns an UNKNOWN state if the requested variable is unknown. The lines identified by (2) and (3) simply reads the values of the critical and warning threshold definitions.
The line identified by (4) checks if the requested variable value falls inside the critical threshold read at line (2). If yes, than return a CRITICAL status.
The line identified by (5) hecks if the requested variable value falls inside the warning threshold read at line (3). If yes, than return a WARNING status.
At line (6) we simply return an OK status.
Now that we have changed the plugin class, we have to change the plugin definition too to describe the new 'warning' and 'critical' parameters:
PluginDefinition pluginDef = new PluginDefinition("TestPlugin", "Simple Test Plugin", tp) .addOption(new PluginOption() .setOption("g") .setLongOpt("get") .setArgName("variable") .setArgsOptional(false) .setRequired(true)) .addOption(new PluginOption() .setOption("w") .setLongOpt("warning") .setArgName("value") .setArgsOptional(false) .setRequired(true)) .addOption(new PluginOption() .setOption("c") .setLongOpt("critical") .setArgName("value") .setArgsOptional(false) .setRequired(true) );
Now that the new parameters are defined, we can change our command definition:
CommandDefinition commandDef = new CommandDefinition("runTest", "TestPlugin") .addArgument(new CommandOption("get", "$ARG1$")) .addArgument(new CommandOption("warning", "$ARG2$")) .addArgument(new CommandOption("critical", "$ARG3$") );
Try to invoke the plugin through the command:
./check_nrpe -n -H 127.0.0.1 -c runTest -a random1 33:66 67:
Invoke it many time: you'll notice that sometime you'll get a warning state, sometime a critical and sometime an OK.
Good, you've embedded JNRPE into your application!