def setUp(self, signal):
     self.tmpdir = tempfile.mkdtemp(prefix="test-connector-metro-")
     client = ClientStub("testhostname", None, None)
     rrd_base_dir = os.path.join(self.tmpdir, "rrds")
     os.mkdir(rrd_base_dir)
     confdb = MetroConfDB(os.path.join(os.path.dirname(__file__),
                                       "connector-metro.db"))
     self.rrdtool_pool = RRDToolPoolManagerStub(rrd_base_dir,
                 "flat", "/usr/bin/rrdtool")
     rrdtool = RRDToolManager(self.rrdtool_pool, confdb)
     threshold_checker = ThresholdChecker(rrdtool, confdb)
     self.btr = BusToRRDtool(confdb, rrdtool, threshold_checker)
     self.btr.setClient(client)
     d = self.btr.startService()
     d.addCallback(lambda _x: confdb.reload())
     return d
示例#2
0
def makeService(options):
    """ the service that wraps everything the connector needs. """
    from vigilo.connector.options import getSettings, parseSubscriptions

    settings = getSettings(options, __name__)

    from vigilo.common.logging import get_logger

    LOGGER = get_logger(__name__)

    from vigilo.common.gettext import translate

    _ = translate(__name__)

    from vigilo.connector.client import client_factory
    from vigilo.connector.handlers import buspublisher_factory

    from vigilo.connector_metro.rrdtool import RRDToolPoolManager
    from vigilo.connector_metro.rrdtool import RRDToolManager
    from vigilo.connector_metro.confdb import MetroConfDB
    from vigilo.connector_metro.threshold import ThresholdChecker
    from vigilo.connector_metro.bustorrdtool import BusToRRDtool

    root_service = service.MultiService()

    # Client du bus
    client = client_factory(settings)
    client.setServiceParent(root_service)
    providers = []

    # Configuration
    try:
        conffile = settings["connector-metro"]["config"]
    except KeyError:
        LOGGER.error(
            _("Please set the path to the configuration " "database generated by VigiConf in the settings.ini.")
        )
        sys.exit(1)
    confdb = MetroConfDB(conffile)
    confdb.setServiceParent(root_service)

    try:
        must_check_th = settings["connector-metro"].as_bool("check_thresholds")
    except KeyError:
        must_check_th = True

    # Gestion RRDTool
    rrd_base_dir = settings["connector-metro"]["rrd_base_dir"]
    rrd_path_mode = settings["connector-metro"]["rrd_path_mode"]
    rrd_bin = settings["connector-metro"].get("rrd_bin", "/usr/bin/rrdtool")
    rrdcached = settings["connector-metro"].get("rrdcached", None)
    try:
        pool_size = settings["connector-metro"].as_int("rrd_processes")
    except KeyError:
        pool_size = None
    rrdtool_pool = RRDToolPoolManager(
        rrd_base_dir, rrd_path_mode, rrd_bin, check_thresholds=must_check_th, rrdcached=rrdcached, pool_size=pool_size
    )
    rrdtool = RRDToolManager(rrdtool_pool, confdb)

    # Gestion des seuils
    if must_check_th:
        threshold_checker = ThresholdChecker(rrdtool, confdb)
        bus_publisher = buspublisher_factory(settings, client)
        bus_publisher.registerProducer(threshold_checker, streaming=True)
        providers.append(bus_publisher)
    else:
        threshold_checker = None

    # Gestionnaire principal des messages
    bustorrdtool = BusToRRDtool(confdb, rrdtool, threshold_checker)
    bustorrdtool.setClient(client)
    subs = parseSubscriptions(settings)
    queue = settings["bus"]["queue"]
    queue_messages_ttl = int(settings["bus"].get("queue_messages_ttl", 0))
    bustorrdtool.subscribe(queue, queue_messages_ttl, subs)
    providers.append(bustorrdtool)

    # Statistiques
    from vigilo.connector.status import statuspublisher_factory

    status_publisher = statuspublisher_factory(settings, client, providers=providers)

    return root_service
 def setUp(self):
     self.btr = BusToRRDtool(Mock(), Mock(), Mock())
     self.btr.rrdtool.start.return_value = defer.succeed(None)
     self.btr.rrdtool.stop.return_value = defer.succeed(None)
     return self.btr.startService()
class FunctionalTestCase(unittest.TestCase):
    """
    Vérification que le passage d'un message produit bien un fichier RRD.
    (création du fichier)
    """


    @deferred(timeout=30)
    @patch('signal.signal') # erreurs de threads
    def setUp(self, signal):
        self.tmpdir = tempfile.mkdtemp(prefix="test-connector-metro-")
        client = ClientStub("testhostname", None, None)
        rrd_base_dir = os.path.join(self.tmpdir, "rrds")
        os.mkdir(rrd_base_dir)
        confdb = MetroConfDB(os.path.join(os.path.dirname(__file__),
                                          "connector-metro.db"))
        self.rrdtool_pool = RRDToolPoolManagerStub(rrd_base_dir,
                    "flat", "/usr/bin/rrdtool")
        rrdtool = RRDToolManager(self.rrdtool_pool, confdb)
        threshold_checker = ThresholdChecker(rrdtool, confdb)
        self.btr = BusToRRDtool(confdb, rrdtool, threshold_checker)
        self.btr.setClient(client)
        d = self.btr.startService()
        d.addCallback(lambda _x: confdb.reload())
        return d

    @deferred(timeout=30)
    def tearDown(self):
        d = self.btr.stopService()
        d.addCallback(lambda _x: rmtree(self.tmpdir))
        return d


    @deferred(timeout=30)
    def test_handled_host(self):
        """Functionnal: messages sur des hôtes déclarés."""

        rrdfile = os.path.join(self.tmpdir, "rrds",
                               "server1.example.com", "Load.rrd")
        # on vérifie que le fichier n'existe pas encore
        # (ce qui lève une exception quand on teste le fichier).
        self.assertRaises(OSError, os.stat, rrdfile)
        msg = { "type": "perf",
                "timestamp": "1165939739",
                "host": "server1.example.com",
                "datasource": "Load",
                "value": "12",
                }
        d = self.btr.processMessage(msg)
        # on vérifie que le fichier correspondant a bien été créé
        def check_created(r):
            self.assertTrue(os.path.exists(rrdfile),
                            "Le fichier n'a pas été créé")
            self.assertTrue(stat.S_ISREG(os.stat(rrdfile).st_mode))
        def check_creation_command(r):
            self.assertTrue(len(self.rrdtool_pool.commands) > 0)
            self.assertEqual(self.rrdtool_pool.commands[0],
                    ('create', rrdfile,
                    ['--step', '300', '--start', '1165939729',
                     'RRA:AVERAGE:0.5:1:600', 'RRA:AVERAGE:0.5:6:700',
                     'RRA:AVERAGE:0.5:24:775', 'RRA:AVERAGE:0.5:288:732',
                     'DS:DS:GAUGE:600:U:U']))
        def check_update_command(r):
            self.assertEqual(self.rrdtool_pool.commands[1],
                             ('update', rrdfile, '1165939739:12'))
        d.addCallback(check_created)
        d.addCallback(check_creation_command)
        d.addCallback(check_update_command)
        return d
class BusToRRDtoolTestCase(unittest.TestCase):
    """
    Vérification que le passage d'un message produit bien un fichier RRD.
    (création du fichier)
    """

    @deferred(timeout=30)
    def setUp(self):
        self.btr = BusToRRDtool(Mock(), Mock(), Mock())
        self.btr.rrdtool.start.return_value = defer.succeed(None)
        self.btr.rrdtool.stop.return_value = defer.succeed(None)
        return self.btr.startService()

    @deferred(timeout=30)
    def tearDown(self):
        return self.btr.stopService()

    @deferred(timeout=30)
    def test_handled_host(self):
        """Prise en compte de messages sur des hôtes déclarés."""
        msg = {
            "type": "perf",
            "timestamp": "1165939739",
            "host": "server1.example.com",
            "datasource": "Load",
            "value": "12",
            "has_thresholds": True,
        }
        self.btr.confdb.has_host.return_value = defer.succeed(True)
        self.btr.threshold_checker.hasThreshold.return_value = msg
        self.btr.rrdtool.createIfNeeded.return_value = msg
        self.btr.rrdtool.processMessage.return_value = msg
        d = self.btr.processMessage(msg)

        def check(r):
            self.assertTrue(self.btr.rrdtool.createIfNeeded.called)
            self.assertTrue(self.btr.rrdtool.processMessage.called)
            self.assertTrue(self.btr.threshold_checker.hasThreshold.called)
            self.assertTrue(self.btr.threshold_checker.checkMessage.called)

        d.addCallback(check)
        return d

    @deferred(timeout=30)
    def test_non_existing_host(self):
        """Reception d'un message pour un hôte absent du fichier de conf"""
        msg = {
            "type": "perf",
            "timestamp": "123456789",
            "host": "dummy_host",
            "datasource": "dummy_datasource",
            "value": "42",
        }
        self.btr.confdb.has_host.return_value = defer.succeed(False)
        d = self.btr._parse_message(msg)

        def check_failure(f):
            self.assertFalse(self.btr.rrdtool.createIfNeeded.called)
            self.assertFalse(self.btr.rrdtool.processMessage.called)
            if not isinstance(f.value, NotInConfiguration):
                self.fail("Raised exeception is not of the right type (got %s)" % type(f.value))

        d.addCallbacks(lambda x: self.fail("No exception raised"), check_failure)
        return d

    @deferred(timeout=30)
    def test_wrong_message_type_1(self):
        """Réception d'un autre message que perf (_parse_message)"""
        msg = {
            "type": "event",
            "timestamp": "1165939739",
            "host": "host",
            "service": "service",
            "status": "CRITICAL",
            "message": "message",
        }
        d = self.btr._parse_message(msg)

        def cb(r):
            self.fail("Il y aurait dû y avoir un errback")

        def eb(f):
            self.assertEqual(f.type, WrongMessageType)

        d.addCallbacks(cb, eb)
        return d

    @deferred(timeout=30)
    def test_wrong_message_type_2(self):
        """Réception d'un autre message que perf (processMessage)"""
        msg = {
            "type": "event",
            "timestamp": "1165939739",
            "host": "host",
            "service": "service",
            "status": "CRITICAL",
            "message": "message",
        }
        self.btr.confdb.has_host.return_value = defer.succeed(True)
        d = self.btr.processMessage(msg)

        def cb(r):
            self.assertFalse(self.btr.rrdtool.createIfNeeded.called)
            self.assertFalse(self.btr.rrdtool.run.called)
            self.assertEqual(self.btr._messages_received, -1)

        d.addCallback(cb)
        return d

    @deferred(timeout=30)
    def test_invalid_message_1(self):
        """Réception d'un message invalide (_parse_message)"""
        msg = {
            "type": "perf",
            "timestamp": "1165939739",
            "host": "server1.example.com",
            # pas de clé datasource
            "value": "12",
        }
        d = self.btr._parse_message(msg)

        def cb(r):
            self.fail("Il y aurait dû y avoir un errback")

        def eb(f):
            self.assertEqual(f.type, InvalidMessage)

        d.addCallbacks(cb, eb)
        return d

    @deferred(timeout=30)
    def test_invalid_message_2(self):
        """Réception d'un message invalide (processMessage)"""
        msg = {
            "type": "perf",
            "timestamp": "1165939739",
            "host": "server1.example.com",
            # pas de clé datasource
            "value": "12",
        }
        d = self.btr.processMessage(msg)

        def cb(r):
            self.assertFalse(self.btr.rrdtool.createIfNeeded.called)
            self.assertFalse(self.btr.rrdtool.run.called)

        d.addCallback(cb)
        return d

    @deferred(timeout=30)
    def test_valid_values(self):
        """Réception d'un message avec une valeur valide"""
        self.btr.confdb.has_host.return_value = defer.succeed(True)
        msg_tpl = {"type": "perf", "timestamp": "1165939739", "host": "server1.example.com", "datasource": "Load"}
        valid_values = ["1", "1.2", "U"]
        dl = []
        for value in valid_values:
            msg = msg_tpl.copy()
            msg["value"] = value
            d = self.btr._parse_message(msg)
            dl.append(d)
        return defer.DeferredList(dl, fireOnOneErrback=True)

    @deferred(timeout=30)
    def test_invalid_value_1(self):
        """Réception d'un message avec une valeur invalide (#802)"""
        msg = {
            "type": "perf",
            "timestamp": "1165939739",
            "host": "server1.example.com",
            "datasource": "Load",
            "value": "Invalid value",
        }
        d = self.btr._parse_message(msg)

        def cb(r):
            self.fail("Il y aurait du y avoir un errback")

        def eb(f):
            self.assertEqual(f.type, InvalidMessage)

        d.addCallbacks(cb, eb)
        return d

    @deferred(timeout=30)
    def test_stats(self):
        """Statistiques"""
        self.btr.confdb.count_datasources.return_value = defer.succeed(4)
        d = self.btr.getStats()

        def cb(r):
            self.assertEqual(r, {"received": 0, "pds_count": 4, "illegal_updates": 0})

        d.addCallback(cb)
        return d

    @deferred(timeout=30)
    def test_no_check_thresholds(self):
        """Désactivation de la vérification des seuils"""
        msg = {"type": "perf", "timestamp": "1165939739", "host": "Host éçà", "datasource": "PDS éçà", "value": "42"}
        self.btr.threshold_checker = None
        d = defer.maybeDeferred(self.btr._check_has_thresholds, msg)

        def check(new_msg):
            self.assertTrue("has_thresholds" in new_msg)
            self.assertFalse(new_msg["has_thresholds"])

        d.addCallback(check)
        return d