Provide user friendly messages for db sync

Currently 'cinder-manage db sync' prints stacktrace if you
pass invalid value for 'version'.

This patch validates 'version' for its type and maximum
limit and displays a meaningful message to the user.

Handles DbMigrationError exception when database schema
file is not present in migration repository.

Closes-Bug: #1546441
Change-Id: Id3dc077b80c2b6353907a1bb5c15cefdb2eae8ed
This commit is contained in:
Dinesh Bhor 2016-02-18 06:17:13 -08:00
parent f79f009f0c
commit 104c0ba78f
2 changed files with 25 additions and 3 deletions

View File

@ -210,11 +210,19 @@ class DbCommands(object):
def __init__(self): def __init__(self):
pass pass
@args('version', nargs='?', default=None, @args('version', nargs='?', default=None, type=int,
help='Database version') help='Database version')
def sync(self, version=None): def sync(self, version=None):
"""Sync the database up to the most recent version.""" """Sync the database up to the most recent version."""
return db_migration.db_sync(version) if version is not None and version > db.MAX_INT:
print(_('Version should be less than or equal to '
'%(max_version)d.') % {'max_version': db.MAX_INT})
sys.exit(1)
try:
return db_migration.db_sync(version)
except db_exc.DbMigrationError as ex:
print("Error during database migration: %s" % ex)
sys.exit(1)
def version(self): def version(self):
"""Print the current database version.""" """Print the current database version."""

View File

@ -19,6 +19,7 @@ import ddt
import fixtures import fixtures
import mock import mock
from oslo_config import cfg from oslo_config import cfg
from oslo_db import exception as oslo_exception
from oslo_utils import timeutils from oslo_utils import timeutils
import six import six
from six.moves import StringIO from six.moves import StringIO
@ -194,7 +195,7 @@ class TestCinderManageCmd(test.TestCase):
@mock.patch('cinder.db.migration.db_sync') @mock.patch('cinder.db.migration.db_sync')
def test_db_commands_sync(self, db_sync): def test_db_commands_sync(self, db_sync):
version = mock.MagicMock() version = 11
db_cmds = cinder_manage.DbCommands() db_cmds = cinder_manage.DbCommands()
db_cmds.sync(version=version) db_cmds.sync(version=version)
db_sync.assert_called_once_with(version) db_sync.assert_called_once_with(version)
@ -206,6 +207,19 @@ class TestCinderManageCmd(test.TestCase):
db_cmds.version() db_cmds.version()
self.assertEqual(1, db_version.call_count) self.assertEqual(1, db_version.call_count)
def test_db_commands_upgrade_out_of_range(self):
version = 2147483647
db_cmds = cinder_manage.DbCommands()
exit = self.assertRaises(SystemExit, db_cmds.sync, version + 1)
self.assertEqual(1, exit.code)
@mock.patch("oslo_db.sqlalchemy.migration.db_sync")
def test_db_commands_script_not_present(self, db_sync):
db_sync.side_effect = oslo_exception.DbMigrationError
db_cmds = cinder_manage.DbCommands()
exit = self.assertRaises(SystemExit, db_cmds.sync, 101)
self.assertEqual(1, exit.code)
@mock.patch('cinder.cmd.manage.DbCommands.online_migrations', @mock.patch('cinder.cmd.manage.DbCommands.online_migrations',
(mock.Mock(side_effect=((2, 2), (0, 0)), __name__='foo'),)) (mock.Mock(side_effect=((2, 2), (0, 0)), __name__='foo'),))
def test_db_commands_online_data_migrations(self): def test_db_commands_online_data_migrations(self):