Add auto_trigger support to watcher
This patch set adds support of auto-triggering of action plans. Change-Id: I36b7dff8eab5f6ebb18f6f4e752cf4b263456293 Partially-Implements: blueprint automatic-triggering-audit
This commit is contained in:
@@ -93,6 +93,7 @@ def get_test_audit(**kwargs):
|
||||
'goal_id': kwargs.get('goal_id', 1),
|
||||
'strategy_id': kwargs.get('strategy_id', None),
|
||||
'scope': kwargs.get('scope', []),
|
||||
'auto_trigger': kwargs.get('auto_trigger', False)
|
||||
}
|
||||
# ObjectField doesn't allow None nor dict, so if we want to simulate a
|
||||
# non-eager object loading, the field should not be referenced at all.
|
||||
|
||||
@@ -18,6 +18,8 @@ from apscheduler.schedulers import background
|
||||
import mock
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from watcher.applier import rpcapi
|
||||
from watcher.common import exception
|
||||
from watcher.decision_engine.audit import continuous
|
||||
from watcher.decision_engine.audit import oneshot
|
||||
from watcher.decision_engine.model.collector import manager
|
||||
@@ -150,6 +152,65 @@ class TestOneShotAuditHandler(base.DbTestCase):
|
||||
self.m_audit_notifications.send_action_notification.call_args_list)
|
||||
|
||||
|
||||
class TestAutoTriggerActionPlan(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestAutoTriggerActionPlan, self).setUp()
|
||||
self.goal = obj_utils.create_test_goal(
|
||||
self.context, id=1, name=dummy_strategy.DummyStrategy.get_name())
|
||||
self.strategy = obj_utils.create_test_strategy(
|
||||
self.context, name=dummy_strategy.DummyStrategy.get_name(),
|
||||
goal_id=self.goal.id)
|
||||
audit_template = obj_utils.create_test_audit_template(
|
||||
self.context)
|
||||
self.audit = obj_utils.create_test_audit(
|
||||
self.context,
|
||||
id=0,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
audit_template_id=audit_template.id,
|
||||
goal_id=self.goal.id,
|
||||
audit_type=objects.audit.AuditType.CONTINUOUS.value,
|
||||
goal=self.goal,
|
||||
auto_trigger=True)
|
||||
self.ongoing_action_plan = obj_utils.create_test_action_plan(
|
||||
self.context,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
audit_id=self.audit.id)
|
||||
self.recommended_action_plan = obj_utils.create_test_action_plan(
|
||||
self.context,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
state=objects.action_plan.State.ONGOING,
|
||||
audit_id=self.audit.id
|
||||
)
|
||||
|
||||
@mock.patch.object(objects.action_plan.ActionPlan, 'list')
|
||||
@mock.patch.object(objects.audit.Audit, 'get_by_id')
|
||||
def test_trigger_action_plan_with_ongoing(self, mock_get_by_id, mock_list):
|
||||
mock_get_by_id.return_value = self.audit
|
||||
mock_list.return_value = [self.ongoing_action_plan]
|
||||
auto_trigger_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
||||
with mock.patch.object(auto_trigger_handler, 'do_schedule'):
|
||||
self.assertRaises(exception.ActionPlanIsOngoing,
|
||||
auto_trigger_handler.post_execute,
|
||||
self.audit, mock.MagicMock(), self.context)
|
||||
|
||||
@mock.patch.object(rpcapi.ApplierAPI, 'launch_action_plan')
|
||||
@mock.patch.object(objects.action_plan.ActionPlan, 'list')
|
||||
@mock.patch.object(objects.audit.Audit, 'get_by_id')
|
||||
def test_trigger_action_plan_without_ongoing(self, mock_get_by_id,
|
||||
mock_list, mock_applier):
|
||||
mock_get_by_id.return_value = self.audit
|
||||
mock_list.return_value = []
|
||||
auto_trigger_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
||||
with mock.patch.object(auto_trigger_handler, 'do_schedule',
|
||||
new_callable=mock.PropertyMock) as m_schedule:
|
||||
m_schedule().uuid = self.recommended_action_plan.uuid
|
||||
auto_trigger_handler.post_execute(self.audit, mock.MagicMock(),
|
||||
self.context)
|
||||
mock_applier.assert_called_once_with(self.context,
|
||||
self.recommended_action_plan.uuid)
|
||||
|
||||
|
||||
class TestContinuousAuditHandler(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -330,21 +330,21 @@ class TestSyncer(base.DbTestCase):
|
||||
self.ctx, id=1, uuid=utils.generate_uuid(),
|
||||
audit_type=objects.audit.AuditType.ONESHOT.value,
|
||||
state=objects.audit.State.PENDING,
|
||||
goal_id=goal1.id, strategy_id=strategy1.id)
|
||||
goal_id=goal1.id, strategy_id=strategy1.id, auto_trigger=False)
|
||||
# Should be modified by the sync() because its associated goal
|
||||
# has been modified (compared to the defined fake goals)
|
||||
audit2 = objects.Audit(
|
||||
self.ctx, id=2, uuid=utils.generate_uuid(),
|
||||
audit_type=objects.audit.AuditType.ONESHOT.value,
|
||||
state=objects.audit.State.PENDING,
|
||||
goal_id=goal2.id, strategy_id=strategy2.id)
|
||||
goal_id=goal2.id, strategy_id=strategy2.id, auto_trigger=False)
|
||||
# Should be modified by the sync() because its associated strategy
|
||||
# has been modified (compared to the defined fake strategies)
|
||||
audit3 = objects.Audit(
|
||||
self.ctx, id=3, uuid=utils.generate_uuid(),
|
||||
audit_type=objects.audit.AuditType.ONESHOT.value,
|
||||
state=objects.audit.State.PENDING,
|
||||
goal_id=goal1.id, strategy_id=strategy3.id)
|
||||
goal_id=goal1.id, strategy_id=strategy3.id, auto_trigger=False)
|
||||
# Modified because of both because its associated goal and associated
|
||||
# strategy should be modified (compared to the defined fake
|
||||
# goals/strategies)
|
||||
@@ -352,7 +352,7 @@ class TestSyncer(base.DbTestCase):
|
||||
self.ctx, id=4, uuid=utils.generate_uuid(),
|
||||
audit_type=objects.audit.AuditType.ONESHOT.value,
|
||||
state=objects.audit.State.PENDING,
|
||||
goal_id=goal2.id, strategy_id=strategy4.id)
|
||||
goal_id=goal2.id, strategy_id=strategy4.id, auto_trigger=False)
|
||||
|
||||
audit1.create()
|
||||
audit2.create()
|
||||
@@ -560,13 +560,13 @@ class TestSyncer(base.DbTestCase):
|
||||
self.ctx, id=1, uuid=utils.generate_uuid(),
|
||||
audit_type=objects.audit.AuditType.ONESHOT.value,
|
||||
state=objects.audit.State.PENDING,
|
||||
goal_id=goal1.id, strategy_id=strategy1.id)
|
||||
goal_id=goal1.id, strategy_id=strategy1.id, auto_trigger=False)
|
||||
# Stale after syncing because the goal has been soft deleted
|
||||
audit2 = objects.Audit(
|
||||
self.ctx, id=2, uuid=utils.generate_uuid(),
|
||||
audit_type=objects.audit.AuditType.ONESHOT.value,
|
||||
state=objects.audit.State.PENDING,
|
||||
goal_id=goal2.id, strategy_id=strategy2.id)
|
||||
goal_id=goal2.id, strategy_id=strategy2.id, auto_trigger=False)
|
||||
audit1.create()
|
||||
audit2.create()
|
||||
|
||||
|
||||
@@ -412,7 +412,7 @@ expected_object_fingerprints = {
|
||||
'Goal': '1.0-93881622db05e7b67a65ca885b4a022e',
|
||||
'Strategy': '1.1-73f164491bdd4c034f48083a51bdeb7b',
|
||||
'AuditTemplate': '1.1-b291973ffc5efa2c61b24fe34fdccc0b',
|
||||
'Audit': '1.1-dc246337c8d511646cb537144fcb0f3a',
|
||||
'Audit': '1.2-910522db78b7b1cb59df614754656db4',
|
||||
'ActionPlan': '1.2-42709eadf6b2bd228ea87817e8c3e31e',
|
||||
'Action': '1.1-52c77e4db4ce0aa9480c9760faec61a1',
|
||||
'EfficacyIndicator': '1.0-655b71234a82bc7478aff964639c4bb0',
|
||||
|
||||
Reference in New Issue
Block a user