#!/usr/bin/perl
eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
	if 0; # not running under some shell
#
#		check_yum: Nagios reporting for software updates
#		Copyright (C) 2008 Ithaka Harbors, Inc.
#
#		This program is free software; you can redistribute it and/or modify
#		it under the terms of the GNU General Public License as published by
#		the Free Software Foundation; either version 2 of the License, or
#		any later version.
#
#		This program is distributed in the hope that it will be useful,
#		but WITHOUT ANY WARRANTY; without even the implied warranty of
#		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#		GNU General Public License for more details.
#
#		You should have received a copy of the GNU General Public License
#		along with this program; if not, write to the Free Software
#		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

=head1 NAME

check_yum - Nagios Software Status Check

=head1 SYNOPSIS

B<check_yum>
[B<-c>, B<--critical>]
[B<-y>, B<--yum>]
[B<-v>, B<--verbose>]
[B<-h>, B<--help>]
[B<-V>, B<--version>]

=head1 DESCRIPTION

Run yum check-updates via sudo to determine if new packages are available.

=head1 REQUIREMENTS

=over 4

=item B<yum>

The system must support yum for rpm management.

=item B<sudo>

Without sudo, yum never reports new packages since it cannot update the local
copies of the package lists.

=item B<Nagios::Plugin>

This provides the return codes that Nagios wants.

=back

=head1 COMMAND LINE OPTIONS

=over 4

=item B<-c> or B<--critical>

A comma separate list of package names to compare (as strings) to the output
from yum. Any match causes check_yum to exit with a critical (instead of
warning) status. kernel,server,httpd may be a good starting value.

=item B<-y> or B<--yum>

Additional command line options for yum (maybe to en/dis-able repositories).

=item B<-v> or B<--verbose>

Outputs debugging information on STDERR.

=item B<-h> or B<--help>

Prints usage information and exits.

=item B<-v> or B<--version>

Prints version information and exits.

=back

=head1 NOTES

sudo must allow running yum without a password. Add a line like:

=over 4

nagios ALL=(root) NOPASSWD: /usr/bin/yum

=back

via visudo to the sudo configuration.

=head1 AUTHOR

Alan Brenner - alan.brenner@ithaka.org; I've written this based on the idea at
http://www.nagiosexchange.org/cgi-bin/page.cgi?g=Detailed%2F2402.html;d=1, but
that did not work correctly for me (yum never reported available updates when
run as user nagios, unless I ran yum by hand as root).

=head1 BUGS

Undoubtedly there are some in here. I (Alan Brenner) expect that the main issue
could be my use of a blank line to distinguish the package list in the yum
output. This works for yum 3.2.8 on CentOS5, but I don't know about any other
release.

=head1 COPYRIGHT

	Copyright (C) 2008 Ithaka Harbors, Inc.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

=cut

use strict;
use Data::Dumper;
use Nagios::Plugin;

our($np,			# Nagios::Plugin object
	$debug,			# verbose or not
	@packages,		# list of packages that cause a critical status
	$line,			# line of output from yum
	$list,			# boolean set to true for first blank line from yum
	$ii,			# for loop index
	$yum			# check_yum return code
);

$np = Nagios::Plugin->new(version => 'Ithaka 1.0',
	usage => "Usage: %s [ -v|--verbose ] [ -t <timeout> ] [ -c <package> ]");
$np->add_arg(spec => 'critical|c=s',
	help => '-c, --critical=string[,string....] A comma separated list of' .
		' package names any one of which will generate a critical status');
$np->add_arg(spec => 'yum|y=s',
	help => '-y, --yum=string Options for yum (passed through check_yum)');

# Parse @ARGV and process standard arguments (e.g. usage, help, version)
$np->getopts;
# Timeout, if necessary
alarm $np->opts->timeout;
$debug = $np->opts->verbose;
@packages = split(/,/, $np->opts->critical);
if ($debug and @packages) {		# output the list, (nicely ;-) formatted
	my $ii = Data::Dumper->new([\@packages], ['packages']);
	$ii->Indent(1);
	warn $ii->Dump();
}

$yum = OK;
$list = 0;
$line = '/usr/bin/sudo /usr/bin/yum ' . $np->opts->yum . ' check-update';
warn "running $line\n" if $debug;
open YUM, "$line|" or $np->nagios_die("Cannot run $line: $!");
while ($line = <YUM>) {
	chomp $line;				# without chomp, $list doesn't get set to 1
	warn "'$line'\n" if $debug;
	$list = 1 if not $line and $line =~ /^\s*$/; # not /^\S+\s+\S+\s+\S+$/
	next unless $list;			# don't go past here unless their are updates
	$yum = WARNING;				# by default any available update is a warning
	if ($yum != CRITICAL) {		# no point in checking, if we already are crit
		foreach $ii (@packages) {
			if (index($line, $ii) > -1) {
				$yum = CRITICAL;
				last;
			}
		}
	}
}
close YUM;

$np->nagios_exit($yum, 'O/S requires an update.') if ($yum != OK);
$np->nagios_exit($yum, 'O/S is up to date.');

