Source code for accre.nrpe
"""
Shared utility functions to use in nrpe scripts
"""
import datetime
import os.path
import re
import sys
[docs]def nrpe_precheck(fname, timeout=600, reboot_grace=7200):
"""
Check that the given nrpe precheck file exists and has been
updated within the specified timeout, or exit critical (2).
If ok, return file contents.
If the file does not exist and the machine has recently rebooted,
an ok will be given instead of a critical status.
A precheck file is a small output file generated by some command
that needs to be run as root which has output to be inspected by an
NRPE check. This is done as a cronjob on a node so that
the NRPE user does not need sudo access to run diagnostics.
Running checks this way also makes it easy to test the check itself
against expected failures.
:param str fname: Absolute path to the precheck file
:param int timeout: Maximum number of seconds that may have passed
since the precheck file was last updated
:param int reboot_grace: Maximum number of seconds after reboot
to allow a grace period where the file may not exist
:returns: Precheck file contents
:rtype: str
"""
grace = False
try:
raw = open('/proc/uptime').read()
uptime = float(raw.split()[0])
if uptime < reboot_grace:
grace = True
except Exception:
# No grace period if we can't read /proc/uptime
pass
try:
last = datetime.datetime.fromtimestamp(os.path.getmtime(fname))
except FileNotFoundError:
if grace:
print(
'OK - NRPE precheck file {0} not found but machine recently '
'rebooted'.format(fname)
)
sys.exit(0)
print('CRITICAL - NRPE precheck file {0} not found'.format(fname))
sys.exit(2)
ttl = (datetime.datetime.now() - last).total_seconds()
if ttl > timeout:
print(
'CRITICAL - NRPE precheck file {0} not modified in last {1}s'
.format(fname, int(ttl))
)
sys.exit(2)
try:
return open(fname).read()
except Exception:
print(
'CRITICAL - NRPE precheck file {0} could not be read'
.format(fname)
)
sys.exit(2)
[docs]def parse_mmlsdisk(raw):
"""
Return mmlsdisk info for each device
:param str raw: Raw input text presumably from an mmlsdisk command
run with the -Y option
:returns: List of device data dictionaries
:rtype: list(dict(str, str))
"""
lines = raw.splitlines()
lines = [s[len('mmlsdisk:'):].strip(':') for s in lines]
keys = lines[0].split(':')
result = []
for line in lines[1:]:
dev = {}
for idx, val in enumerate(line.split(':')):
dev[keys[idx]] = val
result.append(dev)
return result
[docs]def parse_multipath_info(raw):
"""
Return information for each multipath device from output
presumably returned by "multipath -ll" with their name (i.e. "dm-X"),
their serial number, and number of links in the
"active ready running" state.
:param str raw: Raw input text presumably from a multipath -ll command
:returns: List of device data dictionaries
:rtype: list(dict(str, str))
"""
redev = re.compile(
r'(mpath[a-z]+|accre-[a-z0-9-]+|dors2[a-z0-9-]+) '
r'\(([0-9a-f]+)\) (dm-[0-9]+)'
)
result = []
dev = None
for line in raw.splitlines():
m = redev.match(line)
if m:
if dev is not None:
result.append(dev)
dev = {}
dev['title'] = m.group(1)
dev['serial'] = m.group(2)
dev['name'] = m.group(3)
dev['good_links'] = 0
else:
if re.search('active ready running', line) and dev is not None:
dev['good_links'] += 1
if dev is not None:
result.append(dev)
return result