]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
[devref] db_layer: expand on how new migration scripts look like
authorIhar Hrachyshka <ihrachys@redhat.com>
Thu, 16 Jul 2015 12:37:37 +0000 (14:37 +0200)
committerIhar Hrachyshka <ihrachys@redhat.com>
Thu, 16 Jul 2015 12:39:34 +0000 (14:39 +0200)
Most of the text is stolen from the corresponding spec:

Ib27c6eb8c901536f1f30d0911dedd4db13d76e9f

Co-Authored-By: Mike Bayer <mike_mp@zzzcomputing.com>
Change-Id: Ib10c13f841f7cebb90c57f4b0d08fc2c3701da97

doc/source/devref/db_layer.rst

index 5232f1c611ebae06005913f83b3f48bc087e2301..2b6ded3fa05420f0faeeeff930dcfa22a143984e 100644 (file)
@@ -64,6 +64,111 @@ It will apply all the rules from both the expand and the contract branches, in
 proper order.
 
 
+Expand and Contract Scripts
+---------------------------
+
+The obsolete "branchless" design of a migration script included that it
+indicates a specific "version" of the schema, and includes directives that
+apply all necessary changes to the database at once.  If we look for example at
+the script ``2d2a8a565438_hierarchical_binding.py``, we will see::
+
+    # .../alembic_migrations/versions/2d2a8a565438_hierarchical_binding.py
+
+    def upgrade():
+
+        # .. inspection code ...
+
+        op.create_table(
+            'ml2_port_binding_levels',
+            sa.Column('port_id', sa.String(length=36), nullable=False),
+            sa.Column('host', sa.String(length=255), nullable=False),
+            # ... more columns ...
+        )
+
+        for table in port_binding_tables:
+            op.execute((
+                "INSERT INTO ml2_port_binding_levels "
+                "SELECT port_id, host, 0 AS level, driver, segment AS segment_id "
+                "FROM %s "
+                "WHERE host <> '' "
+                "AND driver <> '';"
+            ) % table)
+
+        op.drop_constraint(fk_name_dvr[0], 'ml2_dvr_port_bindings', 'foreignkey')
+        op.drop_column('ml2_dvr_port_bindings', 'cap_port_filter')
+        op.drop_column('ml2_dvr_port_bindings', 'segment')
+        op.drop_column('ml2_dvr_port_bindings', 'driver')
+
+        # ... more DROP instructions ...
+
+The above script contains directives that are both under the "expand"
+and "contract" categories, as well as some data migrations.  the ``op.create_table``
+directive is an "expand"; it may be run safely while the old version of the
+application still runs, as the old code simply doesn't look for this table.
+The ``op.drop_constraint`` and ``op.drop_column`` directives are
+"contract" directives (the drop column moreso than the drop constraint); running
+at least the ``op.drop_column`` directives means that the old version of the
+application will fail, as it will attempt to access these columns which no longer
+exist.
+
+The data migrations in this script are adding new
+rows to the newly added ``ml2_port_binding_levels`` table.
+
+Under the new migration script directory structure, the above script would be
+stated as two scripts; an "expand" and a "contract" script::
+
+    # expansion operations
+    # .../alembic_migrations/versions/liberty/expand/2bde560fc638_hierarchical_binding.py
+
+    def upgrade():
+
+        op.create_table(
+            'ml2_port_binding_levels',
+            sa.Column('port_id', sa.String(length=36), nullable=False),
+            sa.Column('host', sa.String(length=255), nullable=False),
+            # ... more columns ...
+        )
+
+
+    # contraction operations
+    # .../alembic_migrations/versions/liberty/contract/4405aedc050e_hierarchical_binding.py
+
+    def upgrade():
+
+        for table in port_binding_tables:
+            op.execute((
+                "INSERT INTO ml2_port_binding_levels "
+                "SELECT port_id, host, 0 AS level, driver, segment AS segment_id "
+                "FROM %s "
+                "WHERE host <> '' "
+                "AND driver <> '';"
+            ) % table)
+
+        op.drop_constraint(fk_name_dvr[0], 'ml2_dvr_port_bindings', 'foreignkey')
+        op.drop_column('ml2_dvr_port_bindings', 'cap_port_filter')
+        op.drop_column('ml2_dvr_port_bindings', 'segment')
+        op.drop_column('ml2_dvr_port_bindings', 'driver')
+
+        # ... more DROP instructions ...
+
+The two scripts would be present in different subdirectories and also part of
+entirely separate versioning streams.  The "expand" operations are in the
+"expand" script, and the "contract" operations are in the "contract" script.
+
+For the time being, data migration rules also belong to contract branch. There
+is expectation that eventually live data migrations move into middleware that
+will be aware about different database schema elements to converge on, but
+Neutron is still not there.
+
+Scripts that contain only expansion or contraction rules do not require a split
+into two parts.
+
+If a contraction script depends on a script from expansion stream, the
+following directive should be added in the contraction script::
+
+    depends_on = ('<expansion-revision>',)
+
+
 Tests to verify that database migrations and models are in sync
 ---------------------------------------------------------------