Added engine manager and rpcapi related unit tests
Change-Id: I18425885f561b52e62d8496bb64bde058fd258a8
This commit is contained in:
parent
0968920087
commit
5aa354425e
59
masakari/tests/unit/engine/fake_engine.py
Normal file
59
masakari/tests/unit/engine/fake_engine.py
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright (c) 2016 NTT DATA
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_utils import timeutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from masakari import objects
|
||||
from masakari.tests import uuidsentinel
|
||||
|
||||
NOW = timeutils.utcnow().replace(microsecond=0)
|
||||
|
||||
|
||||
def fake_db_notification(**updates):
|
||||
db_notification = {
|
||||
"type": "VM",
|
||||
"id": 1,
|
||||
"payload":
|
||||
{'event': 'STOPPED', 'host_status': 'NORMAL',
|
||||
'cluster_status': 'ONLINE'
|
||||
},
|
||||
"source_host_uuid": uuidsentinel.fake_host,
|
||||
"generated_time": NOW,
|
||||
"status": "running",
|
||||
"notification_uuid": uuidsentinel.fake_notification,
|
||||
"created_at": NOW,
|
||||
"updated_at": None,
|
||||
"deleted_at": None,
|
||||
"deleted": 0
|
||||
}
|
||||
|
||||
for name, field in objects.Notification.fields.items():
|
||||
if name in db_notification:
|
||||
continue
|
||||
if field.nullable:
|
||||
db_notification[name] = None
|
||||
elif field.default != fields.UnspecifiedDefault:
|
||||
db_notification[name] = field.default
|
||||
else:
|
||||
raise Exception('fake_db_notification needs help with %s' % name)
|
||||
|
||||
if updates:
|
||||
db_notification.update(updates)
|
||||
|
||||
return db_notification
|
||||
|
||||
|
||||
def fake_notification_obj(context, **updates):
|
||||
return objects.Notification(**updates)
|
262
masakari/tests/unit/engine/test_engine_mgr.py
Normal file
262
masakari/tests/unit/engine/test_engine_mgr.py
Normal file
@ -0,0 +1,262 @@
|
||||
# All Rights Reserved.
|
||||
# Copyright 2016 NTT DATA
|
||||
#
|
||||
# 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 mock
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import timeutils
|
||||
|
||||
import masakari.conf
|
||||
from masakari import context
|
||||
from masakari import exception
|
||||
from masakari.objects import host as host_obj
|
||||
from masakari.objects import notification as notification_obj
|
||||
from masakari import test
|
||||
from masakari.tests.unit import fakes
|
||||
from masakari.tests import uuidsentinel
|
||||
|
||||
CONF = masakari.conf.CONF
|
||||
|
||||
NOW = timeutils.utcnow().replace(microsecond=0)
|
||||
|
||||
|
||||
class EngineManagerUnitTestCase(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(EngineManagerUnitTestCase, self).setUp()
|
||||
self.engine = importutils.import_object(CONF.engine_manager)
|
||||
self.context = context.RequestContext()
|
||||
|
||||
def _fake_notification_workflow(self, exc=None):
|
||||
if exc:
|
||||
return exc
|
||||
# else the workflow executed successfully
|
||||
|
||||
def _get_vm_type_notification(self):
|
||||
return fakes.create_fake_notification(
|
||||
type="VM", id=1, payload={
|
||||
'event': 'stopped', 'instance_uuid': uuidsentinel.fake_ins,
|
||||
'vir_domain_event': 'fake_event'
|
||||
},
|
||||
source_host_uuid=uuidsentinel.fake_host,
|
||||
generated_time=NOW, status="new",
|
||||
notification_uuid=uuidsentinel.fake_notification)
|
||||
|
||||
def _get_process_type_notification(self):
|
||||
return fakes.create_fake_notification(
|
||||
type="PROCESS", id=1, payload={
|
||||
'event': 'stopped', 'process_name': 'fake_service'
|
||||
},
|
||||
source_host_uuid=uuidsentinel.fake_host,
|
||||
generated_time=NOW, status="new",
|
||||
notification_uuid=uuidsentinel.fake_notification)
|
||||
|
||||
def _get_compute_host_type_notification(self):
|
||||
return fakes.create_fake_notification(
|
||||
type="COMPUTE_HOST", id=1, payload={
|
||||
'event': 'stopped', 'host_status': 'NORMAL',
|
||||
'cluster_status': 'ONLINE'
|
||||
},
|
||||
source_host_uuid=uuidsentinel.fake_host,
|
||||
generated_time=NOW, status="new",
|
||||
notification_uuid=uuidsentinel.fake_notification)
|
||||
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_instance_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_vm_success(self, mock_save,
|
||||
mock_instance_failure):
|
||||
mock_instance_failure.side_effect = self._fake_notification_workflow()
|
||||
notification = self._get_vm_type_notification()
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
mock_instance_failure.assert_called_once_with(
|
||||
self.context, notification.payload.get('instance_uuid'),
|
||||
notification.notification_uuid)
|
||||
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_instance_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_vm_error(self, mock_save,
|
||||
mock_instance_failure):
|
||||
mock_instance_failure.side_effect = self._fake_notification_workflow(
|
||||
exc=exception.InstanceRecoveryFailureException)
|
||||
notification = self._get_vm_type_notification()
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("error", notification.status)
|
||||
mock_instance_failure.assert_called_once_with(
|
||||
self.context, notification.payload.get('instance_uuid'),
|
||||
notification.notification_uuid)
|
||||
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_instance_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_vm_skip_recovery(
|
||||
self, mock_save, mock_instance_failure):
|
||||
notification = self._get_vm_type_notification()
|
||||
mock_instance_failure.side_effect = self._fake_notification_workflow(
|
||||
exc=exception.SkipInstanceRecoveryException)
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
mock_instance_failure.assert_called_once_with(
|
||||
self.context, notification.payload.get('instance_uuid'),
|
||||
notification.notification_uuid)
|
||||
|
||||
@mock.patch.object(host_obj.Host, "get_by_uuid")
|
||||
@mock.patch.object(host_obj.Host, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_process_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_process_event_stopped(
|
||||
self, mock_notification_save, mock_process_failure,
|
||||
mock_host_save, mock_host_obj):
|
||||
notification = self._get_process_type_notification()
|
||||
mock_process_failure.side_effect = self._fake_notification_workflow()
|
||||
fake_host = fakes.create_fake_host()
|
||||
mock_host_obj.return_value = fake_host
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
mock_process_failure.assert_called_once_with(
|
||||
self.context, notification.payload.get('process_name'),
|
||||
fake_host.name,
|
||||
notification.notification_uuid)
|
||||
|
||||
@mock.patch.object(host_obj.Host, "get_by_uuid")
|
||||
@mock.patch.object(host_obj.Host, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_process_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_process_skip_recovery(
|
||||
self, mock_notification_save, mock_process_failure,
|
||||
mock_host_save, mock_host_obj):
|
||||
notification = self._get_process_type_notification()
|
||||
fake_host = fakes.create_fake_host()
|
||||
mock_host_obj.return_value = fake_host
|
||||
mock_process_failure.side_effect = self._fake_notification_workflow(
|
||||
exc=exception.SkipProcessRecoveryException)
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
|
||||
@mock.patch.object(host_obj.Host, "get_by_uuid")
|
||||
@mock.patch.object(host_obj.Host, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_process_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_process_recovery_failure(
|
||||
self, mock_notification_save, mock_process_failure,
|
||||
mock_host_save, mock_host_obj):
|
||||
notification = self._get_process_type_notification()
|
||||
fake_host = fakes.create_fake_host()
|
||||
mock_host_obj.return_value = fake_host
|
||||
mock_process_failure.side_effect = self._fake_notification_workflow(
|
||||
exc=exception.ProcessRecoveryFailureException)
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("error", notification.status)
|
||||
|
||||
@mock.patch.object(host_obj.Host, "get_by_uuid")
|
||||
@mock.patch.object(host_obj.Host, "save")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_process_failure")
|
||||
def test_process_notification_type_process_event_started(
|
||||
self, mock_process_failure, mock_notification_save,
|
||||
mock_host_save, mock_host_obj):
|
||||
notification = self._get_process_type_notification()
|
||||
notification.payload['event'] = 'started'
|
||||
fake_host = fakes.create_fake_host()
|
||||
mock_host_obj.return_value = fake_host
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
self.assertFalse(mock_process_failure.called)
|
||||
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_process_failure")
|
||||
def test_process_notification_type_process_event_other(
|
||||
self, mock_process_failure, mock_notification_save):
|
||||
notification = self._get_process_type_notification()
|
||||
notification.payload['event'] = 'other'
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("ignored", notification.status)
|
||||
self.assertFalse(mock_process_failure.called)
|
||||
|
||||
@mock.patch.object(host_obj.Host, "get_by_uuid")
|
||||
@mock.patch.object(host_obj.Host, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_host_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_compute_host_event_stopped(
|
||||
self, mock_notification_save, mock_host_failure,
|
||||
mock_host_save, mock_host_obj):
|
||||
notification = self._get_compute_host_type_notification()
|
||||
mock_host_failure.side_effect = self._fake_notification_workflow()
|
||||
fake_host = fakes.create_fake_host()
|
||||
fake_host.failover_segment = fakes.create_fake_failover_segment()
|
||||
mock_host_obj.return_value = fake_host
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
mock_host_failure.assert_called_once_with(
|
||||
self.context,
|
||||
fake_host.name, fake_host.failover_segment.recovery_method,
|
||||
notification.notification_uuid)
|
||||
|
||||
@mock.patch.object(host_obj.Host, "get_by_uuid")
|
||||
@mock.patch.object(host_obj.Host, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_host_failure")
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
def test_process_notification_type_compute_host_recovery_exception(
|
||||
self, mock_notification_save, mock_host_failure,
|
||||
mock_host_save, mock_host_obj):
|
||||
notification = self._get_compute_host_type_notification()
|
||||
fake_host = fakes.create_fake_host()
|
||||
fake_host.failover_segment = fakes.create_fake_failover_segment()
|
||||
mock_host_obj.return_value = fake_host
|
||||
mock_host_failure.side_effect = self._fake_notification_workflow(
|
||||
exc=exception.AutoRecoveryFailureException)
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("error", notification.status)
|
||||
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_host_failure")
|
||||
def test_process_notification_type_compute_host_event_started(
|
||||
self, mock_host_failure, mock_notification_save):
|
||||
notification = self._get_compute_host_type_notification()
|
||||
notification.payload['event'] = 'started'
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("finished", notification.status)
|
||||
self.assertFalse(mock_host_failure.called)
|
||||
|
||||
@mock.patch.object(notification_obj.Notification, "save")
|
||||
@mock.patch("masakari.engine.drivers.taskflow."
|
||||
"TaskFlowDriver.execute_host_failure")
|
||||
def test_process_notification_type_compute_host_event_other(
|
||||
self, mock_host_failure, mock_notification_save):
|
||||
notification = self._get_compute_host_type_notification()
|
||||
notification.payload['event'] = 'other'
|
||||
self.engine.process_notification(self.context,
|
||||
notification=notification)
|
||||
self.assertEqual("ignored", notification.status)
|
||||
self.assertFalse(mock_host_failure.called)
|
88
masakari/tests/unit/engine/test_rpcapi.py
Normal file
88
masakari/tests/unit/engine/test_rpcapi.py
Normal file
@ -0,0 +1,88 @@
|
||||
# Copyright (c) 2016 NTT DATA
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Unit Tests for masakari.engine.rpcapi
|
||||
"""
|
||||
|
||||
import copy
|
||||
|
||||
import mock
|
||||
|
||||
from masakari import context
|
||||
from masakari.engine import rpcapi as engine_rpcapi
|
||||
from masakari import objects
|
||||
from masakari import test
|
||||
from masakari.tests.unit.engine import fake_engine
|
||||
|
||||
|
||||
class EngineRpcAPITestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(EngineRpcAPITestCase, self).setUp()
|
||||
self.context = context.RequestContext()
|
||||
self.fake_notification_obj = fake_engine.fake_notification_obj(
|
||||
self.context)
|
||||
|
||||
def _test_engine_api(self, method, rpc_method, server=None, fanout=False,
|
||||
**kwargs):
|
||||
rpcapi = engine_rpcapi.EngineAPI()
|
||||
expected_retval = 'foo' if rpc_method == 'call' else None
|
||||
|
||||
target = {
|
||||
"server": server,
|
||||
"fanout": fanout,
|
||||
"version": kwargs.pop('version', rpcapi.RPC_API_VERSION)
|
||||
}
|
||||
|
||||
expected_msg = copy.deepcopy(kwargs)
|
||||
|
||||
self.fake_args = None
|
||||
self.fake_kwargs = None
|
||||
|
||||
def _fake_prepare_method(*args, **kwds):
|
||||
for kwd in kwds:
|
||||
self.assertEqual(target[kwd], kwds[kwd])
|
||||
return rpcapi.client
|
||||
|
||||
def _fake_rpc_method(*args, **kwargs):
|
||||
self.fake_args = args
|
||||
self.fake_kwargs = kwargs
|
||||
if expected_retval:
|
||||
return expected_retval
|
||||
|
||||
with mock.patch.object(rpcapi.client, "prepare") as mock_prepared:
|
||||
mock_prepared.side_effect = _fake_prepare_method
|
||||
|
||||
with mock.patch.object(rpcapi.client, rpc_method) as mock_method:
|
||||
mock_method.side_effect = _fake_rpc_method
|
||||
retval = getattr(rpcapi, method)(self.context, **kwargs)
|
||||
self.assertEqual(expected_retval, retval)
|
||||
expected_args = [self.context, method, expected_msg]
|
||||
for arg, expected_arg in zip(self.fake_args, expected_args):
|
||||
self.assertEqual(expected_arg, arg)
|
||||
|
||||
for kwarg, value in self.fake_kwargs.items():
|
||||
if isinstance(value, objects.Notification):
|
||||
expected_back = expected_msg[kwarg].obj_to_primitive()
|
||||
backup = value.obj_to_primitive()
|
||||
self.assertEqual(expected_back, backup)
|
||||
else:
|
||||
self.assertEqual(expected_msg[kwarg], value)
|
||||
|
||||
@mock.patch("masakari.rpc.get_client")
|
||||
def test_process_notification(self, mock_get_client):
|
||||
self._test_engine_api('process_notification',
|
||||
rpc_method='cast',
|
||||
notification=self.fake_notification_obj,
|
||||
version='1.0')
|
Loading…
Reference in New Issue
Block a user