glance/glance/db/sqlalchemy/migration.py

138 lines
4.3 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack LLC.
# 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 migrate.versioning import api as versioning_api
# See LP bug #719834. sqlalchemy-migrate changed location of
# exceptions.py after 0.6.0.
try:
from migrate.versioning import exceptions as versioning_exceptions
except ImportError:
from migrate import exceptions as versioning_exceptions
from migrate.versioning import repository as versioning_repository
from oslo.config import cfg
from glance.common import exception
import glance.openstack.common.log as logging
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
def db_version():
"""
Return the database's current migration number
:retval version number
"""
repo_path = get_migrate_repo_path()
sql_connection = CONF.sql_connection
try:
return versioning_api.db_version(sql_connection, repo_path)
except versioning_exceptions.DatabaseNotControlledError, e:
msg = (_("database '%(sql_connection)s' is not under "
"migration control") % locals())
raise exception.DatabaseMigrationError(msg)
def upgrade(version=None):
"""
Upgrade the database's current migration level
:param version: version to upgrade (defaults to latest)
:retval version number
"""
db_version() # Ensure db is under migration control
repo_path = get_migrate_repo_path()
sql_connection = CONF.sql_connection
version_str = version or 'latest'
LOG.info(_("Upgrading %(sql_connection)s to version %(version_str)s") %
locals())
return versioning_api.upgrade(sql_connection, repo_path, version)
def downgrade(version):
"""
Downgrade the database's current migration level
:param version: version to downgrade to
:retval version number
"""
db_version() # Ensure db is under migration control
repo_path = get_migrate_repo_path()
sql_connection = CONF.sql_connection
LOG.info(_("Downgrading %(sql_connection)s to version %(version)s") %
locals())
return versioning_api.downgrade(sql_connection, repo_path, version)
def version_control(version=None):
"""
Place a database under migration control
"""
sql_connection = CONF.sql_connection
try:
_version_control(version)
except versioning_exceptions.DatabaseAlreadyControlledError, e:
msg = (_("database '%(sql_connection)s' is already under migration "
"control") % locals())
raise exception.DatabaseMigrationError(msg)
def _version_control(version):
"""
Place a database under migration control
This will only set the specific version of a database, it won't
run any migrations.
"""
repo_path = get_migrate_repo_path()
sql_connection = CONF.sql_connection
if version is None:
version = versioning_repository.Repository(repo_path).latest
return versioning_api.version_control(sql_connection, repo_path, version)
def db_sync(version=None, current_version=None):
"""
Place a database under migration control and perform an upgrade
:retval version number
"""
sql_connection = CONF.sql_connection
try:
_version_control(current_version or 0)
except versioning_exceptions.DatabaseAlreadyControlledError, e:
pass
if current_version is None:
current_version = int(db_version())
if version is not None and int(version) < current_version:
downgrade(version=version)
elif version is None or int(version) > current_version:
upgrade(version=version)
def get_migrate_repo_path():
"""Get the path for the migrate repository."""
path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
'migrate_repo')
assert os.path.exists(path)
return path