——————————package
Nagios::Scrape;
use
warnings;
use
strict;
use
CGI;
use
LWP::UserAgent;
use
Error;
=head1 NAME
Nagios::Scrape - Scrapes and Parses the status.cgi page of a Nagios installation
=head1 VERSION
Version 0.03
=cut
our
$VERSION
=
'0.03'
;
=head1 SYNOPSIS
This module uses LWP to retrieve the status.cgi page of a Nagios installation, parses
the data into a manageable format, and then makes it accessible.
This is a more lightweight solution to Nagios installations where the status.dat file
can reach 1+mb in size.
use Nagios::Scrape;
my $foo = Nagios::Scrape->new(username => $username, password => $password, url => $url);
@service_alerts = $foo->get_service_status();
@host_alerts = $foo->get_host_status();
=head1 SUBROUTINES/METHODS
=head2 new
Creates a new class given a username and password.
my $nagios = Nagios::Scrape->new(username => $username, password => $password, url => $url);
=cut
sub
new {
my
(
$class
,
%attrs
) =
@_
;
throw Error::Simple(
"Username is required"
)
if
( !
defined
(
$attrs
{username} ) );
throw Error::Simple(
"Password is required"
)
if
( !
defined
(
$attrs
{password} ) );
throw Error::Simple(
"URL is required"
)
if
( !
defined
(
$attrs
{url} ) );
if
( (
$attrs
{url} !~ m/^http/ ) || (
$attrs
{url} !~ m/status.cgi$/ ) );
# Sets default values for host and service states
$attrs
{host_state} = 12;
$attrs
{service_state} = 28;
bless
\
%attrs
,
$class
;
}
=head2 host_state
This method allows you to filter certain host states. The table is as follows:
Hosts:
PENDING 1
UP 2
DOWN 4
UNREACHABLE 8
Add the number for each state that you want to see. For example, to see DOWN
and UNREACHABLE states, set this value to 12. (Default value).
=cut
sub
host_state {
my
(
$self
,
$state
) =
@_
;
$self
->{host_state} =
$state
if
(
defined
(
$state
) );
return
$self
->{host_state};
}
=head2 service_state
This method allows you to filter certain service states. The table is as follows:
Services:
PENDING 1
OK 2
WARNING 4
UNKNOWN 8
CRITICAL 16
Add the number for each state you would like to see. For example, to see WARNING,
UNKNOWN, and CRITICAL states, set the number to 28. (Default value).
=cut
sub
service_state {
my
(
$self
,
$state
) =
@_
;
$self
->{service_state} =
$state
if
(
defined
(
$state
) );
return
$self
->{service_state};
}
=head2 get_service_status
Connects to given URL and retrieves the requested service statuses
=cut
sub
get_service_status {
my
$self
=
shift
;
my
$ua
= LWP::UserAgent->new;
my
$req
=
HTTP::Request->new(
GET
=>
$self
->{url}
.
'?host=all&noheader=yes&servicestatustypes='
.
$self
->{service_state} );
$req
->authorization_basic(
$self
->{username},
$self
->{password} );
my
$response
=
$ua
->request(
$req
);
if
( !
$response
->is_success ) {
die
(
"Could not connect to "
.
$self
->{url} .
" "
.
$response
->status_line
.
"\n"
);
}
return
$self
->parse_service_content(
$response
->content );
}
=head2 get_host_status
Connects to given url and retrieves host statuses
=cut
sub
get_host_status {
my
$self
=
shift
;
my
$ua
= LWP::UserAgent->new;
my
$req
=
HTTP::Request->new(
GET
=>
$self
->{url}
.
'?hostgroup=all&noheader=yes&style=hostdetail&hoststatustypes='
.
$self
->{host_state} );
$req
->authorization_basic(
$self
->{username},
$self
->{password} );
my
$response
=
$ua
->request(
$req
);
if
( !
$response
->is_success ) {
die
(
"Could not connect to "
.
$self
->{url} .
" "
.
$response
->status_line
.
"\n"
);
}
return
$self
->parse_host_content(
$response
->content );
}
=head2 parse_service_content
Will parse the service status page into a manageable array of hashed service details.
=cut
sub
parse_service_content {
my
(
$self
,
$content
) =
@_
;
my
@alerts
;
my
$host
;
while
(
$content
=~ m%
(?:<TD\s+align=left\s+valign=center\s+CLASS=
'status(?:Even|Odd|HOST[A-Z]+)'
>
<A\s+HREF='extinfo.cgi
.+?
# Host name - will be empty TD pair if this is a continuation
# of a host with multiple alerts
'>([^<]+)</A>|<TD></TD>)
.+?
# ' Service description
>([^<]+)</A>
.+?
# Status
CLASS=
'status[A-Z]+'
>([A-Z]+)</TD>
.+?
# ' Time
nowrap>([^<]+)</TD>
.+?
# Duration
nowrap>([^<]+)</TD>
.+?
# Attempts
>([^<]+)</TD>
.+?
# Status Information
>([^<]+)</TD>
.+?
%xsmgi
)
{
# Host might be empty if this is a host with multiple alerts
$host
= $1
if
(
defined
($1));
my
$alert
= {
'type'
=>
'service'
,
'host'
=>
$self
->decode_html(
$host
),
'service'
=>
$self
->decode_html($2),
'status'
=>
$self
->decode_html($3),
'time'
=>
$self
->decode_html($4),
'duration'
=>
$self
->decode_html($5),
'attempts'
=>
$self
->decode_html($6),
'information'
=>
$self
->decode_html($7)
};
push
(
@alerts
,
$alert
);
}
return
@alerts
;
}
=head2 parse_host_content
Will parse the host status page into a manageable array of hashed service details.
=cut
sub
parse_host_content {
my
(
$self
,
$content
) =
@_
;
my
@alerts
;
while
(
$content
=~ m%
<TD\s+align=left\s+valign=center\s+CLASS=
'statusHOST[A-Z]+'
>
.+?
# Host name
>([^<]+)</A>
.+?
# Status
<TD\s+CLASS=
'statusHOST[A-Z]+'
>([^<]+)</TD>
.+?
# Time
nowrap>([^<]+)</TD>
.+?
# Duration
nowrap>([^<]+)</TD>
.+?
# Status Information
>([^<]+)</TD>
.+?
%xsmgi
) {
my
$alert
= {
'type'
=>
'host'
,
'host'
=>
$self
->decode_html($1),
'status'
=>
$self
->decode_html($2),
'time'
=>
$self
->decode_html($3),
'duration'
=>
$self
->decode_html($4),
'information'
=>
$self
->decode_html($5)
};
push
(
@alerts
,
$alert
);
}
return
@alerts
;
}
=head2 decode_html
Simple helper method that smooths out HTML strings from Nagios status.cgi page
=cut
sub
decode_html {
my
(
$self
,
$string
) =
@_
;
$string
= CGI::unescapeHTML(
$string
);
$string
=~ s/nbsp//g;
return
$string
;
}
=head1 AUTHOR
Joe Topjian, C<< <joe at terrarum.net> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-nagios-scrape at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Nagios-Scrape>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Nagios::Scrape
=head1 ACKNOWLEDGEMENTS
Some of this code was taken from www.nagios3book.com/nagios-3-enm/tts/nagios-ttsd.pl which is no longer online.
=head1 LICENSE AND COPYRIGHT
Copyright 2010 Joe Topjian.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;
# End of Nagios::Scrape