Zabbix API starts to play significant role especially when it comes to integration of Zabbix with third-party software like configuration and incident management systems as well as for automation of routine tasks. It is incredibly difficult to manage monitoring of thousands of hosts without some automation in place.

The API was introduced in Zabbix 1.8 and is already used widely. All Zabbix mobile clients are based on the API, even the native WEB front-end is partially built on top of it. The API middleware makes the architecture more modular and helps to avoid direct calls to the database.

Zabbix API provides two main functions:

  • remote management of Zabbix configuration
  • remote retrieval of configuration and historical data

Preparing environment

I will use Perl for my “Hello API” example. Zabbix API is based on JSON-RPC 2.0 specification and Perl provides a very nice module for working with JSON-RPC protocol called JSON::RPC.

On my Ubuntu desktop I didn’t have it installed, so I had to run apt-get:

sudo apt-get install libjson-rpc-perl

Great! Now we are ready to do some hacking.

Authentication

Any Zabbix API client has to authenticate itself before doing actual work. User.login method is exactly what we need.

The method accepts a user name and a password and returns back Authentication ID, a secure hash used for consecutive API calls.

Look at auth.pl:

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use JSON::RPC::Client;
use Data::Dumper;

# Authenticate yourself
my $client = new JSON::RPC::Client;
my $url = 'http://testserver.zabbix.com/zabbix/api_jsonrpc.php';
my $authID;
my $response;

my $json = {
jsonrpc => "2.0",
method => "user.login",
params => {
user => "Admin",
password => "zabbix"
},
id => 1
};

$response = $client->call($url, $json);

# Check if response was successful
die "Authentication failed\n" unless $response->content->{'result'};

$authID = $response->content->{'result'};
print "Authentication successful. Auth ID: " . $authID . "\n";

Note that you should alter $url and also the user name and the password to match your setup.

Let’s run it:

zabbix@testserver:~$ ./auth.pl
Authentication successful. Auth ID: 15ff2edb84ce8e16585e035da42c1e9d
zabbix@testserver:~$

So far so good. Our auth.pl connected and authenticated successfully. Now we have the Authentication ID, which could be re-used for new API calls.

Getting list of hosts

The script hosts.pl does exactly what auth.pl did before but also executes method host.get for getting list of available hosts.

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use JSON::RPC::Client;
use Data::Dumper;

# Authenticate yourself
my $client = new JSON::RPC::Client;
my $url = 'http://testserver.zabbix.com/zabbix/api_jsonrpc.php';
my $authID;
my $response;

my $json = {
jsonrpc => "2.0",
method => "user.login",
params => {
user => "Admin",
password => "zabbix"
},
id => 1
};

$response = $client->call($url, $json);

# Check if response was successful
die "Authentication failed\n" unless $response->content->{'result'};

$authID = $response->content->{'result'};
print "Authentication successful. Auth ID: " . $authID . "\n";

# Get list of all hosts using authID

$json = {
jsonrpc=> '2.0',
method => 'host.get',
params =>
{
output => ['hostid','name'],# get only host id and host name
sortfield => 'name', # sort by host name
},
id => 2,
auth => "$authID",
};
$response = $client->call($url, $json);

# Check if response was successful
die "host.get failed\n" unless $response->content->{result};

print "List of hosts\n-----------------------------\n";
foreach my $host (@{$response->content->{result}}) {
print "Host ID: ".$host->{hostid}." Host: ".$host->{name}."\n";
}

The script generates a list of all our hosts sorted by host name:

zabbix@testserver:~$ ./hosts.pl
Authentication successful. Auth ID: a2977c028faa93bb34d4ed9f2d379d9f
List of hosts
-----------------------------
Host ID: 10085 Host: MySQL DB
Host ID: 10086 Host: Oracle DB
Host ID: 10087 Host: PostgreSQL DB
Host ID: 10088 Host: Test 001
Host ID: 10089 Host: Test 002
Host ID: 10090 Host: Test 003
Host ID: 10084 Host: Zabbix server
zabbix@testserver:~$

Data flow

The diagram represents typical data flow when working with Zabbix API. The authentication (method user.login) is a mandatory step needed for getting Authentication ID. The ID allows us to call any method of the API provided we have enough permissions.

I missed method user.logout in my Perl scripts for simplicity sake. The method invalidates the Authentication ID, therefore it cannot be used anymore.

You may also use function Dumper() from the excellent package Data::Dumper in your code in order to get JSON response in a human readable format:

Dumper($response->content);
The result will look like:
$VAR1 = {
'jsonrpc' => '2.0',
'id' => 2,
'result' => [
{
'name' => 'MySQL DB',
'hostid' => '10085'
},
{
'name' => 'Oracle DB',
'hostid' => '10086'
},
{
'name' => 'PostgreSQL DB',
'hostid' => '10087'
},
{
'name' => 'Test 001',
'hostid' => '10088'
},
{
'name' => 'Test 002',
'hostid' => '10089'
},
{
'name' => 'Test 003',
'hostid' => '10090'
},
{
'name' => 'Zabbix server',
'hostid' => '10084'
}
]
};

I hope we learned how to use Zabbix 2.0 API for basic operations. It wasn’t too difficult, right?

Additional reading

Subscribe
Notify of
26 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
MH
MH
11 years ago

perl, realy?:) Common guys, there are plenty of more funny languages out there:) And several existing clients already.

dimir
dimir
11 years ago

Perl rocks.

Volker Fröhlich
Volker Fröhlich
11 years ago

Thank you for that interesting post!

The first script fails for me on:

die “Authentication failed\n” unless $response->content->{‘result’};

Can’t call method “content” on an undefined value at ./auth2.pl line 28.

Tiago Soares
Tiago Soares
11 years ago

Same error as Volker.

I’m using Zabbix server v2.0.1 (revision 28455) (27 June 2012).

Volker Fröhlich
Volker Fröhlich
11 years ago

That was 1.8. The user has access to the API. I’m under the impression, I don’t even get as far as that. Otherwise the script should terminate in a better way.

Ricardo Klein
11 years ago

Same error here with zabbix 2.0.0 and 2.0.2
Can’t call method “content” on an undefined value at ./auth.pl line 28.

Ricardo Klein
11 years ago

Hey.. I found what was the problem here:
I used:
my $url = 'https://URL/zabbix/api_jsonrpc.php';
And, the https has maybe confused the response, so, with:
my $url = 'http://URL/zabbix/api_jsonrpc.php';

it has worked fine.

CmiRKWdOgV
CmiRKWdOgV
11 years ago
Reply to  Ricardo Klein

Try this:

--- SNIP ---
$client->ua->ssl_opts(verify_hostname => 0);
$response = $client->call($url, $json);
--- SNAP ---

timp
9 years ago
Reply to  CmiRKWdOgV

Or even better

my $ca_cert = '/etc/ssl/certs/ourca.pem';
$client->ua->ssl_opts(verify_hostname => 1);
$client->ua->ssl_opts(SSL_ca_file => $ca_cert);

Here is the explanations
http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm

shekarkcb
shekarkcb
7 years ago
Reply to  timp

I did had tough time figuring out how i am getting
“Can’t call method “content” on an undefined value at” error. Below are the values i had set

$client->ua->ssl_opts(SSL_cert_file => "/etc/httpd/ssl/abcd.crt");
$client->ua->ssl_opts(SSL_key_file => "/etc/httpd/ssl/abcd.key");
$client->ua->ssl_opts(SSL_ca_file => "/etc/httpd/ssl/gd_bundle.crt");

Then used print Dumper $client; to see if actually those are being set, still i was getting same error. Then i did this, this snippet from JSON::RPC::Client module to see if actually reposnse is being set,

if($response) {
if($response->is_error) {
print "Res:".$response->error_message;
} else {
print Dumper $response;
}
} else {
print $client->status_line;
}

this gave me proper erro, in my case 501 Protocol scheme 'https' is not supported (LWP::Protocol::https not installed)
So i installed above module, this solved the issue.
Thanks all for the pointers guys , cheers.

Charles Dunda
Charles Dunda
11 years ago
Reply to  Ricardo Klein

And vice versa.. “http” did not work for me but “https” did. Thanks!

Tiago Soares
Tiago Soares
11 years ago

Ricardo,

That’s it!

Tks!

azurIt
azurIt
11 years ago

I really miss the method for retrieving a graph as an PNG image 🙁

Richlv
11 years ago

now that was a risky comment right there – at least it had that small safety net of “i hope” 😉

Bart Verwilst
Bart Verwilst
11 years ago
Reply to  Richlv

While you’re in a risky mood, let me ask ‘When will 2.2 be released?’ 😉

Lukas Maly
11 years ago

Very interest blog supply, but on the hosts.pl missing “}”

foreach my $host (@{$response->content->{result}}) {
print “Host ID: “.$host->{hostid}.” Host: “.$host->{name}.”\n”;
}

I sested it on Zabbix 2.0.2 and client on Debian 6.0.5.

Thanks

Henrik Johansen
Henrik Johansen
11 years ago

There are a number of problems with the current API implementation – the main concern for working with the API is the lack over proper versioning and backwards compatibility.

Any application using the API will break when the API changes … and it changes a lot (http://www.zabbix.com/documentation/2.0/manual/appendix/api/changes_1.8_-_2.0).

Other issues are related to API response inconsistency. One issue is that most select* options make the API responses difficult to parse (a hash inside a hash with a dynamic numeric index), another is the confusing return codes resulting in spagetti code like this :

case
when response.has_data?
# Response is a success and “has data” — it’s not empty. This
# means we found our host.
puts response.result
#=> [{“hostid”=>”10017”}]
when response.success?
# Response was succssful but doesn’t “have data” — it’s empty, no
# such host!
puts “No such host”
else
# Response was an error. Uh oh!
puts response.error_message
end

All in all – the ZBX API is probably one of the most annoying API’s that I had to work with.

There is a lot of documentation on writing usable API’s out there from various big players (Google. Flicker,etc) …. perhaps worth a read for you …

zabbix_user2012
zabbix_user2012
11 years ago

I am trying to run the auth.pl script. I am getting this error:

“Not a HASH reference at /usr/share/perl5/JSON/RPC/Client.pm at line 193”

Any hints?

Thanks

Adam Carr
Adam Carr
11 years ago

I generate custom monitoring screens over and above Zabbix’s inbuilt maps by calling on the API.

With 1.8 I used this PHP interface (http://andrewfarley.com/php/zabbix-1-8-api-php-class-v1-0) to pull through data.
Since 2.0, I now use this PHP interface instead (http://zabbixapi.confirm.ch/)

Thanks to these I can generate custom graphs exactly to my requirements!

26
0
Would love your thoughts, please comment.x
()
x