Adding migration management commands
This commit is contained in:
parent
8a084f6ff5
commit
9c5290bcb5
@ -6,5 +6,6 @@ include tests/stubs.py
|
||||
include tests/test_data.py
|
||||
include tests/utils.py
|
||||
include run_tests.py
|
||||
include glance/registry/db/migrate_repo/migrate.cfg
|
||||
graft doc
|
||||
graft tools
|
||||
|
126
bin/glance-manage
Executable file
126
bin/glance-manage
Executable file
@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Glance Management Utility
|
||||
"""
|
||||
|
||||
# FIXME(sirp): When we have glance-admin we can consider merging this into it
|
||||
# Perhaps for consistency with Nova, we would then rename glance-admin ->
|
||||
# glance-manage (or the other way around)
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
sys.path.append(ROOT_DIR)
|
||||
|
||||
from glance import version as glance_version
|
||||
from glance.common import config
|
||||
from glance.common import exception
|
||||
import glance.registry.db
|
||||
import glance.registry.db.migration
|
||||
|
||||
|
||||
def create_options(parser):
|
||||
"""
|
||||
Sets up the CLI and config-file options that may be
|
||||
parsed and program commands.
|
||||
|
||||
:param parser: The option parser
|
||||
"""
|
||||
parser.add_option('-v', '--verbose', default=False, dest="verbose",
|
||||
action="store_true",
|
||||
help="Print more verbose output")
|
||||
parser.add_option('-d', '--debug', default=False, dest="debug",
|
||||
action="store_true",
|
||||
help="Print debugging output")
|
||||
config.add_log_options('glance-manage', parser)
|
||||
glance.registry.db.add_options(parser)
|
||||
|
||||
|
||||
def do_db_version(options, args):
|
||||
"""Print database's current migration level"""
|
||||
print glance.registry.db.migration.db_version(options)
|
||||
|
||||
|
||||
def do_upgrade(options, args):
|
||||
"""Upgrade the database's migration level"""
|
||||
try:
|
||||
db_version = args[1]
|
||||
except IndexError:
|
||||
db_version = None
|
||||
|
||||
glance.registry.db.migration.upgrade(options, version=db_version)
|
||||
|
||||
|
||||
def do_downgrade(options, args):
|
||||
"""Downgrade the database's migration level"""
|
||||
try:
|
||||
db_version = args[1]
|
||||
except IndexError:
|
||||
raise exception.MissingArgumentError(
|
||||
"downgrade requires a version argument")
|
||||
|
||||
glance.registry.db.migration.downgrade(options, version=db_version)
|
||||
|
||||
|
||||
def do_version_control(options, args):
|
||||
"""Place a database under migration control"""
|
||||
glance.registry.db.migration.version_control(options)
|
||||
|
||||
|
||||
def dispatch_cmd(options, args):
|
||||
"""Search for do_* cmd in this module and then run it"""
|
||||
cmd = args[0]
|
||||
try:
|
||||
cmd_func = globals()['do_%s' % cmd]
|
||||
except KeyError:
|
||||
sys.exit("ERROR: unrecognized command '%s'" % cmd)
|
||||
|
||||
try:
|
||||
cmd_func(options, args)
|
||||
except exception.Error, e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
||||
|
||||
def main():
|
||||
version = '%%prog %s' % glance_version.version_string()
|
||||
usage = "%prog [options] <cmd>"
|
||||
oparser = optparse.OptionParser(usage, version=version)
|
||||
create_options(oparser)
|
||||
(options, args) = config.parse_options(oparser)
|
||||
|
||||
try:
|
||||
config.setup_logging(options)
|
||||
except RuntimeError, e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
||||
if not args:
|
||||
oparser.print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
dispatch_cmd(options, args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -33,6 +33,9 @@ Kernel-outside:
|
||||
<filename> <name>
|
||||
|
||||
"""
|
||||
|
||||
# FIXME(sirp): This can be merged into glance-admin when that becomes
|
||||
# available
|
||||
import argparse
|
||||
import pprint
|
||||
import sys
|
||||
|
@ -75,6 +75,14 @@ class BadInputError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MissingArgumentError(Error):
|
||||
pass
|
||||
|
||||
|
||||
class DatabaseMigrationError(Error):
|
||||
pass
|
||||
|
||||
|
||||
def wrap_exception(f):
|
||||
def _wrap(*args, **kw):
|
||||
try:
|
||||
|
4
glance/registry/db/migrate_repo/README
Normal file
4
glance/registry/db/migrate_repo/README
Normal file
@ -0,0 +1,4 @@
|
||||
This is a database migration repository.
|
||||
|
||||
More information at
|
||||
http://code.google.com/p/sqlalchemy-migrate/
|
1
glance/registry/db/migrate_repo/__init__.py
Normal file
1
glance/registry/db/migrate_repo/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# template repository default module
|
3
glance/registry/db/migrate_repo/manage.py
Normal file
3
glance/registry/db/migrate_repo/manage.py
Normal file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
from migrate.versioning.shell import main
|
||||
main(debug='False')
|
20
glance/registry/db/migrate_repo/migrate.cfg
Normal file
20
glance/registry/db/migrate_repo/migrate.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
[db_settings]
|
||||
# Used to identify which repository this database is versioned under.
|
||||
# You can use the name of your project.
|
||||
repository_id=Glance Migrations
|
||||
|
||||
# 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=[]
|
1
glance/registry/db/migrate_repo/versions/__init__.py
Normal file
1
glance/registry/db/migrate_repo/versions/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# template repository default versions module
|
94
glance/registry/db/migration.py
Normal file
94
glance/registry/db/migration.py
Normal file
@ -0,0 +1,94 @@
|
||||
# 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 logging
|
||||
import os
|
||||
|
||||
from migrate.versioning import api as versioning_api
|
||||
from migrate.versioning import exceptions as versioning_exceptions
|
||||
|
||||
from glance.common import exception
|
||||
|
||||
|
||||
def db_version(options):
|
||||
"""Return the database's current migration number
|
||||
|
||||
:param options: options dict
|
||||
:retval version number
|
||||
"""
|
||||
repo_path = _find_migrate_repo()
|
||||
sql_connection = options['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(options, version=None):
|
||||
"""Upgrade the database's current migration level
|
||||
|
||||
:param options: options dict
|
||||
:param version: version to upgrade (defaults to latest)
|
||||
:retval version number
|
||||
"""
|
||||
db_version(options) # Ensure db is under migration control
|
||||
repo_path = _find_migrate_repo()
|
||||
sql_connection = options['sql_connection']
|
||||
version_str = version or 'latest'
|
||||
logging.info("Upgrading %(sql_connection)s to version %(version_str)s" %
|
||||
locals())
|
||||
return versioning_api.upgrade(sql_connection, repo_path, version)
|
||||
|
||||
|
||||
def downgrade(options, version):
|
||||
"""Downgrade the database's current migration level
|
||||
|
||||
:param options: options dict
|
||||
:param version: version to downgrade to
|
||||
:retval version number
|
||||
"""
|
||||
db_version(options) # Ensure db is under migration control
|
||||
repo_path = _find_migrate_repo()
|
||||
sql_connection = options['sql_connection']
|
||||
logging.info("Downgrading %(sql_connection)s to version %(version)s" %
|
||||
locals())
|
||||
return versioning_api.downgrade(sql_connection, repo_path, version)
|
||||
|
||||
|
||||
def version_control(options):
|
||||
"""Place a database under migration control
|
||||
|
||||
:param options: options dict
|
||||
"""
|
||||
repo_path = _find_migrate_repo()
|
||||
sql_connection = options['sql_connection']
|
||||
try:
|
||||
versioning_api.version_control(sql_connection, repo_path)
|
||||
except versioning_exceptions.DatabaseAlreadyControlledError, e:
|
||||
msg = ("database '%(sql_connection)s' is already under migration "
|
||||
"control" % locals())
|
||||
raise exception.DatabaseMigrationError(msg)
|
||||
|
||||
|
||||
def _find_migrate_repo():
|
||||
"""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
|
@ -14,3 +14,4 @@ sphinx
|
||||
argparse
|
||||
mox==0.5.0
|
||||
-f http://pymox.googlecode.com/files/mox-0.5.0.tar.gz
|
||||
sqlalchemy-migrate>=0.6
|
||||
|
Loading…
x
Reference in New Issue
Block a user