This post took a bit longer than a week to write, as I’ve been heavily swamped by other projects. But enough about that - away we go.
We’re going to go over the basics of an event broker module. We’re not going to deal too much with the insides of Nagios and the functions that Nagios provides to make our life easier. We’ll go over those items in the future. What we’ll go over in this article, however, is building a basic event broker module skeleton which loads inside nagios. It’s not much. However, it does lay down the basic footprint needed for future discussion. Next week, we’ll deal with handling changes in status.
As stated in my previous article, an event broker is basically a shared library with at least two functions (entry-points) required. We’re going to start off with a skeleton of an event broker which is detailed below and go over what it contains:
#ifndef NSCORE
#define NSCORE
#endif
/* include the needed event broker header files */
#include "../include/nebmodules.h"
#include "../include/nebcallbacks.h"
#include "../include/nebstructs.h"
#include "../include/broker.h"
/* include some Nagios stuff as well */
#include "../include/config.h"
#include "../include/common.h"
#include "../include/nagios.h"
#include "../include/objects.h"
/* specify event broker API version (required) */
NEB_API_VERSION(CURRENT_NEB_API_VERSION);
// Our module handle
void *basic_module_handle=NULL;
// This function gets called when the module gets loaded by the event broker
int nebmodule_init(int flags, char *args, nebmodule *handle) {
basic_module_handle = handle;
write_to_logs_and_console("Loading Basic Event Broker Interface...",NSLOG_INFO_MESSAGE,TRUE);
return 0;
}
// This is our unloading function which gets called by the neb
int nebmodule_deinit(int flags, int reason)
{
write_to_logs_and_console("Unloading Basic Event Broker Interface...",NSLOG_INFO_MESSAGE,TRUE);
return 0;
}
To compile properly, you’ll need access to the nagios header files. The easiest way to do this is to download the source of the Nagios version you are running and extract it. Then inside the nagios-2.xxx directory, create a new directory to store your event broker code. We’re going to store it in a directory called ‘basic’ for simplicity sake. Save it to basic.c, and compile it using gcc as so:
gcc -shared basic.c -o basic.o
This will compiled basic.c as a shared library, and save the compiled form as basic.o. Now you must decide where you want to keep your compiled modules. We’ll store our modules in /usr/local/libexec/nagios/modules. You can change this path based on your installation requirements. Next, you must modify your nagios.cfg to contain the proper event broker related options.
event_broker_options=-1
broker_module=/usr/local/libexec/nagios/modules/basic.o
The event_broker_options declaration dictates what events you want the event broker to manage. From current understanding, there is only 0, which means to monitor nothing, and -1 which means to monitor everything. The second directive broker_module, points to our broker module which we compiled and moved to a standard directory. The broker_module takes 1 or more parameters, seperated by spaces. The first is the path to the module, and the remaining parameters (none shown here), are space seperated parameters to pass to your broker module. Parameters will be covered in later articles.
Now, if you run Nagios by hand, using nagios <path to modified nagios.cfg>, you should see Nagios start up, along with the lines of:
Loading Basic Event Broker Interface...
If you look at the Nagios log file, you’ll see:
Loading Basic Event Broker Interface...
Event broker module '/usr/local/groundwork/modules/basic.o' initialized successfully.
This tells us our event broker module is configured properly in nagios.cfg, and that it is correctly loading.
In the future, changes to the basic.c file should be made, then the gcc command should be used to recompile. Then copy the newly created basic.o module to the module directory. Re-running nagios will start the changed event broker module.
Okay, we’re now going to go over our skeleton module.
#ifndef NSCORE
#define NSCORE
#endif
These lines will define the constant NSCORE, if not already done so. You must do this before including the following header files, as this will allow us to see additional structures. The name NSCORE probably comes from the combination of Net-Saint Core. As Net-Saint was the name of nagios before, and core is usually given to the files which make up the core of nagios, of which needs access to all data structures.
#include "../include/nebmodules.h"
#include "../include/nebcallbacks.h"
#include "../include/nebstructs.h"
#include "../include/broker.h"
These header files define the structures, constants, and functions which we will use as the basic level of being an event broker. We’ll go over the details of these header files and what they contain in later discussion.
/* include some Nagios stuff as well */
#include "../include/config.h"
#include "../include/common.h"
#include "../include/nagios.h"
#include "../include/objects.h"
These headers contain basic data structures and configuration parameters for the nagios system. config.h is created when you run the configure script inside the source directory. If gcc complains of a missing config.h, run configure (with the appropriate flags, especially -enable-event-broker), and try compiling again. We don’t use all the data structures and functions exposed by these header files in this module as it stands now; however, we will be using them in later discussion.
NEB_API_VERSION(CURRENT_NEB_API_VERSION)
This macro needs to be included for the purpose of making sure that when you load an event broker module with nagios, it will be loaded against the right version of the event broker api. If the event broker api differs in anyway, the CURRENT_NEB_API_VERSION will change, and Nagios will not load the module.
// Our module handle
void *basic_module_handle=NULL;
This global variable is a pointer to the memory address of our module. We’ll use this from time to time when registering callbacks. We don’t register callbacks currently, but we will require this later on.
// This function gets called when the module gets loaded by the event broker
int nebmodule_init(int flags, char *args, nebmodule *handle) {
basic_module_handle = handle;
write_to_logs_and_console("Loading Basic Event Broker Interface...",NSLOG_INFO_MESSAGE,TRUE);
return 0;
}
Finally, some meat and potatoes. The nebmodule_init function gets called when the Event Broker attempts to load our module. There are three parameters which get passed to this function. flags is usually a constant which defines the context in which the modules are loading. In the beginning when nagios first loads all modules, this will be equal to the constant NEBMODULE_NORMAL_LOAD. The string args is the same space seperated parameter list that you provide in nagios.cfg (if any). The nebmodule pointer handle is the memory address of our module. The first line in this function assigns basic_module_handle the same address which handle points to. This will be used later when we register our first callbacks. The next line uses a function exposed by nagios. It’s one of the many logging functions that nagios uses and in turn we use. write_to_logs_and_console takes three parameters. The first is the text string of the message you want to write. The second is the type of message. This is going to be one of the many constants that define what type of message it is. But for now, use NSLOG_INFO_MESSAGE, which means this message is informational and doesn’t have any real severity. The last parameter is a boolean which states if we want the text written to the console (in this case, we do).
// This is our unloading function which gets called by the neb
int nebmodule_deinit(int flags, int reason)
{
write_to_logs_and_console("Unloading Basic Event Broker Interface...",NSLOG_INFO_MESSAGE,TRUE);
return 0;
}
This is the last required function needed in our module. nebmodule_deinit gets called whenever nagios needs to gracefully unload modules. If nagios is forced to shutdown; however, this function may not be called. So don’t count on it being called in all circumstances. (In fact, I really can’t find a scenario when this DOES get called; however, the sparse code that there is available in current nagios distributions does have this function, so we’ll keep it there for safety sake). In this, we use the same write_to_logs_and_console function to print a friendly message that we are shutting down.
That’s the basic structure of an event broker module. It’s very simple in nature; however, next time we’ll actually start registering callbacks so we can get told when certain events happen in the nagios process. Add some comments, let me know where you want this to go. Do you want to store status data in a database? In a directory? In some other fashion? Do you want to talk more about the logging functions, or the utility functions in nagios that we can use? Add comments, and we’ll discuss them in future posts.
Until next time (which will hopefully be a week), you should dig into the header files that were included in our sample module. This will give you a heads up during the next post when referencing constants and data structures.
If there’s anything you need to discuss which isn’t related to this article, feel free to contact me at [email protected]
Thanks for the read. Have a wonderful New Years.