[neutron-db-manage] revision: properly bootstrap a new branch
If the intended branch is not present, bootstrap it: - create directory; - mark the new migration script with proper branch label; - make the script down_revision == None to indicate it's a new branch; One missing thing is making the script depends_on the previous release branch. This is currently unsupported by alembic though. Partially-Implements: blueprint online-schema-migrations Change-Id: Ib3b9dfcbdb56db99b07a8e54629dda5933e1c1f5
This commit is contained in:
parent
e95bc6f5be
commit
87fff61b06
|
@ -24,6 +24,9 @@ Create Date: ${create_date}
|
|||
# revision identifiers, used by Alembic.
|
||||
revision = ${repr(up_revision)}
|
||||
down_revision = ${repr(down_revision)}
|
||||
% if branch_labels:
|
||||
branch_labels = ${repr(branch_labels)}
|
||||
% endif
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
|
|
@ -24,6 +24,7 @@ from oslo_config import cfg
|
|||
from oslo_utils import importutils
|
||||
|
||||
from neutron.common import repos
|
||||
from neutron.common import utils
|
||||
|
||||
|
||||
# TODO(ihrachyshka): maintain separate HEAD files per branch
|
||||
|
@ -47,7 +48,10 @@ _core_opts = [
|
|||
cfg.StrOpt('service',
|
||||
choices=VALID_SERVICES,
|
||||
help=_("The advanced service to execute the command against. "
|
||||
"Can be one of '%s'.") % "', '".join(VALID_SERVICES))
|
||||
"Can be one of '%s'.") % "', '".join(VALID_SERVICES)),
|
||||
cfg.BoolOpt('split_branches',
|
||||
default=False,
|
||||
help=_("Enforce using split branches file structure."))
|
||||
]
|
||||
|
||||
_quota_opts = [
|
||||
|
@ -126,28 +130,46 @@ def do_stamp(config, cmd):
|
|||
sql=CONF.command.sql)
|
||||
|
||||
|
||||
def _get_branch_label(branch):
|
||||
'''Get the latest branch label corresponding to release cycle.'''
|
||||
return '%s_%s' % (CURRENT_RELEASE, branch)
|
||||
|
||||
|
||||
def _get_branch_head(branch):
|
||||
'''Get the latest @head specification for a branch.'''
|
||||
return '%s_%s@head' % (CURRENT_RELEASE, branch)
|
||||
return '%s@head' % _get_branch_label(branch)
|
||||
|
||||
|
||||
def do_revision(config, cmd):
|
||||
'''Generate new revision files, one per branch.'''
|
||||
if _separate_migration_branches_supported(CONF):
|
||||
addn_kwargs = {
|
||||
'message': CONF.command.message,
|
||||
'autogenerate': CONF.command.autogenerate,
|
||||
'sql': CONF.command.sql,
|
||||
}
|
||||
|
||||
if _use_separate_migration_branches(CONF):
|
||||
for branch in MIGRATION_BRANCHES:
|
||||
version_path = _get_version_branch_path(CONF, branch)
|
||||
head = _get_branch_head(branch)
|
||||
do_alembic_command(config, cmd,
|
||||
message=CONF.command.message,
|
||||
autogenerate=CONF.command.autogenerate,
|
||||
sql=CONF.command.sql,
|
||||
version_path=version_path,
|
||||
head=head)
|
||||
addn_kwargs['version_path'] = version_path
|
||||
|
||||
if not os.path.exists(version_path):
|
||||
# Bootstrap initial directory structure
|
||||
utils.ensure_dir(version_path)
|
||||
# Each new release stream of migrations is detached from
|
||||
# previous migration chains
|
||||
addn_kwargs['head'] = 'base'
|
||||
# Mark the very first revision in the new branch with its label
|
||||
addn_kwargs['branch_label'] = _get_branch_label(branch)
|
||||
# TODO(ihrachyshka): ideally, we would also add depends_on here
|
||||
# to refer to the head of the previous release stream. But
|
||||
# alembic API does not support it yet.
|
||||
else:
|
||||
addn_kwargs['head'] = _get_branch_head(branch)
|
||||
|
||||
do_alembic_command(config, cmd, **addn_kwargs)
|
||||
else:
|
||||
do_alembic_command(config, cmd,
|
||||
message=CONF.command.message,
|
||||
autogenerate=CONF.command.autogenerate,
|
||||
sql=CONF.command.sql)
|
||||
do_alembic_command(config, cmd, **addn_kwargs)
|
||||
update_heads_file(config)
|
||||
|
||||
|
||||
|
@ -266,7 +288,7 @@ def _get_active_head_file_path(neutron_config):
|
|||
'''Return the path of the file that contains latest head(s), depending on
|
||||
whether multiple branches are used.
|
||||
'''
|
||||
if _separate_migration_branches_supported(neutron_config):
|
||||
if _use_separate_migration_branches(neutron_config):
|
||||
return _get_heads_file_path(neutron_config)
|
||||
return _get_head_file_path(neutron_config)
|
||||
|
||||
|
@ -278,10 +300,11 @@ def _get_version_branch_path(neutron_config, branch=None):
|
|||
return version_path
|
||||
|
||||
|
||||
def _separate_migration_branches_supported(neutron_config):
|
||||
'''Detect whether split migration branches are supported.'''
|
||||
# Use HEADS file to indicate the new, split migration world
|
||||
return os.path.exists(_get_heads_file_path(neutron_config))
|
||||
def _use_separate_migration_branches(neutron_config):
|
||||
'''Detect whether split migration branches should be used.'''
|
||||
return (neutron_config.split_branches or
|
||||
# Use HEADS file to indicate the new, split migration world
|
||||
os.path.exists(_get_heads_file_path(neutron_config)))
|
||||
|
||||
|
||||
def _set_version_locations(config):
|
||||
|
@ -289,7 +312,7 @@ def _set_version_locations(config):
|
|||
version_paths = []
|
||||
|
||||
version_paths.append(_get_version_branch_path(CONF))
|
||||
if _separate_migration_branches_supported(CONF):
|
||||
if _use_separate_migration_branches(CONF):
|
||||
for branch in MIGRATION_BRANCHES:
|
||||
version_paths.append(_get_version_branch_path(CONF, branch))
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ class TestCli(base.BaseTestCase):
|
|||
def test_database_sync_revision(self):
|
||||
self._test_database_sync_revision()
|
||||
|
||||
@mock.patch.object(cli, '_separate_migration_branches_supported',
|
||||
@mock.patch.object(cli, '_use_separate_migration_branches',
|
||||
return_value=False)
|
||||
def test_database_sync_revision_no_branches(self, *args):
|
||||
# Test that old branchless approach is still supported
|
||||
|
@ -242,12 +242,12 @@ class TestCli(base.BaseTestCase):
|
|||
def test_validate_heads_success(self):
|
||||
self._test_validate_heads_file_helper(['a'], ['a'])
|
||||
|
||||
@mock.patch.object(cli, '_separate_migration_branches_supported',
|
||||
@mock.patch.object(cli, '_use_separate_migration_branches',
|
||||
return_value=False)
|
||||
def test_validate_heads_file_branchless_failure(self, *args):
|
||||
self._test_validate_heads_file_helper(['a'], ['b'], branchless=True)
|
||||
|
||||
@mock.patch.object(cli, '_separate_migration_branches_supported',
|
||||
@mock.patch.object(cli, '_use_separate_migration_branches',
|
||||
return_value=False)
|
||||
def test_validate_heads_file_branchless_success(self, *args):
|
||||
self._test_validate_heads_file_helper(['a'], ['a'], branchless=True)
|
||||
|
|
Loading…
Reference in New Issue