Remove ORM relationship between ports and networks

This relationship doesn't serve a purpose and it results
in SQLAlchemy trying to set the network_id column on ports
to NULL when attempting to delete a network with ports in it.

This results in the following exception:

IntegrityError: (1048, u"Column 'network_id' cannot be null")

This exception is not treated as a DBReferenceError by olso.db
which makes detecting races between ports being created on a
network being deleted very noisy in the logs since oslo.db treats
this as a generic DBError.

By removing the relationship, deleting a network will now just
result in a boring standard foreign key constraint failure which
will propagate from oslo.db as a DBReferenceError that is easy
to catch.

The patch that depends on this one adjusts the delete network logic
to capture these ReferenceErrors.

Change-Id: I4166a9bbaded57a77576400929a150123b8f1b2e
This commit is contained in:
Kevin Benton 2017-02-03 17:00:29 -08:00
parent 0df9087b37
commit 7dfa64bf41
3 changed files with 5 additions and 4 deletions

View File

@ -236,7 +236,6 @@ class Network(standard_attr.HasStandardAttributes, model_base.BASEV2,
"""Represents a v2 neutron network."""
name = sa.Column(sa.String(db_const.NAME_FIELD_SIZE))
ports = orm.relationship(Port, backref='networks')
subnets = orm.relationship(
Subnet, backref=orm.backref('networks', lazy='subquery'),
lazy="subquery")

View File

@ -43,9 +43,10 @@ class TestStatusBarriers(testlib_api.SqlTestCase):
def _make_port(self):
net = self._make_net()
with self.ctx.session.begin():
port = models_v2.Port(networks=net, mac_address='1', tenant_id='1',
admin_state_up=True, status='DOWN',
device_id='2', device_owner='3')
port = models_v2.Port(network_id=net.id, mac_address='1',
tenant_id='1', admin_state_up=True,
status='DOWN', device_id='2',
device_owner='3')
self.ctx.session.add(port)
return port

View File

@ -399,6 +399,7 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase):
def test_distributed_port_binding_deleted_by_port_deletion(self):
with self.ctx.session.begin(subtransactions=True):
self.ctx.session.add(models_v2.Network(id='network_id'))
with self.ctx.session.begin(subtransactions=True):
device_owner = constants.DEVICE_OWNER_DVR_INTERFACE
port = models_v2.Port(
id='port_id',