def test_wait_before_retry(self): must_stop = mock.Mock() stdout_consumer = ( ConsumerRegister.get_consumer('Stdout')['consumer_cls']({})) stdout_consumer._wait_before_retry(must_stop) must_stop.wait.assert_called_once_with( timeout=stdout_consumer.retry_delay)
def test_wait_before_retry(self, time_mock): must_stop = threading.Event() stdout_consumer = ( ConsumerRegister.get_consumer('Stdout')['consumer_cls']({})) stdout_consumer._wait_before_retry(must_stop) time_mock.sleep.assert_called_with(1) self.assertEquals(time_mock.sleep.call_count, stdout_consumer.retry_delay)
def launch(self): """Launch sauna daemon Start consumers and producer threads. """ signal.signal(signal.SIGTERM, self.term_handler) signal.signal(signal.SIGINT, self.term_handler) consumers_threads = [] for consumer_data in self.consumers: consumer_name = consumer_data['type'] consumer_info = ConsumerRegister.get_consumer(consumer_name) if not consumer_info: print('Plugin {} does not exist'.format(consumer_name)) exit(1) try: consumer = consumer_info['consumer_cls'](consumer_data) except DependencyError as e: print(str(e)) self.term_handler() exit(1) if isinstance(consumer, QueuedConsumer): consumer_queue = queue.Queue() self._consumers_queues.append(consumer_queue) else: consumer_queue = None consumer_thread = threading.Thread( name='consumer_{}'.format(consumer_name), target=consumer.run, args=(self.must_stop, consumer_queue) ) consumer_thread.start() consumers_threads.append(consumer_thread) logging.debug( 'Running consumer {}'.format(consumer_name) ) producer = threading.Thread( name='producer', target=self.run_producer ) producer.start() producer.join() self.term_handler() for consumer_thread in consumers_threads: consumer_thread.join() logging.debug('Exited main thread')
def launch(self): """Launch sauna daemon Start consumers and producer threads. """ signal.signal(signal.SIGTERM, self.term_handler) signal.signal(signal.SIGINT, self.term_handler) consumers_threads = [] for consumer_data in self.consumers: consumer_name = consumer_data['type'] consumer_info = ConsumerRegister.get_consumer(consumer_name) if not consumer_info: print('Plugin {} does not exist'.format(consumer_name)) sys.exit(1) try: consumer = consumer_info['consumer_cls'](consumer_data) except DependencyError as e: print(str(e)) self.term_handler() sys.exit(1) if isinstance(consumer, QueuedConsumer): consumer_queue = queue.Queue() self._consumers_queues.append(consumer_queue) else: consumer_queue = None consumer_thread = threading.Thread( name='consumer_{}'.format(consumer_name), target=consumer.run, args=(self.must_stop, consumer_queue) ) consumer_thread.start() consumers_threads.append(consumer_thread) logger.debug( 'Running consumer {}'.format(consumer_name) ) producer = threading.Thread( name='producer', target=self.run_producer ) producer.start() producer.join() self.term_handler() for consumer_thread in consumers_threads: consumer_thread.join() logger.debug('Exited main thread')
def launch(self): # Start producer and consumer threads producer = threading.Thread(name='producer', target=self.run_producer) producer.start() consumers_threads = [] for consumer_name, consumer_config in self.config['consumers'].items(): consumer_info = ConsumerRegister.get_consumer(consumer_name) if not consumer_info: print('Plugin {} does not exist'.format(consumer_name)) exit(1) try: consumer = consumer_info['consumer_cls'](consumer_config) except DependencyError as e: print(str(e)) exit(1) if isinstance(consumer, QueuedConsumer): consumer_queue = queue.Queue() self._consumers_queues.append(consumer_queue) else: consumer_queue = None consumer_thread = threading.Thread( name='consumer_{}'.format(consumer_name), target=consumer.run, args=(self.must_stop, consumer_queue)) consumer_thread.start() consumers_threads.append(consumer_thread) logging.debug('Running {} with {}'.format(consumer_name, consumer_config)) signal.signal(signal.SIGTERM, self.term_handler) signal.signal(signal.SIGINT, self.term_handler) producer.join() self.term_handler() for consumer_thread in consumers_threads: consumer_thread.join() logging.debug('Exited main thread')
def test_get_consumer(self): stdout_consumer = ConsumerRegister.get_consumer('Stdout') self.assert_(issubclass(stdout_consumer['consumer_cls'], base.Consumer)) must_be_none = ConsumerRegister.get_consumer('Unknown') self.assertIsNone(must_be_none)
from sauna.consumers.base import QueuedConsumer from sauna.consumers import ConsumerRegister my_consumer = ConsumerRegister('HTTP') @my_consumer.consumer() class HTTPConsumer(QueuedConsumer): def __init__(self, config): super().__init__(config) try: import requests self.requests = requests except ImportError: from ... import DependencyError raise DependencyError(self.__class__.__name__, 'requests', 'requests', 'python3-requests') self.config = { 'url': config.get('url', 'http://localhost'), 'timeout': config.get('timeout', 60), 'headers': config.get('headers', None) } def _send(self, service_check): data = { 'timestamp': service_check.timestamp, 'hostname': service_check.hostname, 'service': service_check.name, 'status': service_check.status, 'output': service_check.output }
from sauna.consumers.base import QueuedConsumer from sauna.consumers import ConsumerRegister my_consumer = ConsumerRegister('Stdout') @my_consumer.consumer() class StdoutConsumer(QueuedConsumer): def _send(self, service_check): print(service_check) @staticmethod def config_sample(): return ''' # Just prints checks on the standard output Stdout: '''
import socket import select from collections import defaultdict from sauna.consumers.base import AsyncConsumer from sauna.consumers import ConsumerRegister my_consumer = ConsumerRegister('TCPServer') @my_consumer.consumer() class TCPServerConsumer(AsyncConsumer): service_checks = {} def __init__(self, config): super().__init__(config) self.config = { 'port': config.get('port', 5555), 'backlog': config.get('port', 128), 'keepalive': config.get('keepalive', True) } self.read_wanted, self.write_wanted = ([], []) self.write_buffers = defaultdict(bytes) def _create_server(self): self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.setblocking(0) self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server.bind(('', self.config['port'])) self.server.listen(self.config['backlog'])
import socket import struct import binascii from copy import deepcopy import itertools from sauna.consumers.base import QueuedConsumer from sauna.consumers import ConsumerRegister my_consumer = ConsumerRegister('NSCA') def encrypt_xor(data, iv, key): for i in (iv, key): i = itertools.cycle(i) data = bytes(x ^ y for x, y in zip(data, i)) return data @my_consumer.consumer() class NSCAConsumer(QueuedConsumer): protocol_version = 3 max_hostname_size = 64 max_service_size = 128 max_output_size = 4096 init_payload_fmt = '!128sL' init_payload_size = struct.calcsize(init_payload_fmt) service_payload_fmt = '!hhIIh{}s{}s{}sh'.format(max_hostname_size, max_service_size,
# forked from http.py to match icinga Rest API from sauna.consumers.base import QueuedConsumer from sauna.consumers import ConsumerRegister my_consumer = ConsumerRegister('HTTP-icinga') @my_consumer.consumer() class HTTPIcingaConsumer(QueuedConsumer): def __init__(self, config): super().__init__(config) try: import requests self.requests = requests except ImportError: from ... import DependencyError raise DependencyError(self.__class__.__name__, 'requests', 'requests', 'python3-requests') self.config = { 'url': config.get('url', 'http://localhost'), 'timeout': config.get('timeout', 60), 'headers': config.get('headers', None) } def _send(self, service_check): data = { "filter": ("host.name==\"" + service_check.hostname + "\" && service.name==\"" + service_check.name + "\""), "exit_status": service_check.status, "plugin_output":
import json from http.server import HTTPServer, BaseHTTPRequestHandler from sauna.consumers.base import AsyncConsumer from sauna.consumers import ConsumerRegister from sauna import __version__ my_consumer = ConsumerRegister('HTTPServer') class StoppableHTTPServer(HTTPServer): """HTTPServer that stops itself when receiving a threading.Event""" def __init__(self, must_stop, *args, **kwargs): super().__init__(*args, **kwargs) self._must_stop = must_stop def service_actions(self): """Called by the serve_forever() loop. Check if Sauna requested the server to shutdown. It cannot call self.shutdown() because the server does not run in a separated thread. """ if self._must_stop.is_set(): self._BaseServer__shutdown_request = True @my_consumer.consumer() class HTTPServerConsumer(AsyncConsumer): def __init__(self, config): super().__init__(config)
import json import re from typing import Optional, Set, List from sauna.consumers.base import BatchQueuedConsumer from sauna.consumers import ConsumerRegister my_consumer = ConsumerRegister('HomeAssistantMQTT') status_to_name = { 0: 'OK', 1: 'Warning', 2: 'Critical', 3: 'Unknown' } @my_consumer.consumer() class HomeAssistantMQTTConsumer(BatchQueuedConsumer): """Report checks to Home Assistant via MQTT. Uses the Home Assistant MQTT discovery functionnality to dynamically create sensors for each couple of host/check. The first time Sauna sees a new check for a host, it inserts a MQTT message on a well known topic that HA monitors with the configuration for the new sensor. Each host/check gets its own MQTT topic that HA starts subscribing to. Afterwards checks are just sent on their own topic. """