395 lines
10 KiB
Python
395 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# 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 namos database
|
|
"""
|
|
|
|
import sqlalchemy
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy import UniqueConstraint
|
|
import uuid
|
|
|
|
from namos.db.sqlalchemy.types import Json
|
|
from namos.db.sqlalchemy.types import Uuid
|
|
from oslo_db.sqlalchemy import models
|
|
from oslo_utils import timeutils
|
|
|
|
|
|
BASE = declarative_base()
|
|
|
|
|
|
class NamosBase(models.ModelBase,
|
|
models.TimestampMixin):
|
|
# TODO(kanagaraj-manickam) Make this as db independent
|
|
__table_args__ = {'mysql_engine': 'InnoDB'}
|
|
|
|
id = sqlalchemy.Column(Uuid, primary_key=True,
|
|
default=lambda: str(uuid.uuid4()))
|
|
name = sqlalchemy.Column(sqlalchemy.String(255),
|
|
unique=True,
|
|
nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
|
|
def expire(self, session, attrs=None):
|
|
session.expire(self, attrs)
|
|
|
|
def refresh(self, session, attrs=None):
|
|
session.refresh(self, attrs)
|
|
|
|
def delete(self, session):
|
|
session.delete(self)
|
|
session.flush()
|
|
|
|
def update_and_save(self, values, session):
|
|
self.update(values)
|
|
self.save(session)
|
|
|
|
def __str__(self):
|
|
return "{id:%s, name:%s}" % (self.id, self.name)
|
|
|
|
def __repr__(self):
|
|
return str(self.to_dict())
|
|
|
|
def to_dict(self):
|
|
result = dict()
|
|
for k, v in self.iteritems():
|
|
if not str(k).endswith('_at'):
|
|
result[k] = v
|
|
return result
|
|
|
|
|
|
class SoftDelete(object):
|
|
deleted_at = sqlalchemy.Column(sqlalchemy.DateTime)
|
|
|
|
def soft_delete(self, session):
|
|
self.update_and_save({'deleted_at': timeutils.utcnow()},
|
|
session=session)
|
|
|
|
|
|
class StateAware(object):
|
|
status = sqlalchemy.Column(
|
|
'status',
|
|
sqlalchemy.String(64),
|
|
nullable=False)
|
|
|
|
|
|
class Description(object):
|
|
description = sqlalchemy.Column(sqlalchemy.Text)
|
|
|
|
|
|
class Extra(object):
|
|
extra = sqlalchemy.Column(Json)
|
|
|
|
|
|
class Region(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'region'
|
|
|
|
# Its of type String to match with keystone region id
|
|
keystone_region_id = sqlalchemy.Column(
|
|
sqlalchemy.String(255),
|
|
nullable=False)
|
|
|
|
|
|
class Device(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
StateAware,
|
|
Description,
|
|
Extra):
|
|
__tablename__ = 'device'
|
|
|
|
display_name = sqlalchemy.Column(sqlalchemy.String(255))
|
|
parent_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('device.id'))
|
|
region_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('region.id'),
|
|
nullable=False)
|
|
# TODO(kanagaraj-manickam) owner with keystone user id as one field??
|
|
|
|
|
|
class DeviceEndpoint(BASE,
|
|
NamosBase,
|
|
Extra):
|
|
__tablename__ = 'device_endpoint'
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("device_id", "type"),
|
|
)
|
|
device_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('device.id'),
|
|
nullable=False)
|
|
type = sqlalchemy.Column(
|
|
sqlalchemy.String(32)
|
|
)
|
|
connection = sqlalchemy.Column(
|
|
Json,
|
|
nullable=False)
|
|
|
|
|
|
class DeviceDriver(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'device_driver'
|
|
__table_args__ = (
|
|
UniqueConstraint("device_id",
|
|
"endpoint_id",
|
|
"device_driver_class_id",
|
|
"service_worker_id"),
|
|
)
|
|
|
|
endpoint_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('device_endpoint.id')
|
|
)
|
|
|
|
device_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('device.id'))
|
|
|
|
device_driver_class_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('device_driver_class.id')
|
|
)
|
|
service_worker_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('service_worker.id')
|
|
)
|
|
|
|
# List of supported drivers in a given openstack release. so when
|
|
# openstack is released, migration script could be updated to pre-populate
|
|
# drivers in this table, which helps to track the drivers being released
|
|
# in the given openstack version.
|
|
|
|
|
|
class DeviceDriverClass(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'device_driver_class'
|
|
|
|
# TODO(kanagaraj-manickam) Correct the max python class path here
|
|
python_class = sqlalchemy.Column(
|
|
sqlalchemy.String(256),
|
|
nullable=False,
|
|
unique=True
|
|
)
|
|
# service type like compute, network, volume, etc
|
|
type = sqlalchemy.Column(
|
|
sqlalchemy.String(64),
|
|
nullable=False
|
|
)
|
|
|
|
# TODO(kanagaraj-manickam) add vendor,
|
|
# additional details like protocol, etc,
|
|
# Capture all related driver details
|
|
|
|
|
|
class Service(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'service'
|
|
|
|
keystone_service_id = sqlalchemy.Column(
|
|
Uuid,
|
|
nullable=False)
|
|
|
|
|
|
class ServiceNode(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Description,
|
|
Extra):
|
|
__tablename__ = 'service_node'
|
|
|
|
fqdn = sqlalchemy.Column(
|
|
sqlalchemy.String(128),
|
|
nullable=False)
|
|
region_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('region.id'))
|
|
|
|
|
|
class ServiceComponent(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Description,
|
|
Extra):
|
|
__tablename__ = 'service_component'
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("name", "node_id", "service_id"),
|
|
)
|
|
|
|
name = sqlalchemy.Column(sqlalchemy.String(255),
|
|
# unique=True,
|
|
nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
|
|
node_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('service_node.id'),
|
|
nullable=False)
|
|
service_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('service.id'),
|
|
nullable=False)
|
|
|
|
|
|
class ServiceWorker(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'service_worker'
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("host", "service_component_id"),
|
|
)
|
|
|
|
name = sqlalchemy.Column(sqlalchemy.String(255),
|
|
# unique=True,
|
|
nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
|
|
pid = sqlalchemy.Column(
|
|
sqlalchemy.String(64),
|
|
nullable=False,
|
|
unique=True
|
|
)
|
|
host = sqlalchemy.Column(
|
|
sqlalchemy.String(248),
|
|
nullable=False
|
|
)
|
|
service_component_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('service_component.id'),
|
|
nullable=False)
|
|
|
|
|
|
class OsloConfigSchema(BASE,
|
|
NamosBase,
|
|
Extra):
|
|
__tablename__ = 'oslo_config_schema'
|
|
|
|
# TODO(mrkanag) Check whether conf is unique across all services or only
|
|
# sepcific to namespace, otherwise uniqueconstraint is name, group_name
|
|
__table_args__ = (
|
|
UniqueConstraint("group_name", "name", "namespace"),
|
|
)
|
|
|
|
name = sqlalchemy.Column(sqlalchemy.String(255),
|
|
# unique=True,
|
|
nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
|
|
help = sqlalchemy.Column(
|
|
sqlalchemy.Text,
|
|
nullable=False,
|
|
default=''
|
|
)
|
|
type = sqlalchemy.Column(
|
|
sqlalchemy.String(128),
|
|
nullable=False
|
|
)
|
|
group_name = sqlalchemy.Column(
|
|
sqlalchemy.String(128),
|
|
nullable=False
|
|
)
|
|
namespace = sqlalchemy.Column(
|
|
sqlalchemy.String(128),
|
|
nullable=False
|
|
)
|
|
# TODO(mrkanag) default value is some time overriden by services, which
|
|
# osloconfig allows, so this column should have values per given service
|
|
default_value = sqlalchemy.Column(
|
|
sqlalchemy.Text
|
|
)
|
|
required = sqlalchemy.Column(
|
|
sqlalchemy.Boolean,
|
|
default=False
|
|
)
|
|
secret = sqlalchemy.Column(
|
|
sqlalchemy.Boolean,
|
|
default=False
|
|
)
|
|
mutable = sqlalchemy.Column(
|
|
sqlalchemy.Boolean,
|
|
default=False
|
|
)
|
|
|
|
|
|
class OsloConfig(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'oslo_config'
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("oslo_config_schema_id", "service_worker_id"),
|
|
)
|
|
|
|
name = sqlalchemy.Column(sqlalchemy.String(255),
|
|
# unique=True,
|
|
nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
|
|
value = sqlalchemy.Column(
|
|
sqlalchemy.Text
|
|
)
|
|
file = sqlalchemy.Column(
|
|
sqlalchemy.String(512)
|
|
)
|
|
oslo_config_schema_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('oslo_config_schema.id'),
|
|
nullable=False
|
|
)
|
|
service_worker_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('service_worker.id'),
|
|
nullable=False
|
|
)
|
|
|
|
|
|
class OsloConfigFile(BASE,
|
|
NamosBase,
|
|
SoftDelete,
|
|
Extra):
|
|
__tablename__ = 'oslo_config_file'
|
|
__table_args__ = (
|
|
UniqueConstraint("name", "service_component_id"),
|
|
)
|
|
|
|
name = sqlalchemy.Column(sqlalchemy.String(255),
|
|
# unique=True,
|
|
nullable=False,
|
|
default=lambda: str(uuid.uuid4()))
|
|
|
|
file = sqlalchemy.Column(
|
|
sqlalchemy.Text
|
|
)
|
|
service_component_id = sqlalchemy.Column(
|
|
Uuid,
|
|
sqlalchemy.ForeignKey('service_component.id'),
|
|
nullable=False
|
|
)
|