Starting with the Zabbix API

The approaches we looked at earlier—direct database edits and XML import/export—were either risky or limited. Editing the database is risky because there is very little validation, and upgrading to a newer version of Zabbix can change the database schema, making our tools and approaches invalid. XML import/export was nice, but very limited—it did not allow modifying users, network discovery rules, actions lots, and lots of things in the Zabbix configuration.

This is where the Zabbix API could help. It is a JSON-based interface to Zabbix configuration and data. It offers way more functionality than XML import/export does, although there are still bits and pieces of configuration that cannot be controlled using it.

The Zabbix API currently is frontend based: it is implemented in PHP. To use it, we connect to the web server running the frontend and issue our requests. There are a lot of ways to do this, but here, we will try to do things in a manner that is language independent—we will use curl and issue the requests from the shell.

Simple operations

The Zabbix API is request-response based. We send a request and get a response—either the data we requested or a success/failure indicator. Let's look at some simple, practical examples of what one can do with the API. We will use simple curl requests to the API. Let's try this on the Zabbix server:

$ curl -s -X POST -H 'Content-Type: application/json-rpc' -d '' http://127.0.0.1/zabbix/api_jsonrpc.php

In this request, we use the POST method and send the JSON string with the -d parameter—empty for now. We also specify the -s parameter, which enables silent or quiet mode and suppresses progress and error messages. The URL is the Zabbix API endpoint, api_jsonrpc.php. This will be the same for all API requests. Additionally, we specify the content type to be application/json-rpc. This is required. If omitted, the Zabbix API will return an empty response, which does not help much. The request we issued should return a response like this:

{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid Request.","data":"JSON-rpc version is not specified."},"id":null}

That did not work, but at least there's an error message. Let's proceed with more valid requests now.

Obtaining the API version

One of the simplest things we can do is query the API for the Zabbix version. This will return the frontend version, which is considered to be the same as the API version. This is the only request that does not require being logged in, besides the login request itself.

To make it easier to edit and issue the requests, let's assign the JSON to a variable, which we will then use in the curl command.

Tip

Alternatively, you can put the JSON string in a file and pass the file contents to curl as -d @file_name.

$ json='{"jsonrpc":"2.0","method":"apiinfo.version","id":1}'

We are using a method called apiinfo.version. How to know which methods are available and what their names are? That information can be found in the Zabbix manual, and we will explore it a bit later. Let's send this request to the API now. API responses lack a trailing newline, and that might make them harder to read—let's also add a newline in the curl command:

$ curl -s -w '
' -X POST -H 'Content-Type: application/json-rpc' -d "$json" http://localhost/zabbix/api_jsonrpc.php

Notice the use of the $json variable in double quotes for the -d parameter and the -w parameter to add the newline. This command should return the API version:

{"jsonrpc":"2.0","result":"3.0.0","id":1}

The version of this instance is 3.0.0. What about the jsonrpc and id values? The jsonrpc value specifies the JSON-RPC version itself. The Zabbix API uses version 2.0, so this will be the same in all requests and all responses. The id value was specified by us in the request, and the response had the same value. It could be useful if we used a framework that allowed asynchronous requests and responses—that way, we could correlate the responses to requests. JSON also supports batching, where multiple requests can be sent in a single connection and responses can be matched by the ID, but this feature is currently broken in Zabbix 3.0.

Logging in

Before one can perform any useful operations via the API, they must log in. Our JSON string would be as follows:

$ json='{"jsonrpc":"2.0","method":"user.login","id":2,"params":{"user":"Admin","password":"zabbix"}}'

Now, run the same curl command we used to get the API version. In all further API requests, we will only change the json variable and then reuse the same curl command. In this case, assuming a correct username and password, it should return the following:

{"jsonrpc":"2.0","result":"df83119ab78bbeb2065049412309f9b4","id":2}

Tip

We increased the request ID to 2. That was not really required—we could have used 3, 5, or 1013. We could have used 1 again—the way we use the API, all requests have a very obvious response, so we do not care about the ID at all. The response still did have the same ID as our request, 2.

This response also has an alphanumeric string in the result property, which is very important for all further work with the API. This is an authentication token or session ID that we will have to submit with all subsequent requests. For our tests, just copy that string and use it in the json variable later.

Enabling and disabling hosts

Hosts may be enabled or disabled by setting a single value. Let's disable our IPMI host and re-enable it a moment later. To do this, we will need the host ID. Usually, when using the API, we'd query the API itself for the ID. In this case, let's keep things simple and look up the ID in the host properties— as with the item before, open the host properties and copy the value for the hostid parameter from the URL. With that number available, let's set our JSON variable:

$ json='{"jsonrpc":"2.0","method":"host.update","params":{"hostid":"10132","status":1},"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

Tip

We got back to using an ID of 1. It really does not matter when using curl like this.

Run the curl command:

{"jsonrpc":"2.0","result":{"hostids":["10132"]},"id":1}

This should indicate success, and the host should be disabled—check the host state in the frontend. Enabling it again is easy, too:

$ json='{"jsonrpc":"2.0","method":"host.update","params":{"hostid":"10132","status":0},"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

Run the curl command again to re-enable this host.

Creating a host

Now on to creating a host using the API. Let's set our JSON variable:

$ json='{"jsonrpc":"2.0","method":"host.create","params":{"host":"API created host","interfaces":[{"type":1,"main":1,"useip":1,"ip":"127.0.0.2","dns":"","port":"10050"}],"groups":[{"groupid":"2"}],"templates":[{"templateid":"10104"}]},"auth": "df83119ab78bbeb2065049412309f9b4","id":1}'

In the default Zabbix database, the group ID of 2 should correspond to the Linux servers group, and the template ID of 10104 should correspond to the Template ICMP Ping template. If the IDs are different on your system, change them in this JSON string. Run the curl command now, and the host should be created successfully:

{"jsonrpc":"2.0","result":{"hostids":["10148"]},"id":1}

As part of the response, we also got the ID of the new host. Feel free to verify in the frontend that this host has been created.

Deleting a host

And the returned ID will be useful now. Let's delete the host we just created:

$ json='{"jsonrpc":"2.0","method":"host.delete","params":["10148"],"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

Note

Make sure the host ID in this request is the same as was returned in the previous request; otherwise, a different host could be deleted.

Run the curl command again. The host should be successfully deleted.

{"jsonrpc":"2.0","result":{"hostids":["10148"]},"id":1}

Creating a value map

Value maps could not be controlled via the API before Zabbix 3.0. They were needed for many templates, though, and people resorted to SQL scripts or even manually creating value maps with hundreds of entries. That's dedication. In Zabbix 3.0, things are much easier, and now, value maps are supported both in the API and XML import/export. Let's create a small value map:

$ json='{"jsonrpc":"2.0","method":"valuemap.create","params":{"name":"Mapping things","mappings":[{"value":"this","newvalue":"that"},{"value":"foo","newvalue":"bar"}]},"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

Run the curl command:

{"jsonrpc":"2.0","result":{"valuemapids":["16"]},"id":1}

If you check the new value map in the frontend, it is a bit easier to read than in that JSON:

Creating a value map

Tip

We covered value maps in Chapter 3, Monitoring with Zabbix Agents and Basic Protocols.

Obtaining history and trends

The methods we have discussed so far mostly dealt with configuration. We may also query some historical data. For example, to grab item history data, we would need to know several things:

  • Item ID
  • The Type of information setting for that item

Both of these can be found out by opening the item properties in the configuration section—the ID will be in the URL, and the type of information will be in that dropdown. Why do we have to specify the type of information? Unfortunately, the Zabbix API does not look it up for us but tries to find the values only in a specific table. By default, the history_uint (integer values) table is queried. To get the values for the CPU load item on A test host, the JSON string would look like this:

$ json='{"jsonrpc":"2.0","method":"history.get","params":{"history":0,"itemids":"23668","limit":3},"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

Note

Remember to replace both auth and itemid for this query.

Here are a couple extra parameters worth discussing here:

  • The history parameter tells the API which table to query. With 0, the history table is queried. With 1, the history_str table is queried. With 2, the history_log table is queried. With 3, history_int is queried (which was the default). With 4, the history_text table is queried. We must manually match this value to the setting in the item properties.
  • The limit parameter limits the number of entries returned. This is quite useful here, as an item could have lots and lots of values. By the way, limit is supported for all other methods as well—we can limit the number of entries when retrieving hosts, items, and all other entities.

Now, run the curl command:

{"jsonrpc":"2.0","result":[{"itemid":"23668","clock":"1430988898","value":"0.0000","ns":"215287328"},{"itemid":"23668","clock":"1430988928","value":"0.0000","ns":"221534597"},{"itemid":"23668","clock":"1430988958","value":"0.0000","ns":"229668635"}],"id":1}

We got our three values, but the output is a bit hard to read. There are many ways to format JSON strings, but in the shell, the easiest would be using Perl or Python commands. Rerun the curl command and append to it | json_pp:

$ curl … | json_pp

Tip

You might also have json_xs, which will have better performance, but performance should be no concern at all for us at this time.

This will invoke the Perl JSON tool, where pp stands for pure Perl, and the output will be a bit more readable:

{
  "jsonrpc" : "2.0",
  "id" : 1,
  "result" : [
    {
        "clock" : "1430988898",
        "itemid" : "23668",
        "value" : "0.0000",
        "ns" : "215287328"
    },
    {
        "ns" : "221534597",
        "value" : "0.0000",
        "itemid" : "23668",
        "clock" : "1430988928"
    },
    {
        "value" : "0.0000",
        "ns" : "229668635",
        "clock" : "1430988958",
        "itemid" : "23668"
    }
  ]
}

Tip

Notice how the output isn't really sorted. Ordering does not mean anything with JSON data, so tools do not normally sort the output.

Alternatively, use python -mjsontool, which will invoke Python's JSON tool module. That's a bit more typing, though.

In the output from the history.get method, each value is accompanied with an item ID, UNIX timestamp, and nanosecond information, the same as the history tables we looked at earlier. That's not very surprising, as the API output comes from those tables. If we convert these values to human-readable format as discussed before by running date -d@<UNIX timestamp>, we will see that they are not recent—actually, they are the oldest values. We can get the most recent values by adding the sortfield and sortorder parameters:

$ json='{"jsonrpc":"2.0","method":"history.get","params":{"history":0,"itemids":"23668","limit":3,"sortfield":"clock","sortorder":"DESC"},"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

These will sort the output by the clock value in descending order and then grab the three most recent values—check the returned Unix timestamps to make sure of that. If there are multiple values with the same clock value, other fields will not be used for secondary sorting.

We can also retrieve trend data—a new feature in Zabbix 3.0:

$ json='{"jsonrpc":"2.0","method":"trend.get","params":{"itemids":"23668","limit":3},"auth":"df83119ab78bbeb2065049412309f9b4","id":1}'

Tip

The Zabbix API does not allow submitting historical data—all item values have to go through the Zabbix server using the zabbix_sender utility, which we discussed in Chapter 11, Advanced Item Monitoring. There are rumors that the API might be moved to the server side, which might allow merging data-submitting in the main API.

Issues with the Zabbix API

The Zabbix API is really great, but there are a few issues with it worth knowing about:

  • Audit: Many Zabbix API operations are not registered in the Zabbix audit log, which can be accessed by going to Administration | Audit. That can make it really complicated to find out who made a particular change and when.
  • Validation: Unfortunately, the API validation leaves a lot to be desired. For example, using the API, one could change a host to a proxy or vice versa, or even set the host status value to a completely bogus value, making that host disappear from the frontend, although no new host with that name could be created. Be very, very careful with the possibility of sending incorrect data to the Zabbix API. It might complain about that data, or it might just silently accept it and make some silly changes.
  • Error messages: Similarly, even when validating input data, the error messages are not always that helpful. Sometimes, they will tell you exactly what is wrong, but you may also get incorrect parameters for a long JSON input string.
  • Performance: The Zabbix API's performance can be extremely bad for some operations. For example, modifying items for a template that is linked to a large number of hosts or linking many hosts to a template might be impossible to perform. While some of these operations could be split up, for example, linking the template to a few hundred hosts at a time, in some cases, one would have to fall back to doing direct SQL queries.
  • Missing functionality: Although the Zabbix API allows us to control most of the Zabbix configuration, there are still some missing areas. By now, that mostly concerns things found in the Administration | General section. Once such functionality is implemented, it will be finally possible for the Zabbix frontend to stop performing direct database queries, and the API will allow writing custom frontends without ever resorting to direct database access.

Using API libraries

While we looked at a low-level API example, you are not likely to use shell scripts to work with the Zabbix API. The shell is not that well suited for working with JSON data even with extra tools, so another programming or scripting language might be a better choice. For many of those languages, one would not have to implement full raw JSON handling, as there are libraries available. At the time of writing this, a list of available libraries is maintained at http://zabbix.org/wiki/Docs/api/libraries. Alternatively, just go to http://zabbix.org and look for the Zabbix API libraries link.

All of these libraries are community supplied. There are no quality guarantees, and any bugs should be reported to the library maintainers, not to Zabbix.

For example, a Perl library called Zabbix::Tiny aims to be a very simple abstraction layer for the Zabbix API, solving the authentication and request ID issues and other repetitive tasks when working with the API. It can be easily installed from the Comprehensive Perl Archive Network (CPAN):

# cpan Zabbix::Tiny

To create a new user, we would save the following in a file:

use strict;
use warnings;
use Zabbix::Tiny;
my $zabbix = Zabbix::Tiny->new(
    server => http://localhost/zabbix/api_jsonrpc.php,
    password => 'zabbix',
    user => 'Admin',
);
$zabbix->do(
    'user.create',
    alias    => 'new_user',
    passwd => 'secure_password',
    usrgrps => [ '13' ],
    name => 'New',
    surname => 'User',
    type => 3,
);

This would create a new user. While most parameters are self-explanatory, the type parameter tells the API whether this is a user, admin, or super admin. A value of 3 denotes the super admin user type. The group ID is hardcoded to 13—that is something to customize. If the file we saved this in were called zabbix_tiny-add_user.pl, we would call it like this:

$ perl  zabbix_tiny-add_user.pl

While this might seem longer than our raw JSON string, it also deals with logging in, and it is easier to write than raw JSON. For more information on this particular Zabbix API library, refer to http://zabbix.org/wiki/Docs/howto/Perl_Zabbix::Tiny_API.

There are a lot of different Zabbix API libraries for various languages—Python alone has seven different libraries at the time of writing this. It can be a bit of a challenge to choose the best one.

If programming around a library is not your thing, there is also a Python-based project to create command line tools for API operations, called Zabbix Gnomes. It can be found at https://github.com/q1x/zabbix-gnomes.

Further reading

We only covered a small portion of the Zabbix API in this chapter; there's lots and lots more. If you plan to use it, consult the official Zabbix manual for information on all the methods, their parameters, and object properties. At the time of this writing, the Zabbix API manual can be found at https://www.zabbix.com/documentation/3.0/manual/api—but even if that changes, just visit https://www.zabbix.com, and look for the documentation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset