Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 338 lines (257 sloc) 10 KB
#!/usr/bin/env -S perl -w # -*- cperl; cperl-indent-level: 4 -*-
# Copyright (C) 2019, Roland van Ipenburg
use strict;
use warnings;
use utf8;
use 5.016000;
BEGIN { our $VERSION = v0.0.2; }
use Monitoring::Plugin;
use HTTP::Tiny;
use JSON;
use List::MoreUtils;
use English qw( -no_match_vars );
use Readonly;
## no critic (ProhibitCallsToUnexportedSubs)
Readonly::Scalar my $SEP => "\N{COMMA}\N{SPACE}";
Readonly::Scalar my $RANGE_NONE => q{~:};
Readonly::Scalar my $TIMEOUT => 15;
Readonly::Scalar my $URL_TEMPLATE => q{http://%s/api/summary};
Readonly::Scalar my $API_VERSION => 0.15;
Readonly::Scalar my $MINUTES_IN_HOUR => 60;
Readonly::Scalar my $MINUTES_IN_DAY => 24 * $MINUTES_IN_HOUR;
Readonly::Hash my %FUNCTIONS => (
status => {},
version => {},
producer => {},
consumer => {},
forwarding => {},
connected => {},
uptime => { warning => q{10:}, critical => q{1:} },
disk_available => { warning => q{500:}, critical => q{100:} },
disk_used => { warning => q{90}, critical => q{95} },
cpu_temp => { warning => q{80}, critical => q{85} },
);
Readonly::Hash my %DISPATCH => (
status => sub { $_[0]->{'systemStatus'} =~ m{^RUNNING$}gsmix },
version => sub { $_[0]->{'sysVersion'} },
producer => sub { $_[0]->{'producer'} =~ m{^ON$}gsmix },
consumer => sub { $_[0]->{'consumer'} =~ m{^ON$}gsmix },
forwarding => sub { $_[0]->{'dataSharing'} =~ m{^ON$}gsmix },
connected => sub { $_[0]->{'serverConnected'} },
uptime => sub {
my $up = $_[0]->{'uptime'};
( $up->{'days'} * $MINUTES_IN_DAY ) +
( $up->{'hours'} * $MINUTES_IN_HOUR ) + $up->{'minutes'};
},
disk_available => sub { $_[0]->{'diskspace'}->{'available'} },
disk_used => sub { $_[0]->{'diskspace'}->{'used'} },
cpu_temp => sub {
$_[0]->{'cputemp'} =~ m{^(?<celcius>[[:digit:].]+)\sC}sxm;
return $LAST_PAREN_MATCH{'celcius'};
},
);
Readonly::Hash my %LOG => (
resource => q{Could not retrieve resource '%s' to get data},
data => q{Could not get data from resource '%s' for function '%s'},
function => q{Unknown function '%s', must be one of %s},
check => q{Function '%s' is level '%s'},
);
## use critic
my $mp = Monitoring::Plugin->new(
usage =>
q{Usage %s -H <host> [ -f <function> ] [ -t <timeout> ] [ -v|--verbose ] [ -c|--critical=<threshold> ] [ -w|--warning=<threshold> ]},
version => v0.0.2,
);
$mp->add_arg(
spec => q{host|H=s},
help => q{-H, --host=HOST)}
);
$mp->add_arg(
spec => q{function|f=s},
help => q{-f, --function=FUNCTION } . join $SEP,
sort keys %FUNCTIONS
);
$mp->add_arg(
spec => 'warning|w=s',
help => q{-w, --warning=INTEGER:INTEGER . See }
. q{https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT }
. q{for the threshold format.},
);
$mp->add_arg(
spec => 'critical|c=s',
help => q{-c, --critical=INTEGER:INTEGER . See }
. q{https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT }
. q{for the threshold format.},
);
$mp->getopts;
alarm( defined $mp->opts->timeout ? $mp->opts->timeout : $TIMEOUT );
my $function = $mp->opts->function;
## no critic (ProhibitCallsToUnexportedSubs)
if ( List::MoreUtils::none { $function eq $_ } keys %FUNCTIONS ) {
## use critic
$mp->plugin_die( sprintf $LOG{function},
( $function, join $SEP, sort keys %FUNCTIONS ) );
}
my $page = sprintf $URL_TEMPLATE, $mp->opts->host;
my $response = HTTP::Tiny->new->get($page);
if ( $response->{success} ) {
my $json = JSON->new();
my $obj = $json->decode( $response->{content} );
my $level = $DISPATCH{$function}($obj);
if ( defined $level ) {
my $code;
if ( $function =~
m{^(status|producer|consumer|forwarding|connected)$}gsmix )
{
## no critic (ProhibitCallsToUnexportedSubs)
$code = Monitoring::Plugin::OK;
## use critic
if ( !$level ) {
## no critic (ProhibitCallsToUnexportedSubs)
$code = Monitoring::Plugin::WARNING;
## use critic
}
}
elsif ( $function eq 'version' ) {
## no critic (ProhibitCallsToUnexportedSubs)
$code = Monitoring::Plugin::OK;
## use critic
if ( $level != $API_VERSION ) {
## no critic (ProhibitCallsToUnexportedSubs)
$code = Monitoring::Plugin::WARNING;
## use critic
}
}
else {
my $warning_threshold = $RANGE_NONE;
my $critical_threshold = $RANGE_NONE;
if ( defined $FUNCTIONS{$function}->{warning} ) {
$warning_threshold = $mp->opts->warning;
$warning_threshold //= $FUNCTIONS{$function}->{warning};
}
if ( defined $FUNCTIONS{$function}->{critical} ) {
$critical_threshold = $mp->opts->critical;
$critical_threshold //= $FUNCTIONS{$function}->{critical};
}
$code = $mp->check_threshold(
check => $level,
warning => $warning_threshold,
critical => $critical_threshold,
);
}
$mp->plugin_exit( $code, sprintf $LOG{check}, $function, $level );
}
else {
$mp->plugin_die( sprintf $LOG{data}, $page, $function );
}
}
else {
$mp->plugin_die( sprintf $LOG{page}, $page );
}
__END__
=encoding utf8
=for stopwords MERCHANTABILITY Ipenburg
=head1 NAME
check_raspberry_shake - check the status of a Raspberry Shake
=head1 USAGE
B<check_raspberry_shake> B<-H> I<host> B<-f> I<function>…
=head1 DESCRIPTION
B<check_raspberry_shake> checks the status of several properties of a Raspberry
Shake.
=head1 REQUIRED ARGUMENTS
The host
=head1 OPTIONS
=over 4
=item B< -?, -h, --help>
Show help
=item B< -v, --verbose>
Be more verbose
=item B<--version>
Show version and license
=item B<--function>
Check for function:
=over 8
=item * status: Running or not
=item * version: System software version, default warns if not 0.15
=item * producer: Data Producer on or not
=item * consumer: Data Consumer on or not
=item * forwarding: Data Forwarding on or not
=item * connected: Server Connection connected or not
=item * uptime: System uptime in minutes, defaults warning 10
critical 5
=item * disk_available: Disk space available in Mb, defaults warning 500
critical 100
=item * disk_used: Disk space used in percentage, defaults warning 90
critical 95
=item * cpu_temp: CPU temperature in degrees Celcius, defaults warning 80
critical 85
=back
=back
=head1 DIAGNOSTICS
=over 4
=item * Could not retrieve page '%s' to get data
(E) The resource containing the data could not be retrieved from the host
=item * Could not get data from resource '%s' for function '%s'
(E) The resource containing the data could be retrieved from the host but the
requested data was not found in that object
=item * Unknown function '%s', must be one of connected, consumer, cpu_temp,
disk_available, disk_used, forwarding, producer, status, uptime, version (E)
The requested function is not supported, must be one of the system properties
'connected', 'consumer', 'cpu_temp', 'disk_available', 'disk_used',
'forwarding', 'producer', 'status', 'uptime' or 'version'.
=back
=head1 EXAMPLES
C<check_raspberry_shake -H rs.local -f cpu_temp>
=head1 DEPENDENCIES
Perl 5.16.0, Monitoring::Plugin, HTTP::Tiny, JSON, List::MoreUtils, Readonly,
English
=head1 EXIT STATUS
The exist status is handled by the monitoring interface.
=head1 CONFIGURATION
The default warning and critical thresholds should be overridden by the
standard -w and -c options of the monitoring interface because they depend on
the usage of the device. The defaults thresholds are:
=over 4
=item * uptime 10: 1:
=item * disk_available 500: 100:
=item * disk_used 90 95
=item * cpu_temp 80: 85:
=back
=head1 INCOMPATIBILITIES
There are no known incompatibilities but since the data is retrieved from an
API in an undefined format, a different system software version could present
the data in a different format which might break things. It is compatible with
system software version C<0.15>.
=head1 BUGS AND LIMITATIONS
The 'status' function only determines between 'RUNNING' and not.
The 'producer', 'consumer', 'forwarding' and 'connected' functions only
determines between 'ON'/'CONNECTED' and not.
Please report any bugs or feature requests at
L<Issues for github.com|https://github.com/ipenburg/check_raspberry_shake/issues>.
=head1 AUTHOR
Roland van Ipenburg, E<lt>ipenburg@xs4all.nlE<gt>
=head1 LICENSE AND COPYRIGHT
Copyright 2019 by Roland van Ipenburg
This program is free software; you can redistribute it and/or modify
it under the GNU General Public License v3.0.
=head1 DISCLAIMER OF WARRANTY
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
=cut
You can’t perform that action at this time.