Merge "Make cinder-manage online migrations more verbose"
This commit is contained in:
commit
a01ec6ecaa
@ -57,6 +57,7 @@ from __future__ import print_function
|
||||
|
||||
import logging as python_logging
|
||||
import os
|
||||
import prettytable
|
||||
import sys
|
||||
import time
|
||||
|
||||
@ -67,9 +68,6 @@ from oslo_log import log as logging
|
||||
import oslo_messaging as messaging
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from cinder import i18n
|
||||
i18n.enable_lazy()
|
||||
|
||||
# Need to register global_opts
|
||||
from cinder.common import config # noqa
|
||||
from cinder.common import constants
|
||||
@ -246,6 +244,7 @@ class DbCommands(object):
|
||||
|
||||
def _run_migration(self, ctxt, max_count, ignore_state):
|
||||
ran = 0
|
||||
migrations = {}
|
||||
for migration_meth in self.online_migrations:
|
||||
count = max_count - ran
|
||||
try:
|
||||
@ -255,16 +254,24 @@ class DbCommands(object):
|
||||
{'method': migration_meth.__name__})
|
||||
found = done = 0
|
||||
|
||||
name = migration_meth.__name__
|
||||
remaining = found - done
|
||||
if found:
|
||||
print(_('%(total)i rows matched query %(meth)s, %(done)i '
|
||||
'migrated') % {'total': found,
|
||||
'meth': migration_meth.__name__,
|
||||
'done': done})
|
||||
print(_('%(found)i rows matched query %(meth)s, %(done)i '
|
||||
'migrated, %(remaining)i remaining') % {'found': found,
|
||||
'meth': name,
|
||||
'done': done,
|
||||
'remaining':
|
||||
remaining})
|
||||
migrations.setdefault(name, (0, 0, 0))
|
||||
migrations[name] = (migrations[name][0] + found,
|
||||
migrations[name][1] + done,
|
||||
migrations[name][2] + remaining)
|
||||
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', type=int,
|
||||
help='Maximum number of objects to consider.')
|
||||
@ -286,11 +293,23 @@ 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, ignore_state)
|
||||
migrations = self._run_migration(ctxt, max_count, ignore_state)
|
||||
migration_info.update(migrations)
|
||||
ran = sum([done for found, done, remaining in migrations.values()])
|
||||
if not unlimited:
|
||||
break
|
||||
|
||||
t = prettytable.PrettyTable([_('Migration'),
|
||||
_('Found'),
|
||||
_('Done'),
|
||||
_('Remaining')])
|
||||
for name in sorted(migration_info.keys()):
|
||||
info = migration_info[name]
|
||||
t.add_row([name, info[0], info[1], info[2]])
|
||||
print(t)
|
||||
|
||||
sys.exit(1 if ran else 0)
|
||||
|
||||
|
||||
|
@ -16,10 +16,12 @@ import sys
|
||||
import time
|
||||
|
||||
import ddt
|
||||
import fixtures
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
from six.moves import StringIO
|
||||
|
||||
try:
|
||||
import rtslib_fb
|
||||
@ -225,6 +227,45 @@ class TestCinderManageCmd(test.TestCase):
|
||||
cinder_manage.DbCommands.online_migrations[0].assert_has_calls(
|
||||
(mock.call(mock.ANY, 50, False),) * 2)
|
||||
|
||||
def _fake_db_command(self, migrations=None):
|
||||
if migrations is None:
|
||||
mock_mig_1 = mock.MagicMock(__name__="mock_mig_1")
|
||||
mock_mig_2 = mock.MagicMock(__name__="mock_mig_2")
|
||||
mock_mig_1.return_value = (5, 4)
|
||||
mock_mig_2.return_value = (6, 6)
|
||||
migrations = (mock_mig_1, mock_mig_2)
|
||||
|
||||
class _CommandSub(cinder_manage.DbCommands):
|
||||
online_migrations = migrations
|
||||
|
||||
return _CommandSub
|
||||
|
||||
@mock.patch('cinder.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
|
||||
db_cmds = self._fake_db_command()
|
||||
command = db_cmds()
|
||||
exit = self.assertRaises(SystemExit,
|
||||
command.online_data_migrations, 10)
|
||||
self.assertEqual(1, exit.code)
|
||||
expected = """\
|
||||
5 rows matched query mock_mig_1, 4 migrated, 1 remaining
|
||||
6 rows matched query mock_mig_2, 6 migrated, 0 remaining
|
||||
+------------+-------+------+-----------+
|
||||
| Migration | Found | Done | Remaining |
|
||||
+------------+-------+------+-----------+
|
||||
| mock_mig_1 | 5 | 4 | 1 |
|
||||
| mock_mig_2 | 6 | 6 | 0 |
|
||||
+------------+-------+------+-----------+
|
||||
"""
|
||||
command.online_migrations[0].assert_has_calls([mock.call(ctxt,
|
||||
10, False)])
|
||||
command.online_migrations[1].assert_has_calls([mock.call(ctxt,
|
||||
6, False)])
|
||||
|
||||
self.assertEqual(expected, sys.stdout.getvalue())
|
||||
|
||||
@mock.patch('cinder.cmd.manage.DbCommands.online_migrations',
|
||||
(mock.Mock(side_effect=((2, 2), (0, 0)), __name__='foo'),))
|
||||
def test_db_commands_online_data_migrations_ignore_state_and_max(self):
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- The cinder-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