From 0b6423f9c99d9edf8c96fefd0f6c453859395aa1 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 30 Sep 2013 00:03:24 +0200 Subject: Import Nagios Plugins site Import the Nagios Plugins web site, Cronjobs, infrastructure scripts, and configuration files. --- .../427640-nagios-plugins-openvz-beans.diff | 1771 ++++++++++++++++++++ 1 file changed, 1771 insertions(+) create mode 100644 web/attachments/427640-nagios-plugins-openvz-beans.diff (limited to 'web/attachments/427640-nagios-plugins-openvz-beans.diff') diff --git a/web/attachments/427640-nagios-plugins-openvz-beans.diff b/web/attachments/427640-nagios-plugins-openvz-beans.diff new file mode 100644 index 0000000..47a8f40 --- /dev/null +++ b/web/attachments/427640-nagios-plugins-openvz-beans.diff @@ -0,0 +1,1771 @@ +diff -urN nothing/check_openvz_beans.py nagios-plugins-openvz-beans/check_openvz_beans.py +--- nothing/check_openvz_beans.py 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/check_openvz_beans.py 2011-11-01 19:04:11.133266362 +0100 +@@ -0,0 +1,589 @@ ++#!/usr/bin/python ++# ++# Nagios check for OpenVZ bean counters ++# ++# usage: ++# check_openvz_beans.py [options] ++# ++# see "check_openvz_beans.py -h" for detailed options ++# ++# Licensed under GPLv2 (or later) ++# ++# Copyright (C) 2011 NOKIA ++# Written by Andreas Kotes ++# ++# Reviewed-by: Pascal Hahn ++# Signed-Off-by: Pascal Hahn ++# Signed-Off-by: Jessvin Thomas ++# ++ ++import os ++import re ++import errno ++import sys ++import socket ++ ++# using 'optparse' for Python 2.4 compatibility ++import optparse ++# using subprocess for clean sudo handling ++import subprocess ++ ++__author__ = ('Andreas Kotes ') ++ ++OPENVZ_CONFPATH = '/etc/vz/conf' ++OPENVZ_UBCSTORE = '/tmp/vzubc.store' ++ ++class Error(Exception): ++ """Module level error.""" ++ pass ++ ++ ++class NoBeanCountersFoundError(Error): ++ "No BeanCounters could be found in output.""" ++ pass ++ ++ ++class BeanCounter(object): ++ """Object storing OpenVZ beancounter information""" ++ FIND_BEAN_COUNTER_RE = r'''(?xms) # verbose, multiline, special ++ ^ # begin entry ++ \s*(?P\S+) # resource name ++ \s*(?P\d+) # held count ++ \s*(?P\d+) # maximum held ++ \s*(?P\d+) # barrier ++ \s*(?P\d+) # limit ++ \s*(?P\d+) # failure counter ++ ''' ++ def __init__(self, uid, resource_txt, use_absolute_failcnt=False, storepath=OPENVZ_UBCSTORE): ++ """Create object storing OpenVZ beancounter information ++ ++ Args ++ uid: int - OpenVZ context identifier ++ resource_txt: str - OpenVZ resource ++ use_absolute_failcnt: ++ bool - Whether to use delta failcnts or not ++ storepath: str - Path to OpenVZ's vzubc's data storage ++ """ ++ self.uid = uid ++ ++ # extract data from text line ++ resourcedata = re.match(BeanCounter.FIND_BEAN_COUNTER_RE, resource_txt).groupdict() ++ self.resource = resourcedata['resource'] ++ self.held = int(resourcedata['held']) ++ self.maxheld = int(resourcedata['maxheld']) ++ self.barrier = int(resourcedata['barrier']) ++ self.limit = int(resourcedata['limit']) ++ self.failcnt = int(resourcedata['failcnt']) ++ ++ if not use_absolute_failcnt: ++ prev_failcnt = self.read_vzubc_failcnt(storepath) ++ # don't update from stale / lower value ++ if (prev_failcnt <= self.failcnt): ++ self.failcnt -= prev_failcnt ++ ++ def read_vzubc_failcnt(self, storepath=OPENVZ_UBCSTORE): ++ """Read data stored by vzubc -r. ++ ++ Args ++ uid: int - OpenVZ context identifier ++ storepath: str - Path to OpenVZ's vzubc's data storage ++ ++ Returns: ++ int - stored value or 0 ++ """ ++ filename = os.path.join(storepath, "ubc.%d.%s.failcnt" % (self.uid, self.resource)) ++ if os.path.exists(filename): ++ return int(open(filename, "r").read()) ++ else: ++ return 0 ++ ++ def __repr__(self): ++ return ('' % ++ (self.uid, self.resource, self.held, self.maxheld, self.barrier, self.limit, self.failcnt)) ++ ++ def __eq__(self, other): ++ if (self.uid == other.uid and ++ self.resource == other.resource and ++ self.held == other.held and ++ self.maxheld == other.maxheld and ++ self.barrier == other.barrier and ++ self.limit == other.limit and ++ self.failcnt == other.failcnt): ++ return True ++ else: ++ return False ++ ++ ++class BeanCounterParser(object): ++ """Parse bean counter information.""" ++ FIND_BEAN_COUNTER_GROUP_RE = r'''(?xms) # verbose, multline, special ++ ^ # begin entry ++ \s*(?P\d+): # group / context number ++ (?P[^:]*)$ # everything up to next group/EOF ++ ''' ++ ++ def parse_beancounters(self, beancounters_data, use_absolute_failcnt=False, storepath=OPENVZ_UBCSTORE): ++ """Populate BeanCounter objects with data. ++ ++ Args: ++ beancounters_data: str - containing the unparsed ++ use_absolute_failcnt: ++ bool - Whether to use delta failcnts or not ++ storepath: str - Path to OpenVZ's vzubc's data storage ++ ++ Raises: ++ NoBeanCountersFoundError - in case no counters where found ++ """ ++ # find all beans blocks ++ result = re.findall(BeanCounterParser.FIND_BEAN_COUNTER_GROUP_RE, beancounters_data) ++ if not result: ++ raise NoBeanCountersFoundError ++ self.beancounters = [] ++ for uid, resource_txt in result: ++ for line in resource_txt.split("\n"): ++ if line: ++ self.beancounters.append(BeanCounter(int(uid), line, use_absolute_failcnt, storepath)) ++ return self.beancounters ++ ++ def __init__(self, beancounters_data, use_absolute_failcnt=False, storepath=OPENVZ_UBCSTORE): ++ """Create a new BeanCounter object ++ ++ Args: ++ beancounters_data: str - containing the unparsed ++ contents of /proc/user_beancounters ++ use_absolute_failcnt: ++ bool - Whether to use delta failcnts or not ++ storepath: str - Path to OpenVZ's vzubc's data storage ++ """ ++ self.parse_beancounters(beancounters_data, use_absolute_failcnt, storepath) ++ ++ def get_beancounters(self): ++ return self.beancounters ++ ++ ++class BeanCounterThreshold(object): ++ """Holds threshold values for BeanCounters""" ++ THRESHOLD_KEYS = { ++ # relevant threshold limiting in OpenVZ ++ # see http://wiki.openvz.org/UBC_parameter_properties ++ # NOTE: custom/missing beancounters are treated limited by limit ++ 'limit' : ['lockedpages', 'numfile' , 'numiptent', 'numothersock', 'numproc', 'numpty', 'numsiginfo', 'numtcpsock', 'shmpages'], ++ 'barrier': ['dcachesize', 'dgramrcvbuf', 'kmemsize', 'numflock', 'oomguarpages', 'othersockbuf', 'privvmpages', 'tcprcvbuf', 'tcpsndbuf', 'vmguarpages'], ++ 'none' : ['physpages'] ++ } ++ ++ def __init__(self, resource=None, critical=95, warning=90): ++ """Create a new verifier. ++ ++ Args: ++ resource: str - resource name (None = wildcard match all resources) ++ critical: int - critical level (percentage of limit) ++ warning: int - critical level (percentage of limit) ++ """ ++ self.resource = resource ++ self.critical = critical ++ self.warning = warning ++ ++ def __repr__(self): ++ if not self.resource: ++ resource = '*' ++ else: ++ resource = self.resource ++ return ('' % ++ (resource, self.critical, self.warning)) ++ ++ def check(self, beancounter, use_maxheld=False): ++ """Check a threshold ++ ++ Args: ++ beancounter: BeanCounter object ++ use_maxheld: bool - use maxheld instead of held counter for limits ++ ++ Returns: ++ None or BeanCounterViolation (or subclass) ++ """ ++ if not self.resource or beancounter.resource == self.resource: ++ if beancounter.failcnt: ++ return BeanCounterFailure(beancounter.resource, beancounter.uid, beancounter.failcnt) ++ ++ # what are we measuring against? ++ if beancounter.resource in BeanCounterThreshold.THRESHOLD_KEYS['barrier']: ++ quota = beancounter.barrier ++ else: ++ quota = beancounter.limit ++ ++ # what are we measuring? ++ if use_maxheld: ++ value = beancounter.maxheld ++ else: ++ value = beancounter.held ++ ++ if value > quota: ++ return BeanCounterOvershoot(beancounter.resource, beancounter.uid, value - quota) ++ ++ # check for critical / warning by comparing our value with the relevant ++ # percentage of our quota. return an object with information how much ++ # over quota we are. ++ if quota and self.critical >= 0 and value >= (quota * (float(self.critical)/100)): ++ return BeanCounterCritical(beancounter.resource, beancounter.uid, value - int((quota * (float(self.critical)/100)))) ++ if quota and self.warning >= 0 and value >= (quota * (float(self.warning)/100)): ++ return BeanCounterWarning(beancounter.resource, beancounter.uid, value - int((quota * (float(self.warning)/100)))) ++ return None ++ ++ ++class BeanCounterViolation(object): ++ """Alert containing a BeanCounter violation.""" ++ def __init__(self, resource, uid, excess): ++ """Create a new BeanCounter violation. ++ ++ Args: ++ resource: str - resource name ++ uid: int - context uid ++ excess: int - how much the limit was exceeded ++ """ ++ self.tag = 'VIOL' ++ self.resource = resource ++ self.uid = uid ++ self.excess = excess ++ ++ def __repr__(self): ++ return ('<%s %s: resource %s in context %d by %d>' % ++ (self.__class__.__name__, self.tag, self.resource, self.uid, self.excess)) ++ ++ ++class BeanCounterFailure(BeanCounterViolation): ++ """Alert containing a BeanCounter failure.""" ++ def __init__(self, resource, uid, excess): ++ """Create a new BeanCounter failure. ++ ++ Args: ++ resource: str - resource name ++ uid: int - context uid ++ excess: int - how much the limit was exceeded ++ """ ++ super(BeanCounterFailure, self).__init__(resource, uid, excess) ++ self.tag = 'FAIL' ++ ++ ++class BeanCounterOvershoot(BeanCounterViolation): ++ """Alert containing a BeanCounter overshoot.""" ++ def __init__(self, resource, uid, excess): ++ """Create a new BeanCounter overshoot. ++ ++ Args: ++ resource: str - resource name ++ uid: int - context uid ++ excess: int - how much the limit was exceeded ++ """ ++ super(BeanCounterOvershoot, self).__init__(resource, uid, excess) ++ self.tag = 'OVER' ++ ++ ++class BeanCounterCritical(BeanCounterViolation): ++ """Alert containing a BeanCounter critical.""" ++ def __init__(self, resource, uid, excess): ++ """Create a new BeanCounter critical alert ++ ++ Args: ++ resource: str - resource name ++ uid: int - context uid ++ excess: int - how much the limit was exceeded ++ """ ++ super(BeanCounterCritical, self).__init__(resource, uid, excess) ++ self.tag = 'CRIT' ++ ++ ++class BeanCounterWarning(BeanCounterViolation): ++ """Alert containing a BeanCounter warning.""" ++ def __init__(self, resource, uid, excess): ++ """Create a new BeanCounter warning alert ++ ++ Args: ++ resource: str - resource name ++ uid: int - context uid ++ excess: int - how much the limit was exceeded ++ """ ++ super(BeanCounterWarning, self).__init__(resource, uid, excess) ++ self.tag = 'WARN' ++ ++ ++class BeanCounterVerifier(object): ++ """Verifier wrapper for bean counters.""" ++ def __init__(self, options): ++ """Create a new set of verifiers ++ ++ Args: ++ options: optparse.Values, options used: ++ warning: int - generic warning level ++ critical: int - generic critical level ++ res_warning: dict - resource name:int level ++ res_critical: dict - resource name:int level ++ """ ++ # add common thresholds ++ self.thresholds = [BeanCounterThreshold(None, options.critical, options.warning)] ++ for resource, level in options.res_warning.items(): ++ # has both critical and warning values? ++ if resource in options.res_critical: ++ self.thresholds.append(BeanCounterThreshold(resource, options.res_critical[resource], level)) ++ else: ++ self.thresholds.append(BeanCounterThreshold(resource, -1, level)) ++ for resource, level in options.res_critical.iteritems(): ++ # already defined during warning value loop? ++ if not resource in options.res_warning: ++ self.thresholds.append(BeanCounterThreshold(resource, level, -1)) ++ ++ def verify(self, beancounters, use_maxheld=False): ++ """Verify BeanCounters ++ ++ Args: ++ beancounters: list of BeanCounters ++ use_maxheld: bool - use maxheld instead of held counter for limits ++ ++ Returns: ++ list of lists (see BeanCounterThreshold.check) ++ """ ++ results = [] ++ for beancounter in beancounters: ++ for threshold in self.thresholds: ++ result = threshold.check(beancounter, use_maxheld) ++ if result: ++ results.append(result) ++ return results ++ ++ ++def shorten_hostname(hostname, parts=2): ++ """Shorten hostname by taking only certain parts from the beginning of it. ++ ++ Args: ++ hostname: str - FQDN ++ parts: int - number of parts to keep ++ """ ++ # return at least the hostname ++ if (parts < 1): ++ parts = 1 ++ if hostname: ++ return '.'.join(hostname.split('.')[:parts]) ++ return None ++ ++ ++def get_vm_hostname(uid, confpath=OPENVZ_CONFPATH): ++ """Get hostname for a vm by getting the hostname from config file ++ ++ Args: ++ uid: int - uid / container context number of vm ++ confpath: str - folder in which to find .conf ++ ++ Returns: ++ str: FQDN as configured, or None ++ """ ++ try: ++ result = re.search(r'HOSTNAME="(.*)"', open(confpath+"/"+str(uid)+".conf", "r").read()) ++ if result: ++ return result.group(1) ++ except IOError: ++ return None ++ ++ ++def get_local_fqdn(): ++ """Get local hostname.""" ++ return socket.gethostname() ++ ++ ++def get_hostname(uid, confpath=OPENVZ_CONFPATH, parts=2): ++ """Get and shorten OpenVZ vm hostname ++ ++ Args: ++ uid: ints - uid / container context number ++ confpath: str - folder in which to find .conf ++ parts: int - number of hostname parts to return ++ ++ Returns: ++ str: hostname ++ """ ++ # the hypervisor itself, or a VM -> use local hostname ++ # NOTE: this assumes a correct confpath and non-existence of it on VMs. ++ if uid == 0 or not os.path.exists(confpath): ++ hostname = get_local_fqdn() ++ else: ++ hostname = get_vm_hostname(uid, confpath) ++ # drop ending domain parts of FQDN ++ return shorten_hostname(hostname, parts) ++ ++ ++def read_data(options): ++ """Read OpenVZ counter data from system ++ ++ Args: ++ options: optparse object: ++ sudo: bool - use sudo to read file or not ++ filename: str - filename to read ++ ++ Return: ++ str: verbatim file contents ++ ++ Sideeffects: ++ May exit to system directly. ++ """ ++ # read into a string directly, or with a "sudo cat" ++ if not options.sudo: ++ try: ++ data = open(options.filename, "r").read() ++ except IOError, (errorcode, errorstr): ++ # file not found? not an OpenVZ system! ++ if (errorcode == errno.ENOENT): ++ print "OK: Not an OpenVZ system, no need to worry about beancounters." ++ sys.exit(0) ++ elif (errorcode == errno.EACCES): ++ print "UNKNOWN: Not permitted to read beancounter information." ++ sys.exit(3) ++ else: ++ print "CRITICAL: Unknown problem reading beancounters." ++ sys.exit(2) ++ else: ++ # call a non-interactive sudo to read the file ++ # needs to be configured via e.g. /etc/sudoers ++ try: ++ data = subprocess.Popen(["/usr/bin/sudo", "-n", "cat", options.filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] ++ except OSError, (errorcode, errorstr): ++ print "CRITICAL: Can't execute sudo to read beancounters. (%d - %s)" % (errorcode, errorstr) ++ sys.exit(2) ++ if not data: ++ print "CRITICAL: Trying to read beancounters with sudo didn't yield data." ++ sys.exit(2) ++ return data ++ ++ ++def create_optionsparser(): ++ """Create optparse.OptionParser object for us ++ ++ Returns: ++ optparse.OptionParser object ++ """ ++ usage = "usage: %prog [options]" ++ parser = optparse.OptionParser(usage=usage, option_class=ExtOption) ++ parser.add_option("-w", "--warning", dest="warning", default=90, ++ action="store_int", help="default warning threshold percentage for everything (default: %default)") ++ parser.add_option("-c", "--critical", dest="critical", default=95, ++ action="store_int", help="default critical threshold percentage for everything (default: %default)") ++ parser.add_option("-W", "--resource-warning", dest="res_warning", default={}, ++ action="keyvalgroup", help="resource specific warning percentage (e.g. foo:50,bar:60)") ++ parser.add_option("-C", "--resource-critical", dest="res_critical", default={}, ++ action="keyvalgroup", help="resource-specific critical percentage (e.g. foo:90,bar:95)") ++ parser.add_option("-f", "--file", dest="filename", default='/proc/user_beancounters', ++ action="store", help="read beancounters from file (default: %default)") ++ parser.add_option("-s", "--sudo", dest="sudo", default=False, ++ action="store_true", help="use 'sudo cat filename' to read file as root (filename see -f)") ++ parser.add_option("-p", "--configs", dest="confpath", default=OPENVZ_CONFPATH, ++ action="store", help="path for OpenVZ config path (to get hostnames, default: %default)") ++ parser.add_option("-d", "--domainparts", dest="domainparts", default=2, ++ action="store_int", help="how many domain parts of the hostname to keep (default: %default)") ++ parser.add_option("-u", "--ubc-store-path", dest="storepath", default=OPENVZ_UBCSTORE, ++ action="store", help="path for vzubc relative information (default: %default)") ++ parser.add_option("-m", "--use-maxheld", dest="use_maxheld", default=False, ++ action="store_true", help="use resource's maxheld instead of current_held (default: %default)") ++ parser.add_option("-a", "--absolute-fails", dest="use_absolute_failcnt", default=False, ++ action="store_true", help="don't use vzubc's relative fail counters (default: %default)") ++ return parser ++ ++ ++class ExtOption(optparse.Option): ++ """Specialized Option class which parses key:val,key:val parameters and integers ++ See optparse documentation for detailed explanation of how this works.""" ++ ACTIONS = optparse.Option.ACTIONS + ("keyvalgroup", "store_int",) ++ STORE_ACTIONS = optparse.Option.STORE_ACTIONS + ("keyvalgroup", "store_int",) ++ TYPED_ACTIONS = optparse.Option.TYPED_ACTIONS + ("keyvalgroup", "store_int",) ++ ALWAYS_TYPED_ACTIONS = optparse.Option.ALWAYS_TYPED_ACTIONS + ("keyvalgroup", "store_int",) ++ ++ def take_action(self, action, dest, opt, value, values, parser): ++ if action == "keyvalgroup": ++ keyvals = value.split(",") ++ for keyval in keyvals: ++ key, val = keyval.split(":") ++ if re.match(r'\d+', val): ++ val = int(val) ++ values.ensure_value(dest, {}).update({key:val}) ++ elif action == "store_int": ++ setattr(values, dest, int(value)) ++ else: ++ optparse.Option.take_action(self, action, dest, opt, value, values, parser) ++ ++ ++def __main__(): ++ optionsparser = create_optionsparser() ++ # args parsing will exit the program if options are used wrong or help is ++ # requested. optionsparser.error exists to system as well - we call it when ++ # extra arguments are given. none are expected, we use options only. ++ options, args = optionsparser.parse_args() ++ if args: ++ optionsparser.error("incorrect number of arguments") ++ ++ # NOTE: read_data itself may exit to system in some cases ++ data = read_data(options) ++ if not data: ++ print "CRITICAL: No data given while reading beancounters." ++ sys.exit(2) ++ ++ # parse beancounters, create verifiers, verify beancounters ++ try: ++ beancounterparser = BeanCounterParser(data, options.use_absolute_failcnt, options.storepath) ++ except NoBeanCountersFoundError: ++ print "CRITICAL: No beancounters found in data read." ++ sys.exit(2) ++ ++ beancounterverifier = BeanCounterVerifier(options) ++ beancounteralerts = beancounterverifier.verify(beancounterparser.get_beancounters(), options.use_maxheld) ++ ++ # find uids and combine alert groups ++ fail = {} ++ over = {} ++ crit = {} ++ warn = {} ++ for alert in beancounteralerts: ++ if isinstance (alert, BeanCounterFailure): ++ fail.setdefault(alert.uid, {}) ++ fail[alert.uid][alert.resource] = alert.excess ++ elif isinstance (alert, BeanCounterOvershoot): ++ over.setdefault(alert.uid, {}) ++ over[alert.uid][alert.resource] = alert.excess ++ elif isinstance (alert, BeanCounterCritical): ++ crit.setdefault(alert.uid, {}) ++ crit[alert.uid][alert.resource] = alert.excess ++ elif isinstance (alert, BeanCounterWarning): ++ warn.setdefault(alert.uid, {}) ++ warn[alert.uid][alert.resource] = alert.excess ++ ++ # default message & exitcode if everything is fine ++ message = "OK: all beancounters below configured thresholds" ++ perfdata = "" ++ exitcode = 0 ++ ++ # set message prefix and errocode accordingly ++ if fail or over or crit: ++ message = "CRITICAL:" ++ exitcode = 2 ++ elif warn: ++ message = "WARNING:" ++ exitcode = 1 ++ ++ # combine specific Nagios message(s) ++ for level, tag in (fail, 'FAIL'), (over, 'OVER'), (crit, 'CRIT'), (warn, 'WARN'): ++ if level: ++ message += " %s:" % tag ++ perfdata += " %s:" % tag ++ for uid, counters in level.items(): ++ hostname = get_hostname(uid, options.confpath, options.domainparts) ++ message += " %s(%d)" % (hostname, uid) ++ perfdata += " HOST %s(%d):" % (hostname, uid) ++ for resource, counter in counters.items(): ++ perfdata += " %s(+%d)" % (resource, counter) ++ ++ # output message & exit ++ if len(perfdata): ++ print "%s|%s" % (message, perfdata) ++ else: ++ print message ++ sys.exit(exitcode) ++ ++ ++if __name__ == "__main__": ++ __main__() +Binary files nothing/check_openvz_beans.pyc and nagios-plugins-openvz-beans/check_openvz_beans.pyc differ +diff -urN nothing/check_openvz_beans-test.py nagios-plugins-openvz-beans/check_openvz_beans-test.py +--- nothing/check_openvz_beans-test.py 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/check_openvz_beans-test.py 2011-11-01 18:28:47.867345265 +0100 +@@ -0,0 +1,775 @@ ++#!/usr/bin/python ++"""check_openvz_beans unit tests.""" ++ ++__author__ = 'Andreas Kotes ' ++ ++import __builtin__ ++import os ++import sys ++import unittest ++import mox ++import optparse ++import StringIO ++import subprocess ++import check_openvz_beans ++ ++class BeanCounterTest(mox.MoxTestBase): ++ """Test the BeanCounter class.""" ++ def testCreate(self): ++ beancounter = check_openvz_beans.BeanCounter(123, "dummy 1 2 3 4 5") ++ self.assertEquals(beancounter.uid, 123) ++ self.assertEquals(beancounter.resource, 'dummy') ++ self.assertEquals(beancounter.held, 1) ++ self.assertEquals(beancounter.maxheld, 2) ++ self.assertEquals(beancounter.barrier, 3) ++ self.assertEquals(beancounter.limit, 4) ++ self.assertEquals(beancounter.failcnt, 5) ++ self.assertEquals(beancounter.__repr__(), ++ '') ++ self.assertTrue(beancounter == check_openvz_beans.BeanCounter(123, "dummy 1 2 3 4 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(124, "dummy 1 2 3 4 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(123, "yummy 1 2 3 4 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(123, "dummy 2 2 3 4 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(123, "dummy 1 3 3 4 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(123, "dummy 1 2 4 4 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(123, "dummy 1 2 3 5 5")) ++ self.assertFalse(beancounter == check_openvz_beans.BeanCounter(123, "dummy 1 2 3 4 6")) ++ ++ ++class BeanCounterParserTest(mox.MoxTestBase): ++ """Test the BeanCounterParser class.""" ++ def setUp(self): ++ super(BeanCounterParserTest, self).setUp() ++ ++ def test_init_and_parsebeancounters(self): ++ beancounters = check_openvz_beans.BeanCounterParser("123: dummy1 1 2 3 4 5\n dummy2 54 63 62 13 53\n234: dummy3 9 8 7 6 5\n") ++ self.assertEquals(beancounters.get_beancounters(), [ ++ check_openvz_beans.BeanCounter(123, ' dummy1 1 2 3 4 5'), ++ check_openvz_beans.BeanCounter(123, ' dummy2 54 63 62 13 53'), ++ check_openvz_beans.BeanCounter(234, ' dummy3 9 8 7 6 5')]) ++ ++ def test_parsefail(self): ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(check_openvz_beans.NoBeanCountersFoundError, check_openvz_beans.BeanCounterParser, "nonsense") ++ ++ ++class BeanCounterThresholdTest(mox.MoxTestBase): ++ """Test the BeanCounterThreshold class.""" ++ def setUp(self): ++ super(BeanCounterThresholdTest, self).setUp() ++ # Mock BeanCounters ++ self.beancounter_mock = self.mox.CreateMock(check_openvz_beans.BeanCounter) ++ self.beancounter_mock.uid = 123 ++ self.beancounter_mock.failcnt = 0 ++ ++ def testCreateSimple(self): ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ self.assertEquals(threshold.resource, None) ++ self.assertEquals(threshold.critical, 95) ++ self.assertEquals(threshold.warning, 90) ++ self.assertEquals(threshold.__repr__(), ++ '') ++ ++ def testCreateCustom(self): ++ threshold = check_openvz_beans.BeanCounterThreshold('dummy', 70, 60) ++ self.assertEquals(threshold.resource, 'dummy') ++ self.assertEquals(threshold.critical, 70) ++ self.assertEquals(threshold.warning, 60) ++ self.assertEquals(threshold.__repr__(), ++ '') ++ ++ def testCheckSimpleOkay(self): ++ self.beancounter_mock.resource = 'dummy_okay' ++ self.beancounter_mock.held = 1 ++ self.beancounter_mock.maxheld = 2 ++ self.beancounter_mock.barrier = 3 ++ self.beancounter_mock.limit = 4 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ self.assertFalse(threshold.check(self.beancounter_mock)) ++ ++ def testCheckSimpleOkayNegWarn(self): ++ self.beancounter_mock.resource = 'dummy_okay' ++ self.beancounter_mock.held = 1 ++ self.beancounter_mock.maxheld = 2 ++ self.beancounter_mock.barrier = 3 ++ self.beancounter_mock.limit = 4 ++ threshold = check_openvz_beans.BeanCounterThreshold(warning=-1) ++ self.assertEqual(threshold.check(self.beancounter_mock), None) ++ ++ def testCheckSimpleOkayNegCrit(self): ++ self.beancounter_mock.resource = 'dummy_okay' ++ self.beancounter_mock.held = 1 ++ self.beancounter_mock.maxheld = 2 ++ self.beancounter_mock.barrier = 3 ++ self.beancounter_mock.limit = 4 ++ threshold = check_openvz_beans.BeanCounterThreshold(critical=-1) ++ self.assertEqual(threshold.check(self.beancounter_mock), None) ++ ++ def testCheckSimpleFail(self): ++ # failcnt engaged ++ self.beancounter_mock.resource = 'dummy_fail' ++ self.beancounter_mock.held = 1 ++ self.beancounter_mock.maxheld = 2 ++ self.beancounter_mock.barrier = 3 ++ self.beancounter_mock.limit = 4 ++ self.beancounter_mock.failcnt = 1 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'FAIL') ++ ++ def testCheckSimpleEqual(self): ++ # eq Limit ++ self.beancounter_mock.resource = 'dummy_equal' ++ self.beancounter_mock.held = 50 ++ self.beancounter_mock.maxheld = 100 ++ self.beancounter_mock.barrier = 100 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold(critical=101, warning=101) ++ self.assertFalse(threshold.check(self.beancounter_mock)) ++ ++ def testCheckSimpleOverGt(self): ++ # over Limit ++ self.beancounter_mock.resource = 'dummy_over' ++ self.beancounter_mock.held = 4 ++ self.beancounter_mock.maxheld = 4 ++ self.beancounter_mock.barrier = 3 ++ self.beancounter_mock.limit = 3 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'OVER') ++ ++ def testCheckSimpleCritEq(self): ++ # eq critical value ++ self.beancounter_mock.resource = 'dummy_crit_eq' ++ self.beancounter_mock.held = 95 ++ self.beancounter_mock.maxheld = 95 ++ self.beancounter_mock.barrier = 100 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'CRIT') ++ ++ def testCheckSimpleCritGt(self): ++ # gt critical value ++ self.beancounter_mock.resource = 'dummy_crit_gt' ++ self.beancounter_mock.held = 96 ++ self.beancounter_mock.maxheld = 96 ++ self.beancounter_mock.barrier = 100 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'CRIT') ++ ++ def testCheckSimpleWarnEq(self): ++ # eq warning value ++ self.beancounter_mock.resource = 'dummy_warn_eq' ++ self.beancounter_mock.held = 90 ++ self.beancounter_mock.maxheld = 90 ++ self.beancounter_mock.barrier = 100 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'WARN') ++ ++ def testCheckSimpleWarnGt(self): ++ # gt warning value ++ self.beancounter_mock.resource = 'dummy_warn_gt' ++ self.beancounter_mock.held = 91 ++ self.beancounter_mock.maxheld = 91 ++ self.beancounter_mock.barrier = 100 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'WARN') ++ ++ def testCheckBarrierQuota(self): ++ # limited by barrier -> would not warn if limited by limit ++ self.beancounter_mock.resource = 'numflock' ++ self.beancounter_mock.held = 45 ++ self.beancounter_mock.maxheld = 45 ++ self.beancounter_mock.barrier = 50 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ result = threshold.check(self.beancounter_mock) ++ self.assertTrue(result) ++ self.assertEquals(result.tag, 'WARN') ++ ++ def testCheckLimitQuota(self): ++ # limited by limit -> would be over if limited by barrier ++ self.beancounter_mock.resource = 'numproc' ++ self.beancounter_mock.held = 50 ++ self.beancounter_mock.maxheld = 56 ++ self.beancounter_mock.barrier = 50 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold() ++ self.assertFalse(threshold.check(self.beancounter_mock)) ++ ++ def testCheckNotResponsible(self): ++ # gt critical value ++ self.beancounter_mock.resource = 'dummy_crit_gt' ++ self.beancounter_mock.held = 50 ++ self.beancounter_mock.maxheld = 96 ++ self.beancounter_mock.barrier = 100 ++ self.beancounter_mock.limit = 100 ++ threshold = check_openvz_beans.BeanCounterThreshold('differentresource') ++ self.assertFalse(threshold.check(self.beancounter_mock)) ++ ++ ++class BeanCounterViolationTest(unittest.TestCase): ++ """Test the BeanCounterViolation class.""" ++ def testCreate(self): ++ violation = check_openvz_beans.BeanCounterViolation('dummy', 123, 10) ++ self.assertEquals(violation.uid, 123) ++ self.assertEquals(violation.resource, 'dummy') ++ self.assertEquals(violation.tag, 'VIOL') ++ self.assertEquals(violation.excess, 10) ++ self.assertEquals(violation.__repr__(), ++ '') ++ ++ ++class BeanCounterFailureTest(unittest.TestCase): ++ """Test the BeanCounterFailure class.""" ++ def testCreate(self): ++ violation = check_openvz_beans.BeanCounterFailure('dummy', 123, 10) ++ self.assertEquals(violation.uid, 123) ++ self.assertEquals(violation.resource, 'dummy') ++ self.assertEquals(violation.tag, 'FAIL') ++ self.assertEquals(violation.excess, 10) ++ self.assertEquals(violation.__repr__(), ++ '') ++ ++ ++class BeanCounterOvershootTest(unittest.TestCase): ++ """Test the BeanCounterOvershoot class.""" ++ def testCreate(self): ++ violation = check_openvz_beans.BeanCounterOvershoot('dummy', 123, 10) ++ self.assertEquals(violation.uid, 123) ++ self.assertEquals(violation.resource, 'dummy') ++ self.assertEquals(violation.tag, 'OVER') ++ self.assertEquals(violation.excess, 10) ++ self.assertEquals(violation.__repr__(), ++ '') ++ ++ ++class BeanCounterCritical(unittest.TestCase): ++ """Test the BeanCounterCritical class.""" ++ def testCreate(self): ++ violation = check_openvz_beans.BeanCounterCritical('dummy', 123, 10) ++ self.assertEquals(violation.uid, 123) ++ self.assertEquals(violation.resource, 'dummy') ++ self.assertEquals(violation.tag, 'CRIT') ++ self.assertEquals(violation.excess, 10) ++ self.assertEquals(violation.__repr__(), ++ '') ++ ++ ++class BeanCounterWarningTest(unittest.TestCase): ++ """Test the BeanCounterWarning class.""" ++ def testCreate(self): ++ violation = check_openvz_beans.BeanCounterWarning('dummy', 123, 10) ++ self.assertEquals(violation.uid, 123) ++ self.assertEquals(violation.resource, 'dummy') ++ self.assertEquals(violation.tag, 'WARN') ++ self.assertEquals(violation.excess, 10) ++ self.assertEquals(violation.__repr__(), ++ '') ++ ++ ++class BeanCounterVerifierInitTest(mox.MoxTestBase): ++ """Test the BeanCounterVerifier class (1/2).""" ++ def setUp(self): ++ super(BeanCounterVerifierInitTest, self).setUp() ++ # Mock BeanCounterThresholds ++ self.values_mock = self.mox.CreateMock(optparse.Values) ++ self.threshold_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterThreshold) ++ self.mox.StubOutWithMock(check_openvz_beans, 'BeanCounterThreshold') ++ ++ # check with common thresholds ++ self.values_mock.critical = 95 ++ self.values_mock.warning = 90 ++ check_openvz_beans.BeanCounterThreshold(None, 95, 90) ++ ++ # check with resource-specific thresholds ++ self.values_mock.res_critical = {'foo':20, 'bar':30} ++ self.values_mock.res_warning = {'foo':10, 'baz':20} ++ check_openvz_beans.BeanCounterThreshold('foo', 20, 10) ++ check_openvz_beans.BeanCounterThreshold('baz', -1, 20) ++ check_openvz_beans.BeanCounterThreshold('bar', 30, -1) ++ ++ self.mox.ReplayAll() ++ ++ def test_init(self): ++ beancounterverifier = check_openvz_beans.BeanCounterVerifier(self.values_mock) ++ ++ ++class BeanCounterVerifierVerifyTest(mox.MoxTestBase): ++ """Test the BeanCounterVerifier class (2/2).""" ++ def setUp(self): ++ super(BeanCounterVerifierVerifyTest, self).setUp() ++ # Mock BeanCounterThresholds ++ self.values_mock = self.mox.CreateMock(optparse.Values) ++ self.threshold_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterThreshold) ++ self.beancounter_mock = self.mox.CreateMock(check_openvz_beans.BeanCounter) ++ self.violation_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterViolation) ++ self.mox.StubOutWithMock(check_openvz_beans, 'BeanCounterThreshold') ++ self.mox.StubOutWithMock(check_openvz_beans.BeanCounterThreshold, 'check') ++ ++ # check with common thresholds ++ self.values_mock.critical = 95 ++ self.values_mock.warning = 90 ++ self.values_mock.res_critical = {} ++ self.values_mock.res_warning = {} ++ check_openvz_beans.BeanCounterThreshold(None, 95, 90).AndReturn(self.threshold_mock) ++ self.threshold_mock.check(mox.IsA(check_openvz_beans.BeanCounter), False) ++ self.threshold_mock.check(mox.IsA(check_openvz_beans.BeanCounter), False).AndReturn(self.violation_mock) ++ self.threshold_mock.check(mox.IsA(check_openvz_beans.BeanCounter), False).AndReturn(self.violation_mock) ++ self.threshold_mock.check(mox.IsA(check_openvz_beans.BeanCounter), False).AndReturn(self.violation_mock) ++ ++ self.mox.ReplayAll() ++ ++ def test_verify(self): ++ beancounterverifier = check_openvz_beans.BeanCounterVerifier(self.values_mock) ++ beancounter_mock = self.mox.CreateMock(check_openvz_beans.BeanCounter) ++ # first one is okay ++ self.assertEquals(len(beancounterverifier.verify([beancounter_mock,], False)), 0) ++ # second one has a violation ++ self.assertEquals(len(beancounterverifier.verify([beancounter_mock,], False)), 1) ++ # third + fourth each have a violation ++ self.assertEquals(len(beancounterverifier.verify([beancounter_mock, beancounter_mock], False)), 2) ++ ++ ++class ExtOptionTest(mox.MoxTestBase): ++ """Test the ExtOption class.""" ++ def setUp(self): ++ super(ExtOptionTest, self).setUp() ++ # Mock optparse objects ++ self.values1 = self.mox.CreateMockAnything() ++ self.values1.ensure_value('foobar', {}).AndReturn(self.values1) ++ self.values1.update({'key1': 'val1'}) ++ self.values1.ensure_value('foobar', {}).AndReturn(self.values1) ++ self.values1.update({'key2': 'val2'}) ++ ++ self.values2 = self.mox.CreateMockAnything() ++ self.values2.intval = 0 ++ ++ self.values3 = self.mox.CreateMockAnything() ++ ++ self.mox.StubOutWithMock(optparse.Option, '__init__') ++ self.mox.StubOutWithMock(optparse.Option, 'take_action') ++ optparse.Option.__init__() ++ optparse.Option.take_action(mox.IsA(optparse.Option), 'something_else', None, None, None, None, None) ++ ++ self.mox.ReplayAll() ++ ++ def test_take_action(self): ++ option = check_openvz_beans.ExtOption() ++ option.take_action('keyvalgroup', 'foobar', 'dunno', 'key1:val1,key2:val2', self.values1, 'dunno') ++ ++ self.assertEquals(self.values2.intval, 0) ++ option.take_action('store_int', 'intval', 'dunno', '10', self.values2, 'dunno') ++ self.assertEquals(self.values2.intval, 10) ++ ++ option.take_action('something_else', None, None, None, None, None) ++ ++ ++class ReadDataTest(mox.MoxTestBase): ++ """Check read_data functions without sudo.""" ++ def setUp(self): ++ super(ReadDataTest, self).setUp() ++ # Mock optparse objects ++ self.options_mock = self.mox.CreateMock(optparse.Values) ++ self.popen_mock = self.mox.CreateMock(subprocess.Popen) ++ self.mox.StubOutWithMock(subprocess, 'Popen') ++ self.saved_stdout = sys.stdout ++ sys.stdout = StringIO.StringIO() ++ ++ def tearDown(self): ++ super(ReadDataTest, self).tearDown() ++ sys.stdout = self.saved_stdout ++ ++ def test_read_data(self): ++ """Test reading OpenVZ counter data from system without sudo - existing file.""" ++ self.options_mock.sudo = False ++ self.options_mock.filename = 'testdata/hostcrit.bcs' ++ self.mox.ReplayAll() ++ ++ result = check_openvz_beans.read_data(self.options_mock) ++ ++ self.assertTrue(isinstance(result, str)) ++ self.assertEquals(len(result), os.path.getsize(self.options_mock.filename)) ++ ++ def test_read_data_missing_file(self): ++ """Test reading OpenVZ counter data from system without sudo - missing file.""" ++ self.options_mock.sudo = False ++ self.options_mock.filename = '/nonexisting/foobar' ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.read_data, self.options_mock) ++ self.assertEqual(sys.stdout.getvalue(), 'OK: Not an OpenVZ system, no need to worry about beancounters.\n') ++ ++ def test_read_data_missing_file(self): ++ """Test reading OpenVZ counter data from system without sudo - unreadable file.""" ++ self.options_mock.sudo = False ++ self.options_mock.filename = 'testdata/unreadable.bcs' ++ try: ++ os.unlink(self.options_mock.filename) ++ except OSError: ++ pass ++ ++ open(self.options_mock.filename, 'w').close() ++ os.chmod(self.options_mock.filename, 0000) ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.read_data, self.options_mock) ++ self.assertEqual(sys.stdout.getvalue(), 'UNKNOWN: Not permitted to read beancounter information.\n') ++ ++ try: ++ os.unlink(self.options_mock.filename) ++ except OSError: ++ pass ++ ++ # FIXME: not all code pathes completely tested due to unmockability of open() ++ ++ def test_read_data_sudo(self): ++ """Test reading OpenVZ counter data from system with sudo - sucess.""" ++ self.options_mock.sudo = True ++ self.options_mock.filename = 'irrelevant' ++ subprocess.Popen(['/usr/bin/sudo', '-n', 'cat', 'irrelevant'], stderr=-1, stdout=-1).AndReturn(self.popen_mock) ++ self.popen_mock.communicate().AndReturn(['somedata']) ++ self.mox.ReplayAll() ++ ++ result = check_openvz_beans.read_data(self.options_mock) ++ ++ self.assertTrue(isinstance(result, str)) ++ self.assertEquals(result, 'somedata') ++ ++ def test_read_data_sudo_oserror(self): ++ """Test reading OpenVZ counter data from system with sudo - OSError.""" ++ self.options_mock.sudo = True ++ self.options_mock.filename = 'irrelevant' ++ subprocess.Popen(['/usr/bin/sudo', '-n', 'cat', 'irrelevant'], stderr=-1, stdout=-1).AndRaise(OSError(42, 'mocketimock')) ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.read_data, self.options_mock) ++ self.assertEqual(sys.stdout.getvalue(), "CRITICAL: Can't execute sudo to read beancounters. (42 - mocketimock)\n") ++ ++ def test_read_data_sudo_nodata(self): ++ """Test reading OpenVZ counter data from system with sudo - no data.""" ++ self.options_mock.sudo = True ++ self.options_mock.filename = 'irrelevant' ++ ++ subprocess.Popen(['/usr/bin/sudo', '-n', 'cat', 'irrelevant'], stderr=-1, stdout=-1).AndReturn(self.popen_mock) ++ self.popen_mock.communicate().AndReturn(['']) ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.read_data, self.options_mock) ++ self.assertEqual(sys.stdout.getvalue(), "CRITICAL: Trying to read beancounters with sudo didn't yield data.\n") ++ ++ ++class GlobalsTest(mox.MoxTestBase): ++ """Check global functions.""" ++ def setUp(self): ++ super(GlobalsTest, self).setUp() ++ self.saved_stdout, sys.stdout = sys.stdout, StringIO.StringIO() ++ ++ def tearDown(self): ++ super(GlobalsTest, self).tearDown() ++ sys.stdout = self.saved_stdout ++ ++ def test_shorten_hostname(self): ++ """Test shortening hostnames.""" ++ self.testfqdn = "hostname.with.long.domain.name" ++ # the (short) hostname should be returned in any case ++ self.assertEqual(check_openvz_beans.shorten_hostname(self.testfqdn, 0), "hostname") ++ self.assertEqual(check_openvz_beans.shorten_hostname(self.testfqdn, 1), "hostname") ++ # various lengths should be returned properly ++ self.assertEqual(check_openvz_beans.shorten_hostname(self.testfqdn, 2), "hostname.with") ++ self.assertEqual(check_openvz_beans.shorten_hostname(self.testfqdn, 5), "hostname.with.long.domain.name") ++ # if more is requested than is there, just give all there is ++ self.assertEqual(check_openvz_beans.shorten_hostname(self.testfqdn, 42), "hostname.with.long.domain.name") ++ ++ def test_get_vm_hostname(self): ++ """Test getting vm hostnames.""" ++ # two known existing hosts ++ self.assertEqual(check_openvz_beans.get_vm_hostname(10, 'testdata'), 'vmokay.pr.foo.test.your.do.main') ++ self.assertEqual(check_openvz_beans.get_vm_hostname(60, 'testdata'), 'vmover1.st.foo.test.your.do.main') ++ # one host whose config file doesn't contain a hostname ++ self.assertEqual(check_openvz_beans.get_vm_hostname(99, 'testdata'), None) ++ # one host where no config file exists ++ self.assertEqual(check_openvz_beans.get_vm_hostname(90, 'testdata'), None) ++ ++ def test_get_local_fqdn(self): ++ """Test getting local hostnames.""" ++ # due to the local nature of hostnames we can only check wether it has a qualifying '.' in it ++ self.assertTrue(check_openvz_beans.get_local_fqdn().find('.') > 0) ++ ++ def test_get_hostname(self): ++ """Test getting and shortening hostnames.""" ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_vm_hostname') ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_local_fqdn') ++ check_openvz_beans.get_local_fqdn().AndReturn('localhost.localdomain') ++ check_openvz_beans.get_local_fqdn().AndReturn('localhost.localdomain') ++ check_openvz_beans.get_vm_hostname(10, 'testdata').AndReturn('hostname.with.long.domain.name') ++ self.mox.ReplayAll() ++ ++ self.assertEqual(check_openvz_beans.get_hostname(0, 'testdata'), 'localhost.localdomain') ++ self.assertEqual(check_openvz_beans.get_hostname(99, 'nonexistent'), 'localhost.localdomain') ++ self.assertEqual(check_openvz_beans.get_hostname(10, 'testdata'), 'hostname.with') ++ ++ self.mox.VerifyAll() ++ self.mox.UnsetStubs() ++ ++ def test_create_optionsparser(self): ++ """Test creating a custom OptionParser.""" ++ parser = check_openvz_beans.create_optionsparser() ++ self.assertTrue(isinstance(parser, optparse.OptionParser)) ++ # FIXME: do we want to check more? ++ ++ ++class MainEarlyFailuresTest(mox.MoxTestBase): ++ def setUp(self): ++ super(MainEarlyFailuresTest, self).setUp() ++ self.saved_stdout, sys.stdout = sys.stdout, StringIO.StringIO() ++ self.option_mock = self.mox.CreateMock(optparse.Values) ++ self.option_mock.use_absolute_failcnt = False ++ self.option_mock.storepath = 'testdata' ++ ++ def tearDown(self): ++ sys.stdout = self.saved_stdout ++ ++ def test___main___wrongargs(self): ++ """Test the __main__ function -- wrong args.""" ++ optionsparser_mock = self.mox.CreateMock(optparse.OptionParser) ++ self.mox.StubOutWithMock(check_openvz_beans, 'create_optionsparser') ++ check_openvz_beans.create_optionsparser().AndReturn(optionsparser_mock) ++ optionsparser_mock.parse_args().AndReturn((self.option_mock, ['arg',])) ++ optionsparser_mock.error('incorrect number of arguments').AndRaise(SystemExit) ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ ++ def test___main___nodata(self): ++ """Test the __main__ function -- no data.""" ++ optionsparser_mock = self.mox.CreateMock(optparse.OptionParser) ++ self.mox.StubOutWithMock(check_openvz_beans, 'create_optionsparser') ++ check_openvz_beans.create_optionsparser().AndReturn(optionsparser_mock) ++ optionsparser_mock.parse_args().AndReturn((self.option_mock, [])) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'read_data') ++ check_openvz_beans.read_data(mox.IsA(optparse.Values)).AndReturn('') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: No data given while reading beancounters.\n') ++ ++ def test___main___nobeancounters(self): ++ """Test the __main__ function -- no beancounters""" ++ optionsparser_mock = self.mox.CreateMock(optparse.OptionParser) ++ self.mox.StubOutWithMock(check_openvz_beans, 'create_optionsparser') ++ check_openvz_beans.create_optionsparser().AndReturn(optionsparser_mock) ++ optionsparser_mock.parse_args().AndReturn((self.option_mock, [])) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'read_data') ++ check_openvz_beans.read_data(mox.IsA(optparse.Values)).AndReturn('somedata') ++ ++ beancounterparser_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterParser) ++ self.mox.StubOutWithMock(check_openvz_beans, 'BeanCounterParser') ++ check_openvz_beans.BeanCounterParser('somedata', False, 'testdata').AndRaise(check_openvz_beans.NoBeanCountersFoundError) ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: No beancounters found in data read.\n') ++ ++ ++class MainRegularTest(mox.MoxTestBase): ++ def setUp(self): ++ super(MainRegularTest, self).setUp() ++ self.saved_stdout, sys.stdout = sys.stdout, StringIO.StringIO() ++ ++ self.optionsparser_mock = self.mox.CreateMock(optparse.OptionParser) ++ self.option_mock = self.mox.CreateMock(optparse.Values) ++ self.option_mock.confpath = 'irrelevant' ++ self.option_mock.domainparts = 21 ++ self.option_mock.use_absolute_failcnt = False ++ self.option_mock.storepath = 'testdata' ++ self.option_mock.use_maxheld = False ++ self.mox.StubOutWithMock(check_openvz_beans, 'create_optionsparser') ++ check_openvz_beans.create_optionsparser().AndReturn(self.optionsparser_mock) ++ self.optionsparser_mock.parse_args().AndReturn((self.option_mock, [])) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'read_data') ++ check_openvz_beans.read_data(mox.IsA(optparse.Values)).AndReturn('somedata') ++ ++ self.beancounterparser_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterParser) ++ self.mox.StubOutWithMock(check_openvz_beans, 'BeanCounterParser') ++ check_openvz_beans.BeanCounterParser('somedata', False, 'testdata').AndReturn(self.beancounterparser_mock) ++ self.beancounterparser_mock.get_beancounters().AndReturn(None) ++ ++ self.beancounterverifier_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterVerifier) ++ self.mox.StubOutWithMock(check_openvz_beans, 'BeanCounterVerifier') ++ check_openvz_beans.BeanCounterVerifier(mox.IsA(optparse.Values)).AndReturn(self.beancounterverifier_mock) ++ ++ def tearDown(self): ++ sys.stdout = self.saved_stdout ++ ++ def test___main___noalerts(self): ++ """Test the __main__ function -- no alerts.""" ++ self.beancounterverifier_mock.verify(None, False).AndReturn([]) ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'OK: all beancounters below configured thresholds\n') ++ ++ def test___main___nospecificalert(self): ++ """Test the __main__ function -- no alerts.""" ++ beancounteralert_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterViolation) ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_mock,]) ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'OK: all beancounters below configured thresholds\n') ++ ++ def test___main___failalert(self): ++ """Test the __main__ function -- fail alert.""" ++ beancounteralert_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterFailure) ++ beancounteralert_mock.uid = 123 ++ beancounteralert_mock.excess = 987 ++ beancounteralert_mock.resource = 'resource' ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_mock,]) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_hostname') ++ check_openvz_beans.get_hostname(123, 'irrelevant', 21).AndReturn('dummy') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: FAIL: dummy(123)| FAIL: HOST dummy(123): resource(+987)\n') ++ ++ def test___main___overalert(self): ++ """Test the __main__ function -- over alert.""" ++ beancounteralert_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterOvershoot) ++ beancounteralert_mock.uid = 123 ++ beancounteralert_mock.excess = 987 ++ beancounteralert_mock.resource = 'resource' ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_mock,]) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_hostname') ++ check_openvz_beans.get_hostname(123, 'irrelevant', 21).AndReturn('dummy') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: OVER: dummy(123)| OVER: HOST dummy(123): resource(+987)\n') ++ ++ def test___main___critalert(self): ++ """Test the __main__ function -- crit alert.""" ++ beancounteralert_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterCritical) ++ beancounteralert_mock.uid = 123 ++ beancounteralert_mock.excess = 987 ++ beancounteralert_mock.resource = 'resource' ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_mock,]) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_hostname') ++ check_openvz_beans.get_hostname(123, 'irrelevant', 21).AndReturn('dummy') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: CRIT: dummy(123)| CRIT: HOST dummy(123): resource(+987)\n') ++ ++ def test___main___warnalert(self): ++ """Test the __main__ function -- warn alert.""" ++ beancounteralert_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterWarning) ++ beancounteralert_mock.uid = 123 ++ beancounteralert_mock.excess = 987 ++ beancounteralert_mock.resource = 'resource' ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_mock,]) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_hostname') ++ check_openvz_beans.get_hostname(123, 'irrelevant', 21).AndReturn('dummy') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'WARNING: WARN: dummy(123)| WARN: HOST dummy(123): resource(+987)\n') ++ ++ def test___main___failwarnalert(self): ++ """Test the __main__ function -- failwarn alert.""" ++ beancounteralert_fail_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterFailure) ++ beancounteralert_fail_mock.uid = 123 ++ beancounteralert_fail_mock.excess = 987 ++ beancounteralert_fail_mock.resource = 'resource' ++ beancounteralert_warn_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterWarning) ++ beancounteralert_warn_mock.uid = 234 ++ beancounteralert_warn_mock.excess = 896 ++ beancounteralert_warn_mock.resource = 'resource' ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_fail_mock, beancounteralert_warn_mock]) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_hostname') ++ check_openvz_beans.get_hostname(123, 'irrelevant', 21).AndReturn('foo') ++ check_openvz_beans.get_hostname(234, 'irrelevant', 21).AndReturn('bar') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: FAIL: foo(123) WARN: bar(234)| FAIL: HOST foo(123): resource(+987) WARN: HOST bar(234): resource(+896)\n') ++ ++ def test___main___multifailwarnalert(self): ++ """Test the __main__ function -- failwarn alert.""" ++ beancounteralert_fail1_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterFailure) ++ beancounteralert_fail1_mock.uid = 123 ++ beancounteralert_fail1_mock.excess = 987 ++ beancounteralert_fail1_mock.resource = 'resource1' ++ beancounteralert_fail2_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterFailure) ++ beancounteralert_fail2_mock.uid = 123 ++ beancounteralert_fail2_mock.excess = 987 ++ beancounteralert_fail2_mock.resource = 'resource2' ++ beancounteralert_warn1_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterWarning) ++ beancounteralert_warn1_mock.uid = 234 ++ beancounteralert_warn1_mock.excess = 896 ++ beancounteralert_warn1_mock.resource = 'resource' ++ beancounteralert_warn2_mock = self.mox.CreateMock(check_openvz_beans.BeanCounterWarning) ++ beancounteralert_warn2_mock.uid = 345 ++ beancounteralert_warn2_mock.excess = 896 ++ beancounteralert_warn2_mock.resource = 'resource' ++ self.beancounterverifier_mock.verify(None, False).AndReturn([beancounteralert_fail1_mock, beancounteralert_fail2_mock, beancounteralert_warn1_mock, beancounteralert_warn2_mock]) ++ ++ self.mox.StubOutWithMock(check_openvz_beans, 'get_hostname') ++ check_openvz_beans.get_hostname(123, 'irrelevant', 21).AndReturn('foo') ++ check_openvz_beans.get_hostname(345, 'irrelevant', 21).AndReturn('baz') ++ check_openvz_beans.get_hostname(234, 'irrelevant', 21).AndReturn('bar') ++ ++ self.mox.ReplayAll() ++ ++ # FIXME: check the Exception value. assertRaisesRegexp() is only available in Python unittest 2.7+ ++ self.assertRaises(SystemExit, check_openvz_beans.__main__) ++ self.assertEqual(sys.stdout.getvalue(), 'CRITICAL: FAIL: foo(123) WARN: baz(345) bar(234)| FAIL: HOST foo(123): resource1(+987) resource2(+987) WARN: HOST baz(345): resource(+896) HOST bar(234): resource(+896)\n') ++ ++if __name__ == '__main__': ++ unittest.main() +diff -urN nothing/debian/changelog nagios-plugins-openvz-beans/debian/changelog +--- nothing/debian/changelog 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/debian/changelog 2011-11-01 18:30:10.247574999 +0100 +@@ -0,0 +1,5 @@ ++nagios-plugins-openvz-beans (0.5-0) stable; urgency=low ++ ++ * initial release packaging ++ ++ -- Andreas Kotes Thu, 01 Nov 2011 18:30:23 +0100 +diff -urN nothing/debian/compat nagios-plugins-openvz-beans/debian/compat +--- nothing/debian/compat 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/debian/compat 2011-10-17 14:23:00.655695188 +0200 +@@ -0,0 +1 @@ ++5 +diff -urN nothing/debian/control nagios-plugins-openvz-beans/debian/control +--- nothing/debian/control 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/debian/control 2011-11-01 16:54:48.381618568 +0100 +@@ -0,0 +1,9 @@ ++Source: nagios-plugins-openvz-beans ++Section: net ++Priority: extra ++Maintainer: Andreas Kotes ++ ++Package: nagios-plugins-openvz-beans ++Architecture: all ++Depends: python-minimal ++Description: Nagios Plugin to check OpenVZ Bean Counters +diff -urN nothing/debian/.gitignore nagios-plugins-openvz-beans/debian/.gitignore +--- nothing/debian/.gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/debian/.gitignore 2011-10-17 14:23:00.655695188 +0200 +@@ -0,0 +1,4 @@ ++files ++nagios-plugins-openvz-beans.debhelper.log ++nagios-plugins-openvz-beans.substvars ++nagios-plugins-openvz-beans/ +diff -urN nothing/debian/rules nagios-plugins-openvz-beans/debian/rules +--- nothing/debian/rules 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/debian/rules 2011-11-01 18:28:09.727238903 +0100 +@@ -0,0 +1,33 @@ ++#!/usr/bin/make -f ++DEBIANDIR=$(CURDIR)/debian ++ ++%: ++ dh $@ ++ ++install: build ++ dh_testdir ++ dh_testroot ++ dh_clean -k ++ dh_installdirs ++ ++ install -d -m0755 $(DEBIANDIR)/nagios-plugins-openvz-beans/usr/lib/nagios/plugins ++ install -m0755 check_openvz_beans.py $(DEBIANDIR)/nagios-plugins-openvz-beans/usr/lib/nagios/plugins ++ install -d -m0755 $(DEBIANDIR)/nagios-plugins-openvz-beans/usr/share/doc/nagios-plugins-openvz-beans ++ install -m0644 README $(DEBIANDIR)/nagios-plugins-openvz-beans/usr/share/doc/nagios-plugins-openvz-beans ++ ++# Build architecture-independent files here. ++binary-indep: build install ++ dh_testdir -i ++ dh_testroot -i ++ dh_installchangelogs -i ++ dh_installdocs -i ++ dh_link -i ++ dh_compress -i ++ dh_fixperms -i ++ dh_installdeb -i ++ dh_gencontrol -i ++ dh_md5sums -i ++ dh_builddeb -i ++ ++binary: binary-indep ++.PHONY: build clean binary-indep binary install +diff -urN nothing/.gitignore nagios-plugins-openvz-beans/.gitignore +--- nothing/.gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/.gitignore 2011-10-17 14:23:00.695695306 +0200 +@@ -0,0 +1 @@ ++*.pyc +diff -urN nothing/nagios-plugins-openvz-beans.spec nagios-plugins-openvz-beans/nagios-plugins-openvz-beans.spec +--- nothing/nagios-plugins-openvz-beans.spec 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/nagios-plugins-openvz-beans.spec 2011-11-01 16:54:35.621582988 +0100 +@@ -0,0 +1,34 @@ ++Name: nagios-plugins-openvz-beans ++Version: 0.5 ++Release: 0 ++Summary: Nagios Plugin to check OpenVZ Bean Counters ++License: GPL ++Group: Applications/System ++Source: check_openvz_beans.py ++ ++Autoreq: 0 ++BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root ++BuildArch: noarch ++Requires: python ++ ++%description ++Nagios Plugin to check OpenVZ Bean Counters ++ ++%prep ++rm -rf %{buildroot} ++ ++%install ++install -d -m0755 %{buildroot}%{_libdir}/nagios/plugins/contrib/ ++install -m0755 %{_sourcefile} %{buildroot}%{_libdir}/nagios/plugins/contrib/ ++ ++ ++%clean ++rm -rf %{buildroot} ++ ++%files ++%dir %{_libdir}/nagios/plugins/contrib ++%attr(755, root, root) %{_libdir}/nagios/plugins/contrib/check_openvz_beans.py ++ ++%changelog ++* Thu Oct 13 2011 Andreas Kotes 0.5 ++ - initial release packaging +diff -urN nothing/README nagios-plugins-openvz-beans/README +--- nothing/README 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/README 2011-11-01 18:04:40.633309403 +0100 +@@ -0,0 +1,75 @@ ++Nagios check for OpenVZ bean counters ++===================================== ++ ++General ++------- ++ ++This Nagios plugin allows to define and check for thresholds against bean ++counters defined in /proc/user_beancounters, which are available in both OpenVZ ++hypervisors and VMs. ++ ++It's possible to set global thresholds via '-c' (for critical) and '-w' (for ++warning) which apply to all resources checked. ++ ++Tresholds for individual resources can be set by using '-C'/'-W' and giving ++comma-separated key:value pairs. ++ ++The script was written to be compatible with Python 2.4 and later. ++ ++Reading /proc/user_beancounters ++------------------------------- ++ ++Since /proc/user_beancounters is only readable by the root user - and running ++Nagios plugins as the root user is highly discouraged - you can either copy ++this file and check against the copy using the -f option. Or - if you have set ++up your /etc/sudoers file to allow it - you can use the -s option, which lets ++check_openvz_beans use 'sudo cat /proc/user_beancounters' to read the file. ++ ++Hostname handling ++----------------- ++The OpenVZ context IDs are resolved by grepping for the HOSTNAME variable in ++the uid's config file found in the path given by '-p'. ++ ++Hostnames (e.g. this.is.a.very.long.hostname) are shortened to their first two ++components per default (e.g. this.is for the former one), but this length can ++be configured using -d (e.g. '-d 1' for 'this', '-d 3' for 'this.is.a'), ++allowing you to identify the affected VM(s) in the Nagios alert message ++already. ++ ++Output ++------ ++ ++The output follows the Nagios Plugin API 3.0, i.e. the script gives the proper ++exit codes (0 = OK, 1 = Warning, 2 = Critical, 3 = Unknown), a simple single ++line of text, and additional perf-data. ++ ++The single line of text informs about WARNING or CRITICAL state, and what's a ++problem: ++ ++FAIL - a resource against its limit and the was blocked by kernel ++OVER - a resource was over its relevant threshold and will cause problems ++CRIT - a resource ran close to its threshold by given (critical) percentage ++WARN - a resource ran close to its threshold by given (warning) percentage ++ ++Data used ++--------- ++ ++The value checked for each resource is the 'held' value, but you could use '-m' ++to use the 'maxheld' value instead. You'll not be able to reset that value, ++though, so any Nagios warning/failure status will stay until the next ++hypervisor reboot. ++ ++Failure counters can't be reset either, but the plugin reads the data stored by ++vzubc's relative mode, i.e. if you inspect the problem with 'vzubc -r', the ++critical status will be resolved. This behaviour can be turned off with '-a'. ++ ++If you are storing data somewhere else than the default '/tmp/vzubc.store', you ++can change that via '-u'. ++ ++vzubc is provided by the vzctl package which isn't used by this code directly, ++nor is there a dependency - you'll have to install it yourself if you want to ++use this functionality. ++ ++Each group lists the hostname & uid of the VM in the regular message, ++additionally the resource name and how much its threshold was exeeded are given ++in the perfdata line. +diff -urN nothing/README.source nagios-plugins-openvz-beans/README.source +--- nothing/README.source 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/README.source 2011-11-01 16:29:20.667358270 +0100 +@@ -0,0 +1,16 @@ ++The implementation can be tested by calling its test scripts ++./check_openvz_beans-test.py, which runs unit tests for almost all of its code, ++and requires Python unittest >= 2.4 as well as pymox. ++ ++Current code coverage of the unit tests is >95%. ++ ++RPMs can be build using the following commandline: ++ ++rpmbuild -bb -D "_sourcefile `pwd`/check_openvz_beans.py" nagios-plugins-openvz-beans.spec ++ ++Debian / Ubuntu packages can be build by simply calling: ++ ++dpkg-buildpackage ++ ++... in both cases the proper developer tools for the corresponding distribution ++have to be installed. +diff -urN nothing/testdata/10.conf nagios-plugins-openvz-beans/testdata/10.conf +--- nothing/testdata/10.conf 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/testdata/10.conf 2011-11-01 19:09:28.124150356 +0100 +@@ -0,0 +1 @@ ++HOSTNAME="vmokay.pr.foo.test.your.do.main" +diff -urN nothing/testdata/60.conf nagios-plugins-openvz-beans/testdata/60.conf +--- nothing/testdata/60.conf 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/testdata/60.conf 2011-11-01 19:09:32.834163485 +0100 +@@ -0,0 +1 @@ ++HOSTNAME="vmover1.st.foo.test.your.do.main" +diff -urN nothing/testdata/hostcrit.bcs nagios-plugins-openvz-beans/testdata/hostcrit.bcs +--- nothing/testdata/hostcrit.bcs 1970-01-01 01:00:00.000000000 +0100 ++++ nagios-plugins-openvz-beans/testdata/hostcrit.bcs 2011-11-01 19:07:53.643886880 +0100 +@@ -0,0 +1,170 @@ ++Version: 2.5 ++ uid resource held maxheld barrier limit failcnt ++ 40: kmemsize 12345678 33456789 34567890 40000000 0 ++ lockedpages 0 5859 32768 65536 0 ++ privvmpages 1234567 2345678 3276800 9223372036854775807 0 ++ shmpages 688 1344 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 0 0 0 ++ numproc 75 88 8000 8000 0 ++ physpages 199301 239798 0 9223372036854775807 0 ++ vmguarpages 0 0 4194304 9223372036854775807 0 ++ oomguarpages 199301 239798 4186112 9223372036854775807 0 ++ numtcpsock 16 21 9223372036854775807 9223372036854775807 0 ++ numflock 4 14 200 220 0 ++ numpty 1 2 64 64 0 ++ numsiginfo 0 9 512 512 0 ++ tcpsndbuf 278016 547280 2703360 9223372036854775807 0 ++ tcprcvbuf 262144 769968 2703360 9223372036854775807 0 ++ othersockbuf 158304 197424 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 58680 262144 262144 0 ++ numothersock 115 125 360 360 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 1655 1958 9312 9312 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ numiptent 20 20 128 128 0 ++ 20: kmemsize 12345678 23456789 34567890 40000000 0 ++ lockedpages 0 5859 32768 65536 0 ++ privvmpages 1234567 2345678 3276800 9223372036854775807 3 ++ shmpages 688 1344 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 0 0 0 ++ numproc 75 88 8000 8000 0 ++ physpages 199301 239798 0 9223372036854775807 0 ++ vmguarpages 0 0 4194304 9223372036854775807 0 ++ oomguarpages 199301 239798 4186112 9223372036854775807 0 ++ numtcpsock 16 21 9223372036854775807 9223372036854775807 0 ++ numflock 4 14 200 220 0 ++ numpty 1 2 64 64 0 ++ numsiginfo 0 9 512 512 0 ++ tcpsndbuf 278016 547280 2703360 9223372036854775807 0 ++ tcprcvbuf 262144 769968 2703360 9223372036854775807 0 ++ othersockbuf 158304 197424 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 58680 262144 262144 0 ++ numothersock 115 125 360 360 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 1655 1958 9312 9312 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ numiptent 20 20 128 128 0 ++ 30: kmemsize 12345678 23456789 34567890 40000000 0 ++ lockedpages 0 5859 32768 65536 0 ++ privvmpages 1234567 2345678 3276800 9223372036854775807 3 ++ shmpages 688 1344 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 0 0 0 ++ numproc 75 88 100 120 2 ++ physpages 199301 239798 0 9223372036854775807 0 ++ vmguarpages 0 0 4194304 9223372036854775807 0 ++ oomguarpages 199301 239798 4186112 9223372036854775807 0 ++ numtcpsock 16 21 9223372036854775807 9223372036854775807 0 ++ numflock 4 14 200 220 0 ++ numpty 1 2 64 64 0 ++ numsiginfo 0 9 512 512 0 ++ tcpsndbuf 278016 547280 2703360 9223372036854775807 0 ++ tcprcvbuf 262144 769968 2703360 9223372036854775807 0 ++ othersockbuf 158304 197424 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 58680 262144 262144 0 ++ numothersock 115 125 360 360 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 1655 1958 9312 9312 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ numiptent 20 20 128 128 0 ++ 10: kmemsize 12345678 30456789 34567890 40000000 0 ++ lockedpages 0 5859 32768 65536 0 ++ privvmpages 1234567 2345678 3276800 9223372036854775807 0 ++ shmpages 688 1344 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 0 0 0 ++ numproc 75 88 8000 8000 0 ++ physpages 199301 239798 0 9223372036854775807 0 ++ vmguarpages 0 0 4194304 9223372036854775807 0 ++ oomguarpages 199301 239798 4186112 9223372036854775807 0 ++ numtcpsock 16 21 9223372036854775807 9223372036854775807 0 ++ numflock 4 14 200 220 0 ++ numpty 1 2 64 64 0 ++ numsiginfo 0 9 512 512 0 ++ tcpsndbuf 278016 547280 2703360 9223372036854775807 0 ++ tcprcvbuf 262144 769968 2703360 9223372036854775807 0 ++ othersockbuf 158304 197424 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 58680 262144 262144 0 ++ numothersock 115 125 360 360 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 1655 1958 9312 9312 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ numiptent 20 20 128 128 0 ++ 50: kmemsize 12345678 31456789 34567890 40000000 0 ++ lockedpages 0 5859 32768 65536 0 ++ privvmpages 1234567 2345678 3276800 9223372036854775807 0 ++ shmpages 688 1344 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 0 0 0 ++ numproc 75 88 8000 8000 0 ++ physpages 199301 239798 0 9223372036854775807 0 ++ vmguarpages 0 0 4194304 9223372036854775807 0 ++ oomguarpages 199301 239798 4186112 9223372036854775807 0 ++ numtcpsock 16 21 9223372036854775807 9223372036854775807 0 ++ numflock 4 14 200 220 0 ++ numpty 1 2 64 64 0 ++ numsiginfo 0 9 512 512 0 ++ tcpsndbuf 278016 547280 2703360 9223372036854775807 0 ++ tcprcvbuf 262144 769968 2703360 9223372036854775807 0 ++ othersockbuf 158304 197424 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 58680 262144 262144 0 ++ numothersock 115 125 360 360 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 1655 1958 9312 9312 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ numiptent 20 20 128 128 0 ++ 60: kmemsize 12345678 40000001 34567890 40000000 0 ++ lockedpages 0 5859 32768 65536 0 ++ privvmpages 1234567 2345678 3276800 9223372036854775807 0 ++ shmpages 688 1344 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 0 0 0 ++ numproc 75 88 8000 8000 0 ++ physpages 199301 239798 0 9223372036854775807 0 ++ vmguarpages 0 0 4194304 9223372036854775807 0 ++ oomguarpages 199301 239798 4186112 9223372036854775807 0 ++ numtcpsock 16 21 9223372036854775807 9223372036854775807 0 ++ numflock 4 14 200 220 0 ++ numpty 1 2 64 64 0 ++ numsiginfo 0 9 512 512 0 ++ tcpsndbuf 278016 547280 2703360 9223372036854775807 0 ++ tcprcvbuf 262144 769968 2703360 9223372036854775807 0 ++ othersockbuf 158304 197424 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 58680 262144 262144 0 ++ numothersock 115 125 360 360 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 1655 1958 9312 9312 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ dummy 0 0 0 0 0 ++ numiptent 20 20 128 128 0 ++ 0: kmemsize 15408521 33415719 9223372036854775807 9223372036854775807 0 ++ lockedpages 8789 12353 9223372036854775807 9223372036854775807 0 ++ privvmpages 41072 104930 9223372036854775807 9223372036854775807 0 ++ shmpages 730 1706 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 9223372036854775807 9223372036854775807 0 ++ numproc 291 472 9223372036854775807 9223372036854775807 0 ++ physpages 9432 54303 9223372036854775807 9223372036854775807 0 ++ vmguarpages 0 0 9223372036854775807 9223372036854775807 0 ++ oomguarpages 9432 54303 9223372036854775807 9223372036854775807 0 ++ numtcpsock 13 21 9223372036854775807 9223372036854775807 0 ++ numflock 5 22 9223372036854775807 9223372036854775807 0 ++ numpty 1 1 9223372036854775807 9223372036854775807 0 ++ numsiginfo 0 6 9223372036854775807 9223372036854775807 0 ++ tcpsndbuf 773048 924800 9223372036854775807 9223372036854775807 0 ++ tcprcvbuf 212992 854408 9223372036854775807 9223372036854775807 0 ++ othersockbuf 204864 283784 9223372036854775807 9223372036854775807 0 ++ dgramrcvbuf 0 16944 9223372036854775807 9223372036854775807 0 ++ numothersock 178 225 9223372036854775807 9223372036854775807 0 ++ dcachesize 0 0 9223372036854775807 9223372036854775807 0 ++ numfile 5141 6779 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 9223372036854775807 9223372036854775807 0 ++ dummy 0 0 9223372036854775807 9223372036854775807 0 ++ numiptent 51 51 9223372036854775807 9223372036854775807 0 -- cgit v1.2.3-74-g34f1