# 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_config import cfg from oslo_log import log as logging from oslo_utils import timeutils from oslo_utils import uuidutils import testtools from senlin.engine.actions import base as action_base from senlin.engine import cluster from senlin.engine import node from senlin.events import base from senlin.events import message as MSG from senlin.objects import notification as nobj from senlin.tests.unit.common import utils CLUSTER_ID = '2c5139a6-24ba-4a6f-bd53-a268f61536de' class TestMessageEvent(testtools.TestCase): def setUp(self): super(TestMessageEvent, self).setUp() self.ctx = utils.dummy_context() @mock.patch.object(nobj.NotificationBase, '_emit') def test__notify_cluster_action(self, mock_emit): cluster_id = uuidutils.generate_uuid() profile_id = uuidutils.generate_uuid() cluster_init = timeutils.utcnow(True) action_id = uuidutils.generate_uuid() cluster_params = { 'id': cluster_id, 'init_at': cluster_init, 'min_size': 1, 'max_size': 10, 'timeout': 4, 'status': 'ACTIVE', 'status_reason': 'Good', 'user': 'user1', 'project': 'project1', } c1 = cluster.Cluster('fake_name', 5, profile_id, **cluster_params) action_params = { 'id': action_id, 'name': 'fake_name', 'start_time': 1.23, 'status': 'RUNNING', 'status_reason': 'Good', 'user': 'user1', 'project': 'project1', } action = action_base.Action(cluster_id, 'CLUSTER_CREATE', self.ctx, **action_params) publisher_id = 'senlin-engine:%s' % cfg.CONF.host expected_payload = { 'senlin_object.data': { 'action': { 'senlin_object.data': { 'action': 'CLUSTER_CREATE', 'created_at': None, 'data': '{}', 'end_time': None, 'id': action_id, 'inputs': '{}', 'name': 'fake_name', 'outputs': '{}', 'project': self.ctx.project_id, 'start_time': 1.23, 'status': 'RUNNING', 'status_reason': 'Good', 'target': cluster_id, 'timeout': 3600, 'user': self.ctx.user_id, }, 'senlin_object.name': 'ActionPayload', 'senlin_object.namespace': 'senlin', 'senlin_object.version': '1.0' }, 'cluster': { 'senlin_object.data': { 'created_at': None, 'data': '{}', 'dependents': '{}', 'desired_capacity': 5, 'domain': '', 'id': cluster_id, 'init_at': mock.ANY, 'max_size': 10, 'metadata': '{}', 'min_size': 1, 'name': 'fake_name', 'profile_id': profile_id, 'project': u'project1', 'status': u'ACTIVE', 'status_reason': u'Good', 'timeout': 4, 'updated_at': None, 'user': u'user1' }, 'senlin_object.name': 'ClusterPayload', 'senlin_object.namespace': 'senlin', 'senlin_object.version': '1.0' }, 'exception': None }, 'senlin_object.name': 'ClusterActionPayload', 'senlin_object.namespace': 'senlin', 'senlin_object.version': '1.0' } res = MSG.MessageEvent._notify_cluster_action( self.ctx, logging.INFO, c1, action, phase='start') self.assertIsNone(res) mock_emit.assert_called_once_with( self.ctx, 'cluster.create.start', publisher_id, mock.ANY) payload = mock_emit.call_args[0][3] self.assertEqual(expected_payload, payload) @mock.patch.object(nobj.NotificationBase, '_emit') def test__notify_node_action(self, mock_emit): node_id = uuidutils.generate_uuid() profile_id = uuidutils.generate_uuid() node_init = timeutils.utcnow(True) action_id = uuidutils.generate_uuid() node_params = { 'id': node_id, 'cluster_id': '', 'index': -1, 'init_at': node_init, 'status': 'ACTIVE', 'status_reason': 'Good', 'user': 'user1', 'project': 'project1', } n1 = node.Node('fake_name', profile_id, **node_params) action_params = { 'id': action_id, 'name': 'fake_name', 'start_time': 1.23, 'status': 'RUNNING', 'status_reason': 'Good', } action = action_base.Action(node_id, 'NODE_CREATE', self.ctx, **action_params) publisher_id = 'senlin-engine:%s' % cfg.CONF.host expected_payload = { 'senlin_object.data': { 'action': { 'senlin_object.data': { 'action': 'NODE_CREATE', 'created_at': None, 'data': '{}', 'end_time': None, 'id': action_id, 'inputs': '{}', 'name': 'fake_name', 'outputs': '{}', 'project': self.ctx.project_id, 'start_time': 1.23, 'status': 'RUNNING', 'status_reason': 'Good', 'target': node_id, 'timeout': 3600, 'user': self.ctx.user_id, }, 'senlin_object.name': 'ActionPayload', 'senlin_object.namespace': 'senlin', 'senlin_object.version': '1.0' }, 'node': { 'senlin_object.data': { 'cluster_id': '', 'created_at': None, 'data': '{}', 'dependents': '{}', 'domain': '', 'id': node_id, 'index': -1, 'init_at': mock.ANY, 'metadata': '{}', 'name': 'fake_name', 'physical_id': None, 'profile_id': profile_id, 'project': 'project1', 'role': '', 'status': 'ACTIVE', 'status_reason': 'Good', 'updated_at': None, 'user': 'user1', }, 'senlin_object.name': 'NodePayload', 'senlin_object.namespace': 'senlin', 'senlin_object.version': '1.0' }, 'exception': None }, 'senlin_object.name': 'NodeActionPayload', 'senlin_object.namespace': 'senlin', 'senlin_object.version': '1.0' } res = MSG.MessageEvent._notify_node_action( self.ctx, logging.INFO, n1, action, phase='start') self.assertIsNone(res) mock_emit.assert_called_once_with( self.ctx, 'node.create.start', publisher_id, mock.ANY) payload = mock_emit.call_args[0][3] self.assertEqual(expected_payload, payload) @mock.patch.object(MSG.MessageEvent, '_notify_cluster_action') @mock.patch.object(base.EventBackend, '_check_entity') def test_dump_cluster_action_event(self, mock_check, mock_notify): mock_check.return_value = 'CLUSTER' entity = mock.Mock() action = mock.Mock(context=self.ctx, entity=entity) res = MSG.MessageEvent.dump(logging.INFO, action) self.assertIsNone(res) mock_check.assert_called_once_with(entity) mock_notify.assert_called_once_with(self.ctx, logging.INFO, entity, action) @mock.patch.object(MSG.MessageEvent, '_notify_cluster_action') @mock.patch.object(base.EventBackend, '_check_entity') def test_dump_cluster_action_event_warn(self, mock_check, mock_notify): mock_check.return_value = 'CLUSTER' entity = mock.Mock() action = mock.Mock(context=self.ctx, entity=entity) res = MSG.MessageEvent.dump(logging.WARNING, action) self.assertIsNone(res) mock_check.assert_called_once_with(entity) mock_notify.assert_called_once_with(self.ctx, logging.WARNING, entity, action) @mock.patch.object(MSG.MessageEvent, '_notify_node_action') @mock.patch.object(base.EventBackend, '_check_entity') def test_dump_node_action_event(self, mock_check, mock_notify): mock_check.return_value = 'NODE' entity = mock.Mock() action = mock.Mock(context=self.ctx, entity=entity) res = MSG.MessageEvent.dump(logging.INFO, action) self.assertIsNone(res) mock_check.assert_called_once_with(entity) mock_notify.assert_called_once_with(self.ctx, logging.INFO, entity, action)