272 lines
9.4 KiB
Python
272 lines
9.4 KiB
Python
# Copyright (c) 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.
|
|
|
|
import uuid
|
|
|
|
from oslo_db.sqlalchemy import models
|
|
from oslo_utils import timeutils
|
|
from sqlalchemy import BigInteger
|
|
from sqlalchemy import Boolean
|
|
from sqlalchemy import Column
|
|
from sqlalchemy import DateTime
|
|
from sqlalchemy.ext import declarative
|
|
from sqlalchemy import ForeignKey
|
|
from sqlalchemy import Index
|
|
from sqlalchemy import Integer
|
|
from sqlalchemy import LargeBinary
|
|
from sqlalchemy import Numeric
|
|
from sqlalchemy.orm import backref
|
|
from sqlalchemy.orm import composite
|
|
from sqlalchemy.orm import relationship
|
|
from sqlalchemy import String
|
|
from sqlalchemy import Text
|
|
|
|
from glare.common import semver_db
|
|
|
|
BASE = declarative.declarative_base()
|
|
|
|
|
|
class ArtifactBase(models.ModelBase):
|
|
"""Base class for Artifact Models."""
|
|
|
|
__table_args__ = {'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'}
|
|
__table_initialized__ = False
|
|
|
|
def save(self, session=None):
|
|
from glare.db.sqlalchemy import api as db_api
|
|
|
|
super(ArtifactBase, self).save(session or db_api.get_session())
|
|
|
|
def keys(self):
|
|
return self.__dict__.keys()
|
|
|
|
def values(self):
|
|
return self.__dict__.values()
|
|
|
|
def items(self):
|
|
return self.__dict__.items()
|
|
|
|
def to_dict(self):
|
|
d = {}
|
|
for c in self.__table__.columns:
|
|
d[c.name] = self[c.name]
|
|
return d
|
|
|
|
|
|
def _parse_property_value(prop):
|
|
columns = [
|
|
'int_value',
|
|
'string_value',
|
|
'bool_value',
|
|
'numeric_value']
|
|
|
|
for prop_type in columns:
|
|
if getattr(prop, prop_type) is not None:
|
|
return getattr(prop, prop_type)
|
|
|
|
|
|
def _parse_blob_value(blob):
|
|
return {
|
|
"id": blob.id,
|
|
"url": blob.url,
|
|
"status": blob.status,
|
|
"external": blob.external,
|
|
"md5": blob.md5,
|
|
"sha1": blob.sha1,
|
|
"sha256": blob.sha256,
|
|
"size": blob.size,
|
|
"content_type": blob.content_type
|
|
}
|
|
|
|
|
|
class Artifact(BASE, ArtifactBase):
|
|
__tablename__ = 'glare_artifacts'
|
|
__table_args__ = (
|
|
Index('ix_glare_artifact_name_and_version', 'name', 'version_prefix',
|
|
'version_suffix'),
|
|
Index('ix_glare_artifact_type', 'type_name'),
|
|
Index('ix_glare_artifact_status', 'status'),
|
|
Index('ix_glare_artifact_owner', 'owner'),
|
|
Index('ix_glare_artifact_visibility', 'visibility'),
|
|
{'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'})
|
|
__protected_attributes__ = set(["created_at", "updated_at"])
|
|
|
|
id = Column(String(36), primary_key=True,
|
|
default=lambda: str(uuid.uuid4()))
|
|
name = Column(String(255), nullable=False)
|
|
type_name = Column(String(255), nullable=False)
|
|
version_prefix = Column(BigInteger().with_variant(Integer, "sqlite"),
|
|
nullable=False)
|
|
version_suffix = Column(String(255))
|
|
version_meta = Column(String(255))
|
|
version = composite(semver_db.DBVersion, version_prefix,
|
|
version_suffix, version_meta,
|
|
comparator_factory=semver_db.VersionComparator)
|
|
description = Column(Text())
|
|
visibility = Column(String(32), nullable=False)
|
|
status = Column(String(32), nullable=False)
|
|
owner = Column(String(255))
|
|
created_at = Column(DateTime, default=lambda: timeutils.utcnow(),
|
|
nullable=False)
|
|
updated_at = Column(DateTime, default=lambda: timeutils.utcnow(),
|
|
nullable=False, onupdate=lambda: timeutils.utcnow())
|
|
activated_at = Column(DateTime)
|
|
|
|
def to_dict(self):
|
|
d = super(Artifact, self).to_dict()
|
|
|
|
d.pop('version_prefix')
|
|
d.pop('version_suffix')
|
|
d.pop('version_meta')
|
|
d['version'] = str(self.version)
|
|
|
|
# parse tags
|
|
tags = []
|
|
for tag in self.tags:
|
|
tags.append(tag.value)
|
|
d['tags'] = tags
|
|
|
|
# parse properties
|
|
for prop in self.properties:
|
|
prop_value = _parse_property_value(prop)
|
|
|
|
if prop.position is not None:
|
|
if prop.name not in d:
|
|
# create new list
|
|
d[prop.name] = []
|
|
# insert value in position
|
|
d[prop.name].insert(prop.position, prop_value)
|
|
elif prop.key_name is not None:
|
|
if prop.name not in d:
|
|
# create new dict
|
|
d[prop.name] = {}
|
|
# insert value in the dict
|
|
d[prop.name][prop.key_name] = prop_value
|
|
else:
|
|
# make scalar
|
|
d[prop.name] = prop_value
|
|
|
|
# parse blobs
|
|
for blob in self.blobs:
|
|
blob_value = _parse_blob_value(blob)
|
|
if blob.key_name is not None:
|
|
if blob.name not in d:
|
|
# create new dict
|
|
d[blob.name] = {}
|
|
# insert value in the dict
|
|
d[blob.name][blob.key_name] = blob_value
|
|
else:
|
|
# make scalar
|
|
d[blob.name] = blob_value
|
|
|
|
return d
|
|
|
|
|
|
class ArtifactTag(BASE, ArtifactBase):
|
|
__tablename__ = 'glare_artifact_tags'
|
|
__table_args__ = (Index('ix_glare_artifact_tags_artifact_id_tag_value',
|
|
'artifact_id', 'value'),
|
|
Index('ix_glare_artifact_tags_artifact_id',
|
|
'artifact_id'),
|
|
{'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'},)
|
|
|
|
id = Column(String(36), primary_key=True, nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
artifact_id = Column(String(36), ForeignKey('glare_artifacts.id'),
|
|
nullable=False)
|
|
artifact = relationship(Artifact,
|
|
backref=backref('tags',
|
|
cascade="all, delete-orphan"))
|
|
value = Column(String(255), nullable=False)
|
|
|
|
|
|
class ArtifactProperty(BASE, ArtifactBase):
|
|
__tablename__ = 'glare_artifact_properties'
|
|
__table_args__ = (
|
|
Index('ix_glare_artifact_properties_artifact_id', 'artifact_id'),
|
|
Index('ix_glare_artifact_properties_name', 'name'),
|
|
{'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'},)
|
|
id = Column(String(36), primary_key=True, nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
artifact_id = Column(String(36), ForeignKey('glare_artifacts.id'),
|
|
nullable=False)
|
|
artifact = relationship(Artifact,
|
|
backref=backref('properties',
|
|
cascade="all, delete-orphan"))
|
|
name = Column(String(255), nullable=False)
|
|
string_value = Column(String(20000))
|
|
int_value = Column(Integer)
|
|
numeric_value = Column(Numeric)
|
|
bool_value = Column(Boolean)
|
|
position = Column(Integer)
|
|
key_name = Column(String(255))
|
|
|
|
|
|
class ArtifactBlob(BASE, ArtifactBase):
|
|
__tablename__ = 'glare_artifact_blobs'
|
|
__table_args__ = (
|
|
Index('ix_glare_artifact_blobs_artifact_id', 'artifact_id'),
|
|
Index('ix_glare_artifact_blobs_name', 'name'),
|
|
{'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'},)
|
|
id = Column(String(36), primary_key=True, nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
artifact_id = Column(String(36), ForeignKey('glare_artifacts.id'),
|
|
nullable=False)
|
|
name = Column(String(255), nullable=False)
|
|
size = Column(BigInteger().with_variant(Integer, "sqlite"))
|
|
md5 = Column(String(32))
|
|
sha1 = Column(String(40))
|
|
sha256 = Column(String(64))
|
|
external = Column(Boolean)
|
|
url = Column(Text)
|
|
status = Column(String(32), nullable=False)
|
|
key_name = Column(String(2048))
|
|
content_type = Column(String(255))
|
|
artifact = relationship(Artifact,
|
|
backref=backref('blobs',
|
|
cascade="all, delete-orphan"))
|
|
|
|
|
|
class ArtifactLock(BASE, ArtifactBase):
|
|
__tablename__ = 'glare_artifact_locks'
|
|
__table_args__ = (
|
|
{'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'},)
|
|
id = Column(String(255), primary_key=True, nullable=False)
|
|
acquired_at = Column(
|
|
DateTime, nullable=False, default=lambda: timeutils.utcnow())
|
|
|
|
|
|
class ArtifactBlobData(BASE, ArtifactBase):
|
|
__tablename__ = 'glare_blob_data'
|
|
__table_args__ = (
|
|
{'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'},)
|
|
id = Column(String(255), primary_key=True, nullable=False)
|
|
data = Column(LargeBinary(length=(2 ** 32) - 1), nullable=False)
|
|
|
|
|
|
def register_models(engine):
|
|
"""Create database tables for all models with the given engine."""
|
|
models = (Artifact, ArtifactTag, ArtifactProperty, ArtifactBlob,
|
|
ArtifactLock)
|
|
for model in models:
|
|
model.metadata.create_all(engine)
|
|
|
|
|
|
def unregister_models(engine):
|
|
"""Drop database tables for all models with the given engine."""
|
|
models = (ArtifactLock, ArtifactBlob, ArtifactProperty, ArtifactTag,
|
|
Artifact)
|
|
for model in models:
|
|
model.metadata.drop_all(engine)
|