File: //lib64/nagios/plugins/check_uptrack_local
#!/usr/bin/python2
# Ksplice Uptrack local Nagios plugin
#
# Copyright (C) 2010-2012 Oracle and/or its affiliates. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function
import optparse
import os
import sys
import time
import yaml
try:
from yaml import CSafeLoader as yaml_loader
except ImportError:
from yaml import SafeLoader as yaml_loader
NAGIOS_OK = 0
NAGIOS_WARNING = 1
NAGIOS_CRITICAL = 2
NAGIOS_UNKNOWN = 3
INACTIVE_THRESHOLD = 12 * 60 * 60 # 12 hours, in seconds
def exit_nagios(status, text, perf=None, longtext=None, longperf=None):
sys.stdout.write(text)
if perf:
sys.stdout.write("|" + perf)
print()
if longtext:
sys.stdout.write(longtext)
if longperf:
sys.stdout.write("|" + longperf)
if longtext or longperf:
print()
sys.exit(status)
try:
import Uptrack
except ImportError as e:
exit_nagios(NAGIOS_UNKNOWN, "Import error", longtext=str(e))
def parse_states(spec):
out = []
mapping = dict(o='outofdate', u='unsupported', i='inactive')
for s in spec.split(","):
if s in mapping:
out.append(mapping[s])
return out
def last_checkin(results):
""" Returns the last checkin time in UTC epoch seconds.
"""
return time.mktime(results["Time"].timetuple())
def my_upgrade_plan(upgrade_plan):
steps = upgrade_plan["Plan"]
steps_str = "No updates to install or remove."
out_of_date = False
if len(steps) > 0:
out_of_date = True
steps_str = "Steps for upgrade:\n * " + \
"\n * ".join(["%s %s (%s)"
% (update_info['Command'], update_info['ID'], update_info['Name'])
for update_info in steps])
return out_of_date, steps_str
def unsupported(results):
return results["Result"]["Code"] == Uptrack.ERROR_UNSUPPORTED
def results_message(results):
return results["Result"]["Message"]
def get_host(results):
return results["Client"]["Hostname"]
def get_ip(results):
"""
The results file may have a 'LocalIP_error' instead of a LocalIP.
"""
try:
return results["Client"]["LocalIP"]
except KeyError:
return "unknown IP"
def get_uuid():
try:
return open(Uptrack.UPTRACK_UUID_FILE).read().strip()
except Exception:
return "unknown UUID"
def main():
parser = optparse.OptionParser("""Usage: %prog [options]""")
specs = optparse.OptionGroup(
parser,
"Nagios State specification",
"These options select under which circumstances the plugin "
"will return which Nagios state. Each option should be a "
"comma-separated string containing zero or more of the "
"choices 'o', 'u', and 'i', for out of date, unsupported, "
"and inactive machines, respectively.")
specs.add_option("-w", "--warning",
type="string",
action="store",
dest="warning",
default="",
help="Machine states to trigger a WARNING state.")
specs.add_option("-c", "--critical",
type="string",
action="store",
dest="critical",
default="",
help="Machine states to trigger a CRITICAL state.")
parser.add_option_group(specs)
(opts, unused_args) = parser.parse_args()
if not opts.critical and not opts.warning:
# If no options are specified, default to a CRITICAL status for out of
# date machines and a WARNING status for inactive machines.
opts.critical = 'o'
opts.warning = 'i'
states = dict()
sysname, unused_hostname, release, version, arch, unused_userarch = Uptrack.getUname()
path = os.path.join(Uptrack.UPTRACK_CACHE_DIR, sysname, arch, release, version)
try:
results = yaml.load(open(os.path.join(path, "results"), 'r').read(),
Loader=yaml_loader)
except Exception as e:
longtext = "\n".join(
[str(e),
"",
"It looks like the Uptrack client has never been run on this system.",
"Please run 'uptrack-upgrade -n' to update the list of available updates.",
"For assistance, please contact ksplice-support_ww@oracle.com."]
)
exit_nagios(NAGIOS_UNKNOWN, "%s is UNKNOWN" % (get_uuid(),),
longtext=longtext)
out_of_date = False
try:
upgrade_plan = yaml.load(open(os.path.join(path, "upgrade_plan"), 'r').read(),
Loader=yaml_loader)
# Am I out of date?
out_of_date, plan = my_upgrade_plan(upgrade_plan)
except Exception:
# Unsupported kernels and trying to upgrade with an invalid access key
# are some of the ways to have a results file but no upgrade plan.
plan = results_message(results)
if out_of_date:
states["outofdate"] = True
# Am I unsupported?
if unsupported(results):
states["unsupported"] = True
# Am I inactive?
if time.time() - last_checkin(results) > INACTIVE_THRESHOLD:
states["inactive"] = True
# Summarize all issues in the perfdata
perfdata = ";".join([state for (state, val) in states.items() if val])
for (rv, spec) in [(NAGIOS_CRITICAL, opts.critical),
(NAGIOS_WARNING, opts.warning)]:
for state in parse_states(spec):
if states.get(state):
exit_nagios(rv,
"%s (%s) is %s" % (get_host(results), get_ip(results), state.upper()),
perf=perfdata, longtext=plan)
exit_nagios(NAGIOS_OK, "%s (%s) is OK" % (get_host(results), get_ip(results)),
perf=perfdata)
if __name__ == '__main__':
sys.exit(main())