diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index a9a04f1e8358..13e04fb601d3 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -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='', 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 diff --git a/nova/tests/unit/test_nova_manage.py b/nova/tests/unit/test_nova_manage.py index be997d1547b6..27c9550fa4c4 100644 --- a/nova/tests/unit/test_nova_manage.py +++ b/nova/tests/unit/test_nova_manage.py @@ -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)) diff --git a/releasenotes/notes/verbose-online-migrations-bd6f57e43328d554.yaml b/releasenotes/notes/verbose-online-migrations-bd6f57e43328d554.yaml new file mode 100644 index 000000000000..299459dbdd78 --- /dev/null +++ b/releasenotes/notes/verbose-online-migrations-bd6f57e43328d554.yaml @@ -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.