magnum/magnum/conductor/handlers/nodegroup_conductor.py

153 lines
5.6 KiB
Python

# Copyright (c) 2018 European Organization for Nuclear Research.
# All Rights Reserved.
#
# 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 heatclient import exc
from oslo_log import log as logging
import six
from magnum.common import exception
from magnum.common import profiler
import magnum.conf
from magnum.drivers.common import driver
from magnum.i18n import _
from magnum.objects import fields
CONF = magnum.conf.CONF
LOG = logging.getLogger(__name__)
# TODO(ttsiouts): notifications about nodegroup operations will be
# added in later commit.
ALLOWED_NODEGROUP_STATES = (
fields.ClusterStatus.CREATE_COMPLETE,
fields.ClusterStatus.UPDATE_COMPLETE,
fields.ClusterStatus.UPDATE_IN_PROGRESS,
fields.ClusterStatus.UPDATE_FAILED,
fields.ClusterStatus.RESUME_COMPLETE,
fields.ClusterStatus.RESTORE_COMPLETE,
fields.ClusterStatus.ROLLBACK_COMPLETE,
fields.ClusterStatus.SNAPSHOT_COMPLETE,
fields.ClusterStatus.CHECK_COMPLETE,
fields.ClusterStatus.ADOPT_COMPLETE
)
def allowed_operation(func):
@functools.wraps(func)
def wrapper(self, context, cluster, nodegroup, *args, **kwargs):
# Before we begin we need to check the status
# of the cluster. If the cluster is in a status
# that does not allow nodegroup creation we just
# fail.
if ('status' in nodegroup
and nodegroup.status not in ALLOWED_NODEGROUP_STATES):
operation = _(
'%(fname)s when nodegroup status is "%(status)s"'
) % {'fname': func.__name__, 'status': cluster.status}
raise exception.NotSupported(operation=operation)
return func(self, context, cluster, nodegroup, *args, **kwargs)
return wrapper
@profiler.trace_cls("rpc")
class Handler(object):
@allowed_operation
def nodegroup_create(self, context, cluster, nodegroup):
LOG.debug("nodegroup_conductor nodegroup_create")
cluster.status = fields.ClusterStatus.UPDATE_IN_PROGRESS
cluster.save()
nodegroup.status = fields.ClusterStatus.CREATE_IN_PROGRESS
nodegroup.create()
try:
cluster_driver = driver.Driver.get_driver_for_cluster(context,
cluster)
cluster_driver.create_nodegroup(context, cluster, nodegroup)
nodegroup.save()
except Exception as e:
nodegroup.status = fields.ClusterStatus.CREATE_FAILED
nodegroup.status_reason = six.text_type(e)
nodegroup.save()
cluster.status = fields.ClusterStatus.UPDATE_FAILED
cluster.save()
if isinstance(e, exc.HTTPBadRequest):
e = exception.InvalidParameterValue(message=six.text_type(e))
raise e
raise
return nodegroup
@allowed_operation
def nodegroup_update(self, context, cluster, nodegroup):
LOG.debug("nodegroup_conductor nodegroup_update")
cluster.status = fields.ClusterStatus.UPDATE_IN_PROGRESS
cluster.save()
nodegroup.status = fields.ClusterStatus.UPDATE_IN_PROGRESS
try:
cluster_driver = driver.Driver.get_driver_for_cluster(context,
cluster)
cluster_driver.update_nodegroup(context, cluster, nodegroup)
nodegroup.save()
except Exception as e:
nodegroup.status = fields.ClusterStatus.UPDATE_FAILED
nodegroup.status_reason = six.text_type(e)
nodegroup.save()
cluster.status = fields.ClusterStatus.UPDATE_FAILED
cluster.save()
if isinstance(e, exc.HTTPBadRequest):
e = exception.InvalidParameterValue(message=six.text_type(e))
raise e
raise
return nodegroup
def nodegroup_delete(self, context, cluster, nodegroup):
LOG.debug("nodegroup_conductor nodegroup_delete")
cluster.status = fields.ClusterStatus.UPDATE_IN_PROGRESS
cluster.save()
nodegroup.status = fields.ClusterStatus.DELETE_IN_PROGRESS
try:
cluster_driver = driver.Driver.get_driver_for_cluster(context,
cluster)
cluster_driver.delete_nodegroup(context, cluster, nodegroup)
except exc.HTTPNotFound:
LOG.info('The nodegroup %s was not found during nodegroup'
' deletion.', nodegroup.uuid)
try:
nodegroup.destroy()
except exception.NodeGroupNotFound:
LOG.info('The nodegroup %s has been deleted by others.',
nodegroup.uuid)
return None
except exc.HTTPConflict:
raise exception.NgOperationInProgress(nodegroup=nodegroup.name)
except Exception as e:
nodegroup.status = fields.ClusterStatus.DELETE_FAILED
nodegroup.status_reason = six.text_type(e)
nodegroup.save()
cluster.status = fields.ClusterStatus.UPDATE_FAILED
cluster.save()
raise
return None