glance-manage should work like nova-manage

nova-manage supports subcommands of db, for nova-manage,
eg) 'nova-manage db sync',
glance manage however has individual commands like db_sync, db_version
etc. This patch aims at adding the db operations as subcommands to db in
glance-manage similar to nova and refactoring this bit of code in
cmd/manage.py

Fixes: bug 1213197
Change-Id: I6fad31766bc1cec2a666a7ebc8df5c732007c5f1
This commit is contained in:
AmalaBasha 2013-09-18 18:52:47 +05:30
parent ce2e5dc60b
commit 7e6319d955
6 changed files with 113 additions and 47 deletions

View File

@ -173,7 +173,7 @@ Optional. Default: ``1``
* ``db_auto_create=False`` * ``db_auto_create=False``
Whether to automatically create the database tables. Otherwise you can Whether to automatically create the database tables. Otherwise you can
manually run `glance-manage db_sync`. manually run `glance-manage db sync`.
Optional. Default: ``False`` Optional. Default: ``False``

View File

@ -21,27 +21,31 @@ The default metadata driver for glance uses sqlalchemy, which implies there
exists a backend database which must be managed. The ``glance-manage`` binary exists a backend database which must be managed. The ``glance-manage`` binary
provides a set of commands for making this easier. provides a set of commands for making this easier.
The commands should be executed as a subcommand of 'db':
Initializing an Empty Database glance-manage db <cmd> <args>
------------------------------
glance-manage db_sync
This will take an empty database and create the necessary tables. Sync the Database
-----------------
glance-manage db sync <version> <current_version>
Place a database under migration control and upgrade, creating it first if necessary.
Determining the Database Version Determining the Database Version
-------------------------------- --------------------------------
glance-manage db_version glance-manage db version
This will print the version of a glance database. This will print the current migration level of a glance database.
Upgrading an Existing Database Upgrading an Existing Database
------------------------------ ------------------------------
glance-manage db_sync <VERSION> glance-manage db upgrade <VERSION>
This will take an existing database and upgrade it to the specified VERSION. This will take an existing database and upgrade it to the specified VERSION.
@ -49,7 +53,7 @@ This will take an existing database and upgrade it to the specified VERSION.
Downgrading an Existing Database Downgrading an Existing Database
-------------------------------- --------------------------------
glance-manage downgrade <VERSION> glance-manage db downgrade <VERSION>
This will downgrade an existing database from the current version to the This will downgrade an existing database from the current version to the
specified VERSION. specified VERSION.

View File

@ -24,7 +24,7 @@ DESCRIPTION
glance-manage is a utility for managing and configuring a Glance installation. glance-manage is a utility for managing and configuring a Glance installation.
One important use of glance-manage is to setup the database. To do this run:: One important use of glance-manage is to setup the database. To do this run::
glance-manage db_sync glance-manage db sync
OPTIONS OPTIONS
======= =======

View File

@ -44,69 +44,130 @@ from oslo.config import cfg
from glance.common import config from glance.common import config
from glance.common import exception from glance.common import exception
import glance.db.sqlalchemy.api import glance.db.sqlalchemy.api
import glance.db.sqlalchemy.migration from glance.db.sqlalchemy import migration
from glance.openstack.common import log from glance.openstack.common import log
CONF = cfg.CONF CONF = cfg.CONF
def do_db_version(): # Decorators for actions
"""Print database's current migration level""" def args(*args, **kwargs):
print(glance.db.sqlalchemy.migration.db_version()) def _decorator(func):
func.__dict__.setdefault('args', []).insert(0, (args, kwargs))
return func
return _decorator
def do_upgrade(): class DbCommands(object):
"""Upgrade the database's migration level""" """Class for managing the db"""
glance.db.sqlalchemy.migration.upgrade(CONF.command.version)
def __init__(self):
pass
def version(self):
"""Print database's current migration level"""
print(migration.db_version())
@args('--version', metavar='<version>', help='Database version')
def upgrade(self, version=None):
"""Upgrade the database's migration level"""
migration.upgrade(version)
@args('--version', metavar='<version>', help='Database version')
def downgrade(self, version=None):
"""Downgrade the database's migration level"""
migration.downgrade(version)
@args('--version', metavar='<version>', help='Database version')
def version_control(self, version=None):
"""Place a database under migration control"""
migration.version_control(version)
@args('--version', metavar='<version>', help='Database version')
@args('--current_version', metavar='<version>',
help='Current Database version')
def sync(self, version=None, current_version=None):
"""
Place a database under migration control and upgrade,
creating first if necessary.
"""
migration.db_sync(version, current_version)
def do_downgrade(): def add_legacy_command_parsers(command_object, subparsers):
"""Downgrade the database's migration level"""
glance.db.sqlalchemy.migration.downgrade(CONF.command.version)
def do_version_control():
"""Place a database under migration control"""
glance.db.sqlalchemy.migration.version_control(CONF.command.version)
def do_db_sync():
"""
Place a database under migration control and upgrade,
creating first if necessary.
"""
glance.db.sqlalchemy.migration.db_sync(CONF.command.version,
CONF.command.current_version)
def add_command_parsers(subparsers):
parser = subparsers.add_parser('db_version') parser = subparsers.add_parser('db_version')
parser.set_defaults(func=do_db_version) parser.set_defaults(action_fn=command_object.version)
parser = subparsers.add_parser('upgrade') parser = subparsers.add_parser('db_upgrade')
parser.set_defaults(func=do_upgrade) parser.set_defaults(action_fn=command_object.upgrade)
parser.add_argument('version', nargs='?') parser.add_argument('version', nargs='?')
parser = subparsers.add_parser('downgrade') parser = subparsers.add_parser('db_downgrade')
parser.set_defaults(func=do_downgrade) parser.set_defaults(action_fn=command_object.downgrade)
parser.add_argument('version') parser.add_argument('version')
parser = subparsers.add_parser('version_control') parser = subparsers.add_parser('db_version_control')
parser.set_defaults(func=do_version_control) parser.set_defaults(action_fn=command_object.version_control)
parser.add_argument('version', nargs='?') parser.add_argument('version', nargs='?')
parser = subparsers.add_parser('db_sync') parser = subparsers.add_parser('db_sync')
parser.set_defaults(func=do_db_sync) parser.set_defaults(action_fn=command_object.sync)
parser.add_argument('version', nargs='?') parser.add_argument('version', nargs='?')
parser.add_argument('current_version', nargs='?') parser.add_argument('current_version', nargs='?')
def add_command_parsers(subparsers):
command_object = DbCommands()
parser = subparsers.add_parser('db')
parser.set_defaults(command_object=command_object)
category_subparsers = parser.add_subparsers(dest='action')
for (action, action_fn) in methods_of(command_object):
parser = category_subparsers.add_parser(action)
action_kwargs = []
for args, kwargs in getattr(action_fn, 'args', []):
# FIXME(basha): hack to assume dest is the arg name without
# the leading hyphens if no dest is supplied
kwargs.setdefault('dest', args[0][2:])
if kwargs['dest'].startswith('action_kwarg_'):
action_kwargs.append(
kwargs['dest'][len('action_kwarg_'):])
else:
action_kwargs.append(kwargs['dest'])
kwargs['dest'] = 'action_kwarg_' + kwargs['dest']
parser.add_argument(*args, **kwargs)
parser.set_defaults(action_fn=action_fn)
parser.set_defaults(action_kwargs=action_kwargs)
parser.add_argument('action_args', nargs='*')
add_legacy_command_parsers(command_object, subparsers)
command_opt = cfg.SubCommandOpt('command', command_opt = cfg.SubCommandOpt('command',
title='Commands', title='Commands',
help='Available commands', help='Available commands',
handler=add_command_parsers) handler=add_command_parsers)
def methods_of(obj):
"""Get all callable methods of an object that don't start with underscore
returns a list of tuples of the form (method_name, method)
"""
result = []
for i in dir(obj):
if callable(getattr(obj, i)) and not i.startswith('_'):
result.append((i, getattr(obj, i)))
return result
def main(): def main():
CONF.register_cli_opt(command_opt) CONF.register_cli_opt(command_opt)
try: try:
@ -125,7 +186,8 @@ def main():
sys.exit("ERROR: %s" % e) sys.exit("ERROR: %s" % e)
try: try:
CONF.command.func()
CONF.command.action_fn()
except exception.GlanceException as e: except exception.GlanceException as e:
sys.exit("ERROR: %s" % e) sys.exit("ERROR: %s" % e)

View File

@ -215,7 +215,7 @@ class Server(object):
os.system('cp %s %s/tests.sqlite' os.system('cp %s %s/tests.sqlite'
% (db_location, self.test_dir)) % (db_location, self.test_dir))
else: else:
cmd = ('%s -m glance.cmd.manage --config-file %s db_sync' % cmd = ('%s -m glance.cmd.manage --config-file %s db sync' %
(sys.executable, conf_filepath)) (sys.executable, conf_filepath))
execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env, execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env,
expect_exit=True) expect_exit=True)

View File

@ -44,7 +44,7 @@ class TestGlanceManage(functional.FunctionalTest):
conf_file.write(self.connection) conf_file.write(self.connection)
conf_file.flush() conf_file.flush()
cmd = ('%s -m glance.cmd.manage --config-file %s db_sync' % cmd = ('%s -m glance.cmd.manage --config-file %s db sync' %
(sys.executable, self.conf_filepath)) (sys.executable, self.conf_filepath))
execute(cmd, raise_error=True) execute(cmd, raise_error=True)