Mark's Meanderings

home

Using the Nagios API

27 Oct 2011

This entry talks about how to set up and test the Nagios API in your environment. We cover the CLI and also using it from the web.

Getting the Code

For now, this project doesn't support packaging or have a setup.py file, so you will have to do it by hand. This isn't very hard, but since the project is in such a state of growth, it's easier this way.

First, you need to check out the code on your local Nagios server. The API daemon needs to run on a machine where it has access to the files that Nagios creates -- the status file, log file, and external commands pipe. This should be on your central Nagios server.

If you are using Nagios in distributed mode, you want to run the daemon on the central machine that receives all of the distributed check results. I.e., the machine that sends the alerts.

$ git clone git://github.com/xb95/nagios-api.git

That command creates a directory appropriately named nagios-api. Inside this directory are several executables, some documentation, and a library directory.

Test Run

Before we can run it, we have to figure out where your Nagios installation is stashing the files we need. Most of these are probably in /etc/nagios3/nagios.cfg, so open that file up and look for:

With these three configuration options, you can now run the API daemon:

$ ./nagios-api -s STATUS_FILE -c COMMAND_FILE -l LOG_FILE

What you should see next is something like:

[Thu Oct 27 14:03:20 2011] {nagios-api:info} Listening on port 6315, starting to rock and roll!

If you do -- congrats! The API daemon is now up and running. If you don't, the most likely culprit will be that it can't find one of the files you indicate. Also, if it can't bind on port 6315, then it would fail. (You can change the port with -p PORT_NUMBER.)

Testing the API

Great. The daemon is up and running ... now what? Well, let's make sure that it worked. Let's break out the CLI program, nagios-cli, and use it. This should work:

$ ./nagios-cli hosts

If everything is working, you should see a list of all of the hosts defined in your Nagios configuration. This isn't particularly exciting information, so let's use the raw mode and see exactly what the global state object says:

$ ./nagios-cli --raw state | python -mjson.tool
{
    "absinthe": {
        "active_checks_enabled": "1", 
        "comments": {}, 
        "current_state": "0", 
        "downtimes": {}, 
        "last_check": "1319742372", 
        "last_hard_state": "0", 
        "last_notification": "0", 
        "notifications_enabled": "1", 
        "plugin_output": "PING OK - Packet loss = 0%, RTA = 0.19 ms", 
        "problem_has_been_acknowledged": "0", 
        "scheduled_downtime_depth": "0", 
        "services": {
            "Adaptec RAID": {
                "active_checks_enabled": "1", 
                "comments": {}, 
                "current_state": "0", 
                "downtimes": {}, 
                "last_check": "1319742359", 
                "last_hard_state": "0", 
                "last_notification": "0", 
                "notifications_enabled": "1", 
                "plugin_output": "Logical Device 0 Optimal,Controller Optimal,Battery Status ZMM Optimal", 
                "problem_has_been_acknowledged": "0", 
                "scheduled_downtime_depth": "0"
            }, 
            "PING": {
                "active_checks_enabled": "1", 
...

Now! Data! You will see a rather large JSON format dump showing a lot of information about every host, service, comment, and downtime defined in Nagios right now. It is updated automatically from the status object Nagios writes out every ~10 seconds.

The nagios-cli tool in raw mode is simply doing an HTTP request for us. The above output could also be retrieved with a simple GET:

$ curl http://localhost:6315/state | python -mjson.tool

The next thing you might want to do is actually do something with the CLI -- say, schedule a downtime for a host that you're about to do an upgrade on. First, let's see what options the CLI has:

$ ./nagios-cli -h

As of this writing there are downtime related options and then two status commands for viewing hosts and services. More will be added later, but let's play with the downtimes.

First, let's pick one of our hosts to operate on. Let's pretend that web01 needs an upgrade. From the CLI, we can easily put it into downtime:

$ ./nagios-cli schedule-downtime web01 4h

Simply, that command puts in a four hour fixed downtime starting immediately for the host web01. If you wanted to put in downtimes for the host and all of the services on it, you can do that with the --recursive option:

$ ./nagios-cli schedule-downtime web01 4h -r

To see all of the options this command supports:

$ ./nagios-cli schedule-downtime -h

Later, when we're done with the upgrade, we can cancel that downtime:

$ ./nagios-cli cancel-downtime web01

Or cancel the downtime for the host and any services that are in downtime:

$ ./nagios-cli cancel-downtime web01 -r

That's a short and easy introduction to the CLI.

Using the API from the Web

If you're like me, the CLI is your one-stop shop for everything. I generally work from terminal because I can express whatever I need easily and manipulate the text with a million and one tools for every occasion. That's great.

Sometimes, though, I just want a web GUI. I don't really want to spend a lot of time debating the finer points of CLIs and GUIs, but here you don't have to -- the API is a RESTful JSON system because it works great from the command line and the web browser.

For now, let's kill the running nagios-api and give it a new command line option:

$ ./nagios-api -s STATUS_FILE -c COMMAND_FILE -l LOG_FILE -o \*

(You have to escape the asterisk, at leats from Bash.) The -o parameter instructs the daemon to send out a Access-Control-Allow-Origin header with every response. This header is part of the relatively new Cross-Origin Resource Sharing spec.

A Short History Lesson

For many years, your web browser has been locked in a box that only allows JavaScript and other dynamic tools to talk to the same origin that served them. I.e., if you load a JavaScript from foo.com on port 80, any HTTP requests that code makes must target foo.com on port 80.

This is called the same origin policy and has been a cornerstone of Internet security for many years. It was a very smart idea that makes a lot of sense, but in the modern day of "dynamic everything!", it has posed some interesting challenges to web developers.

Anyway, this has changed recently with the introduction of the CORS spec linked above. This spec is supported in recent versions of all major browsers (Opera does not support it) and allows us to write JavaScript that targets the Nagios API, even if that API is running on a different host or port. (Which it undoubtedly is.)

Now your API is configured to export the appropriate header (in this case, "allow everybody") and you can write JavaScript that targets the API. Let's test this out.

First, you need to be able to reach your Nagios server from your browser. Try navigating to it on the port you configured (default is 6315), and you should see something like this:

{"content": "Invalid request URI", "success": false}

If you don't see that, then you should stop here and figure out what's wrong. Are you on the right network? VPN up? You know your configuration better than I do.

Once that works, now navigate your browser to jquery.com. We use this site because the next step requires the jQuery library, and the easiest way to make sure it's loaded is just to go to their site in the browser.

Now, fire up your browser's development console. I'm only familiar with this in Chrome, if you use Firefox or Safari, you will have to modify these instructions.

In the development console, you can paste the following code to define a little processing function that we're going to call shortly.

function get_status(data, t, j) {
    if (!data.success) return;
    for (var host in data.content) {
        console.log(host + ' ' + data.content[host].plugin_output);
    }
}

Make sure to hit enter. Okay, now we can actually hit the API and do something. Adjust the following snippet with the appropriate URL, then paste it in and hit enter:

$.getJSON('http://my-nagios-server:6315/state', get_status);

You should see, very shortly, a dump of all of the hosts in your Nagios system with the most recent output from whatever host check you use. In my case I see a bunch of PING results.

And that's it! You can access the API from your browser.

Productionizing

To make sure that your API stays up and running, I would suggest you consider the following:

That's it. Now the API should be resilient to failure and allow you to depend on it in the rest of your infrastructure.

Further Development

The future of the Nagios API is somewhat dependent on what the community needs. For my own purposes, it already does everything I need. Certainly over time I will need a few more functions to be implemented, but that's easy.

Most of my future plans involve the Next Generation of Monitoring Software, whatever it ends up being called, which is a Nagios replacement that I've had cooking in my head for years now. I'll be writing more about that soon, though.