import time from typing import List, Tuple from platypush.backend import Backend from platypush.context import get_plugin from platypush.message.event.ping import HostUpEvent, HostDownEvent from platypush.utils.workers import Worker, Workers class PingBackend(Backend): """ This backend allows you to ping multiple remote hosts at regular intervals. Triggers: - :class:`platypush.message.event.ping.HostDownEvent` if a host stops responding ping requests - :class:`platypush.message.event.ping.HostUpEvent` if a host starts responding ping requests """ class Pinger(Worker): def __init__(self, *args, **kwargs): self.timeout = kwargs.pop('timeout') self.count = kwargs.pop('count') super().__init__(*args, **kwargs) def process(self, host: str) -> Tuple[str, bool]: pinger = get_plugin('ping') response = pinger.ping(host, timeout=self.timeout, count=self.count).output return host, response['success'] is True def __init__(self, hosts: List[str], timeout: float = 5.0, interval: float = 60.0, count: int = 1, *args, **kwargs): """ :param hosts: List of IP addresses or host names to monitor. :param timeout: Ping timeout. :param interval: Interval between two scans. :param count: Number of pings per host. A host will be considered down if all the ping requests fail. """ super().__init__(*args, **kwargs) self.hosts = {h: None for h in hosts} self.timeout = timeout self.interval = interval self.count = count def run(self): super().run() self.logger.info('Starting ping backend with {} hosts to monitor'.format(len(self.hosts))) while not self.should_stop(): workers = Workers(10, self.Pinger, timeout=self.timeout, count=self.count) with workers: for host in self.hosts.keys(): workers.put(host) for response in workers.responses: host, is_up = response if is_up != self.hosts[host]: if is_up: self.bus.post(HostUpEvent(host)) else: self.bus.post(HostDownEvent(host)) self.hosts[host] = is_up time.sleep(self.interval) # vim:sw=4:ts=4:et: