Merge "Handle events with conditions and match_fn"

This commit is contained in:
Zuul 2023-11-16 20:43:49 +00:00 committed by Gerrit Code Review
commit c22fbe766b
3 changed files with 39 additions and 0 deletions

View File

@ -20,6 +20,16 @@ LOG = logging.getLogger(__name__)
class RowEvent(ovsdb_event.RowEvent): # pylint: disable=abstract-method
def match_fn(self, event, row, old):
"""User-overridable custom matching function
This method takes the same arguments as the RowEvent API call
`matches` and allows for more complex matching criteria. This
method will apply additional checks to those specified in the
creation of the RowEvent
"""
return True
def base_match(self, event, row, old):
if self.conditions and not idlutils.row_match(row, self.conditions):
return False
if self.old_conditions:
@ -38,6 +48,8 @@ class RowEvent(ovsdb_event.RowEvent): # pylint: disable=abstract-method
return False
if row._table.name != self.table:
return False
if not self.base_match(event, row, old):
return False
if not self.match_fn(event, row, old):
return False
LOG.debug("Matched %s: %r to row=%s old=%s", event.upper(), self,

View File

@ -28,3 +28,14 @@ class ExceptionalMatchFnEvent(WaitForPortBindingEvent):
def match_fn(self, event, row, old):
raise Exception()
class MatchFnConditionsEvent(event.WaitEvent):
def __init__(self, *args, timeout=1, **kwargs):
super().__init__(*args, timeout=timeout, **kwargs)
def match_fn(self, event, row, old):
# This should only be called if we pass all other conditions
# so make sure wait() returns False if we see any other events. This
# ensures that adding a match_fn() doesn't skip the conditions checks.
return True

View File

@ -138,3 +138,19 @@ class OvnSouthboundTest(base.FunctionalTestCase):
def test_lsp_unbind_if_exists(self):
pname = utils.get_rand_device_name()
self.api.lsp_unbind(pname, if_exists=True).execute(check_error=True)
def test_event_with_match_fn_and_conditions(self):
cond_event = event.MatchFnConditionsEvent(
events=(event.MatchFnConditionsEvent.ROW_UPDATE,),
table="SB_Global",
conditions=(("external_ids", "=", {"foo": "bar"}),))
self.handler.watch_event(cond_event)
# Test that we match on condition with an Event that has a match_fn()
cmd = self.api.db_set("SB_Global", ".", external_ids={"foo": "bar"})
cmd.execute(check_error=True)
self.assertTrue(cond_event.wait())
cond_event.event.clear()
# Test that we don't ignore the condition when match_fn() returns True
cmd = self.api.db_set("SB_Global", ".", external_ids={"bar": "bar"})
cmd.execute(check_error=True)
self.assertFalse(cond_event.wait())