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 <andreas.kotes@nokia.com>
+#
+# Reviewed-by: Pascal Hahn <pascal.hahn@nokia.com>
+# Signed-Off-by: Pascal Hahn <pascal.hahn@nokia.com>
+# Signed-Off-by: Jessvin Thomas <jessvin.thomas@nokia.com>
+#
+
+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 <andreas.kotes@nokia.com>')
+
+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<resource>\S+)                  # resource name
+    \s*(?P<held>\d+)                      # held count
+    \s*(?P<maxheld>\d+)                   # maximum held
+    \s*(?P<barrier>\d+)                   # barrier
+    \s*(?P<limit>\d+)                     # limit
+    \s*(?P<failcnt>\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 ('<BeanCounter for uid %d resource %s: held %d maxheld %d barrier %d limit %d failcnt %d>' %
+           (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<uid>\d+):                      # group / context number
+    (?P<beancounters>[^:]*)$              # 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 ('<BeanCounterThreshold for resource %s: critical %d warning %d>' %
+           (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 <uid>.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 <uid>.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 <andreas.kotes@nokia.com>'
+
+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__(),
+      '<BeanCounter for uid 123 resource dummy: held 1 maxheld 2 barrier 3 limit 4 failcnt 5>')
+    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__(),
+      '<BeanCounterThreshold for resource *: critical 95 warning 90>')
+
+  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__(),
+      '<BeanCounterThreshold for resource dummy: critical 70 warning 60>')
+
+  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__(),
+      '<BeanCounterViolation VIOL: resource dummy in context 123 by 10>')
+
+
+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__(),
+      '<BeanCounterFailure FAIL: resource dummy in context 123 by 10>')
+
+
+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__(),
+      '<BeanCounterOvershoot OVER: resource dummy in context 123 by 10>')
+
+
+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__(),
+      '<BeanCounterCritical CRIT: resource dummy in context 123 by 10>')
+
+
+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__(),
+      '<BeanCounterWarning WARN: resource dummy in context 123 by 10>')
+
+
+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 <andreas.kotes@nokia.com>  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 <andreas.kotes@nokia.com>
+
+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 <andreas.kotes@nokia.com> 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
