Don't start transaction during floating IP delete

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
This commit is contained in:
Kevin Benton 2015-02-27 14:56:39 -08:00
parent 4ced2d1a86
commit 4840fe79d7
3 changed files with 65 additions and 7 deletions

View 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):

View File

@ -1 +1 @@
57dd745253a6
f15b1fb526dd

View File

@ -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']
)