# 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