Beispiel #1
0
 def __init__(self, dmd):
     super(EventDTwistedWorker, self).__init__()
     self._amqpConnectionInfo = getUtility(IAMQPConnectionInfo)
     self._queueSchema = getUtility(IQueueSchema)
     self._consumer_task = TwistedQueueConsumerTask(
         EventPipelineProcessor(dmd))
     self._consumer = QueueConsumer(self._consumer_task, dmd)
Beispiel #2
0
    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)

        if self.options.workerid == 0 and (self.options.daemon
                                           or self.options.cycle):
            self._callHomeCycler.start()
            self._schedule.start()  # maintenance windows

        if self.options.daemon or self.options.cycle:
            self._maintenanceCycle.start()  # heartbeats, etc.

        if (self.options.daemon
                or self.options.cycle) and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()
Beispiel #3
0
 def __init__(self, dmd):
     super(EventDTwistedWorker, self).__init__()
     self._amqpConnectionInfo = getUtility(IAMQPConnectionInfo)
     self._queueSchema = getUtility(IQueueSchema)
     self._consumer_task = TwistedQueueConsumerTask(
         EventPipelineProcessor(dmd)
     )
     self._consumer = QueueConsumer(self._consumer_task, dmd)
Beispiel #4
0
class EventDTwistedWorker(object):
    def __init__(self, dmd):
        super(EventDTwistedWorker, self).__init__()
        self._amqpConnectionInfo = getUtility(IAMQPConnectionInfo)
        self._queueSchema = getUtility(IQueueSchema)
        self._consumer_task = TwistedQueueConsumerTask(EventPipelineProcessor(dmd))
        self._consumer = QueueConsumer(self._consumer_task, dmd)

    def run(self):
        reactor.callWhenRunning(self._start)
        reactor.run()

    def _start(self):
        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
        self._consumer.run()

    @defer.inlineCallbacks
    def _shutdown(self):
        if self._consumer:
            yield self._consumer.shutdown()
Beispiel #5
0
    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)
        metric_destination = os.environ.get("CONTROLPLANE_CONSUMER_URL", "")
        if metric_destination == "":
            metric_destination = "http://localhost:22350/api/metrics/store"
        username = os.environ.get("CONTROLPLANE_CONSUMER_USERNAME", "")
        password = os.environ.get("CONTROLPLANE_CONSUMER_PASSWORD", "")
        pub = publisher.HttpPostPublisher(username, password,
                                          metric_destination)

        log.debug("Creating async MetricReporter")
        daemonTags = {'zenoss_daemon': 'zenactiond', 'internal': True}
        self.metricreporter = TwistedMetricReporter(
            prefix='zenoss.', metricWriter=MetricWriter(pub), tags=daemonTags)
        self.metricreporter.start()
        reactor.addSystemEventTrigger('before', 'shutdown',
                                      self.metricreporter.stop)

        if self.options.workerid == 0 and (self.options.daemon
                                           or self.options.cycle):
            self._callHomeCycler.start()
            self._schedule.start()  # maintenance windows

        if self.options.daemon or self.options.cycle:
            self._maintenanceCycle.start()  # heartbeats, etc.

        if (self.options.daemon
                or self.options.cycle) and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()
    def run(self):
        # Configure all actions with the command-line options
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)

        self._callHomeCycler.start()
        self._schedule.start()  # maintenance windows
        if self.options.daemon:
            self._maintenanceCycle.start()  # heartbeats, etc.
        if self.options.daemon and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()
Beispiel #7
0
    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)
        metric_destination = os.environ.get("CONTROLPLANE_CONSUMER_URL", "")
        if metric_destination == "":
            metric_destination = "http://localhost:22350/api/metrics/store"
        username = os.environ.get("CONTROLPLANE_CONSUMER_USERNAME", "")
        password = os.environ.get("CONTROLPLANE_CONSUMER_PASSWORD", "")
        pub = publisher.HttpPostPublisher(username, password, metric_destination)

        log.debug("Creating async MetricReporter")
        daemonTags = {
            'zenoss_daemon': 'zenactiond',
            'internal': True
        }
        self.metricreporter = TwistedMetricReporter(prefix='zenoss.', metricWriter=MetricWriter(pub), tags=daemonTags)
        self.metricreporter.start()
        reactor.addSystemEventTrigger('before', 'shutdown', self.metricreporter.stop)

        if self.options.workerid == 0 and (self.options.daemon or self.options.cycle):
            self._callHomeCycler.start()
            self._schedule.start()  # maintenance windows

        if self.options.daemon or self.options.cycle:
            self._maintenanceCycle.start()  # heartbeats, etc.

        if (self.options.daemon or self.options.cycle) and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()
Beispiel #8
0
class ZenActionD(ZCmdBase):
    def __init__(self):
        super(ZenActionD, self).__init__()
        self._consumer = None
        self._workers = ProcessWorkers(self.options.workers - 1,
                                       exec_worker,
                                       "zenactiond worker")
        self._heartbeatSender = QueueHeartbeatSender('localhost',
                                                 'zenactiond',
                                                 self.options.maintenancecycle *3)

        self._maintenanceCycle = MaintenanceCycle(self.options.maintenancecycle,
                                                  self._heartbeatSender)
        self._callHomeCycler = CallHomeCycler(self.dmd)
        self._schedule = Schedule(self.options, self.dmd)
        self._schedule.sendEvent = self.dmd.ZenEventManager.sendEvent
        self._schedule.monitor = self.options.monitor

    def buildOptions(self):
        super(ZenActionD, self).buildOptions()
        maintenanceBuildOptions(self.parser)
        workersBuildOptions(self.parser, 1)

        default_max_commands = 10
        self.parser.add_option('--maxcommands', dest="maxCommands", type="int", default=default_max_commands,
                               help='Max number of action commands to perform concurrently (default: %d)' % \
                                    default_max_commands)
        default_url = getDefaultZopeUrl()
        self.parser.add_option('--zopeurl', dest='zopeurl', default=default_url,
                               help="http path to the root of the zope server (default: %s)" % default_url)
        self.parser.add_option("--monitor", dest="monitor",
            default=DEFAULT_MONITOR,
            help="Name of monitor instance to use for heartbeat "
                " events. Default is %s." % DEFAULT_MONITOR)
        self.parser.add_option('--maintenance-window-cycletime',
            dest='maintenceWindowCycletime', default=60, type="int",
            help="How often to check to see if there are any maintenance windows to execute")

    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)

        self._callHomeCycler.start()
        self._schedule.start()  # maintenance windows
        if self.options.daemon:
            self._maintenanceCycle.start()  # heartbeats, etc.
        if self.options.daemon and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()

    def abortIfWaiting(self):
        # If this process is doing nothing, abort the transaction to avoid long INNODB history
        try:
            transaction.abort()
        except Exception:
            pass
        reactor.callLater(30.0, self.abortIfWaiting)

    def _start(self):
        log.info('starting zenactiond consumer.')
        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
        self._consumer.run()


    @defer.inlineCallbacks
    def _shutdown(self, *ignored):
        log.info("Shutting down...")
        self._maintenanceCycle.stop()
        self._workers.shutdown()
        if self._consumer:
            yield self._consumer.shutdown()
Beispiel #9
0
class ZenActionD(ZCmdBase):
    def __init__(self):
        super(ZenActionD, self).__init__()
        self._consumer = None
        self._workers = ProcessWorkers(self.options.workers - 1,
                                       exec_worker,
                                       "zenactiond worker")
        self._heartbeatSender = QueueHeartbeatSender('localhost',
                                                 'zenactiond',
                                                 self.options.maintenancecycle *3)

        self._maintenanceCycle = MaintenanceCycle(self.options.maintenancecycle,
                                                  self._heartbeatSender)
        self._callHomeCycler = CallHomeCycler(self.dmd)
        self._schedule = Schedule(self.options, self.dmd)
        self._schedule.sendEvent = self.dmd.ZenEventManager.sendEvent
        self._schedule.monitor = self.options.monitor

    def buildOptions(self):
        super(ZenActionD, self).buildOptions()
        maintenanceBuildOptions(self.parser)
        workersBuildOptions(self.parser, 1)

        default_max_commands = 10
        self.parser.add_option('--maxcommands', dest="maxCommands", type="int", default=default_max_commands,
                               help='Max number of action commands to perform concurrently (default: %d)' % \
                                    default_max_commands)
        default_url = getDefaultZopeUrl()
        self.parser.add_option('--zopeurl', dest='zopeurl', default=default_url,
                               help="http path to the root of the zope server (default: %s)" % default_url)
        self.parser.add_option("--monitor", dest="monitor",
            default=DEFAULT_MONITOR,
            help="Name of monitor instance to use for heartbeat "
                " events. Default is %s." % DEFAULT_MONITOR)
        self.parser.add_option('--maintenance-window-cycletime',
            dest='maintenceWindowCycletime', default=60, type="int",
            help="How often to check to see if there are any maintenance windows to execute")

    def run(self):
        # Configure all actions with the command-line options
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)

        self._callHomeCycler.start()
        self._schedule.start()  # maintenance windows
        if self.options.daemon:
            self._maintenanceCycle.start()  # heartbeats, etc.
        if self.options.daemon and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()

    def _start(self):
        log.info('starting zenactiond consumer.')
        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
        self._consumer.run()


    @defer.inlineCallbacks
    def _shutdown(self, *ignored):
        log.info("Shutting down...")
        self._maintenanceCycle.stop()
        self._workers.shutdown()
        if self._consumer:
            yield self._consumer.shutdown()
Beispiel #10
0
class ZenActionD(ZCmdBase):

    MSGS_TO_PREFETCH = 1

    def __init__(self):
        super(ZenActionD, self).__init__()
        self._consumer = None
        self._workers = ProcessWorkers(self.options.workers - 1,
                                       exec_worker,
                                       "zenactiond worker")
        self._heartbeatSender = QueueHeartbeatSender('localhost',
                                                 'zenactiond',
                                                 self.options.heartbeatTimeout)

        self._maintenanceCycle = MaintenanceCycle(self.options.maintenancecycle,
                                                  self._heartbeatSender)
        self._callHomeCycler = CallHomeCycler(self.dmd)
        self._schedule = Schedule(self.options, self.dmd)
        self._schedule.sendEvent = self.dmd.ZenEventManager.sendEvent
        self._schedule.monitor = self.options.monitor

    def buildOptions(self):
        super(ZenActionD, self).buildOptions()
        maintenanceBuildOptions(self.parser)
        workersBuildOptions(self.parser, 1)

        default_max_commands = 10
        self.parser.add_option('--maxcommands', dest="maxCommands", type="int", default=default_max_commands,
                               help='Max number of action commands to perform concurrently (default: %d)' % \
                                    default_max_commands)
        default_max_pagingworkers = 1
        self.parser.add_option('--maxpagingworkers', dest="maxPagingWorkers", type="int", default=default_max_pagingworkers,
                               help='max number of paging workers to perform concurrently (default: %d)' % \
                                       default_max_pagingworkers)
        default_pagingworkers_timeout = 30
        self.parser.add_option('--pagingworkerstimeout', dest="pagingWorkersTimeout", type="int", default=default_pagingworkers_timeout,
                               help='Timeout, in seconds, for paging workers (default: %d)' % \
                                       default_pagingworkers_timeout)
        default_url = getDefaultZopeUrl()
        self.parser.add_option('--zopeurl', dest='zopeurl', default=default_url,
                               help="http path to the root of the zope server (default: %s)" % default_url)
        self.parser.add_option("--monitor", dest="monitor",
            default=DEFAULT_MONITOR,
            help="Name of monitor instance to use for heartbeat "
                " events. Default is %s." % DEFAULT_MONITOR)
        self.parser.add_option('--maintenance-window-cycletime',
            dest='maintenceWindowCycletime', default=60, type="int",
            help="How often to check to see if there are any maintenance windows to execute")
        self.parser.add_option('--maintenance-window-batch-size',
            dest='maintenceWindowBatchSize', default=200, type="int",
            help="How many devices update per one transaction on maintenance windows execution")
        self.parser.add_option('--strip-email-body-tags',
            dest='stripEmailBodyTags', default=True, action="store_false",
            help="Strip HTML/XML tags from plaintext email notifications?")

        self.parser.add_option("--workerid", dest='workerid', type='int', default=None,
                               help="ID of the worker instance.")

    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)
        metric_destination = os.environ.get("CONTROLPLANE_CONSUMER_URL", "")
        if metric_destination == "":
            metric_destination = "http://localhost:22350/api/metrics/store"
        username = os.environ.get("CONTROLPLANE_CONSUMER_USERNAME", "")
        password = os.environ.get("CONTROLPLANE_CONSUMER_PASSWORD", "")
        pub = publisher.HttpPostPublisher(username, password, metric_destination)

        log.debug("Creating async MetricReporter")
        daemonTags = {
            'zenoss_daemon': 'zenactiond',
            'internal': True
        }
        self.metricreporter = TwistedMetricReporter(prefix='zenoss.', metricWriter=MetricWriter(pub), tags=daemonTags)
        self.metricreporter.start()
        reactor.addSystemEventTrigger('before', 'shutdown', self.metricreporter.stop)

        if self.options.workerid == 0 and (self.options.daemon or self.options.cycle):
            self._callHomeCycler.start()
            self._schedule.start()  # maintenance windows

        if self.options.daemon or self.options.cycle:
            self._maintenanceCycle.start()  # heartbeats, etc.

        if (self.options.daemon or self.options.cycle) and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()

    def abortIfWaiting(self):
        # If this process is doing nothing, abort the transaction to avoid long INNODB history
        try:
            transaction.abort()
        except Exception:
            pass
        reactor.callLater(30.0, self.abortIfWaiting)

    def _start(self):
        log.info('starting zenactiond consumer.')
        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
        self._consumer.run()


    @defer.inlineCallbacks
    def _shutdown(self, *ignored):
        log.info("Shutting down...")
        self._maintenanceCycle.stop()
        self._workers.shutdown()
        if self._consumer:
            yield self._consumer.shutdown()
Beispiel #11
0
class ZenActionD(ZCmdBase):

    MSGS_TO_PREFETCH = 1

    def __init__(self):
        super(ZenActionD, self).__init__()
        self._consumer = None
        self._workers = ProcessWorkers(self.options.workers - 1, exec_worker,
                                       "zenactiond worker")
        self._heartbeatSender = QueueHeartbeatSender(
            'localhost', 'zenactiond', self.options.heartbeatTimeout)

        self._maintenanceCycle = MaintenanceCycle(
            self.options.maintenancecycle, self._heartbeatSender)
        self._callHomeCycler = CallHomeCycler(self.dmd)
        self._schedule = Schedule(self.options, self.dmd)
        self._schedule.sendEvent = self.dmd.ZenEventManager.sendEvent
        self._schedule.monitor = self.options.monitor

    def buildOptions(self):
        super(ZenActionD, self).buildOptions()
        maintenanceBuildOptions(self.parser)
        workersBuildOptions(self.parser, 1)

        default_max_commands = 10
        self.parser.add_option('--maxcommands', dest="maxCommands", type="int", default=default_max_commands,
                               help='Max number of action commands to perform concurrently (default: %d)' % \
                                    default_max_commands)
        default_max_pagingworkers = 1
        self.parser.add_option('--maxpagingworkers', dest="maxPagingWorkers", type="int", default=default_max_pagingworkers,
                               help='max number of paging workers to perform concurrently (default: %d)' % \
                                       default_max_pagingworkers)
        default_pagingworkers_timeout = 30
        self.parser.add_option('--pagingworkerstimeout', dest="pagingWorkersTimeout", type="int", default=default_pagingworkers_timeout,
                               help='Timeout, in seconds, for paging workers (default: %d)' % \
                                       default_pagingworkers_timeout)
        default_url = getDefaultZopeUrl()
        self.parser.add_option(
            '--zopeurl',
            dest='zopeurl',
            default=default_url,
            help="http path to the root of the zope server (default: %s)" %
            default_url)
        self.parser.add_option(
            "--monitor",
            dest="monitor",
            default=DEFAULT_MONITOR,
            help="Name of monitor instance to use for heartbeat "
            " events. Default is %s." % DEFAULT_MONITOR)
        self.parser.add_option(
            '--maintenance-window-cycletime',
            dest='maintenceWindowCycletime',
            default=60,
            type="int",
            help=
            "How often to check to see if there are any maintenance windows to execute"
        )
        self.parser.add_option(
            '--maintenance-window-batch-size',
            dest='maintenceWindowBatchSize',
            default=200,
            type="int",
            help=
            "How many devices update per one transaction on maintenance windows execution"
        )
        self.parser.add_option(
            '--strip-email-body-tags',
            dest='stripEmailBodyTags',
            default=True,
            action="store_false",
            help="Strip HTML/XML tags from plaintext email notifications?")

        self.parser.add_option("--workerid",
                               dest='workerid',
                               type='int',
                               default=None,
                               help="ID of the worker instance.")

    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)
        metric_destination = os.environ.get("CONTROLPLANE_CONSUMER_URL", "")
        if metric_destination == "":
            metric_destination = "http://localhost:22350/api/metrics/store"
        username = os.environ.get("CONTROLPLANE_CONSUMER_USERNAME", "")
        password = os.environ.get("CONTROLPLANE_CONSUMER_PASSWORD", "")
        pub = publisher.HttpPostPublisher(username, password,
                                          metric_destination)

        log.debug("Creating async MetricReporter")
        daemonTags = {'zenoss_daemon': 'zenactiond', 'internal': True}
        self.metricreporter = TwistedMetricReporter(
            prefix='zenoss.', metricWriter=MetricWriter(pub), tags=daemonTags)
        self.metricreporter.start()
        reactor.addSystemEventTrigger('before', 'shutdown',
                                      self.metricreporter.stop)

        if self.options.workerid == 0 and (self.options.daemon
                                           or self.options.cycle):
            self._callHomeCycler.start()
            self._schedule.start()  # maintenance windows

        if self.options.daemon or self.options.cycle:
            self._maintenanceCycle.start()  # heartbeats, etc.

        if (self.options.daemon
                or self.options.cycle) and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()

    def abortIfWaiting(self):
        # If this process is doing nothing, abort the transaction to avoid long INNODB history
        try:
            transaction.abort()
        except Exception:
            pass
        reactor.callLater(30.0, self.abortIfWaiting)

    def _start(self):
        log.info('starting zenactiond consumer.')
        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
        self._consumer.run()

    @defer.inlineCallbacks
    def _shutdown(self, *ignored):
        log.info("Shutting down...")
        self._maintenanceCycle.stop()
        self._workers.shutdown()
        if self._consumer:
            yield self._consumer.shutdown()
Beispiel #12
0
class ZenActionD(ZCmdBase):

    MSGS_TO_PREFETCH = 1

    def __init__(self):
        super(ZenActionD, self).__init__()
        self._consumer = None
        self._workers = ProcessWorkers(self.options.workers - 1, exec_worker,
                                       "zenactiond worker")
        self._heartbeatSender = QueueHeartbeatSender(
            'localhost', 'zenactiond', self.options.maintenancecycle * 3)

        self._maintenanceCycle = MaintenanceCycle(
            self.options.maintenancecycle, self._heartbeatSender)
        self._callHomeCycler = CallHomeCycler(self.dmd)
        self._schedule = Schedule(self.options, self.dmd)
        self._schedule.sendEvent = self.dmd.ZenEventManager.sendEvent
        self._schedule.monitor = self.options.monitor

    def buildOptions(self):
        super(ZenActionD, self).buildOptions()
        maintenanceBuildOptions(self.parser)
        workersBuildOptions(self.parser, 1)

        default_max_commands = 10
        self.parser.add_option('--maxcommands', dest="maxCommands", type="int", default=default_max_commands,
                               help='Max number of action commands to perform concurrently (default: %d)' % \
                                    default_max_commands)
        default_max_pagingworkers = 1
        self.parser.add_option('--maxpagingworkers', dest="maxPagingWorkers", type="int", default=default_max_pagingworkers,
                               help='max number of paging workers to perform concurrently (default: %d)' % \
                                       default_max_pagingworkers)
        default_pagingworkers_timeout = 30
        self.parser.add_option('--pagingworkerstimeout', dest="pagingWorkersTimeout", type="int", default=default_pagingworkers_timeout,
                               help='Timeout, in seconds, for paging workers (default: %d)' % \
                                       default_pagingworkers_timeout)
        default_url = getDefaultZopeUrl()
        self.parser.add_option(
            '--zopeurl',
            dest='zopeurl',
            default=default_url,
            help="http path to the root of the zope server (default: %s)" %
            default_url)
        self.parser.add_option(
            "--monitor",
            dest="monitor",
            default=DEFAULT_MONITOR,
            help="Name of monitor instance to use for heartbeat "
            " events. Default is %s." % DEFAULT_MONITOR)
        self.parser.add_option(
            '--maintenance-window-cycletime',
            dest='maintenceWindowCycletime',
            default=60,
            type="int",
            help=
            "How often to check to see if there are any maintenance windows to execute"
        )

        self.parser.add_option("--workerid",
                               dest='workerid',
                               type='int',
                               default=None,
                               help="ID of the worker instance.")

    def run(self):
        # Configure all actions with the command-line options
        self.abortIfWaiting()
        options_dict = dict(vars(self.options))
        for name, action in getUtilitiesFor(IAction):
            action.configure(options_dict)

        dao = NotificationDao(self.dmd)
        task = ISignalProcessorTask(dao)

        if self.options.workerid == 0 and (self.options.daemon
                                           or self.options.cycle):
            self._callHomeCycler.start()
            self._schedule.start()  # maintenance windows

        if self.options.daemon or self.options.cycle:
            self._maintenanceCycle.start()  # heartbeats, etc.

        if (self.options.daemon
                or self.options.cycle) and self.options.workers > 1:
            self._workers.startWorkers()

        self._consumer = QueueConsumer(task, self.dmd)
        reactor.callWhenRunning(self._start)
        reactor.run()

    def abortIfWaiting(self):
        # If this process is doing nothing, abort the transaction to avoid long INNODB history
        try:
            transaction.abort()
        except Exception:
            pass
        reactor.callLater(30.0, self.abortIfWaiting)

    def _start(self):
        log.info('starting zenactiond consumer.')
        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
        self._consumer.run()

    @defer.inlineCallbacks
    def _shutdown(self, *ignored):
        log.info("Shutting down...")
        self._maintenanceCycle.stop()
        self._workers.shutdown()
        if self._consumer:
            yield self._consumer.shutdown()