More improvements
This commit is contained in:
parent
c1c40b9ba9
commit
0dddd6ade2
597
check_zfs.py
Normal file → Executable file
597
check_zfs.py
Normal file → Executable file
|
@ -5,8 +5,8 @@
|
||||||
########################################################################
|
########################################################################
|
||||||
##
|
##
|
||||||
## Written by Zachary LaCelle
|
## Written by Zachary LaCelle
|
||||||
## Written by Boris Tassou
|
## Migration to Python3 by Boris Tassou
|
||||||
## Copyright 2020
|
## Copyright 2016
|
||||||
## Licensed under GPL (see below)
|
## Licensed under GPL (see below)
|
||||||
##
|
##
|
||||||
## Nagios script to monitor ZFS pools/filesystems
|
## Nagios script to monitor ZFS pools/filesystems
|
||||||
|
@ -45,433 +45,434 @@ import sys
|
||||||
# Commands to run
|
# Commands to run
|
||||||
# CHANGE THESE IF YOU NEED TO
|
# CHANGE THESE IF YOU NEED TO
|
||||||
##
|
##
|
||||||
zpoolCommand = '/sbin/zpool'
|
ZPOOLCOMMANDE = '/sbin/zpool'
|
||||||
zfsCommand = '/sbin/zfs'
|
ZFSCOMMANDE = '/sbin/zfs'
|
||||||
|
|
||||||
##
|
##
|
||||||
# Variables to print at the end
|
# Variables to print at the end
|
||||||
##
|
##
|
||||||
nagiosStatus = ('OK', 'WARNING', 'CRITICAL', 'UNKNOWN')
|
NAGIOSSTATUS = ('OK', 'WARNING', 'CRITICAL', 'UNKNOWN')
|
||||||
stateNum = 0
|
STATENUM = 0
|
||||||
msg = ''
|
MSG = ''
|
||||||
perfdata = ''
|
PERFDATA = ''
|
||||||
|
|
||||||
##
|
##
|
||||||
# Filled from command line arguments
|
# Filled from command line arguments
|
||||||
##
|
##
|
||||||
checkCapacity = False
|
CHECKCAPACITY = False
|
||||||
capWarnThreshold = 50
|
CAPWARNTHRESHOLD = 50
|
||||||
capCritThreshold = 80
|
CAPCRITTHRESHOLD = 80
|
||||||
checkFragmentation = False
|
CHECKFRAGMENTATION = False
|
||||||
fragWarnThreshold = 50
|
FRAGWARNTHRESHOLD = 50
|
||||||
fragCritThreshold = 80
|
FRAGCRITTHRESHOLD = 80
|
||||||
|
|
||||||
logging.basicConfig(stream=sys.stdout, format='%(message)s', level=logging.WARN)
|
logging.basicConfig(stream=sys.stdout, format='%(message)s', level=logging.WARN)
|
||||||
|
|
||||||
|
|
||||||
def CheckArgBounds(valueArr, minVal, maxVal):
|
def checkargbounds(valuearr, minval, maxval):
|
||||||
"""Check value bounds."""
|
"""Check value bounds."""
|
||||||
for value in valueArr:
|
for value in valuearr:
|
||||||
if value < minVal:
|
if value < minval:
|
||||||
return False
|
return False
|
||||||
elif value > maxVal:
|
elif value > maxval:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def ConvertToGB(valueStr):
|
def converttogb(valuestr):
|
||||||
"""Convert to GB."""
|
"""Convert to GB."""
|
||||||
value = valueStr[:-1]
|
value = valuestr[:-1]
|
||||||
value = value.replace(',', '.')
|
value = value.replace(',', '.')
|
||||||
if valueStr.endswith('G'):
|
if valuestr.endswith('G'):
|
||||||
return float(value)
|
return float(value)
|
||||||
elif valueStr.endswith('T'):
|
elif valuestr.endswith('T'):
|
||||||
gigs = float(value)*1024
|
gigs = float(value)*1024
|
||||||
return float(gigs)
|
return float(gigs)
|
||||||
elif valueStr.endswith('M'):
|
elif valuestr.endswith('M'):
|
||||||
gigs = float(value) / 1024.0
|
gigs = float(value) / 1024.0
|
||||||
return float(gigs)
|
return float(gigs)
|
||||||
elif valueStr.endswith('K'):
|
elif valuestr.endswith('K'):
|
||||||
gigs = float(value) / (1024.0 * 1024.0)
|
gigs = float(value) / (1024.0 * 1024.0)
|
||||||
return float(gigs)
|
return float(gigs)
|
||||||
|
|
||||||
|
|
||||||
def RaiseStateNum(stateNumIn, stateNum):
|
def raisestatenum(statenumin, statenum):
|
||||||
"""Raise state num."""
|
"""Raise state num."""
|
||||||
if stateNumIn > stateNum:
|
if statenumin > statenum:
|
||||||
return stateNumIn
|
return statenumin
|
||||||
return stateNum
|
return statenum
|
||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
##
|
##
|
||||||
# Parse command line args
|
# Parse command line args
|
||||||
##
|
##
|
||||||
parser = argparse.ArgumentParser(
|
PARSER = argparse.ArgumentParser(
|
||||||
prog='check_zfs',
|
prog='check_zfs',
|
||||||
description='Check the ZFS pool specified by an argument.',
|
description='Check the ZFS pool specified by an argument.',
|
||||||
epilog='Note that monitor flags (e.g. capacity) require 2 arguments:\
|
epilog='Note that monitor flags (e.g. capacity) require 2 arguments:\
|
||||||
warning threshold, and critical threshold')
|
warning threshold, and critical threshold')
|
||||||
parser.add_argument('--capacity', help="monitor utilization of zpool (%%, int [0-100])",
|
PARSER.add_argument('--capacity', help="monitor utilization of zpool (%%, int [0-100])",
|
||||||
type=int, nargs=2)
|
type=int, nargs=2)
|
||||||
parser.add_argument('--fragmentation', help="monitor fragmentation of zpool (%%, int [0-100])",
|
PARSER.add_argument('--fragmentation', help="monitor fragmentation of zpool (%%, int [0-100])",
|
||||||
type=int, nargs=2)
|
type=int, nargs=2)
|
||||||
parser.add_argument('pool', help="name of the zpool to check", type=str)
|
PARSER.add_argument('pool', help="name of the zpool to check", type=str)
|
||||||
|
|
||||||
args = parser.parse_args()
|
ARGS = PARSER.parse_args()
|
||||||
|
|
||||||
retVal = True
|
RETVAL = True
|
||||||
if args.capacity is not None:
|
if ARGS.capacity is not None:
|
||||||
checkCapacity = True
|
CHECKCAPACITY = True
|
||||||
capWarnThreshold = args.capacity[0]
|
CAPWARNTHRESHOLD = ARGS.capacity[0]
|
||||||
capCritThreshold = args.capacity[1]
|
CAPCRITTHRESHOLD = ARGS.capacity[1]
|
||||||
capArr = ['i', [capWarnThreshold, capCritThreshold]]
|
CAPARR = ['i', [CAPWARNTHRESHOLD, CAPCRITTHRESHOLD]]
|
||||||
retVal = CheckArgBounds(capArr, 0, 100)
|
RETVAL = checkargbounds(CAPARR, 0, 100)
|
||||||
if retVal is False:
|
if RETVAL is False:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Capacity thresholds must be between 0 and 100 (as a percent).",
|
logging.warning("%s : Capacity thresholds must be between 0 and 100 (as a percent).",
|
||||||
nagiosStatus[stateNum])
|
NAGIOSSTATUS[STATENUM])
|
||||||
parser.print_help()
|
PARSER.print_help()
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
retVal = True
|
RETVAL = True
|
||||||
if args.fragmentation is not None:
|
if ARGS.fragmentation is not None:
|
||||||
checkFragmentation = True
|
CHECKFRAGMENTATION = True
|
||||||
fragWarnThreshold = args.fragmentation[0]
|
FRAGWARNTHRESHOLD = ARGS.fragmentation[0]
|
||||||
fragCritThreshold = args.fragmentation[1]
|
FRAGCRITTHRESHOLD = ARGS.fragmentation[1]
|
||||||
fragArr = ['i', [fragWarnThreshold, fragCritThreshold]]
|
FRAGARR = ['i', [FRAGWARNTHRESHOLD, FRAGCRITTHRESHOLD]]
|
||||||
retVal = CheckArgBounds(fragArr, 0, 100)
|
RETVAL = checkargbounds(FRAGARR, 0, 100)
|
||||||
if retVal is False:
|
if RETVAL is False:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Fragmentation thresholds must be between 0 and 100 (as a percent).",
|
logging.warning("%s : Fragmentation thresholds must be between 0 and 100 (as a percent).",
|
||||||
nagiosStatus[stateNum])
|
NAGIOSSTATUS[STATENUM])
|
||||||
parser.print_help()
|
PARSER.print_help()
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
##
|
##
|
||||||
# Get generic info about the ZFS environment
|
# Get generic info about the ZFS environment
|
||||||
zfsEntries = []
|
ZFSENTRIES = []
|
||||||
fullCommand = ['/usr/bin/sudo', '-n', zfsCommand, 'list']
|
FULLCOMMAND = ['/usr/bin/sudo', '-n', ZFSCOMMANDE, 'list']
|
||||||
try:
|
try:
|
||||||
childProcess = subprocess.Popen(fullCommand, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
CHILDPROCESS = subprocess.Popen(FULLCOMMAND, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE)
|
||||||
except OSError:
|
except OSError:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to your\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to your\
|
||||||
visudo: nagios ALL=NOPASSWD: /sbin/zfs", nagiosStatus[stateNum])
|
visudo: nagios ALL=NOPASSWD: /sbin/zfs", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
zfsString = childProcess.communicate()[0]
|
ZFSSTRING = CHILDPROCESS.communicate()[0]
|
||||||
zfsRetval = childProcess.returncode
|
ZFSRETVAL = CHILDPROCESS.returncode
|
||||||
|
|
||||||
if zfsRetval is 1:
|
if ZFSRETVAL is 1:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zfs", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zfs", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
zfsLines = zfsString.splitlines()
|
ZFSLINES = ZFSSTRING.splitlines()
|
||||||
for idx, line in enumerate(zfsLines):
|
for IDX, LINE in enumerate(ZFSLINES):
|
||||||
if idx != 0:
|
if IDX != 0:
|
||||||
zfsEntry = line.split()
|
ZFSENTRY = LINE.split()
|
||||||
zfsEntries.append(zfsEntry)
|
ZFSENTRIES.append(ZFSENTRY)
|
||||||
|
|
||||||
# Make sure the pool we specified is valid
|
# Make sure the pool we specified is valid
|
||||||
validPool = False
|
VALIDPOOL = False
|
||||||
for entry in zfsEntries:
|
for ENTRY in ZFSENTRIES:
|
||||||
if entry[0].decode() == args.pool:
|
if ENTRY[0].decode() == ARGS.pool:
|
||||||
validPool = True
|
VALIDPOOL = True
|
||||||
if not validPool:
|
if not VALIDPOOL:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Pool %s is invalid. Please select a valid pool.",
|
logging.warning("%s : Pool %s is invalid. Please select a valid pool.",
|
||||||
nagiosStatus[stateNum], args.pool)
|
NAGIOSSTATUS[STATENUM], ARGS.pool)
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
##
|
##
|
||||||
# Get info on zpool
|
# Get info on zpool
|
||||||
|
|
||||||
fullCommand = ['/usr/bin/sudo', '-n', zpoolCommand, 'list', args.pool]
|
FULLCOMMAND = ['/usr/bin/sudo', '-n', ZPOOLCOMMANDE, 'list', ARGS.pool]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
childProcess = subprocess.Popen(fullCommand, stdin=subprocess.PIPE,
|
CHILDPROCESS = subprocess.Popen(FULLCOMMAND, stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
except OSError:
|
except OSError:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
zpoolString = childProcess.communicate()[0]
|
ZPOOLSTRING = CHILDPROCESS.communicate()[0]
|
||||||
zpoolRetval = childProcess.returncode
|
ZPOOLRETVAL = CHILDPROCESS.returncode
|
||||||
|
|
||||||
if zpoolRetval is 1:
|
if ZPOOLRETVAL is 1:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
zpoolLines = zpoolString.splitlines()
|
ZPOOLLINES = ZPOOLSTRING.splitlines()
|
||||||
zpoolMeta = zpoolLines[0].decode().split()
|
ZPOOLMETA = ZPOOLLINES[0].decode().split()
|
||||||
zpoolMetaStr = ','.join(zpoolMeta)
|
ZPOOLMETASTR = ','.join(ZPOOLMETA)
|
||||||
zpoolEntry = zpoolLines[1].decode().split()
|
ZPOOLENTRY = ZPOOLLINES[1].decode().split()
|
||||||
zpoolEntryStr = ','.join(zpoolEntry)
|
ZPOOLENTRYSTR = ','.join(ZPOOLENTRY)
|
||||||
|
|
||||||
name = ''
|
NAME = ''
|
||||||
size = ''
|
SIZE = ''
|
||||||
alloc = ''
|
ALLOC = ''
|
||||||
free = ''
|
FREE = ''
|
||||||
expandsz = ''
|
EXPANDSZ = ''
|
||||||
frag = ''
|
FRAG = ''
|
||||||
cap = ''
|
CAP = ''
|
||||||
dedup = ''
|
DEDUP = ''
|
||||||
health = ''
|
HEALTH = ''
|
||||||
altroot = ''
|
ALTROOT = ''
|
||||||
|
|
||||||
for idx, fieldName in enumerate(zpoolMeta):
|
for IDX, FIELDNAME in enumerate(ZPOOLMETA):
|
||||||
if fieldName == 'NAME':
|
if FIELDNAME == 'NAME':
|
||||||
name = zpoolEntry[idx]
|
NAME = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'SIZE':
|
elif FIELDNAME == 'SIZE':
|
||||||
size = zpoolEntry[idx]
|
SIZE = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'ALLOC':
|
elif FIELDNAME == 'ALLOC':
|
||||||
alloc = zpoolEntry[idx]
|
ALLOC = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'FREE':
|
elif FIELDNAME == 'FREE':
|
||||||
free = zpoolEntry[idx]
|
FREE = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'EXPANDSZ':
|
elif FIELDNAME == 'EXPANDSZ':
|
||||||
expandsz = zpoolEntry[idx]
|
EXPANDSZ = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'FRAG':
|
elif FIELDNAME == 'FRAG':
|
||||||
frag = zpoolEntry[idx]
|
FRAG = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'CAP':
|
elif FIELDNAME == 'CAP':
|
||||||
cap = zpoolEntry[idx]
|
CAP = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'DEDUP':
|
elif FIELDNAME == 'DEDUP':
|
||||||
dedup = zpoolEntry[idx]
|
DEDUP = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'HEALTH':
|
elif FIELDNAME == 'HEALTH':
|
||||||
health = zpoolEntry[idx]
|
HEALTH = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'ALTROOT':
|
elif FIELDNAME == 'ALTROOT':
|
||||||
altroot = zpoolEntry[idx]
|
ALTROOT = ZPOOLENTRY[IDX]
|
||||||
|
|
||||||
if name == '':
|
if NAME == '':
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Missing required field in zpool output: NAME", nagiosStatus[stateNum])
|
logging.warning("%s : Missing required field in zpool output: NAME", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
if health == '':
|
if HEALTH == '':
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Missing required field in zpool output: HEALTH", nagiosStatus[stateNum])
|
logging.warning("%s : Missing required field in zpool output: HEALTH", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
if checkCapacity and cap == '':
|
if CHECKCAPACITY and CAP == '':
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s Cannot monitor capacity without zpool output: CAP.\
|
logging.warning("%s Cannot monitor capacity without zpool output: CAP.\
|
||||||
Outputs are %s", nagiosStatus[stateNum], zpoolMetaStr)
|
Outputs are %s", NAGIOSSTATUS[STATENUM], ZPOOLMETASTR)
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
if checkFragmentation and frag == '':
|
if CHECKFRAGMENTATION and FRAG == '':
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Cannot monitor fragmentation without zpool output: FRAG.\
|
logging.warning("%s : Cannot monitor fragmentation without zpool output: FRAG.\
|
||||||
Outputs are %s", nagiosStatus[stateNum], zpoolMetaStr)
|
Outputs are %s", NAGIOSSTATUS[STATENUM], ZPOOLMETASTR)
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
# Get compressratio on zpool
|
# Get compressratio on zpool
|
||||||
|
|
||||||
checkForCompression = ['/usr/bin/sudo', '-n', zfsCommand, 'get', 'compression', args.pool]
|
CHECKFORCOMPRESSION = ['/usr/bin/sudo', '-n', ZFSCOMMANDE, 'get', 'compression', ARGS.pool]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
childProcess = subprocess.Popen(checkForCompression, stdin=subprocess.PIPE,
|
CHILDPROCESS = subprocess.Popen(CHECKFORCOMPRESSION, stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
except OSError:
|
except OSError:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
zpoolString = childProcess.communicate()[0]
|
ZPOOLSTRING = CHILDPROCESS.communicate()[0]
|
||||||
zpoolRetval = childProcess.returncode
|
ZPOOLRETVAL = CHILDPROCESS.returncode
|
||||||
|
|
||||||
if zpoolRetval is 1:
|
if ZPOOLRETVAL is 1:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
zpoolLines = zpoolString.splitlines()
|
ZPOOLLINES = ZPOOLSTRING.splitlines()
|
||||||
zpoolMeta = zpoolLines[0].decode().split()
|
ZPOOLMETA = ZPOOLLINES[0].decode().split()
|
||||||
zpoolMetaStr = ','.join(zpoolMeta)
|
ZPOOLMETASTR = ','.join(ZPOOLMETA)
|
||||||
zpoolEntry = zpoolLines[1].decode().split()
|
ZPOOLENTRY = ZPOOLLINES[1].decode().split()
|
||||||
zpoolEntryStr = ','.join(zpoolEntry)
|
ZPOOLENTRYSTR = ','.join(ZPOOLENTRY)
|
||||||
|
|
||||||
compressName = ''
|
COMPRESSNAME = ''
|
||||||
compressValue = ''
|
COMPRESSVALUE = ''
|
||||||
|
|
||||||
compressRatioName = ''
|
COMPRESSRATIONAME = ''
|
||||||
compressRatioValue = ''
|
COMPRESSRATIOVALUE = ''
|
||||||
|
|
||||||
for idx, fieldName in enumerate(zpoolMeta):
|
for IDX, FIELDNAME in enumerate(ZPOOLMETA):
|
||||||
if fieldName == 'NAME':
|
if FIELDNAME == 'NAME':
|
||||||
compressName = zpoolEntry[idx]
|
COMPRESSNAME = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'VALUE':
|
elif FIELDNAME == 'VALUE':
|
||||||
compressValue = zpoolEntry[idx]
|
COMPRESSVALUE = ZPOOLENTRY[IDX]
|
||||||
|
|
||||||
if compressName == '':
|
if COMPRESSNAME == '':
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : Missing required field in zpool output: NAME", nagiosStatus[stateNum])
|
logging.warning("%s : Missing required field in zpool output: NAME", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
if compressValue == 'on':
|
if COMPRESSVALUE == 'on':
|
||||||
getCompressRatioCommand = ['/usr/bin/sudo', '-n', zfsCommand, 'get', 'compressratio', args.pool]
|
GETCOMPRESSRATIOCOMMAND = ['/usr/bin/sudo', '-n', ZFSCOMMANDE, 'get',
|
||||||
|
'compressratio', ARGS.pool]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
childProcess = subprocess.Popen(getCompressRatioCommand, stdin=subprocess.PIPE,
|
CHILDPROCESS = subprocess.Popen(GETCOMPRESSRATIOCOMMAND, stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
except OSError:
|
except OSError:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
zpoolString = childProcess.communicate()[0]
|
ZPOOLSTRING = CHILDPROCESS.communicate()[0]
|
||||||
zpoolRetval = childProcess.returncode
|
ZPOOLRETVAL = CHILDPROCESS.returncode
|
||||||
|
|
||||||
if zpoolRetval is 1:
|
if ZPOOLRETVAL is 1:
|
||||||
stateNum = RaiseStateNum(3, stateNum)
|
STATENUM = raisestatenum(3, STATENUM)
|
||||||
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
logging.warning("%s : process must be run as root. Possible solution: add the following to\
|
||||||
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", nagiosStatus[stateNum])
|
your visudo: nagios ALL=NOPASSWD: /sbin/zpool", NAGIOSSTATUS[STATENUM])
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
||||||
zpoolLines = zpoolString.splitlines()
|
ZPOOLLINES = ZPOOLSTRING.splitlines()
|
||||||
zpoolMeta = zpoolLines[0].decode().split()
|
ZPOOLMETA = ZPOOLLINES[0].decode().split()
|
||||||
zpoolMetaStr = ','.join(zpoolMeta)
|
ZPOOLMETASTR = ','.join(ZPOOLMETA)
|
||||||
zpoolEntry = zpoolLines[1].decode().split()
|
ZPOOLENTRY = ZPOOLLINES[1].decode().split()
|
||||||
zpoolEntryStr = ','.join(zpoolEntry)
|
ZPOOLENTRYSTR = ','.join(ZPOOLENTRY)
|
||||||
|
|
||||||
for idx, fieldName in enumerate(zpoolMeta):
|
for IDX, fieldName in enumerate(ZPOOLMETA):
|
||||||
if fieldName == 'NAME':
|
if FIELDNAME == 'NAME':
|
||||||
compressRatioName = zpoolEntry[idx]
|
COMPRESSRATIONAME = ZPOOLENTRY[IDX]
|
||||||
elif fieldName == 'VALUE':
|
elif FIELDNAME == 'VALUE':
|
||||||
compressRatioValue = zpoolEntry[idx]
|
COMPRESSRATIOVALUE = ZPOOLENTRY[IDX]
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
##
|
##
|
||||||
# OK, finally in the actual status checking of the zpool
|
# OK, finally in the actual status checking of the zpool
|
||||||
|
|
||||||
# Let's build up our perfdata, regardless of what we're checking
|
# Let's build up our perfdata, regardless of what we're checking
|
||||||
fragPercent = ''
|
FRAGPERCENT = ''
|
||||||
if frag != '':
|
if FRAG != '':
|
||||||
fragPercent = frag.replace("%", "")
|
FRAGPERCENT = FRAG.replace("%", "")
|
||||||
fragPerfStr = "frag="+str(fragPercent)+"%;"
|
FRAGPERFSTR = "frag="+str(FRAGPERCENT)+"%;"
|
||||||
if checkFragmentation:
|
if CHECKFRAGMENTATION:
|
||||||
fragPerfStr = fragPerfStr+str(fragWarnThreshold)+";"+str(fragCritThreshold)+";"
|
FRAGPERFSTR = FRAGPERFSTR + str(FRAGWARNTHRESHOLD) + ";" + str(FRAGCRITTHRESHOLD) + ";"
|
||||||
else:
|
else:
|
||||||
fragPerfStr += (";;")
|
FRAGPERFSTR += (";;")
|
||||||
perfdata += (fragPerfStr)
|
PERFDATA += (FRAGPERFSTR)
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
capPercent = ''
|
CAPPERCENT = ''
|
||||||
if cap != '':
|
if CAP != '':
|
||||||
capPercent = cap.replace("%", "")
|
CAPPERCENT = CAP.replace("%", "")
|
||||||
capPerfStr = "cap="+str(capPercent)+"%;"
|
CAPPERFSTR = "cap=" + str(CAPPERCENT) + "%;"
|
||||||
if checkCapacity:
|
if CHECKCAPACITY:
|
||||||
capPerfStr = capPerfStr+str(capWarnThreshold)+";"+str(capCritThreshold)+";"
|
CAPPERFSTR = CAPPERFSTR + str(CAPWARNTHRESHOLD) + ";" + str(CAPCRITTHRESHOLD) + ";"
|
||||||
else:
|
else:
|
||||||
capPerfStr += (";;")
|
CAPPERFSTR += (";;")
|
||||||
perfdata += (capPerfStr)
|
PERFDATA += (CAPPERFSTR)
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
# Perfdata for dedup & compression factor
|
# Perfdata for dedup & compression factor
|
||||||
if dedup != '':
|
if DEDUP != '':
|
||||||
dedup_no_x = dedup.rstrip('x')
|
DEDUP_NO_X = DEDUP.rstrip('x')
|
||||||
perfdata += "dedup="+str(dedup_no_x)
|
PERFDATA += "DEDUP=" + str(DEDUP_NO_X)
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
if compressRatioValue != '':
|
if COMPRESSRATIOVALUE != '':
|
||||||
compressRatioNoX = compressRatioValue.rstrip('x')
|
COMPRESSRATIONOX = COMPRESSRATIOVALUE.rstrip('x')
|
||||||
perfdata += "compress_ratio="+str(compressRatioNoX)
|
PERFDATA += "compress_ratio=" + str(COMPRESSRATIONOX)
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
# Sizes can be in K, M, G, or T (maybe P, but I'm not doing this yet)
|
# Sizes can be in K, M, G, or T (maybe P, but I'm not doing this yet)
|
||||||
if size != '':
|
if SIZE != '':
|
||||||
sizeGB = ConvertToGB(size)
|
SIZEGB = converttogb(SIZE)
|
||||||
perfdata += "size="+str(sizeGB)+"GB;;;"
|
PERFDATA += "size=" + str(SIZEGB) + "GB;;;"
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
if alloc != '':
|
if ALLOC != '':
|
||||||
allocGB = ConvertToGB(alloc)
|
ALLOCGB = converttogb(ALLOC)
|
||||||
perfdata += "alloc="+str(allocGB)+"GB;;;"
|
PERFDATA += "alloc=" + str(ALLOCGB) + "GB;;;"
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
if free != '':
|
if FREE != '':
|
||||||
freeGB = ConvertToGB(free)
|
FREEGB = converttogb(FREE)
|
||||||
perfdata += "free="+str(freeGB)+"GB;;;"
|
PERFDATA += "free=" + str(FREEGB) + "GB;;;"
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
##
|
##
|
||||||
# Do mandatory checks
|
# Do mandatory checks
|
||||||
healthNum = -1
|
HEALTHNUM = -1
|
||||||
if health == 'ONLINE':
|
if HEALTH == 'ONLINE':
|
||||||
healthNum = 0
|
HEALTHNUM = 0
|
||||||
elif health == 'OFFLINE':
|
elif HEALTH == 'OFFLINE':
|
||||||
stateNum = RaiseStateNum(1, stateNum)
|
STATENUM = raisestatenum(1, STATENUM)
|
||||||
healthNum = 1
|
HEALTHNUM = 1
|
||||||
elif health == 'REMOVED':
|
elif HEALTH == 'REMOVED':
|
||||||
stateNum = RaiseStateNum(1, stateNum)
|
STATENUM = raisestatenum(1, STATENUM)
|
||||||
healthNum = 2
|
HEALTHNUM = 2
|
||||||
elif health == 'UNAVAIL':
|
elif HEALTH == 'UNAVAIL':
|
||||||
stateNum = RaiseStateNum(1, stateNum)
|
STATENUM = raisestatenum(1, STATENUM)
|
||||||
healthNum = 3
|
HEALTHNUM = 3
|
||||||
elif health == 'DEGRADED':
|
elif HEALTH == 'DEGRADED':
|
||||||
stateNum = RaiseStateNum(2, stateNum)
|
STATENUM = raisestatenum(2, STATENUM)
|
||||||
healthNum = 4
|
HEALTHNUM = 4
|
||||||
elif health == 'FAULTED':
|
elif HEALTH == 'FAULTED':
|
||||||
stateNum = RaiseStateNum(2, stateNum)
|
STATENUM = raisestatenum(2, STATENUM)
|
||||||
healthNum = 5
|
HEALTHNUM = 5
|
||||||
perfdata += "health="+str(healthNum)+";1;3;"
|
PERFDATA += "health=" + str(HEALTHNUM) + ";1;3;"
|
||||||
perfdata += " "
|
PERFDATA += " "
|
||||||
|
|
||||||
##
|
##
|
||||||
# Initial part of msg
|
# Initial part of msg
|
||||||
msg = "POOL: " + str(name)
|
MSG = "POOL: " + str(NAME)
|
||||||
healthMsgFilled = False
|
HEALTHMSGFILLED = False
|
||||||
if healthNum > 0:
|
if HEALTHNUM > 0:
|
||||||
msg += ", STATUS: "+str(health)
|
MSG += ", STATUS: " + str(HEALTH)
|
||||||
healthMsgFilled = True
|
HEALTHMSGFILLED = True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Do optional checks
|
# Do optional checks
|
||||||
fragMsgFilled = False
|
FRAGMSGFILLED = False
|
||||||
capMsgFilled = False
|
CAPMSGFILLED = False
|
||||||
if checkFragmentation and fragPercent != '':
|
if CHECKFRAGMENTATION and FRAGPERFSTR != '':
|
||||||
if fragPercent.isdigit() is True:
|
if FRAGPERFSTR.isdigit() is True:
|
||||||
if int(fragPercent) > int(fragCritThreshold):
|
if int(FRAGPERFSTR) > int(FRAGCRITTHRESHOLD):
|
||||||
fragMsgFilled = True
|
FRAGMSGFILLED = True
|
||||||
stateNum = RaiseStateNum(2, stateNum)
|
STATENUM = raisestatenum(2, STATENUM)
|
||||||
msg += ", FRAG CRIT: " + str(frag)
|
MSG += ", FRAG CRIT: " + str(FRAG)
|
||||||
elif int(fragPercent) > int(fragWarnThreshold):
|
elif int(FRAGPERFSTR) > int(FRAGWARNTHRESHOLD):
|
||||||
fragMsgFilled = True
|
FRAGMSGFILLED = True
|
||||||
stateNum = RaiseStateNum(1, stateNum)
|
STATENUM = raisestatenum(1, STATENUM)
|
||||||
msg += ", FRAG WARN: " + str(frag)
|
MSG += ", FRAG WARN: " + str(FRAG)
|
||||||
if checkCapacity and capPercent != '':
|
if CHECKCAPACITY and CAPPERCENT != '':
|
||||||
if int(capPercent) > int(capCritThreshold):
|
if int(CAPPERCENT) > int(CAPCRITTHRESHOLD):
|
||||||
capMsgFilled = True
|
CAPMSGFILLED = True
|
||||||
stateNum = RaiseStateNum(2, stateNum)
|
STATENUM = raisestatenum(2, STATENUM)
|
||||||
msg += ", CAP CRIT: " + str(cap)
|
MSG += ", CAP CRIT: " + str(CAP)
|
||||||
elif int(capPercent) > int(capWarnThreshold):
|
elif int(CAPPERCENT) > int(CAPWARNTHRESHOLD):
|
||||||
capMsgFilled = True
|
CAPMSGFILLED = True
|
||||||
stateNum = RaiseStateNum(1, stateNum)
|
STATENUM = raisestatenum(1, STATENUM)
|
||||||
msg += ", CAP WARN: "+str(cap)
|
MSG += ", CAP WARN: " + str(CAP)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Build up rest of message
|
# Build up rest of message
|
||||||
if not healthMsgFilled:
|
if not HEALTHMSGFILLED:
|
||||||
msg += ", STATUS: " + str(health)
|
MSG += ", STATUS: " + str(HEALTH)
|
||||||
if size != '':
|
if SIZE != '':
|
||||||
msg += ", SIZE: " + str(size)
|
MSG += ", SIZE: " + str(SIZE)
|
||||||
if alloc != '':
|
if ALLOC != '':
|
||||||
msg += ", ALLOC: " + str(alloc)
|
MSG += ", ALLOC: " + str(ALLOC)
|
||||||
if free != '':
|
if FREE != '':
|
||||||
msg += ", FREE: " + str(free)
|
MSG += ", FREE: " + str(FREE)
|
||||||
if dedup != '':
|
if DEDUP != '':
|
||||||
msg += ", DEDUP: " + str(dedup)
|
MSG += ", DEDUP: " + str(DEDUP)
|
||||||
if compressRatioValue != '':
|
if COMPRESSRATIOVALUE != '':
|
||||||
msg += ", COMPRESS: " + str(compressRatioValue)
|
MSG += ", COMPRESS: " + str(COMPRESSRATIOVALUE)
|
||||||
if frag != '' and not fragMsgFilled:
|
if FRAG != '' and not FRAGMSGFILLED:
|
||||||
msg += ", FRAG: " + str(frag)
|
MSG += ", FRAG: " + str(FRAG)
|
||||||
if cap != '' and not capMsgFilled:
|
if CAP != '' and not CAPMSGFILLED:
|
||||||
msg += ", CAP: " + str(cap)
|
MSG += ", CAP: " + str(CAP)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Print our output and return
|
# Print our output and return
|
||||||
logging.warning("%s: %s | %s", nagiosStatus[stateNum], msg, perfdata)
|
logging.warning("%s: %s | %s", NAGIOSSTATUS[STATENUM], MSG, PERFDATA)
|
||||||
exit(stateNum)
|
sys.exit(STATENUM)
|
||||||
|
|
Loading…
Reference in a new issue