fuel-web/nailgun/nailgun/objects/transaction.py

156 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2016 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.
from nailgun import consts
from nailgun.db import db
from nailgun.db.sqlalchemy import models
from nailgun import errors
from nailgun.objects import NailgunCollection
from nailgun.objects import NailgunObject
from nailgun.objects.node_deployment_info import NodeDeploymentInfo
from nailgun.objects.node_deployment_info import NodeDeploymentInfoCollection
from nailgun.objects.serializers.transaction import TransactionSerializer
class Transaction(NailgunObject):
model = models.Task
serializer = TransactionSerializer
@classmethod
def get_by_uuid(cls, uuid, fail_if_not_found=False, lock_for_update=False):
# maybe consider using uuid as pk?
q = db().query(cls.model).filter_by(uuid=uuid)
if lock_for_update:
q = q.order_by('id')
q = q.with_lockmode('update')
res = q.first()
if not res and fail_if_not_found:
raise errors.ObjectNotFound(
"Task with UUID={0} is not found in DB".format(uuid)
)
return res
@classmethod
def attach_deployment_info(cls, instance, deployment_info):
for node_uid, node_di in deployment_info.items():
NodeDeploymentInfo.create({'task_id': instance.id,
'node_uid': node_uid,
'deployment_info': node_di})
@classmethod
def get_deployment_info(cls, instance, node_uids=None):
if instance is None:
return {}
node_di_list = NodeDeploymentInfoCollection.filter_by(
None, task_id=instance.id)
if node_uids:
node_di_list = NodeDeploymentInfoCollection.filter_by_list(
node_di_list, "node_uid", node_uids)
deployment_info = {node_di.node_uid: node_di.deployment_info
for node_di in node_di_list}
return deployment_info
@classmethod
def attach_network_settings(cls, instance, settings):
instance.network_settings = settings
@classmethod
def get_network_settings(cls, instance):
if instance is not None:
return instance.network_settings
@classmethod
def attach_cluster_settings(cls, instance, settings):
instance.cluster_settings = settings
@classmethod
def get_cluster_settings(cls, instance):
if instance is not None:
return instance.cluster_settings
@classmethod
def attach_tasks_snapshot(cls, instance, tasks_snapshot):
instance.tasks_snapshot = tasks_snapshot
@classmethod
def get_tasks_snapshot(cls, instance):
if instance is not None:
return instance.tasks_snapshot
class TransactionCollection(NailgunCollection):
single = Transaction
@classmethod
def get_by_cluster_id(cls, cluster_id):
return cls.filter_by(None, cluster_id=cluster_id)
@classmethod
def get_last_succeed_run(cls, cluster):
# TODO(bgaifullin) remove hardcoded name of task
return cls.filter_by(
None, cluster_id=cluster.id, name=consts.TASK_NAMES.deployment,
status=consts.TASK_STATUSES.ready
).order_by('-id').limit(1).first()
@classmethod
def get_successful_transactions_per_task(cls, cluster_id,
task_names=None,
nodes_uids=None):
"""Get last successful transaction for every task name.
:param cluster_id: db id of cluster object
:param task_names: list with task names
:param nodes_uids: db Node uids, which state you need
:returns: [(Transaction, node_id, task_name), ...]
"""
history = models.DeploymentHistory
model = cls.single.model
transactions = db().query(
model,
history.node_id,
history.deployment_graph_task_name,
).join(history).filter(
model.cluster_id == cluster_id,
model.name == consts.TASK_NAMES.deployment,
history.status == consts.HISTORY_TASK_STATUSES.ready,
)
if nodes_uids is not None:
transactions = transactions.filter(
history.node_id.in_(nodes_uids),
)
if task_names is not None:
transactions = transactions.filter(
history.deployment_graph_task_name.in_(task_names),
)
transactions = transactions.order_by(
history.deployment_graph_task_name,
history.node_id,
history.task_id.desc(),
).distinct(
history.deployment_graph_task_name, history.node_id
)
return transactions