Skip to content

Commit

Permalink
ovsdb-idl.at: Test IDL behavior during database conversion.
Browse files Browse the repository at this point in the history
Add new 'monitor' command to test-ovsdb utilities to make them just
run IDL loop infinitely.  Other commands can still be placed before
the 'monitor', e.g. setting up conditions, tracking, running a few
transactions.

Having that, adding a couple test cases for IDL with online database
conversion.  Test checks that IDL receives monitor cancellation
notification and successfully re-sends monitor requests.

While at it, adding debug logging to ovsdb-server processes for easier
debugging.

While working on a test the issue was discovered that schema for
standalone databases is not getting updated in the _Server database
after conversion.  Checking the new schema bits only for clustered
databases for now.

Signed-off-by: Ilya Maximets <[email protected]>
Acked-by: Dumitru Ceara <[email protected]>
Signed-off-by: Simon Horman <[email protected]>
  • Loading branch information
igsilya authored and Simon Horman committed Jan 11, 2024
1 parent 2c6b81a commit dd3f062
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 13 deletions.
96 changes: 93 additions & 3 deletions tests/ovsdb-idl.at
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ m4_define([OVSDB_CLUSTER_START_IDLTEST],
done
on_exit 'kill $(cat s*.pid)'
for i in $(seq $n); do
AT_CHECK([ovsdb-server -vraft -vconsole:warn --detach --no-chdir \
--log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i \
--remote=punix:s$i.ovsdb \
AT_CHECK([ovsdb-server -vraft -vconsole:warn -vfile:dbg --detach \
--no-chdir --log-file=s$i.log --pidfile=s$i.pid \
--unixctl=s$i --remote=punix:s$i.ovsdb \
m4_if([$2], [], [], [--remote=$2]) s$i.db])
done

Expand Down Expand Up @@ -2727,3 +2727,93 @@ OVSDB_CHECK_IDL_PERS_UUID_INSERT([simple idl, persistent uuid insert],
011: done
]],
[['This UUID would duplicate a UUID already present within the table or deleted within the same transaction']])


m4_define([OVSDB_CHECK_IDL_CHANGE_AWARE],
[AT_SETUP([simple idl, database change aware, online conversion - $1])
AT_KEYWORDS([ovsdb server idl db_change_aware conversion $1])

m4_if([$1], [clustered],
[OVSDB_CLUSTER_START_IDLTEST([1], [punix:socket])],
[OVSDB_START_IDLTEST])

dnl Add some data.
AT_CHECK([[ovsdb-client transact unix:socket '["idltest",
{"op": "insert",
"table": "simple",
"row": {"i": 1,
"r": 2.0,
"b": true,
"s": "first row",
"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": {"b": false, "s": "second row"}},
{"op": "insert",
"table": "simple",
"row": {"b": true, "s": "third row"}}
]']], [0], [stdout])

dnl Create a new schema by adding 'extra_column' to the 'simple' table.
AT_CHECK([sed 's/"ua": {/"extra_column":{"type": "string"},"ua": {/
s/1.2.3/1.2.4/' \
$abs_srcdir/idltest.ovsschema > new-idltest.ovsschema])
dnl Try "needs-conversion".
AT_CHECK([ovsdb-client needs-conversion unix:socket $abs_srcdir/idltest.ovsschema], [0], [no
])
AT_CHECK([ovsdb-client needs-conversion unix:socket new-idltest.ovsschema], [0], [yes
])

dnl Conditionally exclude the second row from monitoring.
m4_define([COND], [['condition simple [["b","==",true]]']])

dnl Start monitoring.
OVS_DAEMONIZE([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t30 \
idl unix:socket COND monitor \
>idl-c.out 2>idl-c.err], [idl-c.pid])
AT_CAPTURE_FILE([idl-c.out])
AT_CAPTURE_FILE([idl-c.err])

OVS_DAEMONIZE([$PYTHON3 $srcdir/test-ovsdb.py -t30 \
idl $srcdir/idltest.ovsschema unix:socket COND monitor \
>idl-python.out 2>idl-python.err], [idl-python.pid])
AT_CAPTURE_FILE([idl-python.out])
AT_CAPTURE_FILE([idl-python.err])

dnl Wait for monitors to receive the data.
OVS_WAIT_UNTIL([grep -q 'third row' idl-c.err])
OVS_WAIT_UNTIL([grep -q 'third row' idl-python.err])

dnl Convert the database.
AT_CHECK([ovsdb-client convert unix:socket new-idltest.ovsschema])

dnl Check for the monitor cancellation and the data being requested again.
m4_foreach([FILE], [[idl-c], [idl-python]],
[OVS_WAIT_UNTIL([grep -q 'monitor_canceled' FILE.err])
OVS_WAIT_UNTIL([test 2 -eq $(grep -c 'send request, method="monitor_cond_since", params=."idltest"' FILE.err)])

dnl XXX: Checking for the new schema bits conditionally because standalone
dnl databases are not updating the schema in the _Server database properly.
m4_if([$1], [clustered], [OVS_WAIT_UNTIL([grep -q 'extra_column' FILE.err])])

dnl Check that there were no unexpected messages.
AT_CHECK([! grep 'unexpected' FILE.err])

dnl Check that the data is received twice and the condition is working.
AT_CHECK([sort FILE.out | uuidfilt], [0],
[[000: simple: change conditions
001: table simple: i=0 r=0 b=true s=third row u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
001: table simple: i=1 r=2 b=true s=first row u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
002: table simple: i=0 r=0 b=true s=third row u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
002: table simple: i=1 r=2 b=true s=first row u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
]])])
AT_CLEANUP])

OVSDB_CHECK_IDL_CHANGE_AWARE([standalone])
OVSDB_CHECK_IDL_CHANGE_AWARE([clustered])
7 changes: 7 additions & 0 deletions tests/test-ovsdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2800,6 +2800,13 @@ do_idl(struct ovs_cmdl_context *ctx)
} else {
print_idl(idl, step++, terse);
}

/* Just run IDL forever for a simple monitoring. */
if (!strcmp(arg, "monitor")) {
seqno = ovsdb_idl_get_seqno(idl);
i--;
continue;
}
}
seqno = ovsdb_idl_get_seqno(idl);

Expand Down
27 changes: 17 additions & 10 deletions tests/test-ovsdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,16 +757,23 @@ def mock_notify(event, row, updates=None):
poller.block()
else:
# Wait for update.
while idl.change_seqno == seqno and not idl.run():
rpc.run()

poller = ovs.poller.Poller()
idl.wait(poller)
rpc.wait(poller)
poller.block()

print_idl(idl, step, terse)
step += 1
while True:
while idl.change_seqno == seqno and not idl.run():
rpc.run()

poller = ovs.poller.Poller()
idl.wait(poller)
rpc.wait(poller)
poller.block()

print_idl(idl, step, terse)
step += 1

# Run IDL forever in case of a simple monitor, otherwise
# break and execute the command.
seqno = idl.change_seqno
if command != "monitor":
break

seqno = idl.change_seqno

Expand Down

0 comments on commit dd3f062

Please sign in to comment.