d945029151
Change-Id: I70e7636cdfcbc5c5195e5a91b5cc7a401b6c9d72
305 lines
8.7 KiB
Python
305 lines
8.7 KiB
Python
# Copyright 2014 Huawei Technologies Co. Ltd
|
|
#
|
|
# 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.
|
|
|
|
"""Provider interface to manipulate database."""
|
|
import functools
|
|
import logging
|
|
import netaddr
|
|
|
|
from contextlib import contextmanager
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.exc import IntegrityError
|
|
from sqlalchemy.orm import scoped_session
|
|
from sqlalchemy.orm import sessionmaker
|
|
from threading import local
|
|
|
|
from compass.db import exception
|
|
from compass.db import models
|
|
from compass.utils import setting_wrapper as setting
|
|
|
|
|
|
ENGINE = None
|
|
SESSION = sessionmaker(autocommit=False, autoflush=False)
|
|
SCOPED_SESSION = None
|
|
SESSION_HOLDER = local()
|
|
|
|
|
|
def init(database_url=None):
|
|
"""Initialize database.
|
|
|
|
:param database_url: string, database url.
|
|
"""
|
|
global ENGINE
|
|
global SCOPED_SESSION
|
|
if not database_url:
|
|
database_url = setting.SQLALCHEMY_DATABASE_URI
|
|
logging.info('init database %s', database_url)
|
|
ENGINE = create_engine(database_url, convert_unicode=True)
|
|
SESSION.configure(bind=ENGINE)
|
|
SCOPED_SESSION = scoped_session(SESSION)
|
|
models.BASE.query = SCOPED_SESSION.query_property()
|
|
|
|
|
|
def in_session():
|
|
"""check if in database session scope."""
|
|
if hasattr(SESSION_HOLDER, 'session'):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
@contextmanager
|
|
def session():
|
|
"""database session scope.
|
|
|
|
.. note::
|
|
To operate database, it should be called in database session.
|
|
"""
|
|
import traceback
|
|
if hasattr(SESSION_HOLDER, 'session'):
|
|
logging.error('we are already in session')
|
|
raise exception.DatabaseException('session already exist')
|
|
else:
|
|
new_session = SCOPED_SESSION()
|
|
setattr(SESSION_HOLDER, 'session', new_session)
|
|
|
|
try:
|
|
yield new_session
|
|
new_session.commit()
|
|
except Exception as error:
|
|
new_session.rollback()
|
|
logging.error('failed to commit session')
|
|
logging.exception(error)
|
|
if isinstance(error, IntegrityError):
|
|
raise exception.NotAcceptable(
|
|
'operation error in database'
|
|
)
|
|
elif isinstance(error, exception.DatabaseException):
|
|
raise error
|
|
else:
|
|
raise exception.DatabaseException(str(error))
|
|
finally:
|
|
new_session.close()
|
|
SCOPED_SESSION.remove()
|
|
delattr(SESSION_HOLDER, 'session')
|
|
|
|
|
|
def current_session():
|
|
"""Get the current session scope when it is called.
|
|
|
|
:return: database session.
|
|
"""
|
|
try:
|
|
return SESSION_HOLDER.session
|
|
except Exception as error:
|
|
logging.error('It is not in the session scope')
|
|
logging.exception(error)
|
|
if isinstance(error, exception.DatabaseException):
|
|
raise error
|
|
else:
|
|
raise exception.DatabaseException(str(error))
|
|
|
|
|
|
def run_in_session():
|
|
def decorator(func):
|
|
@functools.wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
with session() as my_session:
|
|
return func(my_session, *args, **kwargs)
|
|
return wrapper
|
|
return decorator
|
|
|
|
|
|
def _setup_user_table(user_session):
|
|
"""Initialize default user."""
|
|
logging.info('setup user table')
|
|
from compass.db.api import user
|
|
user.add_user_internal(
|
|
user_session,
|
|
email=setting.COMPASS_ADMIN_EMAIL,
|
|
password=setting.COMPASS_ADMIN_PASSWORD,
|
|
is_admin=True
|
|
)
|
|
|
|
|
|
def _setup_permission_table(permission_session):
|
|
"""Initialize permission table."""
|
|
logging.info('setup permission table.')
|
|
from compass.db.api import permission
|
|
permission.add_permissions_internal(
|
|
permission_session
|
|
)
|
|
|
|
|
|
def _setup_switch_table(switch_session):
|
|
"""Initialize switch table."""
|
|
logging.info('setup switch table')
|
|
from compass.db.api import switch
|
|
switch.add_switch_internal(
|
|
switch_session, long(netaddr.IPAddress(setting.DEFAULT_SWITCH_IP))
|
|
)
|
|
|
|
|
|
def _setup_os_installers(installer_session):
|
|
"""Initialize os_installer table."""
|
|
logging.info('setup os installer table')
|
|
from compass.db.api import installer
|
|
installer.add_os_installers_internal(
|
|
installer_session
|
|
)
|
|
|
|
|
|
def _setup_package_installers(installer_session):
|
|
"""Initialize package_installer table."""
|
|
logging.info('setup package installer table')
|
|
from compass.db.api import installer
|
|
installer.add_package_installers_internal(
|
|
installer_session
|
|
)
|
|
|
|
|
|
def _setup_oses(os_session):
|
|
"""Initialize os table."""
|
|
logging.info('setup os table')
|
|
from compass.db.api import adapter
|
|
adapter.add_oses_internal(
|
|
os_session
|
|
)
|
|
|
|
|
|
def _setup_distributed_systems(distributed_system_session):
|
|
"""Initialize distributed system table."""
|
|
logging.info('setup distributed system table')
|
|
from compass.db.api import adapter
|
|
adapter.add_distributed_systems_internal(
|
|
distributed_system_session
|
|
)
|
|
|
|
|
|
def _setup_adapters(adapter_session):
|
|
"""Initialize package adapter table."""
|
|
logging.info('setup adapter table')
|
|
from compass.db.api import adapter
|
|
adapter.add_adapters_internal(
|
|
adapter_session)
|
|
|
|
|
|
def _setup_os_fields(field_session):
|
|
"""Initialize os field table."""
|
|
logging.info('setup os field table')
|
|
from compass.db.api import metadata
|
|
metadata.add_os_field_internal(field_session)
|
|
|
|
|
|
def _setup_package_fields(field_session):
|
|
"""Initialize package field table."""
|
|
logging.info('setup package field table')
|
|
from compass.db.api import metadata
|
|
metadata.add_package_field_internal(field_session)
|
|
|
|
|
|
def _setup_os_metadatas(metadata_session):
|
|
"""Initialize os metadata table."""
|
|
logging.info('setup os metadata table')
|
|
from compass.db.api import metadata
|
|
metadata.add_os_metadata_internal(metadata_session)
|
|
|
|
|
|
def _setup_package_metadatas(metadata_session):
|
|
"""Initialize package metadata table."""
|
|
logging.info('setup package metadata table')
|
|
from compass.db.api import metadata
|
|
metadata.add_package_metadata_internal(metadata_session)
|
|
|
|
|
|
def _setup_adapter_roles(role_session):
|
|
"""Initialize package adapter role table."""
|
|
logging.info('setup adapter role table')
|
|
from compass.db.api import adapter
|
|
adapter.add_roles_internal(role_session)
|
|
|
|
|
|
@run_in_session()
|
|
def create_db(my_session):
|
|
"""Create database."""
|
|
models.BASE.metadata.create_all(bind=ENGINE)
|
|
_setup_permission_table(my_session)
|
|
_setup_user_table(my_session)
|
|
_setup_switch_table(my_session)
|
|
_setup_os_installers(my_session)
|
|
_setup_package_installers(my_session)
|
|
_setup_oses(my_session)
|
|
_setup_distributed_systems(my_session)
|
|
_setup_adapters(my_session)
|
|
_setup_adapter_roles(my_session)
|
|
_setup_os_fields(my_session)
|
|
_setup_package_fields(my_session)
|
|
_setup_os_metadatas(my_session)
|
|
_setup_package_metadatas(my_session)
|
|
|
|
|
|
def drop_db():
|
|
"""Drop database."""
|
|
models.BASE.metadata.drop_all(bind=ENGINE)
|
|
|
|
|
|
@run_in_session()
|
|
def create_table(my_session, table):
|
|
"""Create table.
|
|
|
|
:param table: Class of the Table defined in the model.
|
|
"""
|
|
table.__table__.create(bind=ENGINE, checkfirst=True)
|
|
if table == models.User:
|
|
_setup_user_table(my_session)
|
|
elif table == models.Permission:
|
|
_setup_permission_table(my_session)
|
|
elif table == models.Switch:
|
|
_setup_switch_table(my_session)
|
|
elif table in [
|
|
models.OSInstaller,
|
|
models.PackageInstaller,
|
|
models.OperatingSystem,
|
|
models.DistributedSystems,
|
|
models.Adapter
|
|
]:
|
|
_setup_os_installers(my_session)
|
|
_setup_package_installers(my_session)
|
|
_setup_adapter_roles(my_session)
|
|
_setup_adapters(my_session)
|
|
_setup_os_fields(my_session)
|
|
_setup_os_metadatas(my_session)
|
|
_setup_package_fields(my_session)
|
|
_setup_package_metadatas(my_session)
|
|
elif table == models.AdapterRole:
|
|
_setup_adapter_roles(my_session)
|
|
elif table in [
|
|
models.OSConfigField,
|
|
models.PackageConfigField,
|
|
models.OSConfigMetadata,
|
|
models.PackageConfigMetadata
|
|
]:
|
|
_setup_os_fields(my_session)
|
|
_setup_os_metadatas(my_session)
|
|
_setup_package_fields(my_session)
|
|
_setup_package_metadatas(my_session)
|
|
|
|
|
|
def drop_table(table):
|
|
"""Drop table.
|
|
|
|
:param table: Class of the Table defined in the model.
|
|
"""
|
|
table.__table__.drop(bind=ENGINE, checkfirst=True)
|