Source code for syscheck.monitor
import sys
from collections import OrderedDict
from uuid import uuid4
from tornado.ioloop import IOLoop
from tornado import gen
from . import logger
from .checker import Checker
[docs]class SystemsMonitor(object):
"""Monitors multiple systems for yes/no status."""
def __init__(self, loop=None):
self.checkers = OrderedDict()
self.categories = []
self.loop = loop or IOLoop.instance()
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
if 'win' in sys.platform:
self.shutdown(wait=False)
else:
self.terminate()
def close(self):
pass
def _add_checker(self, checker, name, description, category, warn):
self.checkers[name] = {
'checker': checker,
'name': name,
'description': description,
'category': category,
'warn': warn
}
if category not in self.categories:
self.categories.append(category)
[docs] def register(self, checker, description='', category='Systems',
warn=False):
"""Register a new system checker.
:param syscheck.Checker checker:
:param str description:
:param str category:
:param bool warn: flag as a warning when the check returns
False
"""
assert isinstance(checker, Checker)
assert isinstance(description, str)
assert isinstance(category, str)
name = str(uuid4())
if description == '':
description = checker.__class__.__name__
self._add_checker(checker, name, description, category, warn)
[docs] def register_category(self, category, checkers):
"""Register a group of checkers all belonging to one
category.
:param str category: name of the category
:param list checkers: list tuples containing Checkers and
(optionally) descriptions and warning
status
Example::
monitor.register_category(
'Category',
[
(DummyChecker(), 'First dummy checker'),
(DummyChecker(), 'Second dummy checker', True)
]
)
"""
assert isinstance(category, str)
assert isinstance(checkers, (tuple, list))
for checker in checkers:
if not isinstance(checker, (tuple, list)):
raise RuntimeError(
"Register categories with tuples: (checker, description)")
description = checker[0].__class__.__name__ if len(checker) is 1 else checker[1]
warn = checker[-1] if len(checker) is 3 else False
self.register(checker[0], description, category, warn)
[docs] def get_categories(self):
"""Return a list of unique checker categories."""
return self.categories
[docs] def jsonize(self):
"""Return a JSON-serializable version of the ``checkers``
dict, i.e., remove the Checker object from each item.
"""
checkers = OrderedDict()
for checker in self.checkers.keys():
current = self.checkers[checker]
checkers[current['name']] = {
key: current[key] for key in current if key != 'checker'
}
return checkers
@gen.coroutine
def _check_one(self, checker):
result = yield gen.maybe_future(checker.check())
raise gen.Return(result)
@gen.coroutine
[docs] def check(self, timeout=5.0):
"""Check the status of all systems.
:param float timeout: time before assuming a system is down in
seconds.
"""
checkers = [self.checkers[name]['checker'] for name in self.checkers]
waiter = gen.WaitIterator(*[self._check_one(checker) for checker in checkers])
statuses = [False]*len(checkers)
while not waiter.done():
try:
result = yield waiter.next()
except Exception as error:
result = False
print("Error {} from {}".format(error, waiter.current_future))
statuses[waiter.current_index] = result
raise gen.Return(statuses)