Make nova-manage online migrations more verbose
This makes the online_data_migrations command for nova-manage a little more verbose in what it is doing. Each time it is run, it will show you all the migrations that need running and how many records remain for each. Basically, you run this until you see all zeroes. Change-Id: I78c6312ec8e226a6ef9185382b6180f246f8fe84
This commit is contained in:
parent
80fd1ccac9
commit
7e71a4e0a2
@ -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
|
||||
|
||||
|
||||
|
@ -592,12 +592,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):
|
||||
@ -622,6 +634,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)
|
||||
@ -636,19 +649,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.
|
Loading…
Reference in New Issue
Block a user