Merge "Make revision bump robust to concurrent removals"

This commit is contained in:
Jenkins 2016-08-12 09:45:51 +00:00 committed by Gerrit Code Review
commit 23db089f36
2 changed files with 31 additions and 11 deletions

View File

@ -13,6 +13,7 @@
from oslo_log import log as logging
from sqlalchemy import event
from sqlalchemy.orm import exc
from sqlalchemy.orm import session as se
from neutron._i18n import _, _LW
@ -53,17 +54,21 @@ class RevisionPlugin(service_base.ServicePluginBase):
def _bump_related_revisions(self, session, obj):
for revises_col in getattr(obj, 'revises_on_change', ()):
related_obj = self._find_related_obj(session, obj, revises_col)
if not related_obj:
LOG.warning(_LW("Could not find related %(col)s for resource "
"%(obj)s to bump revision."),
{'obj': obj, 'col': revises_col})
continue
# if related object revises others, bump those as well
self._bump_related_revisions(session, related_obj)
# no need to bump revisions on related objects being deleted
if related_obj not in session.deleted:
related_obj.bump_revision()
try:
related_obj = self._find_related_obj(session, obj, revises_col)
if not related_obj:
LOG.warning(_LW("Could not find related %(col)s for "
"resource %(obj)s to bump revision."),
{'obj': obj, 'col': revises_col})
continue
# if related object revises others, bump those as well
self._bump_related_revisions(session, related_obj)
# no need to bump revisions on related objects being deleted
if related_obj not in session.deleted:
related_obj.bump_revision()
except exc.ObjectDeletedError:
# object was in session but another writer deleted it
pass
def get_plugin_type(self):
return "revision_plugin"

View File

@ -16,6 +16,7 @@
import netaddr
from neutron import context as nctx
from neutron.db import models_v2
from neutron import manager
from neutron.tests.unit.plugins.ml2 import test_plugin
@ -34,6 +35,20 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase):
get_service_plugins()['L3_ROUTER_NAT'])
self.ctx = nctx.get_admin_context()
def test_handle_expired_object(self):
rp = manager.NeutronManager.get_service_plugins()['revision_plugin']
with self.port():
with self.ctx.session.begin():
ipal_obj = self.ctx.session.query(models_v2.IPAllocation).one()
# load port into our session
port_obj = self.ctx.session.query(models_v2.Port).one()
# simulate concurrent delete in another session
nctx.get_admin_context().session.query(models_v2.Port).delete()
# expire the port so the revision bumping code will trigger a
# lookup on its attributes and encounter an ObjectDeletedError
self.ctx.session.expire(port_obj)
rp._bump_related_revisions(self.ctx.session, ipal_obj)
def test_port_name_update_revises(self):
with self.port() as port:
rev = port['port']['revision']