206 lines
6.5 KiB
Python
206 lines
6.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2013 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 traceback
|
|
|
|
import web
|
|
|
|
from nailgun.api.v1.handlers.base import BaseHandler
|
|
from nailgun.api.v1.handlers.base import content_json
|
|
from nailgun.api.v1.validators.node import NodesFilterValidator
|
|
|
|
from nailgun.db.sqlalchemy.models import Cluster
|
|
from nailgun.db.sqlalchemy.models import Node
|
|
from nailgun.logger import logger
|
|
from nailgun.objects import Task
|
|
from nailgun.orchestrator import deployment_serializers
|
|
from nailgun.orchestrator import provisioning_serializers
|
|
from nailgun.task.helpers import TaskHelper
|
|
from nailgun.task.manager import DeploymentTaskManager
|
|
from nailgun.task.manager import ProvisioningTaskManager
|
|
|
|
|
|
class NodesFilterMixin(object):
|
|
validator = NodesFilterValidator
|
|
|
|
def get_default_nodes(self, cluster):
|
|
"""Method should be overriden and
|
|
return list of nodes
|
|
"""
|
|
raise NotImplementedError('Please Implement this method')
|
|
|
|
def get_nodes(self, cluster):
|
|
"""If nodes selected in filter
|
|
then returns them, else returns
|
|
default nodes.
|
|
"""
|
|
nodes = web.input(nodes=None).nodes
|
|
|
|
if nodes:
|
|
node_ids = self.checked_data(data=nodes)
|
|
return self.get_objects_list_or_404(Node, node_ids)
|
|
|
|
return self.get_default_nodes(cluster)
|
|
|
|
|
|
class DefaultOrchestratorInfo(NodesFilterMixin, BaseHandler):
|
|
"""Base class for default orchestrator data.
|
|
Need to redefine serializer variable
|
|
"""
|
|
|
|
# Override this attribute
|
|
_serializer = None
|
|
|
|
@content_json
|
|
def GET(self, cluster_id):
|
|
""":returns: JSONized default data which will be passed to orchestrator
|
|
:http: * 200 (OK)
|
|
* 404 (cluster not found in db)
|
|
"""
|
|
cluster = self.get_object_or_404(Cluster, cluster_id)
|
|
nodes = self.get_nodes(cluster)
|
|
return self._serializer.serialize(cluster, nodes)
|
|
|
|
|
|
class OrchestratorInfo(BaseHandler):
|
|
"""Base class for replaced data."""
|
|
|
|
def get_orchestrator_info(self, cluster):
|
|
"""Method should return data
|
|
which will be passed to orchestrator
|
|
"""
|
|
raise NotImplementedError('Please Implement this method')
|
|
|
|
def update_orchestrator_info(self, cluster, data):
|
|
"""Method should override data which
|
|
will be passed to orchestrator
|
|
"""
|
|
raise NotImplementedError('Please Implement this method')
|
|
|
|
@content_json
|
|
def GET(self, cluster_id):
|
|
""":returns: JSONized data which will be passed to orchestrator
|
|
:http: * 200 (OK)
|
|
* 404 (cluster not found in db)
|
|
"""
|
|
cluster = self.get_object_or_404(Cluster, cluster_id)
|
|
return self.get_orchestrator_info(cluster)
|
|
|
|
@content_json
|
|
def PUT(self, cluster_id):
|
|
""":returns: JSONized data which will be passed to orchestrator
|
|
:http: * 200 (OK)
|
|
* 400 (wrong data specified)
|
|
* 404 (cluster not found in db)
|
|
"""
|
|
cluster = self.get_object_or_404(Cluster, cluster_id)
|
|
data = self.checked_data()
|
|
self.update_orchestrator_info(cluster, data)
|
|
logger.debug('OrchestratorInfo:'
|
|
' facts for cluster_id {0} were uploaded'
|
|
.format(cluster_id))
|
|
return data
|
|
|
|
@content_json
|
|
def DELETE(self, cluster_id):
|
|
""":returns: {}
|
|
:http: * 202 (orchestrator data deletion process launched)
|
|
* 400 (failed to execute orchestrator data deletion process)
|
|
* 404 (cluster not found in db)
|
|
"""
|
|
cluster = self.get_object_or_404(Cluster, cluster_id)
|
|
self.update_orchestrator_info(cluster, {})
|
|
|
|
raise self.http(202, '{}')
|
|
|
|
|
|
class DefaultProvisioningInfo(DefaultOrchestratorInfo):
|
|
|
|
_serializer = provisioning_serializers
|
|
|
|
def get_default_nodes(self, cluster):
|
|
return TaskHelper.nodes_to_provision(cluster)
|
|
|
|
|
|
class DefaultDeploymentInfo(DefaultOrchestratorInfo):
|
|
|
|
_serializer = deployment_serializers
|
|
|
|
def get_default_nodes(self, cluster):
|
|
return TaskHelper.nodes_to_deploy(cluster)
|
|
|
|
|
|
class ProvisioningInfo(OrchestratorInfo):
|
|
|
|
def get_orchestrator_info(self, cluster):
|
|
return cluster.replaced_provisioning_info
|
|
|
|
def update_orchestrator_info(self, cluster, data):
|
|
cluster.replace_provisioning_info(data)
|
|
return cluster.replaced_provisioning_info
|
|
|
|
|
|
class DeploymentInfo(OrchestratorInfo):
|
|
|
|
def get_orchestrator_info(self, cluster):
|
|
return cluster.replaced_deployment_info
|
|
|
|
def update_orchestrator_info(self, cluster, data):
|
|
cluster.replace_deployment_info(data)
|
|
return cluster.replaced_deployment_info
|
|
|
|
|
|
class SelectedNodesBase(NodesFilterMixin, BaseHandler):
|
|
"""Base class for running task manager on selected nodes."""
|
|
|
|
@content_json
|
|
def PUT(self, cluster_id):
|
|
""":returns: JSONized Task object.
|
|
:http: * 200 (task successfully executed)
|
|
* 404 (cluster or nodes not found in db)
|
|
* 400 (failed to execute task)
|
|
"""
|
|
cluster = self.get_object_or_404(Cluster, cluster_id)
|
|
nodes = self.get_nodes(cluster)
|
|
|
|
try:
|
|
task_manager = self.task_manager(cluster_id=cluster.id)
|
|
task = task_manager.execute(nodes)
|
|
except Exception as exc:
|
|
logger.warn(u'Cannot execute {0} task nodes: {1}'.format(
|
|
task_manager.__class__.__name__, traceback.format_exc()))
|
|
raise self.http(400, message=str(exc))
|
|
|
|
raise self.http(202, Task.to_json(task))
|
|
|
|
|
|
class ProvisionSelectedNodes(SelectedNodesBase):
|
|
"""Handler for provisioning selected nodes."""
|
|
|
|
task_manager = ProvisioningTaskManager
|
|
|
|
def get_default_nodes(self, cluster):
|
|
TaskHelper.nodes_to_provision(cluster)
|
|
|
|
|
|
class DeploySelectedNodes(SelectedNodesBase):
|
|
"""Handler for deployment selected nodes."""
|
|
|
|
task_manager = DeploymentTaskManager
|
|
|
|
def get_default_nodes(self, cluster):
|
|
TaskHelper.nodes_to_deploy(cluster)
|