2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-17 14:28:02 +00:00

python: idl: Fix index not being updated on row modification.

When a row is modified, python IDL doesn't perform any operations on
existing client-side indexes.  This means that if the column on which
index is created changes, the old value will remain in the index and
the new one will not be added to the index.  Beside lookup failures
this is also causing inability to remove modified rows, because the
new column value doesn't exist in the index causing an exception on
attempt to remove it:

 Traceback (most recent call last):
   File "ovsdbapp/backend/ovs_idl/connection.py", line 110, in run
     self.idl.run()
   File "ovs/db/idl.py", line 465, in run
     self.__parse_update(msg.params[2], OVSDB_UPDATE3)
   File "ovs/db/idl.py", line 924, in __parse_update
     self.__do_parse_update(update, version, self.tables)
   File "ovs/db/idl.py", line 964, in __do_parse_update
     changes = self.__process_update2(table, uuid, row_update)
   File "ovs/db/idl.py", line 991, in __process_update2
     del table.rows[uuid]
   File "ovs/db/custom_index.py", line 102, in __delitem__
     index.remove(val)
   File "ovs/db/custom_index.py", line 66, in remove
     self.values.remove(self.index_entry_from_row(row))
   File "sortedcontainers/sortedlist.py", line 2015, in remove
     raise ValueError('{0!r} not in list'.format(value))
 ValueError: Datapath_Binding(
   uuid=UUID('498e66a2-70bc-4587-a66f-0433baf82f60'),
   tunnel_key=16711683, load_balancers=[], external_ids={}) not in list

Fix that by always removing an existing row from indexes before
modification and adding back afterwards.  This ensures that old
values are removed from the index and new ones are added.

This behavior is consistent with the C implementation.

The new test that reproduces the removal issue is added.  Some extra
testing infrastructure added to be able to handle and print out the
'indexed' table from the idltest schema.

Fixes: 13973bc415 ("Add multi-column index support for the Python IDL")
Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2024-May/053159.html
Reported-by: Roberto Bartzen Acosta <roberto.acosta@luizalabs.com>
Acked-by: Mike Pattrick <mkp@redhat.com>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Acked-by: Terry Wilson <twilson@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Ilya Maximets
2024-05-27 23:39:06 +02:00
parent d401291955
commit fad8c8f7f6
4 changed files with 160 additions and 6 deletions

View File

@@ -1013,7 +1013,9 @@ class Idl(object):
if not row:
raise error.Error('Modify non-existing row')
del table.rows[uuid]
old_row = self.__apply_diff(table, row, row_update['modify'])
table.rows[uuid] = row
return Notice(ROW_UPDATE, row, Row(self, table, uuid, old_row))
else:
raise error.Error('<row-update> unknown operation',
@@ -1044,9 +1046,10 @@ class Idl(object):
op = ROW_UPDATE
vlog.warn("cannot add existing row %s to table %s"
% (uuid, table.name))
del table.rows[uuid]
changed |= self.__row_update(table, row, new)
if op == ROW_CREATE:
table.rows[uuid] = row
table.rows[uuid] = row
if changed:
return Notice(ROW_CREATE, row)
else:
@@ -1058,9 +1061,11 @@ class Idl(object):
# XXX rate-limit
vlog.warn("cannot modify missing row %s in table %s"
% (uuid, table.name))
else:
del table.rows[uuid]
changed |= self.__row_update(table, row, new)
if op == ROW_CREATE:
table.rows[uuid] = row
table.rows[uuid] = row
if changed:
return Notice(op, row, Row.from_json(self, table, uuid, old))
return False