Merge "[neutron-db-manage] Introduce contract and expand commands"
This commit is contained in:
commit
43c00a9f65
@ -294,12 +294,12 @@ Applying database migration rules
|
||||
|
||||
To apply just expansion rules, execute::
|
||||
|
||||
neutron-db-manage upgrade expand@head
|
||||
neutron-db-manage upgrade --expand
|
||||
|
||||
After the first step is done, you can stop neutron-server, apply remaining
|
||||
non-expansive migration rules, if any::
|
||||
|
||||
neutron-db-manage upgrade contract@head
|
||||
neutron-db-manage upgrade --contract
|
||||
|
||||
and finally, start your neutron-server again.
|
||||
|
||||
|
@ -98,10 +98,18 @@ CONF.register_cli_opts(_db_opts, 'database')
|
||||
CONF.register_opts(_quota_opts, 'QUOTAS')
|
||||
|
||||
|
||||
def do_alembic_command(config, cmd, *args, **kwargs):
|
||||
def do_alembic_command(config, cmd, revision=None, desc=None, **kwargs):
|
||||
args = []
|
||||
if revision:
|
||||
args.append(revision)
|
||||
|
||||
project = config.get_main_option('neutron_project')
|
||||
alembic_util.msg(_('Running %(cmd)s for %(project)s ...') %
|
||||
{'cmd': cmd, 'project': project})
|
||||
if desc:
|
||||
alembic_util.msg(_('Running %(cmd)s (%(desc)s) for %(project)s ...') %
|
||||
{'cmd': cmd, 'desc': desc, 'project': project})
|
||||
else:
|
||||
alembic_util.msg(_('Running %(cmd)s for %(project)s ...') %
|
||||
{'cmd': cmd, 'project': project})
|
||||
try:
|
||||
getattr(alembic_command, cmd)(config, *args, **kwargs)
|
||||
except alembic_util.CommandError as e:
|
||||
@ -126,30 +134,48 @@ def add_alembic_subparser(sub, cmd):
|
||||
|
||||
|
||||
def do_upgrade(config, cmd):
|
||||
if not CONF.command.revision and not CONF.command.delta:
|
||||
desc = None
|
||||
|
||||
if ((CONF.command.revision or CONF.command.delta) and
|
||||
(CONF.command.expand or CONF.command.contract)):
|
||||
raise SystemExit(_(
|
||||
'Phase upgrade options do not accept revision specification'))
|
||||
|
||||
if CONF.command.expand:
|
||||
desc = EXPAND_BRANCH
|
||||
revision = _get_branch_head(EXPAND_BRANCH)
|
||||
|
||||
elif CONF.command.contract:
|
||||
desc = CONTRACT_BRANCH
|
||||
revision = _get_branch_head(CONTRACT_BRANCH)
|
||||
|
||||
elif not CONF.command.revision and not CONF.command.delta:
|
||||
raise SystemExit(_('You must provide a revision or relative delta'))
|
||||
|
||||
revision = CONF.command.revision or ''
|
||||
if '-' in revision:
|
||||
raise SystemExit(_('Negative relative revision (downgrade) not '
|
||||
'supported'))
|
||||
else:
|
||||
revision = CONF.command.revision or ''
|
||||
if '-' in revision:
|
||||
raise SystemExit(_('Negative relative revision (downgrade) not '
|
||||
'supported'))
|
||||
|
||||
delta = CONF.command.delta
|
||||
if delta:
|
||||
if '+' in revision:
|
||||
raise SystemExit(_('Use either --delta or relative revision, '
|
||||
'not both'))
|
||||
if delta < 0:
|
||||
raise SystemExit(_('Negative delta (downgrade) not supported'))
|
||||
revision = '%s+%d' % (revision, delta)
|
||||
delta = CONF.command.delta
|
||||
if delta:
|
||||
if '+' in revision:
|
||||
raise SystemExit(_('Use either --delta or relative revision, '
|
||||
'not both'))
|
||||
if delta < 0:
|
||||
raise SystemExit(_('Negative delta (downgrade) not supported'))
|
||||
revision = '%s+%d' % (revision, delta)
|
||||
|
||||
# leave branchless 'head' revision request backward compatible by
|
||||
# applying all heads in all available branches.
|
||||
if revision == 'head':
|
||||
revision = 'heads'
|
||||
|
||||
# leave branchless 'head' revision request backward compatible by applying
|
||||
# all heads in all available branches.
|
||||
if revision == 'head':
|
||||
revision = 'heads'
|
||||
if not CONF.command.sql:
|
||||
run_sanity_checks(config, revision)
|
||||
do_alembic_command(config, cmd, revision, sql=CONF.command.sql)
|
||||
do_alembic_command(config, cmd, revision=revision,
|
||||
desc=desc, sql=CONF.command.sql)
|
||||
|
||||
|
||||
def no_downgrade(config, cmd):
|
||||
@ -158,7 +184,7 @@ def no_downgrade(config, cmd):
|
||||
|
||||
def do_stamp(config, cmd):
|
||||
do_alembic_command(config, cmd,
|
||||
CONF.command.revision,
|
||||
revision=CONF.command.revision,
|
||||
sql=CONF.command.sql)
|
||||
|
||||
|
||||
@ -311,6 +337,11 @@ def add_command_parsers(subparsers):
|
||||
default='',
|
||||
help='Change MySQL storage engine of current '
|
||||
'existing tables')
|
||||
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('--expand', action='store_true')
|
||||
group.add_argument('--contract', action='store_true')
|
||||
|
||||
parser.set_defaults(func=do_upgrade)
|
||||
|
||||
parser = subparsers.add_parser('downgrade', help="(No longer supported)")
|
||||
|
@ -25,6 +25,7 @@ import pkg_resources
|
||||
from neutron.db import migration
|
||||
from neutron.db.migration import cli
|
||||
from neutron.tests import base
|
||||
from neutron.tests.unit import testlib_api
|
||||
|
||||
|
||||
class FakeConfig(object):
|
||||
@ -135,14 +136,14 @@ class TestCli(base.BaseTestCase):
|
||||
attrs=attrs)
|
||||
cli.migration_entrypoints[project] = entrypoint
|
||||
|
||||
def _main_test_helper(self, argv, func_name, exp_args=(), exp_kwargs=[{}]):
|
||||
def _main_test_helper(self, argv, func_name, exp_kwargs=[{}]):
|
||||
with mock.patch.object(sys, 'argv', argv),\
|
||||
mock.patch.object(cli, 'run_sanity_checks'),\
|
||||
mock.patch.object(cli, 'validate_labels'):
|
||||
|
||||
cli.main()
|
||||
self.do_alembic_cmd.assert_has_calls(
|
||||
[mock.call(mock.ANY, func_name, *exp_args, **kwargs)
|
||||
[mock.call(mock.ANY, func_name, **kwargs)
|
||||
for kwargs in exp_kwargs]
|
||||
)
|
||||
|
||||
@ -150,15 +151,13 @@ class TestCli(base.BaseTestCase):
|
||||
self._main_test_helper(
|
||||
['prog', 'stamp', 'foo'],
|
||||
'stamp',
|
||||
('foo',),
|
||||
[{'sql': False}]
|
||||
[{'revision': 'foo', 'sql': False}]
|
||||
)
|
||||
|
||||
self._main_test_helper(
|
||||
['prog', 'stamp', 'foo', '--sql'],
|
||||
'stamp',
|
||||
('foo',),
|
||||
[{'sql': True}]
|
||||
[{'revision': 'foo', 'sql': True}]
|
||||
)
|
||||
|
||||
def test_current(self):
|
||||
@ -192,7 +191,7 @@ class TestCli(base.BaseTestCase):
|
||||
self._main_test_helper(
|
||||
['prog', 'revision', '--autogenerate', '-m', 'message'],
|
||||
'revision',
|
||||
(), expected_kwargs
|
||||
expected_kwargs
|
||||
)
|
||||
self.assertEqual(len(self.projects), update.call_count)
|
||||
update.reset_mock()
|
||||
@ -204,7 +203,7 @@ class TestCli(base.BaseTestCase):
|
||||
self._main_test_helper(
|
||||
['prog', 'revision', '--sql', '-m', 'message'],
|
||||
'revision',
|
||||
(), expected_kwargs
|
||||
expected_kwargs
|
||||
)
|
||||
self.assertEqual(len(self.projects), update.call_count)
|
||||
|
||||
@ -215,26 +214,70 @@ class TestCli(base.BaseTestCase):
|
||||
# Test that old branchless approach is still supported
|
||||
self._test_database_sync_revision(separate_branches=False)
|
||||
|
||||
def test_upgrade(self):
|
||||
def test_upgrade_revision(self):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--sql', 'head'],
|
||||
'upgrade',
|
||||
('heads',),
|
||||
[{'sql': True}]
|
||||
[{'desc': None, 'revision': 'heads', 'sql': True}]
|
||||
)
|
||||
|
||||
def test_upgrade_delta(self):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--delta', '3'],
|
||||
'upgrade',
|
||||
('+3',),
|
||||
[{'sql': False}]
|
||||
[{'desc': None, 'revision': '+3', 'sql': False}]
|
||||
)
|
||||
|
||||
def test_upgrade_revision_delta(self):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', 'kilo', '--delta', '3'],
|
||||
'upgrade',
|
||||
('kilo+3',),
|
||||
[{'sql': False}]
|
||||
[{'desc': None, 'revision': 'kilo+3', 'sql': False}]
|
||||
)
|
||||
|
||||
def test_upgrade_expand(self):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--expand'],
|
||||
'upgrade',
|
||||
[{'desc': cli.EXPAND_BRANCH,
|
||||
'revision': 'expand@head',
|
||||
'sql': False}]
|
||||
)
|
||||
|
||||
def test_upgrade_expand_contract_are_mutually_exclusive(self):
|
||||
with testlib_api.ExpectedException(SystemExit):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--expand --contract'], 'upgrade')
|
||||
|
||||
def _test_upgrade_conflicts_with_revision(self, mode):
|
||||
with testlib_api.ExpectedException(SystemExit):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--%s revision1' % mode], 'upgrade')
|
||||
|
||||
def _test_upgrade_conflicts_with_delta(self, mode):
|
||||
with testlib_api.ExpectedException(SystemExit):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--%s +3' % mode], 'upgrade')
|
||||
|
||||
def test_upgrade_expand_conflicts_with_revision(self):
|
||||
self._test_upgrade_conflicts_with_revision('expand')
|
||||
|
||||
def test_upgrade_contract_conflicts_with_revision(self):
|
||||
self._test_upgrade_conflicts_with_revision('contract')
|
||||
|
||||
def test_upgrade_expand_conflicts_with_delta(self):
|
||||
self._test_upgrade_conflicts_with_delta('expand')
|
||||
|
||||
def test_upgrade_contract_conflicts_with_delta(self):
|
||||
self._test_upgrade_conflicts_with_delta('contract')
|
||||
|
||||
def test_upgrade_contract(self):
|
||||
self._main_test_helper(
|
||||
['prog', 'upgrade', '--contract'],
|
||||
'upgrade',
|
||||
[{'desc': cli.CONTRACT_BRANCH,
|
||||
'revision': 'contract@head',
|
||||
'sql': False}]
|
||||
)
|
||||
|
||||
def assert_command_fails(self, command):
|
||||
|
Loading…
Reference in New Issue
Block a user