Tag the alembic migration revisions for Liberty

Previously when we had one repo with one alembic branch we would
create a milestone revision on that single branch. Now we have
multiple repos and expand/contract branches for each repo.

So from now on we tag the final revision on every branch when we make
a milestone release. Update the cli to support the command:
  neutron-db-manage upgrade <milestone>
where <milestone> becomes an alias for all the revisions for a
milestone.

Partial-Bug: #1499033

Change-Id: I38623986dd574bec01fe147f9c6a747f3f512bb7
This commit is contained in:
Henry Gessau
2015-09-27 15:36:59 -04:00
parent bcf9052e8c
commit 52236764a3
5 changed files with 90 additions and 13 deletions

View File

@@ -21,6 +21,13 @@ from alembic import op
import sqlalchemy as sa
from sqlalchemy.engine import reflection
# Neutron milestones for upgrade aliases
LIBERTY = 'liberty'
NEUTRON_MILESTONES = [
# earlier milestones were not tagged
LIBERTY,
]
CREATION_OPERATIONS = (sa.sql.ddl.CreateIndex,
sa.sql.ddl.CreateTable,

View File

@@ -21,11 +21,17 @@ Create Date: 2015-08-13 08:01:19.709839
"""
from alembic import op
from neutron.db import migration
# revision identifiers, used by Alembic.
revision = '4af11ca47297'
down_revision = '11926bcfe72d'
from alembic import op
# milestone identifier, used by neutron-db-manage
neutron_milestone = [migration.LIBERTY]
def upgrade():

View File

@@ -21,14 +21,19 @@ Create Date: 2015-08-23 00:22:47.618593
"""
from alembic import op
import sqlalchemy as sa
from neutron.db import migration
from neutron.extensions import dns
# revision identifiers, used by Alembic.
revision = '34af2b5c5a59'
down_revision = '9859ac9c136'
from alembic import op
import sqlalchemy as sa
from neutron.extensions import dns
# milestone identifier, used by neutron-db-manage
neutron_milestone = [migration.LIBERTY]
def upgrade():

View File

@@ -26,11 +26,12 @@ from oslo_utils import importutils
import pkg_resources
from neutron.common import utils
from neutron.db import migration
HEAD_FILENAME = 'HEAD'
HEADS_FILENAME = 'HEADS'
CURRENT_RELEASE = "liberty"
CURRENT_RELEASE = migration.LIBERTY
EXPAND_BRANCH = 'expand'
CONTRACT_BRANCH = 'contract'
@@ -131,8 +132,20 @@ def add_alembic_subparser(sub, cmd):
return sub.add_parser(cmd, help=getattr(alembic_command, cmd).__doc__)
def _find_milestone_revisions(config, milestone, branch=None):
"""Return the revision(s) for a given milestone."""
script = alembic_script.ScriptDirectory.from_config(config)
return [
(m.revision, label)
for m in _get_revisions(script)
for label in (m.branch_labels or [None])
if milestone in getattr(m.module, 'neutron_milestone', []) and
(branch is None or branch in m.branch_labels)
]
def do_upgrade(config, cmd):
desc = None
branch = None
if ((CONF.command.revision or CONF.command.delta) and
(CONF.command.expand or CONF.command.contract)):
@@ -140,11 +153,11 @@ def do_upgrade(config, cmd):
'Phase upgrade options do not accept revision specification'))
if CONF.command.expand:
desc = EXPAND_BRANCH
branch = EXPAND_BRANCH
revision = _get_branch_head(EXPAND_BRANCH)
elif CONF.command.contract:
desc = CONTRACT_BRANCH
branch = CONTRACT_BRANCH
revision = _get_branch_head(CONTRACT_BRANCH)
elif not CONF.command.revision and not CONF.command.delta:
@@ -170,10 +183,16 @@ def do_upgrade(config, cmd):
if revision == 'head':
revision = 'heads'
if not CONF.command.sql:
run_sanity_checks(config, revision)
do_alembic_command(config, cmd, revision=revision,
desc=desc, sql=CONF.command.sql)
if revision in migration.NEUTRON_MILESTONES:
revisions = _find_milestone_revisions(config, revision, branch)
else:
revisions = [(revision, branch)]
for revision, branch in revisions:
if not CONF.command.sql:
run_sanity_checks(config, revision)
do_alembic_command(config, cmd, revision=revision,
desc=branch, sql=CONF.command.sql)
def no_downgrade(config, cmd):

View File

@@ -49,6 +49,7 @@ class FakeRevision(object):
self.down_revision = down_revision
self.is_branch_point = is_branch_point
self.revision = tools.get_random_string()
self.module = mock.MagicMock()
class MigrationEntrypointsMemento(fixtures.Fixture):
@@ -643,6 +644,45 @@ class TestCli(base.BaseTestCase):
def test__use_separate_migration_branches_with_branch_points(self, *mocks):
self.assertTrue(cli._use_separate_migration_branches(self.configs[0]))
@mock.patch('alembic.script.ScriptDirectory.walk_revisions')
def test__find_milestone_revisions_one_branch(self, walk_mock):
c_revs = [FakeRevision(labels={cli.CONTRACT_BRANCH}) for r in range(5)]
c_revs[1].module.neutron_milestone = [migration.LIBERTY]
walk_mock.return_value = c_revs
m = cli._find_milestone_revisions(self.configs[0], 'liberty',
cli.CONTRACT_BRANCH)
self.assertEqual(1, len(m))
m = cli._find_milestone_revisions(self.configs[0], 'liberty',
cli.EXPAND_BRANCH)
self.assertEqual(0, len(m))
@mock.patch('alembic.script.ScriptDirectory.walk_revisions')
def test__find_milestone_revisions_two_branches(self, walk_mock):
c_revs = [FakeRevision(labels={cli.CONTRACT_BRANCH}) for r in range(5)]
c_revs[1].module.neutron_milestone = [migration.LIBERTY]
e_revs = [FakeRevision(labels={cli.EXPAND_BRANCH}) for r in range(5)]
e_revs[3].module.neutron_milestone = [migration.LIBERTY]
walk_mock.return_value = c_revs + e_revs
m = cli._find_milestone_revisions(self.configs[0], 'liberty')
self.assertEqual(2, len(m))
m = cli._find_milestone_revisions(self.configs[0], 'mitaka')
self.assertEqual(0, len(m))
@mock.patch('alembic.script.ScriptDirectory.walk_revisions')
def test__find_milestone_revisions_branchless(self, walk_mock):
revisions = [FakeRevision() for r in range(5)]
revisions[2].module.neutron_milestone = [migration.LIBERTY]
walk_mock.return_value = revisions
m = cli._find_milestone_revisions(self.configs[0], 'liberty')
self.assertEqual(1, len(m))
m = cli._find_milestone_revisions(self.configs[0], 'mitaka')
self.assertEqual(0, len(m))
class TestSafetyChecks(base.BaseTestCase):