Merge "convergence: add adopt support"

This commit is contained in:
Jenkins 2015-07-14 00:55:46 +00:00 committed by Gerrit Code Review
commit 41e5d679cf
6 changed files with 50 additions and 18 deletions

View File

@ -259,6 +259,7 @@ class Resource(object):
db_res = resource_objects.Resource.get_obj(context, resource_id)
# TODO(sirushtim): Load stack from cache
stack = stack_mod.Stack.load(context, db_res.stack_id)
stack.adopt_stack_data = data.get('adopt_stack_data')
# NOTE(sirushtim): Because on delete/cleanup operations, we simply
# update with another template, the stack object won't have the
# template of the previous stack-run.
@ -676,7 +677,11 @@ class Resource(object):
set(data[u'id'] for data in resource_data.values()
if data is not None)
)
runner = scheduler.TaskRunner(self.create)
adopt_data = self.stack._adopt_kwargs(self)
if adopt_data['resource_data'] is None:
runner = scheduler.TaskRunner(self.create)
else:
runner = scheduler.TaskRunner(self.adopt, **adopt_data)
runner()
@scheduler.wrappertask

View File

@ -688,7 +688,6 @@ class EngineService(service.Service):
six.text_type(ex))
def _stack_create(stack):
_create_stack_user(stack)
# Create/Adopt a stack, and create the periodic task if successful
if stack.adopt_stack_data:
stack.adopt()
@ -710,14 +709,15 @@ class EngineService(service.Service):
nested_depth, user_creds_id, stack_user_project_id, convergence,
parent_resource_name)
# once validations are done
# if convergence is enabled, take convergence path
stack.store()
_create_stack_user(stack)
if convergence:
# TODO(later): call _create_stack_user(stack)
# call stack.converge_stack(template=stack.t, action=stack.CREATE)
raise exception.NotSupported(feature=_('Convergence engine'))
action = stack.CREATE
if stack.adopt_stack_data:
action = stack.ADOPT
stack.converge_stack(template=stack.t, action=action)
else:
stack.store()
self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id,
_stack_create, stack)
@ -782,8 +782,6 @@ class EngineService(service.Service):
self._validate_deferred_auth_context(cnxt, updated_stack)
updated_stack.validate()
# Once all the validations are done
# if convergence is enabled, take the convergence path
if current_kwargs['convergence']:
current_stack.converge_stack(template=tmpl,
new_stack=updated_stack)

View File

@ -939,7 +939,7 @@ class Stack(collections.Mapping):
"""
Updates the stack and triggers convergence for resources
"""
if action is not self.CREATE:
if action not in [self.CREATE, self.ADOPT]:
# no back-up template for create action
self.prev_raw_template_id = getattr(self.t, 'id', None)
@ -995,9 +995,11 @@ class Stack(collections.Mapping):
LOG.info(_LI("Triggering resource %(rsrc_id)s "
"for %(is_update)s update"),
{'rsrc_id': rsrc_id, 'is_update': is_update})
input_data = {'input_data': {},
'adopt_stack_data': self.adopt_stack_data}
self.worker_client.check_resource(self.context, rsrc_id,
self.current_traversal,
{}, is_update)
input_data, is_update)
def _get_best_existing_rsrc_db(self, rsrc_name):
candidate = None

View File

@ -123,7 +123,7 @@ class WorkerService(service.Service):
stack.state_set(stack.action, stack.FAILED, failure_reason)
if (not stack.disable_rollback and
stack.action in (stack.CREATE, stack.UPDATE)):
stack.action in (stack.CREATE, stack.ADOPT, stack.UPDATE)):
self._trigger_rollback(cnxt, stack)
else:
stack.purge_db()
@ -137,11 +137,13 @@ class WorkerService(service.Service):
The node may be associated with either an update or a cleanup of its
associated resource.
'''
adopt_data = data.get('adopt_stack_data')
data = dict(sync_point.deserialize_input_data(data))
try:
cache_data = {in_data.get(
'name'): in_data for in_data in data.values()
if in_data is not None}
cache_data['adopt_stack_data'] = adopt_data
rsrc, stack = resource.Resource.load(cnxt, resource_id, cache_data)
except (exception.ResourceNotFound, exception.NotFound):
return

View File

@ -212,7 +212,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
for rsrc_id, is_update in leaves:
expected_calls.append(
mock.call.worker_client.WorkerClient.check_resource(
stack.context, rsrc_id, stack.current_traversal, {},
stack.context, rsrc_id, stack.current_traversal,
{'input_data': {}, 'adopt_stack_data': None},
is_update))
self.assertEqual(expected_calls, mock_cr.mock_calls)
@ -268,7 +269,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
for rsrc_id, is_update in leaves:
expected_calls.append(
mock.call.worker_client.WorkerClient.check_resource(
stack.context, rsrc_id, stack.current_traversal, {},
stack.context, rsrc_id, stack.current_traversal,
{'input_data': {}, 'adopt_stack_data': None},
is_update))
self.assertEqual(expected_calls, mock_cr.mock_calls)
@ -403,7 +405,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
for rsrc_id, is_update in leaves:
expected_calls.append(
mock.call.worker_client.WorkerClient.check_resource(
stack.context, rsrc_id, stack.current_traversal, {},
stack.context, rsrc_id, stack.current_traversal,
{'input_data': {}, 'adopt_stack_data': None},
is_update))
leaves = curr_stack.convergence_dependencies.leaves()
@ -411,7 +414,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
expected_calls.append(
mock.call.worker_client.WorkerClient.check_resource(
curr_stack.context, rsrc_id, curr_stack.current_traversal,
{}, is_update))
{'input_data': {}, 'adopt_stack_data': None},
is_update))
self.assertEqual(expected_calls, mock_cr.mock_calls)
def test_conv_empty_template_stack_update_delete(self, mock_cr):
@ -482,7 +486,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
for rsrc_id, is_update in leaves:
expected_calls.append(
mock.call.worker_client.WorkerClient.check_resource(
stack.context, rsrc_id, stack.current_traversal, {},
stack.context, rsrc_id, stack.current_traversal,
{'input_data': {}, 'adopt_stack_data': None},
is_update))
leaves = curr_stack.convergence_dependencies.leaves()
@ -490,7 +495,8 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
expected_calls.append(
mock.call.worker_client.WorkerClient.check_resource(
curr_stack.context, rsrc_id, curr_stack.current_traversal,
{}, is_update))
{'input_data': {}, 'adopt_stack_data': None},
is_update))
self.assertEqual(expected_calls, mock_cr.mock_calls)
def test_mark_complete_purges_db(self, mock_cr):

View File

@ -1430,6 +1430,7 @@ class ResourceTest(common.HeatTestCase):
def test_create_convergence(self, mock_create):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.CREATE
res._store()
self._assert_resource_lock(res.id, None, None)
res_data = {(1, True): {u'id': 1, u'name': 'A', 'attrs': {}},
@ -1459,6 +1460,24 @@ class ResourceTest(common.HeatTestCase):
self.assertItemsEqual([5, 3], res.requires)
self._assert_resource_lock(res.id, None, 2)
@mock.patch.object(resource.Resource, 'adopt')
def test_adopt_convergence(self, mock_adopt):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.ADOPT
res._store()
self.stack.adopt_stack_data = {'resources': {'test_res': {
'resource_id': 'fluffy'}}}
self._assert_resource_lock(res.id, None, None)
res_data = {(1, True): {u'id': 5, u'name': 'A', 'attrs': {}},
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
res.create_convergence(res_data, 'engine-007')
mock_adopt.assert_called_once_with(
resource_data={'resource_id': 'fluffy'})
self.assertItemsEqual([5, 3], res.requires)
self._assert_resource_lock(res.id, None, 2)
@mock.patch.object(resource.Resource, 'update')
def test_update_convergence(self, mock_update):
tmpl = rsrc_defn.ResourceDefinition('test_res',