Prevent executor finalization until exception are not handled

If exception was raised during the deployment early call to
executor.finalize() caused exception stack trace to be garbage
collected. As a result attempt to log it caused another exception.

This commit moves executor finalization to __exit__ method
which is invoked after the logging. In case of success finalize()
is going to be called twice but due to the fact that it clears
the state it doesn't cause any issues

Targets-blueprint: dependency-driven-resource-deallocation
Change-Id: I160dbdfd938ee3eed7ddd27bc0e082a576401fad
This commit is contained in:
Snihyr Kostyantyn 2016-09-13 22:10:28 +03:00 committed by Stan Lagun
parent 2b57eb3fca
commit 9bbd33d42d
2 changed files with 60 additions and 55 deletions

View File

@ -214,58 +214,50 @@ class TaskExecutor(object):
return result
def _execute(self, pkg_loader):
get_plugin_loader().register_in_loader(pkg_loader)
executor = dsl_executor.MuranoDslExecutor(
pkg_loader, ContextManager(), self.session)
try:
obj = executor.load(self.model)
except Exception as e:
executor.finalize()
return self.exception_result(e, None, '<load>')
if obj is not None:
with dsl_executor.MuranoDslExecutor(
pkg_loader, ContextManager(), self.session) as executor:
try:
self._validate_model(obj.object, pkg_loader, executor)
obj = executor.load(self.model)
except Exception as e:
executor.finalize()
return self.exception_result(e, obj, '<validate>')
return self.exception_result(e, None, '<load>')
try:
LOG.debug('Invoking pre-cleanup hooks')
self.session.start()
executor.object_store.cleanup()
except Exception as e:
executor.finalize()
return self.exception_result(e, obj, '<GC>')
finally:
LOG.debug('Invoking post-cleanup hooks')
self.session.finish()
self._model['ObjectsCopy'] = copy.deepcopy(self._model.get('Objects'))
action_result = None
if self.action:
try:
LOG.debug('Invoking pre-execution hooks')
self.session.start()
if obj is not None:
try:
action_result = self._invoke(executor)
finally:
try:
self._model = executor.finalize(obj)
except Exception as e:
return self.exception_result(e, None, '<model>')
self._validate_model(obj.object, pkg_loader, executor)
except Exception as e:
return self.exception_result(e, obj, '<validate>')
try:
LOG.debug('Invoking pre-cleanup hooks')
self.session.start()
executor.object_store.cleanup()
except Exception as e:
executor.finalize()
return self.exception_result(e, obj, self.action['method'])
return self.exception_result(e, obj, '<GC>')
finally:
LOG.debug('Invoking post-execution hooks')
LOG.debug('Invoking post-cleanup hooks')
self.session.finish()
self._model['ObjectsCopy'] = \
copy.deepcopy(self._model.get('Objects'))
try:
action_result = serializer.serialize(action_result, executor)
except Exception as e:
return self.exception_result(e, None, '<result>')
action_result = None
if self.action:
try:
LOG.debug('Invoking pre-execution hooks')
self.session.start()
try:
action_result = self._invoke(executor)
finally:
self._model = executor.finalize(obj)
except Exception as e:
return self.exception_result(e, obj, self.action['method'])
LOG.debug('Invoking post-execution hooks')
self.session.finish()
try:
action_result = serializer.serialize(action_result, executor)
except Exception as e:
return self.exception_result(e, None, '<result>')
pkg_loader.compact_fixation_table()
return {

View File

@ -24,7 +24,7 @@ from yaql.language import exceptions as yaql_exceptions
from yaql.language import specs
from yaql.language import utils
from murano.common.i18n import _LW
from murano.common.i18n import _LW, _LE
from murano.dsl import attribute_store
from murano.dsl import constants
from murano.dsl import dsl
@ -463,14 +463,27 @@ class MuranoDslExecutor(object):
value, cls, context)
def finalize(self, model_root=None):
if model_root:
used_objects = serializer.collect_objects(model_root)
self.object_store.prepare_finalize(used_objects)
model = serializer.serialize_model(model_root, self)
self.object_store.finalize()
else:
model = None
self.object_store.prepare_finalize(None)
self.object_store.finalize()
self._static_properties.clear()
return model
# NOTE(ksnihyr): should be no-except
try:
if model_root:
used_objects = serializer.collect_objects(model_root)
self.object_store.prepare_finalize(used_objects)
model = serializer.serialize_model(model_root, self)
self.object_store.finalize()
else:
model = None
self.object_store.prepare_finalize(None)
self.object_store.finalize()
self._static_properties.clear()
return model
except Exception as e:
LOG.exception(
_LE("Exception %s occurred"
" during MuranoDslExecutor finalization"), e)
return None
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.finalize()