Add IPAllocation object to session info to stop GC

This adds the IPAllocation object created in the _store_ip_allocation
method to the session info dictionary to prevent it from being
immediately garbage collected. This is necessary because otherwise a
new persistent object will be created when the fixed_ips relationship
is referenced during the rest of the port create/update opertions.
This persistent object will then interfere with a retry operation
that uses the same session if it tries to create a conflicting record.

By preventing the object from being garbage collected, the reference
to fixed IPs will re-use the newly created sqlalchemy object instead
which will properly be cleaned up on a rollback.

This also removes the 'passive_delete' option from the fixed_ips
relationship on ports because IPAllocation objects would now be
left in the session after port deletes. At first glance, this might
look like a performance penalty because fixed_ips would be looked
up before port deletes; however, we already do that in the IPAM
code as well as the ML2 code so this relationship is already being
loaded on the delete_port operation.

Closes-Bug: #1556178
Change-Id: Ieee1343bb90cf111c55e00b9cabc27943b46c350
(cherry picked from commit 7d9169967f)
This commit is contained in:
Kevin Benton 2016-03-13 20:52:09 -07:00 committed by Ihar Hrachyshka
parent e9622b0bb0
commit b30eb16bd0
2 changed files with 8 additions and 1 deletions

View File

@ -107,6 +107,12 @@ class DbBasePluginCommon(common_db_mixin.CommonDbMixin):
subnet_id=subnet_id
)
context.session.add(allocated)
# NOTE(kevinbenton): We add this to the session info so the sqlalchemy
# object isn't immediately garbage collected. Otherwise when the
# fixed_ips relationship is referenced a new persistent object will be
# added to the session that will interfere with retry operations.
# See bug 1556178 for details.
context.session.info.setdefault('allocated_ips', []).append(allocated)
def _make_subnet_dict(self, subnet, fields=None, context=None):
res = {'id': subnet['id'],

View File

@ -119,7 +119,8 @@ class Port(model_base.BASEV2, HasId, HasTenant):
network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"),
nullable=False)
fixed_ips = orm.relationship(IPAllocation, backref='port', lazy='joined',
passive_deletes='all')
cascade='all, delete-orphan')
mac_address = sa.Column(sa.String(32), nullable=False)
admin_state_up = sa.Column(sa.Boolean(), nullable=False)
status = sa.Column(sa.String(16), nullable=False)