[ovs-dev] [PATCH v2] python: Send old values of the updated cols in notify for update2

Numan Siddique nusiddiq at redhat.com
Tue Jul 26 17:58:14 UTC 2016


When python IDL calls the "notify" function after processing the "update2"
message from ovsdb-server, it is suppose to send the old values of the
updated columns as the last parameter. But the recent commit "897c8064"
sends the updated values. This breaks the behaviour.
This patch fixes this issue. It also updates the description of
the 'updates' param of the notify function to make it more clear.

Fixes: 897c8064 ("python: move Python idl to work with monitor_cond")
Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
---
 python/ovs/db/idl.py |  19 ++++++---
 tests/ovsdb-idl.at   | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-ovsdb.py  |  53 +++++++++++++++++++------
 3 files changed, 162 insertions(+), 18 deletions(-)


v1 -> v2
--------
 * Added test case


diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index 437e9b0..92a7382 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -333,7 +333,8 @@ class Idl(object):
         :type event:    ROW_CREATE, ROW_UPDATE, or ROW_DELETE
         :param row:     The row as it is after the operation has occured
         :type row:      Row
-        :param updates: For updates, row with only updated columns
+        :param updates: For updates, row with only old values of the changed
+                        columns
         :type updates:  Row
         """
 
@@ -511,9 +512,10 @@ class Idl(object):
             if not row:
                 raise error.Error('Modify non-existing row')
 
-            self.__apply_diff(table, row, row_update['modify'])
+            old_row_diff_json = self.__apply_diff(table, row,
+                                                  row_update['modify'])
             self.notify(ROW_UPDATE, row,
-                        Row.from_json(self, table, uuid, row_update['modify']))
+                        Row.from_json(self, table, uuid, old_row_diff_json))
             changed = True
         else:
             raise error.Error('<row-update> unknown operation',
@@ -576,7 +578,8 @@ class Idl(object):
                         row_update[column.name] = self.__column_name(column)
 
     def __apply_diff(self, table, row, row_diff):
-        for column_name, datum_json in six.iteritems(row_diff):
+        old_row_diff_json = {}
+        for column_name, datum_diff_json in six.iteritems(row_diff):
             column = table.columns.get(column_name)
             if not column:
                 # XXX rate-limit
@@ -585,17 +588,21 @@ class Idl(object):
                 continue
 
             try:
-                datum = ovs.db.data.Datum.from_json(column.type, datum_json)
+                datum_diff = ovs.db.data.Datum.from_json(column.type,
+                                                         datum_diff_json)
             except error.Error as e:
                 # XXX rate-limit
                 vlog.warn("error parsing column %s in table %s: %s"
                           % (column_name, table.name, e))
                 continue
 
-            datum = row._data[column_name].diff(datum)
+            old_row_diff_json[column_name] = row._data[column_name].to_json()
+            datum = row._data[column_name].diff(datum_diff)
             if datum != row._data[column_name]:
                 row._data[column_name] = datum
 
+        return old_row_diff_json
+
     def __row_update(self, table, row, row_json):
         changed = False
         for column_name, datum_json in six.iteritems(row_json):
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index 5d9bb81..e5ead56 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -1106,3 +1106,111 @@ OVSDB_CHECK_IDL_PARTIAL_UPDATE_MAP_COLUMN([map, simple2 idl-partial-update-map-c
 009: name=String2 smap=[[key2 : value2]] imap=[[3 : myids2]]
 010: End test
 ]])
+
+m4_define([OVSDB_CHECK_IDL_NOTIFY_PY],
+  [AT_SETUP([$1 - Python])
+   AT_SKIP_IF([test $HAVE_PYTHON = no])
+   AT_KEYWORDS([ovsdb server idl Python notify $4])
+   AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
+                  [0], [stdout], [ignore])
+   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   AT_CHECK([$PYTHON $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $2],
+            [0], [stdout], [ignore], [kill `cat pid`])
+   AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$5],,, [[| $5]]),
+            [0], [$3], [], [kill `cat pid`])
+   OVSDB_SERVER_SHUTDOWN
+   AT_CLEANUP])
+
+
+m4_define([OVSDB_CHECK_IDL_NOTIFY],
+   [OVSDB_CHECK_IDL_NOTIFY_PY($@)])
+
+
+OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify],
+  [['track-notify' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"i": 1,
+               "r": 2.0,
+               "b": true,
+               "s": "mystring",
+               "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"],
+               "ia": ["set", [1, 2, 3]],
+               "ra": ["set", [-0.5]],
+               "ba": ["set", [true]],
+               "sa": ["set", ["abc", "def"]],
+               "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"],
+                              ["uuid", "aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}},
+      {"op": "insert",
+       "table": "simple",
+       "row": {}}]' \
+    '["idltest",
+      {"op": "update",
+       "table": "simple",
+       "where": [],
+       "row": {"b": false}}]' \
+    '["idltest",
+      {"op": "update",
+       "table": "simple",
+       "where": [],
+       "row": {"r": 123.5}}]' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"i": -1,
+               "r": 125,
+               "b": false,
+               "s": "",
+               "ia": ["set", [1]],
+               "ra": ["set", [1.5]],
+               "ba": ["set", [false]],
+               "sa": ["set", []],
+               "ua": ["set", []]}}]' \
+    '["idltest",
+      {"op": "update",
+       "table": "simple",
+       "where": [["i", "<", 1]],
+       "row": {"s": "newstring"}}]' \
+    '["idltest",
+      {"op": "delete",
+       "table": "simple",
+       "where": [["i", "==", 0]]}]' \
+    'reconnect']],
+  [[000: empty
+001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
+002: event:create, row={i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>}, updates=None
+002: event:create, row={i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates=None
+002: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+003: {"error":null,"result":[{"count":2}]}
+004: event:update, row={i=1 r=2 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates={b=true uuid=<0>}
+004: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: i=1 r=2 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+005: {"error":null,"result":[{"count":2}]}
+006: event:update, row={i=0 r=123.5 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>}, updates={r=0 uuid=<1>}
+006: event:update, row={i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates={r=2 uuid=<0>}
+006: i=0 r=123.5 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+006: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]}
+008: event:create, row={i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>}, updates=None
+008: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+008: i=0 r=123.5 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+008: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+009: {"error":null,"result":[{"count":2}]}
+010: event:update, row={i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>}, updates={s= uuid=<6>}
+010: event:update, row={i=0 r=123.5 b=false s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>}, updates={s= uuid=<1>}
+010: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+010: i=0 r=123.5 b=false s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+010: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+011: {"error":null,"result":[{"count":1}]}
+012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>}, updates=None
+012: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+012: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+013: reconnect
+014: event:create, row={i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>}, updates=None
+014: event:create, row={i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates=None
+014: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+014: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+015: done
+]])
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index 83fe4af..88180a3 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -149,23 +149,30 @@ def do_parse_schema(schema_string):
     print(ovs.json.to_string(schema.to_json(), sort_keys=True))
 
 
+def get_simple_table_printable_row(row):
+    simple_columns = ["i", "r", "b", "s", "u", "ia",
+                      "ra", "ba", "sa", "ua", "uuid"]
+    s = ""
+    for column in simple_columns:
+        if hasattr(row, column) and not (type(getattr(row, column))
+                                         is ovs.db.data.Atom):
+            s += "%s=%s " % (column, getattr(row, column))
+    s = s.strip()
+    s = re.sub('""|,|u?\'', "", s)
+    s = re.sub('UUID\(([^)]+)\)', r'\1', s)
+    s = re.sub('False', 'false', s)
+    s = re.sub('True', 'true', s)
+    s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
+    return s
+
+
 def print_idl(idl, step):
     n = 0
     if "simple" in idl.tables:
-        simple_columns = ["i", "r", "b", "s", "u", "ia",
-                          "ra", "ba", "sa", "ua", "uuid"]
         simple = idl.tables["simple"].rows
         for row in six.itervalues(simple):
-            s = "%03d:" % step
-            for column in simple_columns:
-                if hasattr(row, column) and not (type(getattr(row, column))
-                                                 is ovs.db.data.Atom):
-                    s += " %s=%s" % (column, getattr(row, column))
-            s = re.sub('""|,|u?\'', "", s)
-            s = re.sub('UUID\(([^)]+)\)', r'\1', s)
-            s = re.sub('False', 'false', s)
-            s = re.sub('True', 'true', s)
-            s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
+            s = "%03d: " % step
+            s += get_simple_table_printable_row(row)
             print(s)
             n += 1
 
@@ -415,6 +422,12 @@ def update_condition(idl, commands):
 
 def do_idl(schema_file, remote, *commands):
     schema_helper = ovs.db.idl.SchemaHelper(schema_file)
+    track_notify = False
+
+    if commands and commands[0] == "track-notify":
+        commands = commands[1:]
+        track_notify = True
+
     if commands and commands[0].startswith("?"):
         readonly = {}
         for x in commands[0][1:].split("?"):
@@ -445,6 +458,22 @@ def do_idl(schema_file, remote, *commands):
     seqno = 0
     step = 0
 
+    def mock_notify(event, row, updates=None):
+        output = "%03d: " % step
+        output += "event:" + str(event) + ", row={"
+        output += get_simple_table_printable_row(row) + "}, updates="
+        if updates is None:
+            output += "None"
+        else:
+            output += "{" + get_simple_table_printable_row(updates) + "}"
+
+        output += '\n'
+        sys.stdout.write(output)
+        sys.stdout.flush()
+
+    if track_notify and "simple" in idl.tables:
+        idl.notify = mock_notify
+
     commands = list(commands)
     if len(commands) >= 1 and "condition" in commands[0]:
         update_condition(idl, commands.pop(0))
-- 
2.7.4




More information about the dev mailing list