deb-heat/heat/common/lifecycle_plugin_utils.py
Steven Hardy 70112c103a Move logging to use oslo_log library
The oslo-incubator log modlule has been removed, so port to the oslo_log
library.  Note this uses the new (non namespaced, e.g oslo.log) import
convention, we'll need to align other imports in a future commit.

Some import reordering was required due to pedantic H30[57] checks, and
the services have all been converted to initialize the oslo_log library
as this is done differently to the log.py in incubator.

Change-Id: Ib5a97123fe1b287bc531e42d7887c13ba6205628
2015-02-17 09:23:34 +00:00

121 lines
4.4 KiB
Python

#
# 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.
'''
Utility for fetching and running plug point implementation classes
'''
from oslo_log import log as logging
from heat.common.i18n import _LE
from heat.common.i18n import _LI
from heat.engine import resources
LOG = logging.getLogger(__name__)
pp_class_instances = None
def get_plug_point_class_instances():
'''
Get list of instances of classes that (may) implement pre and post
stack operation methods.
The list of class instances is sorted using get_ordinal methods
on the plug point classes. If class1.ordinal() < class2.ordinal(),
then class1 will be before before class2 in the list.
'''
global pp_class_instances
if pp_class_instances is None:
pp_class_instances = []
pp_classes = []
try:
slps = resources.global_env().get_stack_lifecycle_plugins()
pp_classes = [cls for name, cls in slps]
except Exception:
LOG.exception(_LE("failed to get lifecycle plug point classes"))
for ppc in pp_classes:
try:
pp_class_instances.append(ppc())
except Exception:
LOG.exception(
_LE("failed to instantiate stack lifecycle class %s"), ppc)
try:
pp_class_instances = sorted(pp_class_instances,
key=lambda ppci: ppci.get_ordinal())
except Exception:
LOG.exception(_LE("failed to sort lifecycle plug point classes"))
return pp_class_instances
def do_pre_ops(cnxt, stack, current_stack=None, action=None):
'''
Call available pre-op methods sequentially, in order determined with
get_ordinal(), with parameters context, stack, current_stack, action
On failure of any pre_op method, will call post-op methods corresponding
to successful calls of pre-op methods
'''
cinstances = get_plug_point_class_instances()
if action is None:
action = stack.action
failure, failure_exception_message, success_count = _do_ops(
cinstances, 'do_pre_op', cnxt, stack, current_stack, action, None)
if failure:
cinstances = cinstances[0:success_count]
_do_ops(cinstances, 'do_post_op', cnxt, stack, current_stack,
action, True)
raise Exception(failure_exception_message)
def do_post_ops(cnxt, stack, current_stack=None, action=None,
is_stack_failure=False):
'''
Call available post-op methods sequentially, in order determined with
get_ordinal(), with parameters context, stack, current_stack,
action, is_stack_failure
'''
cinstances = get_plug_point_class_instances()
if action is None:
action = stack.action
_do_ops(cinstances, 'do_post_op', cnxt, stack, current_stack, action, None)
def _do_ops(cinstances, opname, cnxt, stack, current_stack=None, action=None,
is_stack_failure=None):
success_count = 0
failure = False
failure_exception_message = None
for ci in cinstances:
op = getattr(ci, opname, None)
if callable(op):
try:
if is_stack_failure is not None:
op(cnxt, stack, current_stack, action, is_stack_failure)
else:
op(cnxt, stack, current_stack, action)
success_count += 1
except Exception as ex:
LOG.exception(_LE(
"%(opname) %(ci)s failed for %(a)s on %(sid)s") %
{'opname': opname, 'ci': type(ci),
'a': action, 'sid': stack.id})
failure = True
failure_exception_message = ex.args[0] if ex.args else str(ex)
break
LOG.info(_LI("done with class=%(c)s, stackid=%(sid)s, action=%(a)s") %
{'c': type(ci), 'sid': stack.id, 'a': action})
return (failure, failure_exception_message, success_count)