The row_update2 "insert"/"initial" handling only generated a ROW_CREATE
notification, and bumped change_seqno, when __row_update() reported that
an alerted column differed from its default. The C IDL treats an insert
as a change by definition: ovsdb_idl_insert_row() discards
ovsdb_idl_row_change()'s return value, and the insert case in
ovsdb_idl_process_update() falls through to an unconditional
OVSDB_IDL_UPDATE_DB_CHANGED. Only the modify case is gated.
A client that registers only columns with n_min == 0, or columns with
alert cleared, therefore never learns that a row was inserted: the row
silently appears in the replica, notify() is not called and Idl.run()
returns False. An equivalent C client gets a change_seqno bump and
finds the row on its next scan.
Drop the gate so that an insert always reports
OVSDB_IDL_UPDATE_DB_CHANGED with a ROW_CREATE notice, matching C.
Fixes: 897c8064f55c ("python: move Python idl to work with monitor_cond")
Assisted-by: Claude Opus 5
Signed-off-by: Terry Wilson <[email protected]>
---
python/automake.mk | 1 +
python/ovs/db/idl.py | 6 ++----
python/ovs/tests/test_idl.py | 42 ++++++++++++++++++++++++++++++++++++
3 files changed, 45 insertions(+), 4 deletions(-)
create mode 100644 python/ovs/tests/test_idl.py
diff --git a/python/automake.mk b/python/automake.mk
index c3e960c82..3de655227 100644
--- a/python/automake.mk
+++ b/python/automake.mk
@@ -46,6 +46,7 @@ ovs_pytests = \
python/ovs/tests/test_decoders.py \
python/ovs/tests/test_dns_resolve.py \
python/ovs/tests/test_filter.py \
+ python/ovs/tests/test_idl.py \
python/ovs/tests/test_kv.py \
python/ovs/tests/test_list.py \
python/ovs/tests/test_odp.py \
diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index 4d0b7ac38..3107987c1 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -1047,11 +1047,9 @@ class Idl(object):
else:
row_update = row_update['initial']
self.__add_default(table, row_update)
- changed = self.__row_update(table, row, row_update)
+ self.__row_update(table, row, row_update)
table.rows[uuid] = row
- if changed:
- return OVSDB_IDL_UPDATE_DB_CHANGED, Notice(ROW_CREATE, row)
- return OVSDB_IDL_UPDATE_NO_CHANGES, None
+ return OVSDB_IDL_UPDATE_DB_CHANGED, Notice(ROW_CREATE, row)
elif "modify" in row_update:
if not row:
# XXX rate-limit
diff --git a/python/ovs/tests/test_idl.py b/python/ovs/tests/test_idl.py
new file mode 100644
index 000000000..4b254187f
--- /dev/null
+++ b/python/ovs/tests/test_idl.py
@@ -0,0 +1,42 @@
+import uuid
+
+import pytest
+
+import ovs.db.idl
+
+
+# Every column is optional (n_min == 0), so a row at its defaults arrives
+# with no columns at all and __add_default() has nothing to inject.
+SCHEMA = {
+ "name": "idltest",
+ "version": "1.0.0",
+ "tables": {
+ "optional": {
+ "columns": {
+ "s": {"type": {"key": "string", "min": 0, "max": 1}},
+ },
+ },
+ },
+}
+
+
[email protected]
+def idl():
+ helper = ovs.db.idl.SchemaHelper(schema_json=SCHEMA)
+ helper.register_all()
+ return ovs.db.idl.Idl("unix:/nonexistent.sock", helper)
+
+
[email protected]("row_update", [{}, {"s": "x"}])
[email protected]("alert", [True, False])
+def test_update2_insert_always_notifies(idl, row_update, alert):
+ table = idl.tables["optional"]
+ table.columns["s"].alert = alert
+ row_uuid = uuid.uuid4()
+
+ result, notice = idl._process_update2(table, row_uuid,
+ {"insert": row_update})
+
+ assert result == ovs.db.idl.OVSDB_IDL_UPDATE_DB_CHANGED
+ assert notice == ovs.db.idl.Notice(ovs.db.idl.ROW_CREATE,
+ table.rows[row_uuid])
--
2.55.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev