File Coverage

blib/lib/Mojo/Zabbix.pm
Criterion Covered Total %
statement 24 110 21.8
branch 0 48 0.0
condition 0 15 0.0
subroutine 8 25 32.0
pod 0 15 0.0
total 32 213 15.0


line stmt bran cond sub pod time code
1             package Mojo::Zabbix;
2              
3 1     1   25383 use strict;
  1         2  
  1         37  
4 1     1   7 use warnings;
  1         3  
  1         40  
5              
6 1     1   567 use Mojo::UserAgent;
  1         416999  
  1         9  
7 1     1   41 use Scalar::Util qw(reftype refaddr);
  1         2  
  1         48  
8 1     1   6 use Carp;
  1         2  
  1         49  
9 1     1   5 use Time::HiRes qw(gettimeofday tv_interval);
  1         2  
  1         10  
10 1     1   137 use POSIX qw(strftime);
  1         3  
  1         8  
11              
12              
13             our $VERSION = '0.11';
14              
15              
16             # useful defaults Zabbix Constant list:
17              
18             use constant {
19 1         1596 Z_AGENT_PORT => 10050,
20             Z_SERVER_PORT => 10051,
21             Z_SNMP_PORT => 161,
22              
23             # zabbix api constants definitions
24              
25             OUTPUT_EXTEND => 'extend',
26             OUTPUT_REFER => 'refer',
27             OUTPUT_SHORTEN => 'shorten',
28             HOST_INTERFACE_SECONDARY => 0,
29             HOST_INTERFACE_PRIMARY => 1,
30             HOST_INTERFACE_TYPE_UNKNOWN => 0,
31             HOST_INTERFACE_TYPE_AGENT => 1,
32             HOST_INTERFACE_TYPE_SNMP => 2,
33             HOST_INTERFACE_TYPE_IPMI => 3,
34             HOST_INTERFACE_TYPE_JMX => 4,
35             HOST_USE_DNS => 0,
36             HOST_USE_IP => 1,
37             HOST_STATUS_ON => 0,
38             HOST_STATUS_OFF => 1,
39             ITEM_TYPE_AGENT => 0,
40             ITEM_TYPE_SNMP1 => 1,
41             ITEM_TYPE_TRAPPER => 2,
42             ITEM_TYPE_SIMPLE => 3,
43             ITEM_TYPE_SNMP2 => 4,
44             ITEM_TYPE_INTERN => 5,
45             ITEM_TYPE_SNMP3 => 6,
46             ITEM_TYPE_AAGENT => 7,
47              
48             # zabbix agent (active)
49              
50             ITEM_TYPE_AGGR => 8,
51             ITEM_TYPE_HTTP => 9,
52             ITEM_TYPE_EXTERN => 10,
53             ITEM_TYPE_DBMON => 11,
54             ITEM_TYPE_IPMI => 12,
55             ITEM_TYPE_SSH => 13,
56             ITEM_TYPE_TELNET => 14,
57             ITEM_TYPE_CALC => 15,
58             ITEM_TYPE_JMX => 16,
59             ITEM_TYPE_SNMPT => 17,
60             ITEM_STATUS_ACTIVE => 0,
61             ITEM_STATUS_DISABLED => 1,
62             ITEM_STATUS_NOT_SUP => 3,
63             ITEM_VALUE_FLOAT => 0,
64             ITEM_VALUE_CHAR => 1,
65             ITEM_VALUE_LOG => 2,
66             ITEM_VALUE_UINT => 3,
67             ITEM_VALUE_TEXT => 4,
68             ITEM_DATA_DEC => 0,
69             ITEM_DATA_OCT => 1,
70             ITEM_DATA_HEX => 2,
71             ITEM_DATA_BIN => 3, # same as BOOL-ean
72             ITEM_DATA_BOOL => 3,
73             ITEM_DELTA_ASIS => 0,
74             ITEM_DELTA_PERSEC => 1,
75             ITEM_DELTA_CHANGE => 2,
76             ITEM_SSH_AUTH_PASSWORD => 0,
77             ITEM_SSH_AUTH_PUBKEY => 1,
78             ITEM_FLAG_PLAIN => 0,
79             ITEM_FLAG_DISCOVERED => 4,
80             ITEM_SNMP_PRIV_NANP => 0,
81             ITEM_SNMP_PRIV_ANP => 1,
82             ITEM_SNMP_PRIV_AP => 2,
83             TRIGGER_STATUS_ACTIVE => 0,
84             TRIGGER_STATUS_DISABLED => 1,
85             TRIGGER_VALUE_OK => 2,
86             TRIGGER_VALUE_PROBLEM => 3,
87             TRIGGER_VALUE_ON => 4,
88             TRIGGER_SEVERITY_UNKN => 0,
89             TRIGGER_SEVERITY_INFO => 1,
90             TRIGGER_SEVERITY_WARN => 2,
91             TRIGGER_SEVERITY_AVRG => 3,
92             TRIGGER_SEVERITY_HIGH => 4,
93             TRIGGER_SEVERITY_DISA => 5,
94             TRIGGER_TYPE_NORMAL => 0,
95             TRIGGER_TYPE_MULTI => 1,
96             TRIGGER_FLAG_GOOD => 0,
97             TRIGGER_FLAG_UNCERTAIN => 1,
98             TRIGGER_STATUS_ICMPPING_FAIL => 0,
99             TRIGGER_STATUS_ICMPPING_SUCCESS => 1,
100              
101             # http://www.zabbix.com/documentation/2.0/manual/appendix/api/user/definitions
102             USER_TYPE_USER => 1,
103             USER_TYPE_ADMIN => 2,
104             USER_TYPE_SUPERADMIN => 3,
105             USER_TYPE_ROOT => 3, # same as Super Admin
106             USER_THEME_1 => 'originalblue',
107             USER_THEME_2 => 'darkblue',
108             USER_THEME_3 => 'darkorange',
109              
110             # 0 seconds means disabled
111             USER_AUTOLOGIN_DISABLE => 0,
112              
113             # http://www.zabbix.com/documentation/2.0/manual/appendix/api/usergroup/definitions
114             GROUP_ACCESS_DEFAULT => 0,
115             GROUP_ACCESS_INTERNAL => 1,
116             GROUP_ACCESS_DISABLED => 2,
117             GROUP_STATUS_ENABLED => 0,
118             GROUP_STATUS_DISABLED => 1,
119             GROUP_DEBUG_ENABLED => 1,
120             GROUP_DEBUG_DISABLED => 0,
121 1     1   170 };
  1         3  
122              
123             sub new {
124 0     0 0   my $class = shift;
125 0           my $required = 1;
126 0           my $args = {
127             url => \$required,
128             trace => 0,
129             debug => 0,
130             username => \$required,
131             password => \$required,
132             @_,
133             };
134              
135 0           for my $k ( keys %$args ) {
136 0 0 0       if ( ref $args->{$k}
137             && refaddr( $args->{$k} ) == refaddr( \$required ) )
138             {
139 0           die "Missing value for $k";
140             }
141             }
142              
143 0           $args->{url} =~ s,/+$,,g;
144              
145             my $self = bless {
146             UserAgent => undef,
147             Request => undef,
148             Count => 1,
149             Auth => undef,
150             API_URL => $args->{url},
151             Output => OUTPUT_EXTEND,
152             Debug => $args->{debug} ? 1 : 0,
153             Trace => $args->{trace} ? 1 : 0,
154             User => $args->{username},
155             Password => $args->{password},
156 0 0         _call_start => 0,
    0          
157             }, $class;
158              
159             # init json object
160 0           $self->_json;
161              
162             # init useragent
163 0           $self->ua;
164              
165             # authenticate
166 0           $self->auth;
167 0           return $self;
168             }
169              
170             sub output {
171 0     0 0   my $self = shift;
172              
173 0 0         $self->{Output} = $_[0]
174             if (@_);
175              
176 0           return $self->{Output};
177             }
178              
179             sub ua {
180 0     0 0   my $self = shift;
181              
182 0 0         unless ( $self->{UserAgent} ) {
183              
184 0           $self->{UserAgent} = Mojo::UserAgent->new;
185 0           $self->{UserAgent}->transactor->name("Mojo::Zabbix");
186 0           $self->{UserAgent}->inactivity_timeout(10);
187             }
188              
189 0           return $self->{UserAgent};
190             }
191              
192             sub _json {
193 0     0     my $self = shift;
194              
195 0 0         unless ( defined $self->{JSON} ) {
196 0           $self->{JSON} = JSON::PP->new;
197             $self->{JSON}->ascii->pretty->allow_nonref->allow_blessed
198 0           ->allow_bignum;
199             }
200 0           return $self->{JSON};
201             }
202              
203             sub trace {
204 0     0 0   my $self = shift;
205              
206 0 0         $self->{Trace} = $_[0]
207             if (@_);
208              
209 0           return $self->{Trace};
210             }
211              
212             sub debug {
213 0     0 0   my $self = shift;
214              
215 0 0         $self->{Debug} = $_[0]
216             if (@_);
217              
218 0           return $self->{Debug};
219             }
220              
221             sub auth {
222 0     0 0   my $self = shift;
223              
224 0 0         if ( not defined $self->{Auth} ) {
    0          
225 0           $self->{Auth} = '';
226             my $res = $self->http_request(
227             'user', 'login',
228             {
229             user => $self->{User},
230             password => $self->{Password},
231             }
232 0           );
233              
234             #confess $res->{error}->{data}
235             warn "$res->{error}->{data}\nError Code: $res->{error}->{code}
236             \nResponse: $res->{error}->{message}"
237 0 0         if defined $res->{error};
238              
239             #print "$res->{error}";
240 0           $self->{Password} = '***';
241 0           $self->{Auth} = $res->{result};
242             }
243             elsif ( $self->{Auth} eq '' ) {
244 0           return (); # empty for first auth call
245             }
246              
247 0 0         return $self->{Auth} unless defined wantarray;
248 0           return ( auth => $self->{Auth} );
249             }
250              
251             sub next_id {
252 0     0 0   return ++shift->{'Count'};
253             }
254              
255             sub int_debug {
256 0     0 0   my ( $self, $data ) = @_;
257 0           my $tempass;
258 0 0 0       if ( defined $data->{'params'}
      0        
259             and ref( $data->{'params'} ) eq 'HASH'
260             and exists $data->{'params'}->{'password'} )
261             {
262 0           $tempass = $data->{'params'}->{'password'};
263 0           $data->{'params'}->{'password'} = '******';
264             }
265 0           my $json = $self->{JSON}->encode($data);
266              
267             $self->_dbgmsg( "TX: " . $json )
268 0 0         if $self->{Debug};
269             $data->{'params'}->{'password'} = $tempass
270             if ( ref( $data->{'params'} ) eq 'HASH'
271 0 0 0       and exists $data->{'params'}->{'password'} );
272              
273             }
274              
275             sub out_debug {
276 0     0 0   my ( $self, $data ) = @_;
277 0           my $json = $self->{JSON}->encode($data);
278             $self->_dbgmsg( "RX: " . $json )
279 0 0         if $self->{Debug};
280              
281             }
282              
283             sub get {
284 0     0 0   my ( $self, $object, $params ) = @_;
285 0           return $self->http_request( $object, "get", $params );
286             }
287              
288             sub update {
289 0     0 0   my ( $self, $object, $params ) = @_;
290 0           return $self->http_request( $object, "update", $params );
291             }
292              
293             sub delete {
294 0     0 0   my ( $self, $object, $params ) = @_;
295 0           return $self->http_request( $object, "delete", $params );
296             }
297              
298             sub create {
299 0     0 0   my ( $self, $object, $params ) = @_;
300 0           return $self->http_request( $object, "create", $params );
301             }
302              
303             sub exists {
304 0     0 0   my ( $self, $object, $params ) = @_;
305 0           return $self->http_request( $object, "exists", $params );
306             }
307              
308             sub http_request {
309 0     0 0   my ( $self, $object, $op, $params ) = @_;
310              
311 0 0         if ( $self->{Trace} ) {
312 0           $self->{_call_start} = [gettimeofday];
313 0           $self->_dbgmsg("Starting method $object.$op");
314             }
315              
316 0 0         if ($params) {
317             $params->{output} = $self->{Output}
318 0 0 0       if ( reftype($params) eq 'HASH' and not defined $params->{output} );
319             }
320             else {
321 0           $params = [];
322             }
323 0           my $zrurl = "$self->{API_URL}/api_jsonrpc.php";
324 0           my $myjson = {
325             jsonrpc => "2.0",
326             method => "$object.$op",
327             params => $params,
328             id => $self->next_id,
329             ( $self->auth ),
330             };
331 0 0         $self->int_debug($myjson) if $self->{Debug};
332              
333 0           my $res = $self->ua->post( $zrurl, json => $myjson );
334              
335 0 0         unless ( $res->success ) {
336 0           my $err = $res->error;
337 0 0         warn "$err->{code} response: $err->{message}" if $err->{code};
338 0           warn "Connection error: $err->{message}";
339              
340             }
341              
342 0 0         if ( $self->{Trace} ) {
343 0           $self->_dbgmsg("Finished method $object.$op");
344             $self->_dbgmsg( "Spent "
345             . tv_interval( $self->{_call_start} )
346 0           . "s on $object.$op" );
347             }
348 0 0         $self->out_debug( $res->res->json ) if $self->{Debug};
349 0           return $res->res->json;
350             }
351              
352             sub _dbgmsg {
353 0     0     my $self = shift;
354             warn strftime( '[%F %T]', localtime ) . ' '
355             . __PACKAGE__ . ' @ #'
356 0           . $self->{Count} . ' '
357             . join( ', ', @_ ) . "\n";
358             }
359              
360             1;
361            
362             __END__