Make stack check convergence aware
Change-Id: I6883a1c2694fb77f76c7b93ed02f9263bfb6bb09 Story: #1727142 Task: 17325
This commit is contained in:
parent
61048ef16b
commit
c5390a99e3
|
@ -389,6 +389,9 @@ def check_resource_update(rsrc, template_id, requires, engine_id,
|
|||
if rsrc.action == resource.Resource.INIT:
|
||||
rsrc.create_convergence(template_id, requires, engine_id,
|
||||
stack.time_remaining(), check_message)
|
||||
elif rsrc.action == resource.Resource.CHECK:
|
||||
rsrc.check_convergence(engine_id, stack.time_remaining(),
|
||||
check_message)
|
||||
else:
|
||||
rsrc.update_convergence(template_id, requires, engine_id,
|
||||
stack.time_remaining(), stack,
|
||||
|
@ -398,6 +401,9 @@ def check_resource_update(rsrc, template_id, requires, engine_id,
|
|||
def check_resource_cleanup(rsrc, template_id, engine_id,
|
||||
timeout, msg_queue):
|
||||
"""Delete the Resource if appropriate."""
|
||||
if rsrc.action == resource.Resource.CHECK:
|
||||
return
|
||||
|
||||
check_message = functools.partial(_check_for_message, msg_queue)
|
||||
rsrc.delete_convergence(template_id, engine_id, timeout,
|
||||
check_message)
|
||||
|
|
|
@ -1417,6 +1417,12 @@ class Resource(status.ResourceStatus):
|
|||
else:
|
||||
raise UpdateReplace(self.name)
|
||||
|
||||
def check_convergence(self, engine_id, timeout, progress_callback=None):
|
||||
"""Check the resource synchronously."""
|
||||
self._calling_engine_id = engine_id
|
||||
runner = scheduler.TaskRunner(self.check)
|
||||
runner(timeout=timeout, progress_callback=progress_callback)
|
||||
|
||||
def update_convergence(self, template_id, new_requires, engine_id,
|
||||
timeout, new_stack, progress_callback=None):
|
||||
"""Update the resource synchronously.
|
||||
|
|
|
@ -2151,10 +2151,16 @@ class EngineService(service.ServiceBase):
|
|||
stack = parser.Stack.load(cnxt, stack=s)
|
||||
LOG.info("Checking stack %s", stack.name)
|
||||
|
||||
stored_event = NotifyEvent()
|
||||
self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id,
|
||||
stack.check, notify=stored_event)
|
||||
stored_event.wait()
|
||||
if stack.convergence:
|
||||
stack.thread_group_mgr = self.thread_group_mgr
|
||||
stack.converge_stack(template=stack.t,
|
||||
action=stack.CHECK)
|
||||
else:
|
||||
stored_event = NotifyEvent()
|
||||
self.thread_group_mgr.start_with_lock(
|
||||
cnxt, stack, self.engine_id,
|
||||
stack.check, notify=stored_event)
|
||||
stored_event.wait()
|
||||
|
||||
@context.request_context
|
||||
def stack_restore(self, cnxt, stack_identity, snapshot_id):
|
||||
|
|
|
@ -984,7 +984,8 @@ class Stack(collections.Mapping):
|
|||
|
||||
if (self.convergence and
|
||||
self.action in {self.UPDATE, self.DELETE, self.CREATE,
|
||||
self.ADOPT, self.ROLLBACK, self.RESTORE}):
|
||||
self.ADOPT, self.ROLLBACK, self.RESTORE,
|
||||
self.CHECK}):
|
||||
# These operations do not use the stack lock in convergence, so
|
||||
# never defer.
|
||||
return False
|
||||
|
@ -1339,16 +1340,18 @@ class Stack(collections.Mapping):
|
|||
def converge_stack(self, template, action=UPDATE, new_stack=None,
|
||||
pre_converge=None):
|
||||
"""Update the stack template and trigger convergence for resources."""
|
||||
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)
|
||||
if action != self.CHECK:
|
||||
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)
|
||||
# switch template and reset dependencies
|
||||
self.defn = self.defn.clone_with_new_template(
|
||||
template, self.identifier(), clear_resource_data=True)
|
||||
|
||||
# switch template and reset dependencies
|
||||
self.defn = self.defn.clone_with_new_template(template,
|
||||
self.identifier(),
|
||||
clear_resource_data=True)
|
||||
self.reset_dependencies()
|
||||
self._resources = None
|
||||
self.reset_dependencies()
|
||||
self._resources = None
|
||||
else:
|
||||
assert new_stack is None
|
||||
|
||||
if action != self.CREATE:
|
||||
self.updated_time = oslo_timeutils.utcnow()
|
||||
|
|
|
@ -81,6 +81,19 @@ class Engine(message_processor.MessageProcessor):
|
|||
srv.create_stack(cnxt, stack_name, hot_tmpl,
|
||||
params={}, files={}, environment_files=None, args={})
|
||||
|
||||
@message_processor.asynchronous
|
||||
def check_stack(self, stack_name):
|
||||
cnxt = utils.dummy_context()
|
||||
db_stack = db_api.stack_get_by_name(cnxt, stack_name)
|
||||
srv = service.EngineService("host", "engine")
|
||||
srv.thread_group_mgr = SynchronousThreadGroupManager()
|
||||
srv.worker_service = self.worker
|
||||
stack_identity = {'stack_name': stack_name,
|
||||
'stack_id': db_stack.id,
|
||||
'tenant': db_stack.tenant,
|
||||
'path': ''}
|
||||
srv.stack_check(cnxt, stack_identity)
|
||||
|
||||
@message_processor.asynchronous
|
||||
def update_stack(self, stack_name, scenario_tmpl):
|
||||
cnxt = utils.dummy_context()
|
||||
|
|
|
@ -25,8 +25,9 @@ class RealityStore(object):
|
|||
ret = []
|
||||
resources = db_api.resource_get_all(self.cntxt)
|
||||
for res in resources:
|
||||
if (res.name == logical_name and res.action in ("CREATE", "UPDATE")
|
||||
and res.status == "COMPLETE"):
|
||||
if (res.name == logical_name and
|
||||
res.action in ("CREATE", "UPDATE",
|
||||
"CHECK") and res.status == "COMPLETE"):
|
||||
ret.append(res)
|
||||
return ret
|
||||
|
||||
|
@ -38,7 +39,8 @@ class RealityStore(object):
|
|||
|
||||
ret = []
|
||||
for res in resources:
|
||||
if res.action in ("CREATE", "UPDATE") and res.status == "COMPLETE":
|
||||
if res.action in ("CREATE", "UPDATE",
|
||||
"CHECK") and res.status == "COMPLETE":
|
||||
ret.append(res)
|
||||
return ret
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# 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.
|
||||
|
||||
def check_resource_count(expected_count):
|
||||
test.assertEqual(expected_count, len(reality.all_resources()))
|
||||
|
||||
example_template = Template({
|
||||
'A': RsrcDef({}, []),
|
||||
'B': RsrcDef({}, []),
|
||||
'C': RsrcDef({'a': '4alpha'}, ['A', 'B']),
|
||||
'D': RsrcDef({'c': GetRes('C')}, []),
|
||||
'E': RsrcDef({'ca': GetAtt('C', 'a')}, []),
|
||||
})
|
||||
engine.create_stack('foo', example_template)
|
||||
engine.noop(5)
|
||||
engine.call(check_resource_count, 5)
|
||||
engine.call(verify, example_template)
|
||||
|
||||
engine.check_stack('foo')
|
||||
engine.noop(10)
|
||||
engine.call(check_resource_count, 5)
|
||||
engine.call(verify, example_template)
|
Loading…
Reference in New Issue