Merge "Make nova-manage online migrations more verbose"
This commit is contained in:
+20
-3
@@ -66,6 +66,7 @@ from oslo_log import log as logging
|
||||
import oslo_messaging as messaging
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
import prettytable
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
@@ -881,6 +882,7 @@ class DbCommands(object):
|
||||
|
||||
def _run_migration(self, ctxt, max_count):
|
||||
ran = 0
|
||||
migrations = {}
|
||||
for migration_meth in self.online_migrations:
|
||||
count = max_count - ran
|
||||
try:
|
||||
@@ -890,16 +892,20 @@ class DbCommands(object):
|
||||
method=migration_meth))
|
||||
found = done = 0
|
||||
|
||||
name = migration_meth.__name__
|
||||
if found:
|
||||
print(_('%(total)i rows matched query %(meth)s, %(done)i '
|
||||
'migrated') % {'total': found,
|
||||
'meth': migration_meth.__name__,
|
||||
'meth': name,
|
||||
'done': done})
|
||||
migrations.setdefault(name, (0, 0))
|
||||
migrations[name] = (migrations[name][0] + found,
|
||||
migrations[name][1] + done)
|
||||
if max_count is not None:
|
||||
ran += done
|
||||
if ran >= max_count:
|
||||
break
|
||||
return ran
|
||||
return migrations
|
||||
|
||||
@args('--max-count', metavar='<number>', dest='max_count',
|
||||
help='Maximum number of objects to consider')
|
||||
@@ -920,11 +926,22 @@ class DbCommands(object):
|
||||
print(_('Running batches of %i until complete') % max_count)
|
||||
|
||||
ran = None
|
||||
migration_info = {}
|
||||
while ran is None or ran != 0:
|
||||
ran = self._run_migration(ctxt, max_count)
|
||||
migrations = self._run_migration(ctxt, max_count)
|
||||
migration_info.update(migrations)
|
||||
ran = sum([done for found, done in migrations.values()])
|
||||
if not unlimited:
|
||||
break
|
||||
|
||||
t = prettytable.PrettyTable([_('Migration'),
|
||||
_('Total Needed'),
|
||||
_('Completed')])
|
||||
for name in sorted(migration_info.keys()):
|
||||
info = migration_info[name]
|
||||
t.add_row([name, info[0], info[1]])
|
||||
print(t)
|
||||
|
||||
return ran and 1 or 0
|
||||
|
||||
|
||||
|
||||
@@ -586,12 +586,24 @@ class DBCommandsTestCase(test.NoDBTestCase):
|
||||
|
||||
@mock.patch('nova.context.get_admin_context')
|
||||
def test_online_migrations(self, mock_get_context):
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', StringIO()))
|
||||
ctxt = mock_get_context.return_value
|
||||
command_cls = self._fake_db_command()
|
||||
command = command_cls()
|
||||
command.online_data_migrations(10)
|
||||
command_cls.online_migrations[0].assert_called_once_with(ctxt, 10)
|
||||
command_cls.online_migrations[1].assert_called_once_with(ctxt, 6)
|
||||
expected = """\
|
||||
5 rows matched query mock_mig_1, 4 migrated
|
||||
6 rows matched query mock_mig_2, 6 migrated
|
||||
+------------+--------------+-----------+
|
||||
| Migration | Total Needed | Completed |
|
||||
+------------+--------------+-----------+
|
||||
| mock_mig_1 | 5 | 4 |
|
||||
| mock_mig_2 | 6 | 6 |
|
||||
+------------+--------------+-----------+
|
||||
"""
|
||||
self.assertEqual(expected, sys.stdout.getvalue())
|
||||
|
||||
@mock.patch('nova.context.get_admin_context')
|
||||
def test_online_migrations_no_max_count(self, mock_get_context):
|
||||
@@ -616,6 +628,7 @@ class DBCommandsTestCase(test.NoDBTestCase):
|
||||
def test_online_migrations_error(self):
|
||||
fake_migration = mock.MagicMock()
|
||||
fake_migration.side_effect = Exception
|
||||
fake_migration.__name__ = 'fake'
|
||||
command_cls = self._fake_db_command((fake_migration,))
|
||||
command = command_cls()
|
||||
command.online_data_migrations(None)
|
||||
@@ -630,19 +643,19 @@ class DBCommandsTestCase(test.NoDBTestCase):
|
||||
|
||||
def test_online_migrations_no_max(self):
|
||||
with mock.patch.object(self.commands, '_run_migration') as rm:
|
||||
rm.return_value = 0
|
||||
rm.return_value = {}
|
||||
self.assertEqual(0,
|
||||
self.commands.online_data_migrations())
|
||||
|
||||
def test_online_migrations_finished(self):
|
||||
with mock.patch.object(self.commands, '_run_migration') as rm:
|
||||
rm.return_value = 0
|
||||
rm.return_value = {}
|
||||
self.assertEqual(0,
|
||||
self.commands.online_data_migrations(max_count=5))
|
||||
|
||||
def test_online_migrations_not_finished(self):
|
||||
with mock.patch.object(self.commands, '_run_migration') as rm:
|
||||
rm.return_value = 5
|
||||
rm.return_value = {'mig': (10, 5)}
|
||||
self.assertEqual(1,
|
||||
self.commands.online_data_migrations(max_count=5))
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- The nova-manage online_data_migrations command now prints a
|
||||
tabular summary of completed and remaining records. The goal
|
||||
here is to get all your numbers to zero. The previous execution
|
||||
return code behavior is retained for scripting.
|
||||
Reference in New Issue
Block a user