e1f5bcf08c
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
204 lines
5.8 KiB
Python
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
|