deb-sahara/sahara/utils/cluster_progress_ops.py
Li, Chen e1f5bcf08c Add CLUSTER_STATUS
We should define a set of CLUSTER_STATUS in stead of using direct string
in code.

1. Add cluster.py in utils/
2. Add cluster status.
3. move cluster operation related methods from general.py to cluster.py

Change-Id: Id95d982a911ab5d0f789265e03bff2256cf75856
2015-08-03 09:12:36 +08:00

204 lines
5.8 KiB
Python

# Copyright (c) 2014 Mirantis Inc.
#
# 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.
import functools
from oslo_config import cfg
from oslo_utils import excutils
from oslo_utils import timeutils
import six
from sahara import conductor as c
from sahara.conductor import resource
from sahara import context
from sahara.utils import cluster as cluster_utils
conductor = c.API
CONF = cfg.CONF
event_log_opts = [
cfg.BoolOpt('disable_event_log',
default=False,
help="Disables event log feature.")
]
CONF.register_opts(event_log_opts)
def add_successful_event(instance):
if CONF.disable_event_log:
return
cluster_id = instance.cluster_id
step_id = get_current_provisioning_step(cluster_id)
if step_id:
conductor.cluster_event_add(context.ctx(), step_id, {
'successful': True,
'node_group_id': instance.node_group_id,
'instance_id': instance.instance_id,
'instance_name': instance.instance_name,
'event_info': None,
})
def add_fail_event(instance, exception):
if CONF.disable_event_log:
return
cluster_id = instance.cluster_id
step_id = get_current_provisioning_step(cluster_id)
event_info = six.text_type(exception)
if step_id:
conductor.cluster_event_add(context.ctx(), step_id, {
'successful': False,
'node_group_id': instance.node_group_id,
'instance_id': instance.instance_id,
'instance_name': instance.instance_name,
'event_info': event_info,
})
def add_provisioning_step(cluster_id, step_name, total):
if (CONF.disable_event_log or
not cluster_utils.check_cluster_exists(cluster_id)):
return
prev_step = get_current_provisioning_step(cluster_id)
if prev_step:
conductor.cluster_provision_step_update(context.ctx(), prev_step)
step_type = context.ctx().current_instance_info.step_type
new_step = conductor.cluster_provision_step_add(
context.ctx(), cluster_id, {
'step_name': step_name,
'step_type': step_type,
'total': total,
'started_at': timeutils.utcnow(),
})
context.current().current_instance_info.step_id = new_step
return new_step
def get_current_provisioning_step(cluster_id):
if (CONF.disable_event_log or
not cluster_utils.check_cluster_exists(cluster_id)):
return None
current_instance_info = context.ctx().current_instance_info
return current_instance_info.step_id
def event_wrapper(mark_successful_on_exit, **spec):
""""General event-log wrapper
:param mark_successful_on_exit: should we send success event
after execution of function
:param spec: extra specification
:parameter step: provisioning step name (only for provisioning
steps with only one event)
:parameter param: tuple (name, pos) with parameter specification,
where 'name' is the name of the parameter of function, 'pos' is the
position of the parameter of function. This parameter is used to
extract info about Instance or Cluster.
"""
def decorator(func):
@functools.wraps(func)
def handler(*args, **kwargs):
if CONF.disable_event_log:
return func(*args, **kwargs)
step_name = spec.get('step', None)
instance = _find_in_args(spec, *args, **kwargs)
cluster_id = instance.cluster_id
if not cluster_utils.check_cluster_exists(cluster_id):
return func(*args, **kwargs)
if step_name:
# It's single process, let's add provisioning step here
add_provisioning_step(cluster_id, step_name, 1)
try:
value = func(*args, **kwargs)
except Exception as e:
with excutils.save_and_reraise_exception():
add_fail_event(instance, e)
if mark_successful_on_exit:
add_successful_event(instance)
return value
return handler
return decorator
def _get_info_from_instance(arg):
if isinstance(arg, resource.InstanceResource):
return arg
return None
def _get_info_from_cluster(arg):
if isinstance(arg, resource.ClusterResource):
return context.InstanceInfo(arg.id)
return None
def _get_event_info(arg):
try:
return arg.get_event_info()
except AttributeError:
return None
def _get_info_from_obj(arg):
functions = [_get_info_from_instance, _get_info_from_cluster,
_get_event_info]
for func in functions:
value = func(arg)
if value:
return value
return None
def _find_in_args(spec, *args, **kwargs):
param_values = spec.get('param', None)
if param_values:
p_name, p_pos = param_values
obj = kwargs.get(p_name, None)
if obj:
return _get_info_from_obj(obj)
return _get_info_from_obj(args[p_pos])
# If param is not specified, let's search instance in args
for arg in args:
val = _get_info_from_instance(arg)
if val:
return val
for arg in kwargs.values():
val = _get_info_from_instance(arg)
if val:
return val
# If instance not found in args, let's get instance info from context
return context.ctx().current_instance_info