Avoid race condition when processing RowEvents
In https://review.opendev.org/#/c/753824/ ovsdbapp adds the ability
to pass a "frozen" object to the RowEventHandler so that if a
transaction is started from the main thread that changes the row,
it won't step on the values that the Event is trying to process.
This patch copies in the relevant code from newer ovsdbapp ond ovs
to avoid bumping their required versions in a stable branch.
Change-Id: I87489596e2ff224431f7e83f43a1725172ee0953
Related-Bug: #1896816
(cherry picked from commit ab6d4afd95
)
This commit is contained in:
parent
df9ef3df03
commit
7ce3c8e1f1
|
@ -0,0 +1,64 @@
|
|||
# Copyright 2021 Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# We don't technically require ovs 2.10 or ovsdbapp that has these fixes so
|
||||
# just include them here for stable releases
|
||||
try:
|
||||
from ovs.db import custom_index
|
||||
|
||||
IndexEntryClass = custom_index.IndexEntryClass
|
||||
except ImportError:
|
||||
import collections
|
||||
|
||||
from ovs.db import data
|
||||
|
||||
def IndexEntryClass(table):
|
||||
def defaults_uuid_to_row(atom, base):
|
||||
return atom.value
|
||||
|
||||
columns = ['uuid'] + list(table.columns.keys())
|
||||
cls = collections.namedtuple(table.name, columns)
|
||||
cls._table = table
|
||||
cls.__new__.__defaults__ = (None,) + tuple(
|
||||
data.Datum.default(c.type).to_python(defaults_uuid_to_row)
|
||||
for c in table.columns.values())
|
||||
return cls
|
||||
|
||||
|
||||
try:
|
||||
from ovsdbapp.backend.ovs_idl import idlutils
|
||||
|
||||
frozen_row = idlutils.frozen_row
|
||||
except AttributeError:
|
||||
def frozen_row(row):
|
||||
try:
|
||||
IndexEntry = row._table.rows.IndexEntry
|
||||
except AttributeError:
|
||||
row._table.rows = IndexEntryClass(row._table)
|
||||
return IndexEntry(
|
||||
uuid=row.uuid,
|
||||
**{col: getattr(row, col)
|
||||
for col in row._table.columns if hasattr(row, col)})
|
||||
|
||||
|
||||
try:
|
||||
from ovsdbapp.backend.ovs_idl import event as row_event
|
||||
from ovsdbapp import event as ovsdb_event
|
||||
|
||||
RowEventHandler = row_event.RowEventHandler
|
||||
except AttributeError:
|
||||
class RowEventHandler(ovsdb_event.RowEventHandler):
|
||||
def notify(self, event, row, updates=None):
|
||||
row = frozen_row(row)
|
||||
super().notify(event, row, updates)
|
|
@ -26,7 +26,6 @@ from ovs.stream import Stream
|
|||
from ovsdbapp.backend.ovs_idl import connection
|
||||
from ovsdbapp.backend.ovs_idl import event as row_event
|
||||
from ovsdbapp.backend.ovs_idl import idlutils
|
||||
from ovsdbapp import event
|
||||
|
||||
from neutron.common.ovn import constants as ovn_const
|
||||
from neutron.common.ovn import exceptions
|
||||
|
@ -34,6 +33,7 @@ from neutron.common.ovn import hash_ring_manager
|
|||
from neutron.common.ovn import utils
|
||||
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
|
||||
from neutron.db import ovn_hash_ring_db
|
||||
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import backports
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
@ -346,7 +346,7 @@ class FIPAddDeleteEvent(row_event.RowEvent):
|
|||
self.driver.delete_mac_binding_entries(row.external_ip)
|
||||
|
||||
|
||||
class OvnDbNotifyHandler(event.RowEventHandler):
|
||||
class OvnDbNotifyHandler(backports.RowEventHandler):
|
||||
def __init__(self, driver):
|
||||
super(OvnDbNotifyHandler, self).__init__()
|
||||
self.driver = driver
|
||||
|
@ -362,7 +362,7 @@ class Ml2OvnIdlBase(connection.OvsdbIdl):
|
|||
|
||||
class BaseOvnIdl(Ml2OvnIdlBase):
|
||||
def __init__(self, remote, schema):
|
||||
self.notify_handler = event.RowEventHandler()
|
||||
self.notify_handler = backports.RowEventHandler()
|
||||
super(BaseOvnIdl, self).__init__(remote, schema)
|
||||
|
||||
@classmethod
|
||||
|
|
Loading…
Reference in New Issue