NAME¶
Zabbix::API -- Access the JSON-RPC API of a Zabbix server
SYNOPSIS¶
use Zabbix::API;
my $zabbix = Zabbix::API->new(server => 'http://example.com/zabbix/api_jsonrpc.php',
verbosity => 0);
eval { $zabbix->login(user => 'calvin',
password => 'hobbes') };
if ($@) { die 'could not authenticate' };
my $items = $zabbix->fetch('Item', params => { search => { ... } });
DESCRIPTION¶
This module manages authentication and querying to a Zabbix server via its
JSON-RPC interface. (Zabbix v1.8+ is required for API usage; prior versions
have no JSON-RPC API at all.)
What you need to start out is probably the "fetch" method in
"Zabbix::API"; be sure to check out also what the various
"Zabbix::API::Foo" classes do, as this is how you'll be manipulating
the objects you have just fetched.
Finally, there are examples in the "examples/" folder (well, at least
one) and in the unit tests.
METHODS¶
- new(server => URL, [verbosity => INT], [env_proxy => BOOL])
- This is the main constructor for the Zabbix::API class. It creates a
LWP::UserAgent instance but does not open any connections yet.
"env_proxy" is passed to the LWP::UserAgent constructor, so if
it is set to a true value then the UA should follow $http_proxy and
others.
"server" is misleading, as the URL expected is actually the whole
path to the JSON-RPC page, which usually is
"http://example.com/zabbix/api_jsonrpc.php".
Returns an instance of the "Zabbix::API" class.
- login(user => STR, password => STR)
- Send login information to the Zabbix server and set the auth cookie if the
authentication was successful.
Due to the current state of flux of the Zabbix API, this may or may not work
depending on your version of Zabbix. "user.authenticate" is
marked as having been introduced in version 1.8; so is
"user.login", which deprecates "authenticate". Our
method uses "login". Version 1.8.4 is confirmed as working with
"login".
- logout()
- Try to log out properly. Unfortunately, the "user.logout" method
is completely undocumented and does not appear to work at the moment (see
the bug report here: https://support.zabbix.com/browse/ZBX-3907
<https://support.zabbix.com/browse/ZBX-3907>). Users of this
distribution are advised not to log out at all. They will not be able
to log back in until the server has decided their ban period is over
(around 30s). Furthermore, another bug in Zabbix (resolved in 1.8.5)
prevents successful logins to reset the failed logins counter, which means
that after three (possibly non-consecutive) failed logins every failed
login triggers the ban period.
The test suite logs in and out once per test file. The logout method does
not work. There are more than three test files. Do the math :(
- raw_query(method => STR, [params => HASHREF])
- Send a JSON-RPC query to the Zabbix server. The "params" hashref
should contain the method's parameters; query parameters (query ID, auth
cookie, JSON-RPC version, and HTTP request headers) are set by the method
itself.
Return a "HTTP::Response" object.
If the verbosity is set to 1, will print the "HTTP::Response" to
STDOUT. If set to 2, will print the Data::Dumper output of same (it also
contains the "HTTP::Request" being replied to).
If the verbosity is strictly greater than 0, the internal LWP::UserAgent
instance will also print HTTP request progress.
- query(method => STR, [params => HASHREF])
- Wrapper around "raw_query" that will return the decoded result
data instead.
- api_version
- Query the Zabbix server for the API version number and return it.
- fetch(CLASS, [params => HASHREF])
- This method fetches objects from the server. The PARAMS hashref should
contain API method parameters that identify the objects you're trying to
fetch, for instance:
$zabbix->fetch('Item', params => { search => { key_ => 'system.uptime' } });
The default value of PARAMS is an empty hashref, which should mean
"fetch every object of type CLASS".
The method delegates a lot of work to the CLASS so that it can be as generic
as possible. Any CLASS name in the "Zabbix::API" namespace is
usable as long as it descends from "Zabbix::API::CRUDE" (to be
precise, it should implement a number of methods, some of which
"CRUDE" implements, some of which are provided by specialized
subclasses provided in the distribution). The string
"Zabbix::API::" will be prepended if it is missing.
Returns an arrayref of CLASS instances.
- fetch_single(CLASS, [params => HASHREF])
- Like "fetch", but also checks how many objects the server sent
back. If no objects were sent, returns "undef". If one object
was sent, returns that. If more objects were sent, throws an exception.
This helps against malformed queries; Zabbix tends to return all
objects of a class when a query contains strange parameters (like
"searhc" or "fliter").
- useragent
- Accessor for the LWP::UserAgent object that handles HTTP queries and
responses. Several useful options can be set: timeout, redirects,
etc.
- verbosity([VERBOSITY])
- Mutator for the verbosity level.
Implemented verbosities so far are 0, 1 and 2, where:
- 0
- does not emit any messages,
- 1
- prints out the "LWP::UserAgent" progress messages and the
responses sent by the Zabbix server,
- 2
- prints out the "LWP::UserAgent" progress messages and dumps to
stdout (via "Data::Dumper") the queries sent to the server and
the responses received.
LOW-LEVEL ACCESS¶
Several attributes are available if you want to dig into the class' internals,
through the standard blessed-hash-as-an-instance mechanism. Those are:
- server
- A string containing the URL to which JSON-RPC queries should be
POSTed.
- verbosity
- Verbosity level. So far levels 0 to 2 are supported (i.e. do something
different).
- cookie
- A string containing the current session's auth cookie, or the empty string
if unauthenticated.
- env_proxy
- Direct access to the LWP::UserAgent initial configuration regarding
proxies. Setting this attribute after construction does nothing.
BUGS AND MISSING FEATURES¶
THE GREAT RACE CONDITION¶
Consider the following:
my $host = $zabbix->fetch('Host', params => ...);
my $same_host = Zabbix::API::Host->new(root => $zabbix,
params => same...);
$same_host->push;
is_deeply($host, $same_host); # yup
isnt($host, $same_host); # also yup
This means you can change the attribute A in $host and push it, and it will
change on the server; then you can change some other attribute B in $same_host
and push it, and it will change on the server... and attribute A will be
changed back to its old value before you changed it in $host since $host and
$same_host are different references to different objects and don't know about
each other! Of course this is also true if someone else is fiddling with the
hosts directly on the web interface or in any other way.
To work around this, you have to "pull()" just before you start
changing things.
MOOSE, ABSENCE OF¶
The distribution doesn't use Moose, because it was written with light
dependencies in mind. This is actually a problem in that I do not have the
time to write proper accessors to cover all types of manipulations one might
expect on, for instance, a graph's items. Hence to push (in the stack sense) a
new item into a graph's list of items, you have to use the push builtin on the
dereferenced items mutator, instead of writing something like
$graph->items->push($foo);
which would be easy to allow with Moose traits. Plus, I had to write boilerplate
validation code, which would have been taken care of by Moose at least where
types and type coercions are concerned.
It is quite slow. The server itself does not appear to be lightning fast; at
least a recent Zabbix (1.8.5) on a Debian squeeze VM takes a couple seconds to
reply to even trivial JSON-RPC queries. This is compounded by the fact that
Zabbix::API is being extra paranoid about default values and name/id
collisions and fetches data maybe more often than necessary, for instance
immediately before and after a "push()".
Several types of objects are not implemented in this distribution; feel free to
contribute them or write your own distribution (see Zabbix::API::CRUDE for the
gory API details).
The "logout" business.
SEE ALSO¶
The Zabbix API documentation, at
<
http://www.zabbix.com/documentation/start>
LWP::UserAgent
AUTHOR¶
Fabrice Gabolde <fabrice.gabolde@uperto.com>
COPYRIGHT AND LICENSE¶
Copyright (C) 2011, 2012, 2013 SFR
This library is free software; you can redistribute it and/or modify it under
the terms of the GPLv3.