Files
watcher/watcher/tests/objects/test_action_plan.py
licanwei 38e4b48d70 stale the action plan
Check the creation time of the actionplan,
and set the state to SUPERSEDED if it has expired.

Change-Id: I900e8dc5011dec4cffd58913b9c5083a6131d70d
Implements: blueprint stale-action-plan
2017-03-18 13:46:34 +08:00

325 lines
14 KiB
Python

# Copyright 2015 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import iso8601
import mock
from watcher.common import exception
from watcher.common import utils as common_utils
from watcher import conf
from watcher.db.sqlalchemy import api as db_api
from watcher import notifications
from watcher import objects
from watcher.tests.db import base
from watcher.tests.db import utils
CONF = conf.CONF
class TestActionPlanObject(base.DbTestCase):
audit_id = 2
strategy_id = 2
scenarios = [
('non_eager', dict(
eager=False,
fake_action_plan=utils.get_test_action_plan(
created_at=datetime.datetime.utcnow(),
audit_id=audit_id,
strategy_id=strategy_id))),
('eager_with_non_eager_load', dict(
eager=True,
fake_action_plan=utils.get_test_action_plan(
created_at=datetime.datetime.utcnow(),
audit_id=audit_id,
strategy_id=strategy_id))),
('eager_with_eager_load', dict(
eager=True,
fake_action_plan=utils.get_test_action_plan(
created_at=datetime.datetime.utcnow(),
strategy_id=strategy_id,
strategy=utils.get_test_strategy(id=strategy_id),
audit_id=audit_id,
audit=utils.get_test_audit(id=audit_id)))),
]
def setUp(self):
super(TestActionPlanObject, self).setUp()
p_action_plan_notifications = mock.patch.object(
notifications, 'action_plan', autospec=True)
self.m_action_plan_notifications = p_action_plan_notifications.start()
self.addCleanup(p_action_plan_notifications.stop)
self.m_send_update = self.m_action_plan_notifications.send_update
self.fake_audit = utils.create_test_audit(id=self.audit_id)
self.fake_strategy = utils.create_test_strategy(
id=self.strategy_id, name="DUMMY")
def eager_load_action_plan_assert(self, action_plan):
if self.eager:
self.assertIsNotNone(action_plan.audit)
fields_to_check = set(
super(objects.Audit, objects.Audit).fields
).symmetric_difference(objects.Audit.fields)
db_data = {
k: v for k, v in self.fake_audit.as_dict().items()
if k in fields_to_check}
object_data = {
k: v for k, v in action_plan.audit.as_dict().items()
if k in fields_to_check}
self.assertEqual(db_data, object_data)
@mock.patch.object(db_api.Connection, 'get_action_plan_by_id')
def test_get_by_id(self, mock_get_action_plan):
mock_get_action_plan.return_value = self.fake_action_plan
action_plan_id = self.fake_action_plan['id']
action_plan = objects.ActionPlan.get(
self.context, action_plan_id, eager=self.eager)
mock_get_action_plan.assert_called_once_with(
self.context, action_plan_id, eager=self.eager)
self.assertEqual(self.context, action_plan._context)
self.eager_load_action_plan_assert(action_plan)
self.assertEqual(0, self.m_send_update.call_count)
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
def test_get_by_uuid(self, mock_get_action_plan):
mock_get_action_plan.return_value = self.fake_action_plan
uuid = self.fake_action_plan['uuid']
action_plan = objects.ActionPlan.get(
self.context, uuid, eager=self.eager)
mock_get_action_plan.assert_called_once_with(
self.context, uuid, eager=self.eager)
self.assertEqual(self.context, action_plan._context)
self.eager_load_action_plan_assert(action_plan)
self.assertEqual(0, self.m_send_update.call_count)
def test_get_bad_id_and_uuid(self):
self.assertRaises(exception.InvalidIdentity,
objects.ActionPlan.get, self.context,
'not-a-uuid', eager=self.eager)
@mock.patch.object(db_api.Connection, 'get_action_plan_list')
def test_list(self, mock_get_list):
mock_get_list.return_value = [self.fake_action_plan]
action_plans = objects.ActionPlan.list(self.context, eager=self.eager)
self.assertEqual(1, mock_get_list.call_count)
self.assertEqual(1, len(action_plans))
self.assertIsInstance(action_plans[0], objects.ActionPlan)
self.assertEqual(self.context, action_plans[0]._context)
for action_plan in action_plans:
self.eager_load_action_plan_assert(action_plan)
self.assertEqual(0, self.m_send_update.call_count)
@mock.patch.object(db_api.Connection, 'update_action_plan')
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
def test_save(self, mock_get_action_plan, mock_update_action_plan):
mock_get_action_plan.return_value = self.fake_action_plan
fake_saved_action_plan = self.fake_action_plan.copy()
fake_saved_action_plan['state'] = objects.action_plan.State.SUCCEEDED
fake_saved_action_plan['updated_at'] = datetime.datetime.utcnow()
mock_update_action_plan.return_value = fake_saved_action_plan
expected_action_plan = fake_saved_action_plan.copy()
expected_action_plan[
'created_at'] = expected_action_plan['created_at'].replace(
tzinfo=iso8601.iso8601.Utc())
expected_action_plan[
'updated_at'] = expected_action_plan['updated_at'].replace(
tzinfo=iso8601.iso8601.Utc())
uuid = self.fake_action_plan['uuid']
action_plan = objects.ActionPlan.get_by_uuid(
self.context, uuid, eager=self.eager)
action_plan.state = objects.action_plan.State.SUCCEEDED
action_plan.save()
mock_get_action_plan.assert_called_once_with(
self.context, uuid, eager=self.eager)
mock_update_action_plan.assert_called_once_with(
uuid, {'state': objects.action_plan.State.SUCCEEDED})
self.assertEqual(self.context, action_plan._context)
self.eager_load_action_plan_assert(action_plan)
self.m_send_update.assert_called_once_with(
self.context, action_plan,
old_state=self.fake_action_plan['state'])
self.assertEqual(
{k: v for k, v in expected_action_plan.items()
if k not in action_plan.object_fields},
{k: v for k, v in action_plan.as_dict().items()
if k not in action_plan.object_fields})
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
def test_refresh(self, mock_get_action_plan):
returns = [dict(self.fake_action_plan, state="first state"),
dict(self.fake_action_plan, state="second state")]
mock_get_action_plan.side_effect = returns
uuid = self.fake_action_plan['uuid']
expected = [mock.call(self.context, uuid, eager=self.eager),
mock.call(self.context, uuid, eager=self.eager)]
action_plan = objects.ActionPlan.get(
self.context, uuid, eager=self.eager)
self.assertEqual("first state", action_plan.state)
action_plan.refresh(eager=self.eager)
self.assertEqual("second state", action_plan.state)
self.assertEqual(expected, mock_get_action_plan.call_args_list)
self.assertEqual(self.context, action_plan._context)
self.eager_load_action_plan_assert(action_plan)
class TestCreateDeleteActionPlanObject(base.DbTestCase):
def setUp(self):
super(TestCreateDeleteActionPlanObject, self).setUp()
p_action_plan_notifications = mock.patch.object(
notifications, 'action_plan', autospec=True)
self.m_action_plan_notifications = p_action_plan_notifications.start()
self.addCleanup(p_action_plan_notifications.stop)
self.m_send_update = self.m_action_plan_notifications.send_update
self.fake_strategy = utils.create_test_strategy(name="DUMMY")
self.fake_audit = utils.create_test_audit()
self.fake_action_plan = utils.get_test_action_plan(
created_at=datetime.datetime.utcnow())
@mock.patch.object(db_api.Connection, 'create_action_plan')
def test_create(self, mock_create_action_plan):
mock_create_action_plan.return_value = self.fake_action_plan
action_plan = objects.ActionPlan(
self.context, **self.fake_action_plan)
action_plan.create()
expected_action_plan = self.fake_action_plan.copy()
expected_action_plan['created_at'] = expected_action_plan[
'created_at'].replace(tzinfo=iso8601.iso8601.Utc())
mock_create_action_plan.assert_called_once_with(expected_action_plan)
self.assertEqual(self.context, action_plan._context)
@mock.patch.multiple(
db_api.Connection,
get_action_plan_by_uuid=mock.DEFAULT,
soft_delete_action_plan=mock.DEFAULT,
update_action_plan=mock.DEFAULT,
get_efficacy_indicator_list=mock.DEFAULT,
soft_delete_efficacy_indicator=mock.DEFAULT,
)
def test_soft_delete(self, get_action_plan_by_uuid,
soft_delete_action_plan, update_action_plan,
get_efficacy_indicator_list,
soft_delete_efficacy_indicator):
efficacy_indicator = utils.get_test_efficacy_indicator(
action_plan_id=self.fake_action_plan['id'])
uuid = self.fake_action_plan['uuid']
m_get_action_plan = get_action_plan_by_uuid
m_soft_delete_action_plan = soft_delete_action_plan
m_get_efficacy_indicator_list = get_efficacy_indicator_list
m_soft_delete_efficacy_indicator = soft_delete_efficacy_indicator
m_update_action_plan = update_action_plan
m_get_action_plan.return_value = self.fake_action_plan
fake_deleted_action_plan = self.fake_action_plan.copy()
fake_deleted_action_plan['deleted_at'] = datetime.datetime.utcnow()
m_update_action_plan.return_value = fake_deleted_action_plan
m_soft_delete_action_plan.return_value = fake_deleted_action_plan
expected_action_plan = fake_deleted_action_plan.copy()
expected_action_plan['created_at'] = expected_action_plan[
'created_at'].replace(tzinfo=iso8601.iso8601.Utc())
expected_action_plan['deleted_at'] = expected_action_plan[
'deleted_at'].replace(tzinfo=iso8601.iso8601.Utc())
del expected_action_plan['audit']
del expected_action_plan['strategy']
m_get_efficacy_indicator_list.return_value = [efficacy_indicator]
action_plan = objects.ActionPlan.get_by_uuid(
self.context, uuid, eager=False)
action_plan.soft_delete()
m_get_action_plan.assert_called_once_with(
self.context, uuid, eager=False)
m_get_efficacy_indicator_list.assert_called_once_with(
self.context, filters={"action_plan_uuid": uuid},
limit=None, marker=None, sort_dir=None, sort_key=None)
m_soft_delete_action_plan.assert_called_once_with(uuid)
m_soft_delete_efficacy_indicator.assert_called_once_with(
efficacy_indicator['uuid'])
m_update_action_plan.assert_called_once_with(
uuid, {'state': objects.action_plan.State.DELETED})
self.assertEqual(self.context, action_plan._context)
self.assertEqual(expected_action_plan, action_plan.as_dict())
@mock.patch.multiple(
db_api.Connection,
get_action_plan_by_uuid=mock.DEFAULT,
destroy_action_plan=mock.DEFAULT,
get_efficacy_indicator_list=mock.DEFAULT,
destroy_efficacy_indicator=mock.DEFAULT,
)
def test_destroy(self, get_action_plan_by_uuid, destroy_action_plan,
get_efficacy_indicator_list, destroy_efficacy_indicator):
m_get_action_plan = get_action_plan_by_uuid
m_destroy_action_plan = destroy_action_plan
m_get_efficacy_indicator_list = get_efficacy_indicator_list
m_destroy_efficacy_indicator = destroy_efficacy_indicator
efficacy_indicator = utils.get_test_efficacy_indicator(
action_plan_id=self.fake_action_plan['id'])
uuid = self.fake_action_plan['uuid']
m_get_action_plan.return_value = self.fake_action_plan
m_get_efficacy_indicator_list.return_value = [efficacy_indicator]
action_plan = objects.ActionPlan.get_by_uuid(self.context, uuid)
action_plan.destroy()
m_get_action_plan.assert_called_once_with(
self.context, uuid, eager=False)
m_get_efficacy_indicator_list.assert_called_once_with(
self.context, filters={"action_plan_uuid": uuid},
limit=None, marker=None, sort_dir=None, sort_key=None)
m_destroy_action_plan.assert_called_once_with(uuid)
m_destroy_efficacy_indicator.assert_called_once_with(
efficacy_indicator['uuid'])
self.assertEqual(self.context, action_plan._context)
@mock.patch.object(notifications.action_plan, 'send_update', mock.Mock())
class TestStateManager(base.DbTestCase):
def setUp(self):
super(TestStateManager, self).setUp()
self.state_manager = objects.action_plan.StateManager()
def test_check_expired(self):
CONF.set_default('action_plan_expiry', 0,
group='watcher_decision_engine')
strategy_1 = utils.create_test_strategy(
uuid=common_utils.generate_uuid())
audit_1 = utils.create_test_audit(
uuid=common_utils.generate_uuid())
action_plan_1 = utils.create_test_action_plan(
state=objects.action_plan.State.RECOMMENDED,
uuid=common_utils.generate_uuid(),
audit_id=audit_1.id,
strategy_id=strategy_1.id)
self.state_manager.check_expired(self.context)
action_plan = objects.action_plan.ActionPlan.get_by_uuid(
self.context, action_plan_1.uuid)
self.assertEqual(objects.action_plan.State.SUPERSEDED,
action_plan.state)