Merge pull request #39 from opinkerfi/plugin_check_yum_update

Updated check_yum to 0.8.9
This commit is contained in:
Garðar Þorsteinsson 2019-10-23 15:45:05 +00:00 committed by GitHub
commit 9eda5324d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 273 additions and 274 deletions

View File

@ -1,24 +1,29 @@
#!/usr/bin/python #!/usr/bin/env python
# coding=utf-8 #
# Author: Hari Sekhon
# Date: 2008-04-29 17:21:08 +0100 (Tue, 29 Apr 2008)
#
# https://github.com/harisekhon/nagios-plugins
#
# License: see accompanying LICENSE file
#
"""Nagios plugin to check the YUM package management system for package updates. """
Can optionally alert on any available updates as well as just Nagios plugin to test for Yum updates on RedHat / CentOS Linux.
security related updates"""
__title__ = "check_yum" Can optionally alert on any available updates as well as just security related updates
__version__ = "0.8.0"
# Standard Nagios return codes See also: check_yum.pl (also part of the Advanced Nagios Plugins Collection)
OK = 0
WARNING = 1 Tested on CentOS 5 / 6 / 7
CRITICAL = 2 """
UNKNOWN = 3
import os import os
import re import re
import sys import sys
import signal import signal
OLD_PYTHON = False OLD_PYTHON = False
# pylint: disable=wrong-import-position
try: try:
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
except ImportError: except ImportError:
@ -26,28 +31,41 @@ except ImportError:
import commands import commands
from optparse import OptionParser from optparse import OptionParser
__author__ = "Hari Sekhon"
__title__ = "Nagios Plugin for Yum updates on RedHat/CentOS systems"
__version__ = "0.8.9"
# Standard Nagios return codes
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3
DEFAULT_TIMEOUT = 30 DEFAULT_TIMEOUT = 30
support_msg = "Please make sure you have upgraded to the latest version from " + \
"https://github.com/harisekhon/nagios-plugins. If the problem persists, " + \
"please raise a ticket at https://github.com/harisekhon/nagios-plugins/issues "+ \
"with the full -vvv output"
def end(status, message, perfdata=''): def end(status, message):
"""Exits the plugin with first arg as the return code and the second """Exits the plugin with first arg as the return code and the second
arg as the message to output""" arg as the message to output"""
check = "YUM " check = "YUM "
if status == OK: if status == OK:
print "%sOK: %s | %s" % (check, message, perfdata) print "%sOK: %s" % (check, message)
sys.exit(OK) sys.exit(OK)
elif status == WARNING: elif status == WARNING:
print "%sWARNING: %s | %s" % (check, message, perfdata) print "%sWARNING: %s" % (check, message)
sys.exit(WARNING) sys.exit(WARNING)
elif status == CRITICAL: elif status == CRITICAL:
print "%sCRITICAL: %s | %s" % (check, message, perfdata) print "%sCRITICAL: %s" % (check, message)
sys.exit(CRITICAL) sys.exit(CRITICAL)
else: else:
print "UNKNOWN: %s" % message print "UNKNOWN: %s" % message
sys.exit(UNKNOWN) sys.exit(UNKNOWN)
YUM = "/usr/bin/yum" YUM = "/usr/bin/yum"
def check_yum_usable(): def check_yum_usable():
@ -62,26 +80,28 @@ def check_yum_usable():
end(UNKNOWN, "%s is not executable" % YUM) end(UNKNOWN, "%s is not executable" % YUM)
class YumTester: class YumTester(object):
"""Class to hold all portage test functions and state""" """Class to hold all portage test functions and state"""
def __init__(self): def __init__(self):
"""Initialize all object variables""" """Initialize all object variables"""
self.all_updates = False self.all_updates = False
self.no_cache_update = False self.no_cache_update = False
self.no_warn_on_lock = False self.no_warn_on_lock = False
self.enable_repo = "" self.enable_repo = ""
self.disable_repo = "" self.disable_repo = ""
self.timeout = DEFAULT_TIMEOUT self.disable_plugin = ""
self.verbosity = 0 self.yum_config = ""
self.timeout = DEFAULT_TIMEOUT
self.verbosity = 0
self.warn_on_any_update = False self.warn_on_any_update = False
def validate_all_variables(self): def validate_all_variables(self):
"""Validates all object variables to make sure the """Validates all object variables to make sure the
environment is sane""" environment is sane"""
if self.timeout == None: if self.timeout is None:
self.timeout = DEFAULT_TIMEOUT self.timeout = DEFAULT_TIMEOUT
try: try:
self.timeout = int(self.timeout) self.timeout = int(self.timeout)
@ -92,7 +112,7 @@ class YumTester:
if self.timeout < 1 or self.timeout > 3600: if self.timeout < 1 or self.timeout > 3600:
end(UNKNOWN, "Timeout must be a number between 1 and 3600 seconds") end(UNKNOWN, "Timeout must be a number between 1 and 3600 seconds")
if self.verbosity == None: if self.verbosity is None:
self.verbosity = 0 self.verbosity = 0
try: try:
self.verbosity = int(self.verbosity) self.verbosity = int(self.verbosity)
@ -104,13 +124,13 @@ class YumTester:
def run(self, cmd): def run(self, cmd):
"""runs a system command and returns """runs a system command and returns
an array of lines of the output""" an array of lines of the output"""
if cmd == "" or cmd == None: if not cmd:
end(UNKNOWN, "Internal python error - " \ end(UNKNOWN, "Internal python error - " \
+ "no cmd supplied for run function") + "no cmd supplied for run function")
if self.no_cache_update: if self.no_cache_update:
cmd += " -C" cmd += " -C"
@ -121,32 +141,43 @@ class YumTester:
for repo in self.disable_repo.split(","): for repo in self.disable_repo.split(","):
cmd += " --disablerepo=%s" % repo cmd += " --disablerepo=%s" % repo
if self.disable_plugin:
# --disableplugin can take a comma separated list directly
#for plugin in self.disable_plugin.split(","):
#cmd += " --disableplugin=%s" % plugin
cmd += " --disableplugin=%s" % self.disable_plugin
if self.yum_config:
for repo in self.yum_config.split(","):
cmd += " --config=%s" % repo
self.vprint(3, "running command: %s" % cmd) self.vprint(3, "running command: %s" % cmd)
if OLD_PYTHON: if OLD_PYTHON:
self.vprint(3, "subprocess not available, probably old python " \ self.vprint(3, "subprocess not available, probably old python " \
+ "version, using shell instead") + "version, using shell instead")
os.environ['LANG'] = "en_US"
returncode, stdout = commands.getstatusoutput(cmd) returncode, stdout = commands.getstatusoutput(cmd)
if returncode >= 256: if returncode >= 256:
returncode = returncode / 256 returncode = returncode / 256
else: else:
try: try:
process = Popen( cmd.split(), env = {'LANG': 'en_US'}
stdin=PIPE, process = Popen(cmd.split(), stdin=PIPE, stdout=PIPE, stderr=STDOUT, env=env)
stdout=PIPE,
stderr=STDOUT )
except OSError, error: except OSError, error:
error = str(error) error = str(error)
if error == "No such file or directory": if error == "No such file or directory":
end(UNKNOWN, "Cannot find utility '%s'" % cmd.split()[0]) end(UNKNOWN, "Cannot find utility '%s'" % cmd.split()[0])
end(UNKNOWN, "Error trying to run utility '%s' - %s" \ end(UNKNOWN, "Error trying to run utility '%s' - %s" \
% (cmd.split()[0], error)) % (cmd.split()[0], error))
output = process.communicate() output = process.communicate()
# for using debug outputs, either do not comment above line or explicitly set exit code below
#output = [open(os.path.dirname(__file__) + '/test_input.txt').read(), '']
returncode = process.returncode returncode = process.returncode
stdout = output[0] stdout = output[0]
if stdout == None or stdout == "": if not stdout:
end(UNKNOWN, "No output from utility '%s'" % cmd.split()[0]) end(UNKNOWN, "No output from utility '%s'" % cmd.split()[0])
self.vprint(3, "Returncode: '%s'\nOutput: '%s'" \ self.vprint(3, "Returncode: '%s'\nOutput: '%s'" \
@ -158,19 +189,21 @@ class YumTester:
def check_returncode(self, returncode, output): def check_returncode(self, returncode, output):
"""Takes the returncode and output (as an array of lines) """Takes the returncode and output (as an array of lines)
of the YUM program execution and tests for failures, exits of the yum program execution and tests for failures, exits
with an appropriate message if any are found""" with an appropriate message if any are found"""
if returncode == 0: if returncode == 0:
pass for line in output:
if "You must run this command as root" in line:
end(UNKNOWN, "You must run this plugin as root")
elif returncode == 100: elif returncode == 100:
# Updates Available # Updates Available
pass pass
elif returncode == 200: elif returncode == 200:
if "lock" in output[-2] or "another copy is running" in output[-2]: if "lock" in output[-2] or "another copy is running" in output[-2]:
msg = "Cannot check for updates, " \ msg = "Cannot check for updates, " \
+ "another instance of YUM is running" + "another instance of yum is running"
if self.no_warn_on_lock: if self.no_warn_on_lock:
end(OK, msg) end(OK, msg)
else: else:
@ -179,10 +212,15 @@ class YumTester:
output = self.strip_output(output) output = self.strip_output(output)
end(UNKNOWN, "%s" % output) end(UNKNOWN, "%s" % output)
else: else:
if not 'Loading "security" plugin' in output \ if 'No more mirrors to try' in output:
end(UNKNOWN, 'connectivity issue to repos: \'No more mirrors to try\'. ' + \
'You could also try running --cache-only and ' + \
'scheduling a separate \'yum makecache\' via cron or similar')
elif (not ('Loading "security" plugin' in output or 'Loaded plugins:.*security' in output)) \
or "Command line error: no such option: --security" in output: or "Command line error: no such option: --security" in output:
end(UNKNOWN, "Security plugin for YUM is required. Try to " \ end(UNKNOWN, "Security plugin for yum is required. Try to " \
+ "'yum install yum-security' and then re-run " \ + "'yum install yum-security' (RHEL5) or " \
+ "'yum install yum-plugin-security' (RHEL6) and then re-run " \
+ "this plugin. Alternatively, to just alert on " \ + "this plugin. Alternatively, to just alert on " \
+ "any update which does not require the security " \ + "any update which does not require the security " \
+ "plugin, try --all-updates") + "plugin, try --all-updates")
@ -192,8 +230,8 @@ class YumTester:
def strip_output(self, output): def strip_output(self, output):
"""Cleans up the output from the plugin and returns it. """Cleans up the output from the plugin and returns it.
Takes and returns an array of the lines of output Takes and returns an array of the lines of output
and returns a single string""" and returns a single string"""
self.vprint(3, "stripping output of 'Loading ... plugin' lines") self.vprint(3, "stripping output of 'Loading ... plugin' lines")
@ -243,149 +281,137 @@ class YumTester:
return number_security_updates, number_other_updates return number_security_updates, number_other_updates
def get_all_updates(self): def get_all_updates(self):
"""Gets all updates. Returns a single integer of the """Gets all updates. Returns a single integer of the
number of available updates""" number of available updates"""
cmd = "%s check-update" % YUM cmd = "%s check-update" % YUM
output = self.run(cmd) output = self.run(cmd)
output2 = "\n".join(output).split("\n\n") output2 = [_ for _ in "\n".join(output).split("\n\n") if _]
if self.verbosity >= 4 : if self.verbosity >= 4:
for section in output2: for section in output2:
print "\nSection:\n%s\n" % section print "\nSection:\n%s\n" % section
if len(output2) > 2 or \ if len(output2) > 2 or \
not ( "Setting up repositories" in output2[0] or \ not ("Setting up repositories" in output2[0] or \
"Loaded plugins: " in output2[0] or \ "Loaded plugins: " in output2[0] or \
re.search('Loading\s+".+"\s+plugin', output2[0]) ): re.search(r'Loading\s+".+"\s+plugin', output2[0])):
end(WARNING, "Yum output signature does not match current known " \ end(WARNING, "Yum output signature does not match current known " \
+ "format. Please make sure you have upgraded to the " \ + "format. " + support_msg)
+ "latest version of this plugin. If the problem " \ number_packages = 0
+ "persists, please contact the author for a fix")
if len(output2) == 1: if len(output2) == 1:
# There are no updates but we have passed # There are no updates but we have passed
# the loading and setting up of repositories # the loading and setting up of repositories
number_packages = 0 pass
else: else:
number_packages = len([x for x in output2[1].split("\n") \ for line in output2[1].split("\n"):
if len(x.split()) > 1 ]) if len(line.split()) > 1 and \
line[0:1] != " " and \
"Obsoleting Packages" not in line:
number_packages += 1
try: try:
number_packages = int(number_packages) number_packages = int(number_packages)
if number_packages < 0: if number_packages < 0:
raise ValueError raise ValueError
except ValueError: except ValueError:
end(UNKNOWN, "Error parsing package information, invalid package " \ end(UNKNOWN, "Error parsing package information, invalid package " \
+ "number, YUM output may have changed. Please make " \ + "number, yum output may have changed. " + support_msg)
+ "sure you have upgraded to the latest version of " \
+ "this plugin. If the problem persists, then please " \
+ "contact the author for a fix")
# Extra layer of checks. This is a security plugin so it's preferable # Extra layer of checks. This is a security plugin so it's preferable
# to fail on error rather than pass silently leaving you with an # to fail on error rather than pass silently leaving you with an
# insecure system # insecure system
count = 0 count = 0
re_kernel_security_update = re.compile('^Security: kernel-.+ is an installed security update')
re_kernel_update = re.compile('^Security: kernel-.+ is the currently running version')
re_package_format = \ re_package_format = \
re.compile("^.+\.(i[3456]86|x86_64|noarch)\s+.+\s+.+$") re.compile(r'^.+\.(i[3456]86|x86_64|noarch)\s+.+\s+.+$')
# This is to work around a YUM truncation issue effectively changing # This is to work around a yum truncation issue effectively changing
# the package output format. Currently only very long kmod lines # the package output format. Currently only very long kmod lines
# are seen to have caused this so we stick to what we know for safety # are seen to have caused this so we stick to what we know for safety
# and raise an unknown error on anything else for maximum security # and raise an unknown error on anything else for maximum security
#re_package_format_truncated = \ #re_package_format_truncated = \
# re.compile("^[\w-]+-kmod-\d[\d\.-]+.*\s+.+\s+.+$") # re.compile("^[\w-]+-kmod-\d[\d\.-]+.*\s+.+\s+.+$")
obsoleting_packages = False
for line in output: for line in output:
if ' excluded ' in line:
continue
elif obsoleting_packages and line[0:1] == " ":
continue
elif "Obsoleting Packages" in line:
obsoleting_packages = True
continue
elif re_kernel_security_update.match(line):
end(WARNING, 'Kernel security update is installed but requires a reboot')
elif re_kernel_update.match(line):
continue
if re_package_format.match(line): if re_package_format.match(line):
count += 1 count += 1
if count != number_packages: if count != number_packages:
end(UNKNOWN, "Error parsing package information, inconsistent " \ end(UNKNOWN, "Error parsing package information, inconsistent " \
+ "package count, yum output may have changed. Please " \ + "package count (%d count vs %s num packages)" % (count, number_packages) \
+ "make sure you have upgraded to the latest version " \ + ", yum output may have changed. " + support_msg)
+ "of this plugin. If the problem persists, then " \
+ "please contact the author for a fix")
return number_packages, "'updates'=%s" % (number_packages) return number_packages
def get_security_updateinfo(self):
"""Fetches errata numbers and package names"""
cmd = "%s list-security" % YUM
output = self.run(cmd)
errata = []
for line in output:
try:
if line.split()[1] != "security" and line.split()[1][-4:] != "Sec.":
continue
except:
continue
(advisoryid, etype, package) = line.split()
errata.append( { "name": package, "advisory": advisoryid } )
return errata
def get_security_updates(self): def get_security_updates(self):
"""Gets all updates, but differentiates between """Gets all updates, but differentiates between
security and normal updates. Returns a tuple of the number security and normal updates. Returns a tuple of the number
of security and normal updates""" of security and normal updates"""
cmd = "%s --security check-update" % YUM cmd = "%s --security check-update" % YUM
output = self.run(cmd) output = self.run(cmd)
re_security_summary_rhel5 = re.compile("Needed \d+ of \d+ packages, for security") re_security_summary = \
re_security_summary_rhel6 = re.compile("\d+ package\(s\) needed for security, out of \d+ available") re.compile(r'Needed (\d+) of (\d+) packages, for security')
re_no_security_updates_available_rhel5 = re.compile("No packages needed, for security, \d+ available") re_summary_rhel6 = re.compile(r'(\d+) package\(s\) needed for security, out of (\d+) available')
re_no_security_updates_available_rhel6 = re.compile("No packages needed for security; \d+ packages available") re_no_sec_updates = \
re.compile(r'No packages needed,? for security[;,] (\d+) (?:packages )?available')
re_kernel_update = re.compile(r'^Security: kernel-.+ is an installed security update')
summary_line_found = False summary_line_found = False
for line in output: for line in output:
if re_no_security_updates_available_rhel5.match(line): _ = re_summary_rhel6.match(line)
if _:
summary_line_found = True
number_security_updates = _.group(1)
number_total_updates = _.group(2)
break
_ = re_no_sec_updates.match(line)
if _:
summary_line_found = True summary_line_found = True
number_security_updates = 0 number_security_updates = 0
number_total_updates = line.split()[5] number_total_updates = _.group(1)
break break
if re_no_security_updates_available_rhel6.match(line): _ = re_security_summary.match(line)
if _:
summary_line_found = True summary_line_found = True
number_security_updates = 0 number_security_updates = _.group(1)
number_total_updates = line.split()[5] number_total_updates = _.group(2)
break
if re_security_summary_rhel5.match(line):
summary_line_found = True
number_security_updates = line.split()[1]
number_total_updates = line.split()[3]
break
if re_security_summary_rhel6.match(line):
summary_line_found = True
number_security_updates = line.split()[0]
number_total_updates = line.split()[7]
break break
_ = re_kernel_update.match(line)
if _:
end(CRITICAL, "Kernel security update is installed but requires a reboot")
if not summary_line_found: if not summary_line_found:
end(WARNING, "Cannot find summary line in YUM output. Please " \ end(WARNING, "Cannot find summary line in yum output. " + support_msg)
+ "make sure you have upgraded to the latest version " \
+ "of this plugin. If the problem persists, please " \
+ "contact the author for a fix")
try: try:
number_security_updates = int(number_security_updates) number_security_updates = int(number_security_updates)
number_total_updates = int(number_total_updates) number_total_updates = int(number_total_updates)
except ValueError: except ValueError:
end(WARNING, "Error parsing package information, YUM output " \ end(WARNING, "Error parsing package information, yum output " \
+ "may have changed. Please make sure you have " \ + "may have changed. " + support_msg)
+ "upgraded to the latest version of this plugin. " \
+ "If the problem persists, the please contact the " \
+ "author for a fix")
number_other_updates = number_total_updates - number_security_updates number_other_updates = number_total_updates - number_security_updates
if len(output) > number_total_updates + 25: from_excluded_regex = re.compile(' from .+ excluded ')
if len([_ for _ in output if not from_excluded_regex.search(_)]) > number_total_updates + 25:
end(WARNING, "Yum output signature is larger than current known " \ end(WARNING, "Yum output signature is larger than current known " \
+ "format, please make sure you have upgraded to the " \ + "format. " + support_msg)
+ "latest version of this plugin. If the problem " \
+ "persists, please contact the author for a fix")
return number_security_updates, number_other_updates return number_security_updates, number_other_updates
@ -394,26 +420,25 @@ class YumTester:
"""Starts tests and controls logic flow""" """Starts tests and controls logic flow"""
check_yum_usable() check_yum_usable()
self.vprint(3, "%s - Version %s\n" \ self.vprint(3, "%s - Version %s\nAuthor: %s\n" \
% (__title__, __version__)) % (__title__, __version__, __author__))
self.validate_all_variables() self.validate_all_variables()
self.set_timeout() self.set_timeout()
if self.all_updates: if self.all_updates:
return self.test_all_updates() return self.test_all_updates()
else: return self.test_security_updates()
return self.test_security_updates()
def test_all_updates(self): def test_all_updates(self):
"""Tests for all updates, and returns a tuple """Tests for all updates, and returns a tuple
of the status code and output""" of the status code and output"""
status = UNKNOWN status = UNKNOWN
message = "code error - please contact author for a fix" message = "code error. " + support_msg
number_updates, perfdata = self.get_all_updates() number_updates = self.get_all_updates()
if number_updates == 0: if number_updates == 0:
status = OK status = OK
message = "0 Updates Available" message = "0 Updates Available"
@ -424,20 +449,20 @@ class YumTester:
else: else:
message = "%s Updates Available" % number_updates message = "%s Updates Available" % number_updates
return status, message, perfdata message += " | total_updates_available=%s" % number_updates
return status, message
def test_security_updates(self): def test_security_updates(self):
"""Tests for security updates and returns a tuple """Tests for security updates and returns a tuple
of the status code and output""" of the status code and output"""
status = UNKNOWN status = UNKNOWN
message = "code error - please contact author for a fix" message = "code error. " + support_msg
number_security_updates, number_other_updates = \ number_security_updates, number_other_updates = \
self.get_security_updates() self.get_security_updates()
perfdata = "'security_updates'=%s 'other_updates'=%s" % (number_security_updates, number_other_updates)
if number_security_updates == 0: if number_security_updates == 0:
status = OK status = OK
message = "0 Security Updates Available" message = "0 Security Updates Available"
@ -448,6 +473,7 @@ class YumTester:
elif number_security_updates > 1: elif number_security_updates > 1:
message = "%s Security Updates Available" \ message = "%s Security Updates Available" \
% number_security_updates % number_security_updates
if number_other_updates != 0: if number_other_updates != 0:
if self.warn_on_any_update and status != CRITICAL: if self.warn_on_any_update and status != CRITICAL:
status = WARNING status = WARNING
@ -456,13 +482,10 @@ class YumTester:
else: else:
message += ". %s Non-Security Updates Available" \ message += ". %s Non-Security Updates Available" \
% number_other_updates % number_other_updates
message += " | security_updates_available=%s non_security_updates_available=%s total_updates_available=%s" \
if number_security_updates and self.long_output: % (number_security_updates, number_other_updates, number_security_updates + number_other_updates)
errata = self.get_security_updateinfo()
for e in errata: return status, message
message += "\n%s - %s" % (e['advisory'], e['name'])
return status, message, perfdata
def vprint(self, threshold, message): def vprint(self, threshold, message):
@ -479,88 +502,97 @@ def main():
tester = YumTester() tester = YumTester()
parser = OptionParser() parser = OptionParser()
parser.add_option( "--all-updates", parser.add_option("-A",
action="store_true", "--all-updates",
dest="all_updates", action="store_true",
help="Does not distinguish between security and " \ dest="all_updates",
+ "non-security updates, but returns critical for " \ help="Does not distinguish between security and " \
+ "any available update. This may be used if the " \ + "non-security updates, but returns critical for " \
+ "YUM security plugin is absent or you want to " \ + "any available update. This may be used if the " \
+ "maintain every single package at the latest " \ + "yum security plugin is absent or you want to " \
+ "version. You may want to use " \ + "maintain every single package at the latest " \
+ "--warn-on-any-update instead of this option") + "version. You may want to use " \
+ "--warn-on-any-update instead of this option")
parser.add_option( "--warn-on-any-update", parser.add_option("-W",
action="store_true", "--warn-on-any-update",
dest="warn_on_any_update", action="store_true",
help="Warns if there are any (non-security) package " \ dest="warn_on_any_update",
+ "updates available. By default only warns when " \ help="Warns if there are any (non-security) package " \
+ "security related updates are available. If " \ + "updates available. By default only warns when " \
+ "--all-updates is used, then this option is " \ + "security related updates are available. If " \
+ "redundant as --all-updates will return a " \ + "--all-updates is used, then this option is " \
+ "critical result on any available update, " \ + "redundant as --all-updates will return a " \
+ "whereas using this switch still allows you to " \ + "critical result on any available update, " \
+ "differentiate between the severity of updates ") + "whereas using this switch still allows you to " \
+ "differentiate between the severity of updates ")
parser.add_option( "-C", parser.add_option("-C",
"--cache-only", "--cache-only",
action="store_true", action="store_true",
dest="no_cache_update", dest="no_cache_update",
help="Run entirely from cache and do not update the " \ help="Run entirely from cache and do not update the " \
+ "cache when running YUM. Useful if you have " \ + "cache when running yum. Useful if you have " \
+ "'yum makecache' cronned so that the nagios " \ + "'yum makecache' cronned so that the nagios " \
+ "check itself doesn't have to do it, possibly " \ + "check itself doesn't have to do it, possibly " \
+ "speeding up execution (by 1-2 seconds in tests)") + "speeding up execution (by 1-2 seconds in tests)")
parser.add_option( "--no-warn-on-lock", parser.add_option("-c",
action="store_true", "--config",
dest="no_warn_on_lock", dest="yum_config",
help="Return OK instead of WARNING when YUM is locked " \ help="Run with custom repository config in order to use " \
+ "and fails to check for updates due to another " \ + "custom repositories in case of special setup for")
+ "instance running. This is not recommended from " \
+ "the security standpoint, but may be wanted to " \
+ "reduce the number of alerts that may " \
+ "intermittently pop up when someone is running " \
+ "YUM interactively for package management")
parser.add_option( "--enablerepo", parser.add_option("-N",
dest="repository_to_enable", "--no-warn-on-lock",
help="Explicitly enables a reposity when calling YUM. " action="store_true",
+ "Can take a comma separated list of repositories") dest="no_warn_on_lock",
help="Return OK instead of WARNING when yum is locked " \
+ "and fails to check for updates due to another " \
+ "instance running. This is not recommended from " \
+ "the security standpoint, but may be wanted to " \
+ "reduce the number of alerts that may " \
+ "intermittently pop up when someone is running " \
+ "yum for package management")
parser.add_option( "--disablerepo", parser.add_option("-e",
dest="repository_to_disable", "--enablerepo",
help="Explicitly disables a repository when calling YUM " dest="repository_to_enable",
+ "Can take a comma separated list of repositories") help="Explicitly enables a reposity when calling yum. " +
"Can take a comma separated list of repositories")
parser.add_option( "-l", parser.add_option("-d",
"--long-output", "--disablerepo",
action="store_true", dest="repository_to_disable",
dest="long_output", help="Explicitly disables a repository when calling yum. " \
help="Shows more detailed output including the errata " + "Can take a comma separated list of repositories")
+ "ID.")
parser.add_option( "-t", parser.add_option("--disableplugin",
"--timeout", dest="plugin_to_disable",
dest="timeout", help="Explicitly disables a plugin when calling yum. " \
help="Sets a timeout in seconds after which the " \ + "Can take a comma separated list of plugins")
+"plugin will exit (defaults to %s seconds). " \
parser.add_option("-t",
"--timeout",
dest="timeout",
help="Sets a timeout in seconds after which the " \
+"plugin will exit (defaults to %s seconds). " \
% DEFAULT_TIMEOUT) % DEFAULT_TIMEOUT)
parser.add_option( "-v", parser.add_option("-v",
"--verbose", "--verbose",
action="count", action="count",
dest="verbosity", dest="verbosity",
help="Verbose mode. Can be used multiple times to " \ help="Verbose mode. Can be used multiple times to " \
+ "increase output. Use -vvv for debugging output. " \ + "increase output. Use -vvv for debugging output. " \
+ "By default only one result line is printed as " \ + "By default only one result line is printed as " \
+ "per Nagios standards") + "per Nagios standards")
parser.add_option( "-V", parser.add_option("-V",
"--version", "--version",
action="store_true", action="store_true",
dest="version", dest="version",
help="Print version number and exit") help="Print version number and exit")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
@ -568,23 +600,24 @@ def main():
parser.print_help() parser.print_help()
sys.exit(UNKNOWN) sys.exit(UNKNOWN)
tester.all_updates = options.all_updates tester.all_updates = options.all_updates
tester.no_cache_update = options.no_cache_update tester.no_cache_update = options.no_cache_update
tester.no_warn_on_lock = options.no_warn_on_lock tester.no_warn_on_lock = options.no_warn_on_lock
tester.enable_repo = options.repository_to_enable tester.enable_repo = options.repository_to_enable
tester.disable_repo = options.repository_to_disable tester.disable_repo = options.repository_to_disable
tester.timeout = options.timeout tester.disable_plugin = options.plugin_to_disable
tester.verbosity = options.verbosity tester.yum_config = options.yum_config
tester.warn_on_any_update = options.warn_on_any_update tester.timeout = options.timeout
tester.long_output = options.long_output tester.verbosity = options.verbosity
tester.warn_on_any_update = options.warn_on_any_update
if options.version: if options.version:
print "%s - Version %s\n" \ print "%s - Version %s\nAuthor: %s\n" \
% (__title__, __version__) % (__title__, __version__, __author__)
sys.exit(OK) sys.exit(OK)
result, output, perfdata = tester.test_yum_updates() result, output = tester.test_yum_updates()
end(result, output, perfdata) end(result, output)
if __name__ == "__main__": if __name__ == "__main__":
@ -593,37 +626,3 @@ if __name__ == "__main__":
except KeyboardInterrupt: except KeyboardInterrupt:
print "Caught Control-C..." print "Caught Control-C..."
sys.exit(CRITICAL) sys.exit(CRITICAL)
#Copyright © ??, Hari Sekhon <harisekhon@gmail.com>.
#Copyright © 2012, Christoph Anton Mitterer <mail@christoph.anton.mitterer.name>.
#All rights reserved.
#
#
#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; version 2
#of the License.
#
#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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.