cascade_service: DB infrastructure
Base DAL implementation and DevStack integration. Our database schema is under design so the models may be changed later. Partially implements: blueprint implement-dal Change-Id: I8b16b3217e6b72e04bd8886d01d638f2d5a5c388
This commit is contained in:
parent
c5d6976471
commit
be30bb2fd8
36
cmd/manage.py
Normal file
36
cmd/manage.py
Normal file
@ -0,0 +1,36 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from tricircle.db import core
|
||||
import tricircle.db.migration_helpers as migration_helpers
|
||||
|
||||
|
||||
def main(argv=None, config_files=None):
|
||||
core.initialize()
|
||||
cfg.CONF(args=argv[2:],
|
||||
project='tricircle',
|
||||
default_config_files=config_files)
|
||||
migration_helpers.find_migrate_repo()
|
||||
migration_helpers.sync_repo(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
config_file = sys.argv[1]
|
||||
main(argv=sys.argv, config_files=[config_file])
|
@ -40,6 +40,9 @@ if [[ "$Q_ENABLE_TRICIRCLE" == "True" ]]; then
|
||||
configure_tricircle_plugin
|
||||
echo export PYTHONPATH=\$PYTHONPATH:$TRICIRCLE_DIR >> $RC_DIR/.localrc.auto
|
||||
|
||||
recreate_database tricircle
|
||||
python "$TRICIRCLE_DIR/cmd/manage.py" "$TRICIRCLE_CASCADE_CONF"
|
||||
|
||||
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
|
||||
echo_summary "Initializing Cascading Service"
|
||||
|
||||
|
63
tricircle/context.py
Normal file
63
tricircle/context.py
Normal file
@ -0,0 +1,63 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
from oslo_context import context as oslo_ctx
|
||||
|
||||
from tricircle.db import core
|
||||
|
||||
|
||||
class ContextBase(oslo_ctx.RequestContext):
|
||||
def __init__(self, auth_token=None, user_id=None, tenant_id=None,
|
||||
is_admin=False, request_id=None, overwrite=True,
|
||||
user_name=None, tenant_name=None, **kwargs):
|
||||
super(ContextBase, self).__init__(
|
||||
auth_token=auth_token,
|
||||
user=user_id or kwargs.get('user', None),
|
||||
tenant=tenant_id or kwargs.get('tenant', None),
|
||||
domain=kwargs.get('domain', None),
|
||||
user_domain=kwargs.get('user_domain', None),
|
||||
project_domain=kwargs.get('project_domain', None),
|
||||
is_admin=is_admin,
|
||||
read_only=kwargs.get('read_only', False),
|
||||
show_deleted=kwargs.get('show_deleted', False),
|
||||
request_id=request_id,
|
||||
resource_uuid=kwargs.get('resource_uuid', None),
|
||||
overwrite=overwrite)
|
||||
self.user_name = user_name
|
||||
self.tenant_name = tenant_name
|
||||
|
||||
def to_dict(self):
|
||||
ctx_dict = super(ContextBase, self).to_dict()
|
||||
ctx_dict.update({
|
||||
'user_name': self.user_name,
|
||||
'tenant_name': self.tenant_name
|
||||
})
|
||||
return ctx_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, ctx):
|
||||
return cls(**ctx)
|
||||
|
||||
|
||||
class Context(ContextBase):
|
||||
def __init__(self, **kwargs):
|
||||
super(Context, self).__init__(**kwargs)
|
||||
self._session = None
|
||||
|
||||
@property
|
||||
def session(self):
|
||||
if not self._session:
|
||||
self._session = core.get_session()
|
||||
return self._session
|
0
tricircle/db/__init__.py
Normal file
0
tricircle/db/__init__.py
Normal file
139
tricircle/db/core.py
Normal file
139
tricircle/db/core.py
Normal file
@ -0,0 +1,139 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
from oslo_config import cfg
|
||||
import oslo_db.options as db_options
|
||||
from oslo_db.sqlalchemy import session as db_session
|
||||
from oslo_utils import strutils
|
||||
import sqlalchemy as sql
|
||||
from sqlalchemy.ext import declarative
|
||||
from sqlalchemy.inspection import inspect
|
||||
|
||||
import tricircle.db.exception as db_exception
|
||||
|
||||
_engine_facade = None
|
||||
ModelBase = declarative.declarative_base()
|
||||
|
||||
|
||||
def _filter_query(model, query, filters):
|
||||
"""Apply filter to query
|
||||
:param model:
|
||||
:param query:
|
||||
:param filters: list of filter dict with key 'key', 'comparator', 'value'
|
||||
like {'key': 'site_id', 'comparator': 'eq', 'value': 'test_site_uuid'}
|
||||
:return:
|
||||
"""
|
||||
filter_dict = {}
|
||||
for query_filter in filters:
|
||||
# only eq filter supported at first
|
||||
if query_filter['comparator'] != 'eq':
|
||||
continue
|
||||
|
||||
key = query_filter['key']
|
||||
if key not in model.attributes:
|
||||
continue
|
||||
if isinstance(inspect(model).columns[key].type, sql.Boolean):
|
||||
filter_dict[key] = strutils.bool_from_string(query_filter['value'])
|
||||
else:
|
||||
filter_dict[key] = query_filter['value']
|
||||
if filter_dict:
|
||||
return query.filter_by(**filter_dict)
|
||||
else:
|
||||
return query
|
||||
|
||||
|
||||
def _get_engine_facade():
|
||||
global _engine_facade
|
||||
|
||||
if not _engine_facade:
|
||||
_engine_facade = db_session.EngineFacade.from_config(cfg.CONF)
|
||||
|
||||
return _engine_facade
|
||||
|
||||
|
||||
def _get_resource(context, model, pk_value):
|
||||
res_obj = context.session.query(model).get(pk_value)
|
||||
if not res_obj:
|
||||
raise db_exception.ResourceNotFound(model, pk_value)
|
||||
return res_obj
|
||||
|
||||
|
||||
def create_resource(context, model, res_dict):
|
||||
res_obj = model.from_dict(res_dict)
|
||||
context.session.add(res_obj)
|
||||
return res_obj.to_dict()
|
||||
|
||||
|
||||
def delete_resource(context, model, pk_value):
|
||||
res_obj = _get_resource(context, model, pk_value)
|
||||
context.session.delete(res_obj)
|
||||
|
||||
|
||||
def get_engine():
|
||||
return _get_engine_facade().get_engine()
|
||||
|
||||
|
||||
def get_resource(context, model, pk_value):
|
||||
return _get_resource(context, model, pk_value).to_dict()
|
||||
|
||||
|
||||
def get_session(expire_on_commit=False):
|
||||
return _get_engine_facade().get_session(expire_on_commit=expire_on_commit)
|
||||
|
||||
|
||||
def initialize():
|
||||
db_options.set_defaults(
|
||||
cfg.CONF,
|
||||
connection='sqlite:///:memory:')
|
||||
|
||||
|
||||
def query_resource(context, model, filters):
|
||||
query = context.session.query(model)
|
||||
objs = _filter_query(model, query, filters)
|
||||
return [obj.to_dict() for obj in objs]
|
||||
|
||||
|
||||
def update_resource(context, model, pk_value, update_dict):
|
||||
res_obj = _get_resource(context, model, pk_value)
|
||||
for key in update_dict:
|
||||
if key not in model.attributes:
|
||||
continue
|
||||
skip = False
|
||||
for pkey in inspect(model).primary_key:
|
||||
if pkey.name == key:
|
||||
skip = True
|
||||
break
|
||||
if skip:
|
||||
continue
|
||||
setattr(res_obj, key, update_dict[key])
|
||||
return res_obj.to_dict()
|
||||
|
||||
|
||||
class DictBase(object):
|
||||
attributes = []
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d):
|
||||
return cls(**d)
|
||||
|
||||
def to_dict(self):
|
||||
d = {}
|
||||
for attr in self.__class__.attributes:
|
||||
d[attr] = getattr(self, attr)
|
||||
return d
|
||||
|
||||
def __getitem__(self, key):
|
||||
return getattr(self, key)
|
24
tricircle/db/exception.py
Normal file
24
tricircle/db/exception.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
class ResourceNotFound(Exception):
|
||||
def __init__(self, model, pk_value):
|
||||
res_type = model.__name__.lower()
|
||||
message = "Could not find %(res_type)s: %(pk_value)s" % {
|
||||
'res_type': res_type,
|
||||
'pk_value': pk_value
|
||||
}
|
||||
super(ResourceNotFound, self).__init__(message)
|
17
tricircle/db/migrate_repo/__init__.py
Normal file
17
tricircle/db/migrate_repo/__init__.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
DB_INIT_VERSION = 0
|
26
tricircle/db/migrate_repo/migrate.cfg
Normal file
26
tricircle/db/migrate_repo/migrate.cfg
Normal file
@ -0,0 +1,26 @@
|
||||
[db_settings]
|
||||
# Used to identify which repository this database is versioned under.
|
||||
# You can use the name of your project.
|
||||
repository_id=tricircle
|
||||
|
||||
# The name of the database table used to track the schema version.
|
||||
# This name shouldn't already be used by your project.
|
||||
# If this is changed once a database is under version control, you'll need to
|
||||
# change the table name in each database too.
|
||||
version_table=migrate_version
|
||||
|
||||
# When committing a change script, Migrate will attempt to generate the
|
||||
# sql for all supported databases; normally, if one of them fails - probably
|
||||
# because you don't have that database installed - it is ignored and the
|
||||
# commit continues, perhaps ending successfully.
|
||||
# Databases in this list MUST compile successfully during a commit, or the
|
||||
# entire commit will fail. List the databases your application will actually
|
||||
# be using to ensure your updates to that database work properly.
|
||||
# This must be a list; example: ['postgres','sqlite']
|
||||
required_dbs=[]
|
||||
|
||||
# When creating new change scripts, Migrate will stamp the new script with
|
||||
# a version number. By default this is latest_version + 1. You can set this
|
||||
# to 'true' to tell Migrate to use the UTC timestamp instead.
|
||||
use_timestamp_numbering=False
|
||||
|
73
tricircle/db/migrate_repo/versions/001_init.py
Normal file
73
tricircle/db/migrate_repo/versions/001_init.py
Normal file
@ -0,0 +1,73 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
import migrate
|
||||
import sqlalchemy as sql
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = sql.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
cascaded_sites = sql.Table(
|
||||
'cascaded_sites', meta,
|
||||
sql.Column('site_id', sql.String(length=64), primary_key=True),
|
||||
sql.Column('site_name', sql.String(length=64), unique=True,
|
||||
nullable=False),
|
||||
sql.Column('az_id', sql.String(length=64), nullable=False),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8')
|
||||
cascaded_site_service_configuration = sql.Table(
|
||||
'cascaded_site_service_configuration', meta,
|
||||
sql.Column('service_id', sql.String(length=64), primary_key=True),
|
||||
sql.Column('site_id', sql.String(length=64), nullable=False),
|
||||
sql.Column('service_name', sql.String(length=64), unique=True,
|
||||
nullable=False),
|
||||
sql.Column('service_type', sql.String(length=64), nullable=False),
|
||||
sql.Column('service_url', sql.String(length=512), nullable=False),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8')
|
||||
cascaded_service_types = sql.Table(
|
||||
'cascaded_service_types', meta,
|
||||
sql.Column('id', sql.Integer, primary_key=True),
|
||||
sql.Column('service_type', sql.String(length=64), unique=True),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8')
|
||||
cascaded_site_services = sql.Table(
|
||||
'cascaded_site_services', meta,
|
||||
sql.Column('site_id', sql.String(length=64), primary_key=True),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8')
|
||||
|
||||
tables = [cascaded_sites, cascaded_site_service_configuration,
|
||||
cascaded_service_types, cascaded_site_services]
|
||||
for table in tables:
|
||||
table.create()
|
||||
|
||||
fkeys = [
|
||||
{'columns': [cascaded_site_service_configuration.c.site_id],
|
||||
'references': [cascaded_sites.c.site_id]},
|
||||
{'columns': [cascaded_site_service_configuration.c.service_type],
|
||||
'references': [cascaded_service_types.c.service_type]}
|
||||
]
|
||||
for fkey in fkeys:
|
||||
migrate.ForeignKeyConstraint(columns=fkey['columns'],
|
||||
refcolumns=fkey['references'],
|
||||
name=fkey.get('name')).create()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
raise NotImplementedError('can not downgrade from init repo.')
|
0
tricircle/db/migrate_repo/versions/__init__.py
Normal file
0
tricircle/db/migrate_repo/versions/__init__.py
Normal file
38
tricircle/db/migration_helpers.py
Normal file
38
tricircle/db/migration_helpers.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
import os
|
||||
|
||||
from oslo_db.sqlalchemy import migration
|
||||
|
||||
from tricircle import db
|
||||
from tricircle.db import core
|
||||
from tricircle.db import migrate_repo
|
||||
|
||||
|
||||
def find_migrate_repo(package=None, repo_name='migrate_repo'):
|
||||
package = package or db
|
||||
path = os.path.abspath(os.path.join(
|
||||
os.path.dirname(package.__file__), repo_name))
|
||||
# TODO(zhiyuan) handle path not valid exception
|
||||
return path
|
||||
|
||||
|
||||
def sync_repo(version):
|
||||
repo_abs_path = find_migrate_repo()
|
||||
init_version = migrate_repo.DB_INIT_VERSION
|
||||
engine = core.get_engine()
|
||||
migration.db_sync(engine, repo_abs_path, version, init_version)
|
97
tricircle/db/models.py
Normal file
97
tricircle/db/models.py
Normal file
@ -0,0 +1,97 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
import sqlalchemy as sql
|
||||
|
||||
from tricircle.db import core
|
||||
|
||||
|
||||
def create_site(context, site_dict):
|
||||
with context.session.begin():
|
||||
return core.create_resource(context, Site, site_dict)
|
||||
|
||||
|
||||
def delete_site(context, site_id):
|
||||
with context.session.begin():
|
||||
return core.delete_resource(context, Site, site_id)
|
||||
|
||||
|
||||
def get_site(context, site_id):
|
||||
with context.session.begin():
|
||||
return core.get_resource(context, Site, site_id)
|
||||
|
||||
|
||||
def list_sites(context, filters):
|
||||
with context.session.begin():
|
||||
return core.query_resource(context, Site, filters)
|
||||
|
||||
|
||||
def update_site(context, site_id, update_dict):
|
||||
with context.session.begin():
|
||||
return core.update_resource(context, Site, site_id, update_dict)
|
||||
|
||||
|
||||
def create_service_type(context, type_dict):
|
||||
with context.session.begin():
|
||||
return core.create_resource(context, ServiceType, type_dict)
|
||||
|
||||
|
||||
def create_site_service_configuration(context, config_dict):
|
||||
with context.session.begin():
|
||||
return core.create_resource(context, SiteServiceConfiguration,
|
||||
config_dict)
|
||||
|
||||
|
||||
class Site(core.ModelBase, core.DictBase):
|
||||
__tablename__ = 'cascaded_sites'
|
||||
attributes = ['site_id', 'site_name', 'az_id']
|
||||
site_id = sql.Column('site_id', sql.String(length=64), primary_key=True)
|
||||
site_name = sql.Column('site_name', sql.String(length=64), unique=True,
|
||||
nullable=False)
|
||||
az_id = sql.Column('az_id', sql.String(length=64), nullable=False)
|
||||
|
||||
|
||||
class SiteServiceConfiguration(core.ModelBase, core.DictBase):
|
||||
__tablename__ = 'cascaded_site_service_configuration'
|
||||
attributes = ['service_id', 'site_id', 'service_name',
|
||||
'service_type', 'service_url']
|
||||
service_id = sql.Column('service_id', sql.String(length=64),
|
||||
primary_key=True)
|
||||
site_id = sql.Column('site_id', sql.String(length=64),
|
||||
sql.ForeignKey('cascaded_sites.site_id'),
|
||||
nullable=False)
|
||||
service_name = sql.Column('service_name', sql.String(length=64),
|
||||
unique=True, nullable=False)
|
||||
service_type = sql.Column(
|
||||
'service_type', sql.String(length=64),
|
||||
sql.ForeignKey('cascaded_service_types.service_type'),
|
||||
nullable=False)
|
||||
service_url = sql.Column('service_url', sql.String(length=512),
|
||||
nullable=False)
|
||||
|
||||
|
||||
class ServiceType(core.ModelBase, core.DictBase):
|
||||
__tablename__ = 'cascaded_service_types'
|
||||
attributes = ['id', 'service_type']
|
||||
id = sql.Column('id', sql.Integer, primary_key=True)
|
||||
service_type = sql.Column('service_type', sql.String(length=64),
|
||||
unique=True)
|
||||
|
||||
|
||||
class SiteService(core.ModelBase, core.DictBase):
|
||||
__tablename__ = 'cascaded_site_services'
|
||||
attributes = ['site_id']
|
||||
site_id = sql.Column('site_id', sql.String(length=64), primary_key=True)
|
0
tricircle/tests/__init__.py
Normal file
0
tricircle/tests/__init__.py
Normal file
0
tricircle/tests/unit/__init__.py
Normal file
0
tricircle/tests/unit/__init__.py
Normal file
0
tricircle/tests/unit/db/__init__.py
Normal file
0
tricircle/tests/unit/db/__init__.py
Normal file
107
tricircle/tests/unit/db/test_models.py
Normal file
107
tricircle/tests/unit/db/test_models.py
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# 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.
|
||||
|
||||
|
||||
import unittest
|
||||
|
||||
from tricircle import context
|
||||
from tricircle.db import core
|
||||
from tricircle.db import exception
|
||||
from tricircle.db import models
|
||||
|
||||
|
||||
class ModelsTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
core.initialize()
|
||||
core.ModelBase.metadata.create_all(core.get_engine())
|
||||
self.context = context.Context()
|
||||
|
||||
def test_obj_to_dict(self):
|
||||
site = {'site_id': 'test_site_uuid',
|
||||
'site_name': 'test_site',
|
||||
'az_id': 'test_az_uuid'}
|
||||
site_obj = models.Site.from_dict(site)
|
||||
for attr in site_obj.attributes:
|
||||
self.assertEqual(getattr(site_obj, attr), site[attr])
|
||||
|
||||
def test_create(self):
|
||||
site = {'site_id': 'test_site_uuid',
|
||||
'site_name': 'test_site',
|
||||
'az_id': 'test_az_uuid'}
|
||||
site_ret = models.create_site(self.context, site)
|
||||
self.assertEqual(site_ret, site)
|
||||
|
||||
service_type = {'id': 1,
|
||||
'service_type': 'nova'}
|
||||
type_ret = models.create_service_type(self.context, service_type)
|
||||
self.assertEqual(type_ret, service_type)
|
||||
|
||||
configuration = {
|
||||
'service_id': 'test_config_uuid',
|
||||
'site_id': 'test_site_uuid',
|
||||
'service_name': 'nova_service',
|
||||
'service_type': 'nova',
|
||||
'service_url': 'http://test_url'
|
||||
}
|
||||
config_ret = models.create_site_service_configuration(self.context,
|
||||
configuration)
|
||||
self.assertEqual(config_ret, configuration)
|
||||
|
||||
def test_update(self):
|
||||
site = {'site_id': 'test_site_uuid',
|
||||
'site_name': 'test_site',
|
||||
'az_id': 'test_az1_uuid'}
|
||||
models.create_site(self.context, site)
|
||||
update_dict = {'site_id': 'fake_uuid',
|
||||
'site_name': 'test_site2',
|
||||
'az_id': 'test_az2_uuid'}
|
||||
ret = models.update_site(self.context, 'test_site_uuid', update_dict)
|
||||
# primary key value will not be updated
|
||||
self.assertEqual(ret['site_id'], 'test_site_uuid')
|
||||
self.assertEqual(ret['site_name'], 'test_site2')
|
||||
self.assertEqual(ret['az_id'], 'test_az2_uuid')
|
||||
|
||||
def test_delete(self):
|
||||
site = {'site_id': 'test_site_uuid',
|
||||
'site_name': 'test_site',
|
||||
'az_id': 'test_az_uuid'}
|
||||
models.create_site(self.context, site)
|
||||
models.delete_site(self.context, 'test_site_uuid')
|
||||
self.assertRaises(exception.ResourceNotFound, models.get_site,
|
||||
self.context, 'test_site_uuid')
|
||||
|
||||
def test_query(self):
|
||||
site1 = {'site_id': 'test_site1_uuid',
|
||||
'site_name': 'test_site1',
|
||||
'az_id': 'test_az1_uuid'}
|
||||
site2 = {'site_id': 'test_site2_uuid',
|
||||
'site_name': 'test_site2',
|
||||
'az_id': 'test_az2_uuid'}
|
||||
models.create_site(self.context, site1)
|
||||
models.create_site(self.context, site2)
|
||||
filters = [{'key': 'site_name',
|
||||
'comparator': 'eq',
|
||||
'value': 'test_site2'}]
|
||||
sites = models.list_sites(self.context, filters)
|
||||
self.assertEqual(len(sites), 1)
|
||||
self.assertEqual(sites[0], site2)
|
||||
filters = [{'key': 'site_name',
|
||||
'comparator': 'eq',
|
||||
'value': 'test_site3'}]
|
||||
sites = models.list_sites(self.context, filters)
|
||||
self.assertEqual(len(sites), 0)
|
||||
|
||||
def tearDown(self):
|
||||
core.ModelBase.metadata.drop_all(core.get_engine())
|
Loading…
Reference in New Issue
Block a user