]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Tag the alembic migration revisions for Liberty
authorHenry Gessau <gessau@cisco.com>
Sun, 27 Sep 2015 19:36:59 +0000 (15:36 -0400)
committerArmando Migliaccio <armamig@gmail.com>
Fri, 2 Oct 2015 16:27:39 +0000 (16:27 +0000)
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.

Closes-Bug: #1499033

Change-Id: I38623986dd574bec01fe147f9c6a747f3f512bb7
(cherry picked from commit 52236764a3a7c23ec24a86ccb84bc6737e2a4791)
Conflicts:
        neutron/db/migration/cli.py
neutron/tests/unit/db/test_migration.py

neutron/db/migration/__init__.py
neutron/db/migration/alembic_migrations/versions/liberty/contract/4af11ca47297_drop_cisco_monolithic_tables.py
neutron/db/migration/alembic_migrations/versions/liberty/expand/34af2b5c5a59_add_dns_name_to_port.py
neutron/db/migration/cli.py
neutron/tests/unit/db/test_migration.py

index 5561e884d59b765daff15f82afdfde05d921c920..81b491083083b4fe19a39bf33ff216e65437cd35 100644 (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,
index ee39fa9529143baa03da037989d67540f2d8a01d..7a91b79b31e798543ff768e4243f35a77f2fccff 100644 (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():
index ba523ae655b99c68e6746aeefbe509c1aab25d77..3b2707c74b9039cd2c2cb772e536998e70e62b6e 100644 (file)
@@ -21,16 +21,21 @@ Create Date: 2015-08-23 00:22:47.618593
 
 """
 
-# revision identifiers, used by Alembic.
-revision = '34af2b5c5a59'
-down_revision = '9859ac9c136'
-
 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'
+
+# milestone identifier, used by neutron-db-manage
+neutron_milestone = [migration.LIBERTY]
+
+
 def upgrade():
     op.add_column('ports',
                   sa.Column('dns_name',
index 4c7ea5b1be35da5c579dc917763b2b660a129d4f..4c4169a0c0d4ef46aecb0cb8a5ffff88ac888967 100644 (file)
@@ -25,12 +25,13 @@ from oslo_utils import importutils
 import pkg_resources
 
 from neutron.common import utils
+from neutron.db import migration
 
 
 # TODO(ihrachyshka): maintain separate HEAD files per branch
 HEAD_FILENAME = 'HEAD'
 HEADS_FILENAME = 'HEADS'
-CURRENT_RELEASE = "liberty"
+CURRENT_RELEASE = migration.LIBERTY
 
 EXPAND_BRANCH = 'expand'
 CONTRACT_BRANCH = 'contract'
@@ -126,8 +127,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 script.walk_revisions(base='base', head='heads')
+        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)):
@@ -135,11 +148,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:
@@ -165,10 +178,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):
index 399fc5070f3cb68cda59746ebbc4faf76c665a6b..a88a6e93ca4de417d6ef43eb0ac3a03e86e002cc 100644 (file)
@@ -26,6 +26,7 @@ import mock
 import pkg_resources
 import sqlalchemy as sa
 
+from neutron.common import utils
 from neutron.db import migration
 from neutron.db.migration import autogen
 from neutron.db.migration import cli
@@ -45,6 +46,8 @@ class FakeRevision(object):
             labels = set()
         self.branch_labels = labels
         self.down_revision = down_revision
+        self.revision = utils.get_random_string(10)
+        self.module = mock.MagicMock()
 
 
 class MigrationEntrypointsMemento(fixtures.Fixture):
@@ -601,6 +604,45 @@ class TestCli(base.BaseTestCase):
             alembic_ag_api.render_python_code(contract.upgrade_ops)
         )
 
+    @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):