375 lines
12 KiB
Python
375 lines
12 KiB
Python
# Copyright 2013: Mirantis Inc.
|
|
# 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.
|
|
"""
|
|
SQLAlchemy models for rally data.
|
|
"""
|
|
import datetime as dt
|
|
import uuid
|
|
|
|
import sqlalchemy as sa
|
|
import sqlalchemy.orm # noqa (used as sa.orm)
|
|
|
|
if sa.__version__.startswith("2."):
|
|
from sqlalchemy.orm import declarative_base
|
|
else:
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
|
|
from rally.common.db import sa_types
|
|
from rally import consts
|
|
|
|
|
|
BASE = declarative_base()
|
|
|
|
|
|
def UUID():
|
|
return str(uuid.uuid4())
|
|
|
|
|
|
class RallyBase(object):
|
|
"""Base class for models."""
|
|
__table_initialized__ = False
|
|
metadata = None
|
|
|
|
created_at = sa.Column(sa.DateTime, default=dt.datetime.utcnow)
|
|
updated_at = sa.Column(sa.DateTime, default=dt.datetime.utcnow,
|
|
onupdate=dt.datetime.utcnow)
|
|
|
|
def as_dict(self):
|
|
result = {}
|
|
res = sa.inspect(self)
|
|
|
|
for c in self.__table__.columns:
|
|
if c.key not in res.unloaded:
|
|
result[c.name] = getattr(self, c.name)
|
|
|
|
for r in self.__mapper__.relationships:
|
|
if r.key not in res.unloaded:
|
|
result[r.key] = getattr(self, r.key)
|
|
|
|
return result
|
|
|
|
def get(self, key, default=None):
|
|
return getattr(self, key, default)
|
|
|
|
def update(self, values):
|
|
"""Make the model object behave like a dict."""
|
|
for k, v in values.items():
|
|
setattr(self, k, v)
|
|
|
|
|
|
class Env(BASE, RallyBase):
|
|
"""Represent an environment."""
|
|
__tablename__ = "envs"
|
|
__table_args__ = (
|
|
sa.Index("env_uuid", "uuid", unique=True),
|
|
sa.Index("env_name", "name", unique=True),
|
|
sa.Index("env_status", "status")
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
name = sa.Column(sa.String(255), nullable=False)
|
|
description = sa.Column(sa.Text, default="")
|
|
status = sa.Column(sa.String(36), nullable=False)
|
|
extras = sa.Column(sa_types.MutableJSONEncodedDict, default={})
|
|
config = sa.Column(sa_types.MutableJSONEncodedDict, default={})
|
|
spec = sa.Column(sa_types.MutableJSONEncodedDict, default={})
|
|
|
|
|
|
class Platform(BASE, RallyBase):
|
|
"""Represent environment's platforms."""
|
|
__tablename__ = "platforms"
|
|
__table_args__ = (
|
|
sa.Index("platform_uuid", "uuid", unique=True),
|
|
sa.Index("platform_env_uuid", "env_uuid")
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
env_uuid = sa.Column(sa.String(36), nullable=False)
|
|
|
|
status = sa.Column(sa.String(36), nullable=False)
|
|
|
|
plugin_name = sa.Column(sa.String(36), nullable=False)
|
|
plugin_spec = sa.Column(sa_types.MutableJSONEncodedDict, default={},
|
|
nullable=False)
|
|
plugin_data = sa.Column(sa_types.MutableJSONEncodedDict, default={})
|
|
|
|
platform_name = sa.Column(sa.String(36))
|
|
platform_data = sa.Column(sa_types.MutableJSONEncodedDict, default={})
|
|
|
|
|
|
class Task(BASE, RallyBase):
|
|
"""Represents a task."""
|
|
__tablename__ = "tasks"
|
|
__table_args__ = (
|
|
sa.Index("task_uuid", "uuid", unique=True),
|
|
sa.Index("task_status", "status"),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
|
|
env_uuid = sa.Column(sa.String(36), nullable=False)
|
|
|
|
# we do not save the whole input task
|
|
input_task = sa.orm.deferred(sa.Column(sa.Text, default=""))
|
|
|
|
title = sa.Column(sa.String(128), default="")
|
|
description = sa.Column(sa.Text, default="")
|
|
|
|
validation_result = sa.Column(
|
|
sa_types.MutableJSONEncodedDict, default={}, nullable=False)
|
|
|
|
# we do not calculate the duration of a validation step yet
|
|
validation_duration = sa.orm.deferred(sa.Column(sa.Float))
|
|
|
|
task_duration = sa.Column(sa.Float, default=0.0)
|
|
pass_sla = sa.Column(sa.Boolean, default=True)
|
|
status = sa.Column(sa.String(36), default=consts.TaskStatus.INIT)
|
|
|
|
|
|
class Subtask(BASE, RallyBase):
|
|
__tablename__ = "subtasks"
|
|
__table_args__ = (
|
|
sa.Index("subtask_uuid", "uuid", unique=True),
|
|
sa.Index("subtask_status", "status"),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
|
|
task_uuid = sa.Column(
|
|
sa.String(36),
|
|
sa.ForeignKey(Task.uuid),
|
|
nullable=False,
|
|
)
|
|
|
|
task = sa.orm.relationship(
|
|
Task,
|
|
backref=sa.orm.backref("subtasks"),
|
|
foreign_keys=task_uuid,
|
|
primaryjoin=(task_uuid == Task.uuid),
|
|
)
|
|
|
|
title = sa.Column(sa.String(128), default="")
|
|
description = sa.Column(sa.Text, default="")
|
|
|
|
# we do not support subtask contexts feature yet, see
|
|
# https://review.openstack.org/#/c/404168/
|
|
contexts = sa.orm.deferred(sa.Column(
|
|
sa_types.JSONEncodedDict, default={}, nullable=False))
|
|
|
|
contexts_results = sa.orm.deferred(sa.Column(
|
|
sa_types.MutableJSONEncodedList, default=[], nullable=False))
|
|
|
|
sla = sa.Column(
|
|
sa_types.JSONEncodedDict, default={}, nullable=False)
|
|
|
|
# It is always False for now
|
|
run_in_parallel = sa.orm.deferred(
|
|
sa.Column(sa.Boolean, default=False, nullable=False))
|
|
|
|
duration = sa.Column(sa.Float, default=0.0)
|
|
pass_sla = sa.Column(sa.Boolean, default=True)
|
|
status = sa.Column(sa.String(36), default=consts.SubtaskStatus.RUNNING)
|
|
|
|
|
|
class Workload(BASE, RallyBase):
|
|
__tablename__ = "workloads"
|
|
__table_args__ = (
|
|
sa.Index("workload_uuid", "uuid", unique=True),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
|
|
task_uuid = sa.Column(
|
|
sa.String(36),
|
|
sa.ForeignKey(Task.uuid),
|
|
nullable=False,
|
|
)
|
|
|
|
subtask_uuid = sa.Column(
|
|
sa.String(36),
|
|
sa.ForeignKey(Subtask.uuid),
|
|
nullable=False,
|
|
)
|
|
|
|
subtask = sa.orm.relationship(
|
|
Subtask,
|
|
backref=sa.orm.backref("workloads"),
|
|
foreign_keys=subtask_uuid,
|
|
primaryjoin=(subtask_uuid == Subtask.uuid),
|
|
)
|
|
|
|
name = sa.Column(sa.String(64), nullable=False)
|
|
description = sa.Column(sa.Text, default="")
|
|
position = sa.Column(sa.Integer, default=0, nullable=False)
|
|
|
|
runner = sa.Column(
|
|
sa_types.JSONEncodedDict, default={}, nullable=False)
|
|
|
|
runner_type = sa.Column(sa.String(64), nullable=False)
|
|
|
|
contexts = sa.Column(
|
|
sa_types.JSONEncodedDict, default={}, nullable=False)
|
|
|
|
contexts_results = sa.Column(
|
|
sa_types.MutableJSONEncodedList, default=[], nullable=False)
|
|
|
|
sla = sa.Column(
|
|
sa_types.JSONEncodedDict, default={}, nullable=False)
|
|
|
|
sla_results = sa.Column(
|
|
sa_types.MutableJSONEncodedDict, default={}, nullable=False)
|
|
|
|
args = sa.Column(
|
|
sa_types.JSONEncodedDict, default={}, nullable=False)
|
|
|
|
hooks = sa.Column(
|
|
sa_types.JSONEncodedList, default=[], nullable=False)
|
|
|
|
start_time = sa.Column(sa_types.TimeStamp)
|
|
|
|
load_duration = sa.Column(sa.Float, default=0.0)
|
|
full_duration = sa.Column(sa.Float, default=0.0)
|
|
min_duration = sa.Column(sa.Float)
|
|
max_duration = sa.Column(sa.Float)
|
|
total_iteration_count = sa.Column(sa.Integer, default=0)
|
|
failed_iteration_count = sa.Column(sa.Integer, default=0)
|
|
|
|
statistics = sa.Column(
|
|
sa_types.MutableJSONEncodedDict, default={}, nullable=False)
|
|
|
|
pass_sla = sa.Column(sa.Boolean, default=True)
|
|
_profiling_data = sa.orm.deferred(sa.Column(sa.Text, default=""))
|
|
|
|
|
|
class WorkloadData(BASE, RallyBase):
|
|
__tablename__ = "workloaddata"
|
|
__table_args__ = (
|
|
sa.Index("workload_data_uuid", "uuid", unique=True),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
|
|
task_uuid = sa.Column(
|
|
sa.String(36),
|
|
sa.ForeignKey(Task.uuid),
|
|
nullable=False,
|
|
)
|
|
|
|
workload_uuid = sa.Column(
|
|
sa.String(36),
|
|
sa.ForeignKey(Workload.uuid),
|
|
nullable=False,
|
|
)
|
|
|
|
workload = sa.orm.relationship(
|
|
Workload,
|
|
backref=sa.orm.backref("workload_data"),
|
|
foreign_keys=workload_uuid,
|
|
primaryjoin=(workload_uuid == Workload.uuid),
|
|
)
|
|
|
|
chunk_order = sa.Column(sa.Integer, nullable=False)
|
|
chunk_data = sa.Column(
|
|
sa_types.MutableJSONEncodedDict, default={}, nullable=False)
|
|
# all these fields are not used
|
|
iteration_count = sa.orm.deferred(sa.Column(sa.Integer, nullable=False))
|
|
failed_iteration_count = sa.orm.deferred(sa.Column(
|
|
sa.Integer, nullable=False))
|
|
chunk_size = sa.orm.deferred(sa.Column(
|
|
sa.Integer, nullable=False))
|
|
compressed_chunk_size = sa.orm.deferred(sa.Column(
|
|
sa.Integer, nullable=False))
|
|
started_at = sa.orm.deferred(sa.Column(
|
|
sa.DateTime, default=dt.datetime.utcnow, nullable=False))
|
|
finished_at = sa.orm.deferred(sa.Column(
|
|
sa.DateTime, default=dt.datetime.utcnow, nullable=False))
|
|
|
|
|
|
class Tag(BASE, RallyBase):
|
|
__tablename__ = "tags"
|
|
__table_args__ = (
|
|
sa.Index("d_type_tag", "uuid", "type", "tag", unique=True),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
type = sa.Column(sa.String(36), nullable=False)
|
|
tag = sa.Column(sa.String(255), nullable=False)
|
|
|
|
|
|
class Verifier(BASE, RallyBase):
|
|
"""Represents a verifier."""
|
|
|
|
__tablename__ = "verifiers"
|
|
__table_args__ = (
|
|
sa.Index("verifier_uuid", "uuid", unique=True),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
|
|
name = sa.Column(sa.String(255), unique=True)
|
|
description = sa.Column(sa.Text)
|
|
|
|
type = sa.Column(sa.String(255), nullable=False)
|
|
platform = sa.Column(sa.String(255))
|
|
|
|
source = sa.Column(sa.String(255))
|
|
version = sa.Column(sa.String(255))
|
|
system_wide = sa.Column(sa.Boolean)
|
|
|
|
status = sa.Column(sa.String(36), default=consts.VerifierStatus.INIT,
|
|
nullable=False)
|
|
|
|
extra_settings = sa.Column(sa_types.MutableJSONEncodedDict)
|
|
|
|
|
|
class Verification(BASE, RallyBase):
|
|
"""Represents a verification."""
|
|
|
|
__tablename__ = "verifications"
|
|
__table_args__ = (
|
|
sa.Index("verification_uuid", "uuid", unique=True),
|
|
)
|
|
|
|
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
|
uuid = sa.Column(sa.String(36), default=UUID, nullable=False)
|
|
|
|
verifier_uuid = sa.Column(sa.String(36),
|
|
sa.ForeignKey(Verifier.uuid),
|
|
nullable=False)
|
|
env_uuid = sa.Column(sa.String(36), nullable=False)
|
|
|
|
run_args = sa.Column(sa_types.MutableJSONEncodedDict)
|
|
|
|
status = sa.Column(sa.String(36), default=consts.VerificationStatus.INIT,
|
|
nullable=False)
|
|
|
|
tests_count = sa.Column(sa.Integer, default=0)
|
|
failures = sa.Column(sa.Integer, default=0)
|
|
skipped = sa.Column(sa.Integer, default=0)
|
|
success = sa.Column(sa.Integer, default=0)
|
|
unexpected_success = sa.Column(sa.Integer, default=0)
|
|
expected_failures = sa.Column(sa.Integer, default=0)
|
|
tests_duration = sa.Column(sa.Float, default=0.0)
|
|
|
|
tests = sa.Column(sa_types.MutableJSONEncodedDict, default={})
|