]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Don't start transaction during floating IP delete
authorKevin Benton <blak111@gmail.com>
Fri, 27 Feb 2015 22:56:39 +0000 (14:56 -0800)
committerKevin Benton <blak111@gmail.com>
Tue, 10 Mar 2015 01:53:09 +0000 (18:53 -0700)
The previous floating IP code was starting a transaction to
delete the floating IP object from the database and then
calling the core plugin's delete_port method which could make
many yielding calls, risking deadlocks.

This patch updates the relationship between floating IP and the
ports table to allow the port deletion to automatically clear
the floating IP object via a cascade.

Closes-Bug: #1426543
Closes-Bug: #1426482
Change-Id: I4b1cdc198c18d5c673a35aaf9c7e960f97f1e20b

neutron/db/l3_db.py
neutron/db/migration/alembic_migrations/versions/HEAD
neutron/db/migration/alembic_migrations/versions/f15b1fb526dd_cascade_floatingip.py [new file with mode: 0644]

index f3aa036b4be3ff5aa08235baf753999188067970..7b76293977ce50f4f6843766e6b0f33b6e254e4f 100644 (file)
@@ -97,7 +97,8 @@ class FloatingIP(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
 
     floating_ip_address = sa.Column(sa.String(64), nullable=False)
     floating_network_id = sa.Column(sa.String(36), nullable=False)
-    floating_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id'),
+    floating_port_id = sa.Column(sa.String(36),
+                                 sa.ForeignKey('ports.id', ondelete="CASCADE"),
                                  nullable=False)
     fixed_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id'))
     fixed_ip_address = sa.Column(sa.String(64))
@@ -912,11 +913,13 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase):
     def _delete_floatingip(self, context, id):
         floatingip = self._get_floatingip(context, id)
         router_id = floatingip['router_id']
-        with context.session.begin(subtransactions=True):
-            context.session.delete(floatingip)
-            self._core_plugin.delete_port(context.elevated(),
-                                          floatingip['floating_port_id'],
-                                          l3_port_check=False)
+        # Foreign key cascade will take care of the removal of the
+        # floating IP record once the port is deleted. We can't start
+        # a transaction first to remove it ourselves because the delete_port
+        # method will yield in its post-commit activities.
+        self._core_plugin.delete_port(context.elevated(),
+                                      floatingip['floating_port_id'],
+                                      l3_port_check=False)
         return router_id
 
     def delete_floatingip(self, context, id):
index 906e0b60c57e5db4e942e67e8828d9c52d88074a..b553d5259228e9a480f237e0038290e6c153ba4a 100644 (file)
@@ -1 +1 @@
-57dd745253a6
+f15b1fb526dd
diff --git a/neutron/db/migration/alembic_migrations/versions/f15b1fb526dd_cascade_floatingip.py b/neutron/db/migration/alembic_migrations/versions/f15b1fb526dd_cascade_floatingip.py
new file mode 100644 (file)
index 0000000..b351546
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright 2015 OpenStack Foundation
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+"""Cascade Floating IP Floating Port deletion
+
+Revision ID: f15b1fb526dd
+Revises: 57dd745253a6
+Create Date: 2014-08-24 21:56:36.422885
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'f15b1fb526dd'
+down_revision = '57dd745253a6'
+
+from alembic import op
+from sqlalchemy.engine import reflection
+
+
+def _drop_constraint():
+    inspector = reflection.Inspector.from_engine(op.get_bind())
+    fk_name = [fk['name'] for fk in
+               inspector.get_foreign_keys('floatingips')
+               if 'floating_port_id' in fk['constrained_columns']]
+    op.drop_constraint(fk_name[0], 'floatingips', 'foreignkey')
+
+
+def upgrade():
+    _drop_constraint()
+    op.create_foreign_key(
+        name=None,
+        source='floatingips', referent='ports',
+        local_cols=['floating_port_id'], remote_cols=['id'], ondelete='CASCADE'
+    )
+
+
+def downgrade():
+    _drop_constraint()
+    op.create_foreign_key(
+        name=None,
+        source='floatingips', referent='ports',
+        local_cols=['floating_port_id'], remote_cols=['id']
+    )