1
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
18
from heat.engine import resource
19
from heat.engine import stack
20
from heat.engine import sync_point
21
from heat.engine import worker
22
from heat.rpc import worker_client
23
from heat.tests import common
24
from heat.tests.engine import tools
25
from heat.tests import utils
28
class WorkerServiceTest(common.HeatTestCase):
30
super(WorkerServiceTest, self).setUp()
31
thread_group_mgr = mock.Mock()
32
self.worker = worker.WorkerService('host-1',
37
def test_make_sure_rpc_version(self):
40
worker.WorkerService.RPC_API_VERSION,
41
('RPC version is changed, please update this test to new version '
42
'and make sure additional test cases are added for RPC APIs '
43
'added in new version'))
45
@mock.patch('heat.common.messaging.get_rpc_server',
46
return_value=mock.Mock())
47
@mock.patch('oslo_messaging.Target',
48
return_value=mock.Mock())
49
@mock.patch('heat.rpc.worker_client.WorkerClient',
50
return_value=mock.Mock())
51
def test_service_start(self,
58
# Make sure target is called with proper parameters
59
target_class.assert_called_once_with(
60
version=worker.WorkerService.RPC_API_VERSION,
61
server=self.worker.host,
62
topic=self.worker.topic)
64
# Make sure rpc server creation with proper target
65
# and WorkerService is initialized with it
66
target = target_class.return_value
67
rpc_server_method.assert_called_once_with(target,
69
rpc_server = rpc_server_method.return_value
70
self.assertEqual(rpc_server,
71
self.worker._rpc_server,
72
"Failed to create RPC server")
74
# Make sure rpc server is started.
75
rpc_server.start.assert_called_once_with()
77
# Make sure rpc client is created and initialized in WorkerService
78
rpc_client = rpc_client_class.return_value
79
rpc_client_class.assert_called_once_with()
80
self.assertEqual(rpc_client,
81
self.worker._rpc_client,
82
"Failed to create RPC client")
84
def test_service_stop(self):
85
with mock.patch.object(self.worker, '_rpc_server') as mock_rpc_server:
87
mock_rpc_server.stop.assert_called_once_with()
88
mock_rpc_server.wait.assert_called_once_with()
91
@mock.patch.object(worker, 'construct_input_data')
92
@mock.patch.object(worker, 'check_stack_complete')
93
@mock.patch.object(worker, 'propagate_check_resource')
94
@mock.patch.object(worker, 'check_resource_cleanup')
95
@mock.patch.object(worker, 'check_resource_update')
96
class CheckWorkflowUpdateTest(common.HeatTestCase):
97
@mock.patch.object(worker_client.WorkerClient, 'check_resource',
100
super(CheckWorkflowUpdateTest, self).setUp()
101
thread_group_mgr = mock.Mock()
102
self.worker = worker.WorkerService('host-1',
106
self.worker._rpc_client = worker_client.WorkerClient()
107
self.ctx = utils.dummy_context()
108
self.stack = tools.get_stack(
109
'check_workflow_create_stack', self.ctx,
110
template=tools.string_template_five, convergence=True)
111
self.stack.converge_stack(self.stack.t)
112
self.resource = self.stack['A']
113
self.is_update = True
114
self.graph_key = (self.resource.id, self.is_update)
116
def test_resource_not_available(
117
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
118
self.worker.check_resource(
119
self.ctx, 'non-existant-id', self.stack.current_traversal, {},
121
for mocked in [mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid]:
122
self.assertFalse(mocked.called)
124
def test_stale_traversal(
125
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
126
self.worker.check_resource(self.ctx, self.resource.id,
127
'stale-traversal', {}, True)
128
for mocked in [mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid]:
129
self.assertFalse(mocked.called)
131
def test_is_update_traversal(
132
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
133
self.worker.check_resource(
134
self.ctx, self.resource.id, self.stack.current_traversal, {},
136
mock_cru.assert_called_once_with(self.resource,
137
self.resource.stack.t.id,
139
self.assertFalse(mock_crc.called)
142
for req, fwd in self.stack.convergence_dependencies.leaves():
143
expected_calls.append(
144
(mock.call.worker.propagate_check_resource.
145
assert_called_once_with(
146
self.ctx, mock.ANY, mock.ANY,
147
self.stack.current_traversal, mock.ANY,
148
self.graph_key, {}, self.is_update)))
149
mock_csc.assert_called_once_with(
150
self.ctx, mock.ANY, self.stack.current_traversal,
154
@mock.patch.object(resource.Resource, 'make_replacement')
155
def test_is_update_traversal_raise_update_replace(
156
self, mock_mr, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
157
mock_cru.side_effect = resource.UpdateReplace
158
self.worker.check_resource(
159
self.ctx, self.resource.id, self.stack.current_traversal, {},
161
mock_cru.assert_called_once_with(self.resource,
162
self.resource.stack.t.id,
164
self.assertTrue(mock_mr.called)
165
self.assertFalse(mock_crc.called)
166
self.assertFalse(mock_pcr.called)
167
self.assertFalse(mock_csc.called)
169
@mock.patch.object(resource.Resource, 'make_replacement')
170
def test_is_update_traversal_raise_update_inprogress(
171
self, mock_mr, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
172
mock_cru.side_effect = resource.UpdateInProgress
173
self.worker.check_resource(
174
self.ctx, self.resource.id, self.stack.current_traversal, {},
176
mock_cru.assert_called_once_with(self.resource,
177
self.resource.stack.t.id,
179
self.assertFalse(mock_mr.called)
180
self.assertFalse(mock_crc.called)
181
self.assertFalse(mock_pcr.called)
182
self.assertFalse(mock_csc.called)
185
@mock.patch.object(worker, 'construct_input_data')
186
@mock.patch.object(worker, 'check_stack_complete')
187
@mock.patch.object(worker, 'propagate_check_resource')
188
@mock.patch.object(worker, 'check_resource_cleanup')
189
@mock.patch.object(worker, 'check_resource_update')
190
class CheckWorkflowCleanupTest(common.HeatTestCase):
191
@mock.patch.object(worker_client.WorkerClient, 'check_resource',
194
super(CheckWorkflowCleanupTest, self).setUp()
195
thread_group_mgr = mock.Mock()
196
self.worker = worker.WorkerService('host-1',
200
self.worker._rpc_client = worker_client.WorkerClient()
201
self.ctx = utils.dummy_context()
202
tstack = tools.get_stack(
203
'check_workflow_create_stack', self.ctx,
204
template=tools.string_template_five, convergence=True)
205
tstack.converge_stack(tstack.t, action=tstack.CREATE)
206
self.stack = stack.Stack.load(self.ctx, stack_id=tstack.id)
207
self.stack.converge_stack(self.stack.t, action=self.stack.DELETE)
208
self.resource = self.stack['A']
209
self.is_update = False
210
self.graph_key = (self.resource.id, self.is_update)
212
def test_is_cleanup_traversal(
213
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
214
self.worker.check_resource(
215
self.ctx, self.resource.id, self.stack.current_traversal, {},
217
self.assertFalse(mock_cru.called)
218
mock_crc.assert_called_once_with(
219
self.resource, self.resource.stack.t.id,
222
def test_is_cleanup_traversal_raise_update_inprogress(
223
self, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid):
224
mock_crc.side_effect = resource.UpdateInProgress
225
self.worker.check_resource(
226
self.ctx, self.resource.id, self.stack.current_traversal, {},
228
mock_crc.assert_called_once_with(self.resource,
229
self.resource.stack.t.id,
231
self.assertFalse(mock_cru.called)
232
self.assertFalse(mock_pcr.called)
233
self.assertFalse(mock_csc.called)
236
class MiscMethodsTest(common.HeatTestCase):
238
super(MiscMethodsTest, self).setUp()
239
self.ctx = utils.dummy_context()
240
self.stack = tools.get_stack(
241
'check_workflow_create_stack', self.ctx,
242
template=tools.string_template_five, convergence=True)
243
self.stack.converge_stack(self.stack.t)
244
self.resource = self.stack['A']
246
def test_construct_input_data(self):
247
expected_input_data = {'attrs': {'value': None},
249
'physical_resource_id': None,
251
actual_input_data = worker.construct_input_data(self.resource)
252
self.assertEqual(expected_input_data, actual_input_data)
254
@mock.patch.object(sync_point, 'sync')
255
def test_check_stack_complete_root(self, mock_sync):
256
worker.check_stack_complete(
257
self.ctx, self.stack, self.stack.current_traversal,
258
self.stack['E'].id, self.stack.convergence_dependencies,
260
mock_sync.assert_called_once_with(
261
self.ctx, self.stack.id, self.stack.current_traversal, True,
262
mock.ANY, mock.ANY, {(self.stack['E'].id, True): None})
264
@mock.patch.object(sync_point, 'sync')
265
def test_check_stack_complete_child(self, mock_sync):
266
worker.check_stack_complete(
267
self.ctx, self.stack, self.stack.current_traversal,
268
self.resource.id, self.stack.convergence_dependencies,
270
self.assertFalse(mock_sync.called)
272
@mock.patch.object(sync_point, 'sync')
273
def test_propagate_check_resource(self, mock_sync):
274
worker.propagate_check_resource(
275
self.ctx, mock.ANY, mock.ANY,
276
self.stack.current_traversal, mock.ANY,
278
self.assertTrue(mock_sync.called)
280
@mock.patch.object(resource.Resource, 'create_convergence')
281
def test_check_resource_update_create(self, mock_create):
282
worker.check_resource_update(self.resource, self.resource.stack.t.id,
284
self.assertTrue(mock_create.called)
286
@mock.patch.object(resource.Resource, 'update_convergence')
287
def test_check_resource_update_update(self, mock_update):
288
self.resource.resource_id = 'physical-res-id'
289
worker.check_resource_update(self.resource, self.resource.stack.t.id,
291
self.assertTrue(mock_update.called)
293
@mock.patch.object(resource.Resource, 'delete_convergence')
294
def test_check_resource_cleanup_delete(self, mock_delete):
295
self.resource.current_template_id = 'new-template-id'
296
worker.check_resource_cleanup(self.resource, self.resource.stack.t.id,
298
self.assertTrue(mock_delete.called)
300
@mock.patch.object(resource.Resource, 'delete_convergence')
301
def test_check_resource_cleanup_nodelete(self, mock_delete):
302
worker.check_resource_cleanup(self.resource, self.resource.stack.t.id,
304
self.assertFalse(mock_delete.called)