From 0def7b4d382cca516a8ab94be1c485eb08cf6a96 Mon Sep 17 00:00:00 2001 From: licanwei Date: Fri, 19 Apr 2019 14:30:09 +0800 Subject: [PATCH] separate launching audit scheduler Now there are only one scheduler for launching audit task and executing audit jobs. We have found an exception where the scheduler stops for some reason when executing audit. In order to keep launching audit task normal, we need to split into two schedulers. Change-Id: I45dccaf062290cfc7d7fcfc27fe11d6f87f38afa --- watcher/decision_engine/audit/continuous.py | 30 +++++++++++++------ .../audit/test_audit_handlers.py | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/watcher/decision_engine/audit/continuous.py b/watcher/decision_engine/audit/continuous.py index ed5267bd5..f9682d6e3 100644 --- a/watcher/decision_engine/audit/continuous.py +++ b/watcher/decision_engine/audit/continuous.py @@ -21,7 +21,6 @@ import datetime from dateutil import tz -from apscheduler.jobstores import memory from croniter import croniter from watcher.common import context @@ -40,21 +39,29 @@ CONF = conf.CONF class ContinuousAuditHandler(base.AuditHandler): def __init__(self): super(ContinuousAuditHandler, self).__init__() - self._scheduler = None + # scheduler for executing audits + self._audit_scheduler = None + # scheduler for a periodic task to launch audit + self._period_scheduler = None self.context_show_deleted = context.RequestContext(is_admin=True, show_deleted=True) @property def scheduler(self): - if self._scheduler is None: - self._scheduler = scheduling.BackgroundSchedulerService( + if self._audit_scheduler is None: + self._audit_scheduler = scheduling.BackgroundSchedulerService( jobstores={ 'default': job_store.WatcherJobStore( engine=sq_api.get_engine()), - 'memory': memory.MemoryJobStore() } ) - return self._scheduler + return self._audit_scheduler + + @property + def period_scheduler(self): + if self._period_scheduler is None: + self._period_scheduler = scheduling.BackgroundSchedulerService() + return self._period_scheduler def _is_audit_inactive(self, audit): audit = objects.Audit.get_by_uuid( @@ -135,6 +142,10 @@ class ContinuousAuditHandler(base.AuditHandler): return False def launch_audits_periodically(self): + # if audit scheduler stop, restart it + if not self.scheduler.running: + self.scheduler.start() + audit_context = context.RequestContext(is_admin=True) audit_filters = { 'audit_type': objects.audit.AuditType.CONTINUOUS.value, @@ -207,10 +218,11 @@ class ContinuousAuditHandler(base.AuditHandler): audit.save() def start(self): - self.scheduler.add_job( + self.period_scheduler.add_job( self.launch_audits_periodically, 'interval', seconds=CONF.watcher_decision_engine.continuous_audit_interval, - next_run_time=datetime.datetime.now(), - jobstore='memory') + next_run_time=datetime.datetime.now()) + self.period_scheduler.start() + # audit scheduler start self.scheduler.start() diff --git a/watcher/tests/decision_engine/audit/test_audit_handlers.py b/watcher/tests/decision_engine/audit/test_audit_handlers.py index 63a5b135d..de1000116 100644 --- a/watcher/tests/decision_engine/audit/test_audit_handlers.py +++ b/watcher/tests/decision_engine/audit/test_audit_handlers.py @@ -462,7 +462,7 @@ class TestContinuousAuditHandler(base.DbTestCase): def test_is_audit_inactive(self, mock_jobs): audit_handler = continuous.ContinuousAuditHandler() mock_jobs.return_value = mock.MagicMock() - audit_handler._scheduler = mock.MagicMock() + audit_handler._audit_scheduler = mock.MagicMock() ap_jobs = [job.Job(mock.MagicMock(), name='execute_audit', func=audit_handler.execute_audit,