+ OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+ AT_KEYWORDS([ovsdb server positive unix $5])
+ $2 > schema
+ AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
+ AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+ m4_foreach([txn], [$3],
+ [AT_CHECK([ovsdb-client transact unix:socket 'txn'], [0], [stdout], [ignore],
+ [test ! -e pid || kill `cat pid`])
+cat stdout >> output
+])
+ AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
+ [test ! -e pid || kill `cat pid`])
+ OVSDB_SERVER_SHUTDOWN
+ AT_CLEANUP])
+
+EXECUTION_EXAMPLES
+\f
+AT_BANNER([ovsdb-server miscellaneous features])
+
+AT_SETUP([truncating corrupted database log])
+AT_KEYWORDS([ovsdb server positive unix])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
+dnl Do one transaction and save the output.
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 0, "name": "zero"}}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [])
+cat stdout >> output
+dnl Add some crap to the database log and run another transaction, which should
+dnl ignore the crap and truncate it out of the log.
+echo 'xxx' >> db
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 1, "name": "one"}}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
+AT_CHECK([grep 'syntax error: db: parse error.* in header line "xxx"' stderr],
+ [0], [ignore])
+cat stdout >> output
+dnl Run a final transaction to verify that both transactions succeeeded.
+dnl The crap that we added should have been truncated by the previous run,
+dnl so ovsdb-server shouldn't log a warning this time.
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+ {"op": "select",
+ "table": "ordinals",
+ "where": [],
+ "sort": ["number"]}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [])
+cat stdout >> output
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0],
+ [[[{"uuid":["uuid","<0>"]}]
+[{"uuid":["uuid","<1>"]}]
+[{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0},{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
+]], [],
+ [test ! -e pid || kill `cat pid`])
+AT_CLEANUP
+
+AT_SETUP([truncating database log with bad transaction])
+AT_KEYWORDS([ovsdb server positive unix])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
+dnl Do one transaction and save the output.
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 0, "name": "zero"}}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [])
+cat stdout >> output
+dnl Add some crap to the database log and run another transaction, which should
+dnl ignore the crap and truncate it out of the log.
+echo 'OVSDB JSON 15 ffbcdae4b0386265f9ea3280dd7c8f0b72a20e56
+{"invalid":{}}' >> db
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 1, "name": "one"}}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
+AT_CHECK([grep 'syntax "{"invalid":{}}": unknown table: No table named invalid.' stderr],
+ [0], [ignore])
+cat stdout >> output
+dnl Run a final transaction to verify that both transactions succeeeded.
+dnl The crap that we added should have been truncated by the previous run,
+dnl so ovsdb-server shouldn't log a warning this time.
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+ {"op": "select",
+ "table": "ordinals",
+ "where": [],
+ "sort": ["number"]}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [])
+cat stdout >> output
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0],
+ [[[{"uuid":["uuid","<0>"]}]
+[{"uuid":["uuid","<1>"]}]
+[{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0},{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
+]], [],
+ [test ! -e pid || kill `cat pid`])
+AT_CLEANUP
+
+AT_SETUP([ovsdb-client get-schema-version])
+AT_KEYWORDS([ovsdb server positive])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=punix:socket db], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-client get-schema-version unix:socket ordinals], [0], [5.1.3
+])
+OVSDB_SERVER_SHUTDOWN
+AT_CLEANUP
+
+AT_SETUP([database multiplexing implementation])
+AT_KEYWORDS([ovsdb server positive])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+ordinal_schema > schema1
+constraint_schema > schema2
+AT_CHECK([ovsdb-tool create db1 schema1], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=punix:socket db1 db2], [0], [ignore], [ignore])
+AT_CHECK(
+ [[ovsdb-client list-dbs unix:socket]],
+ [0], [constraints
+ordinals
+], [ignore], [test ! -e pid || kill `cat pid`])
+AT_CHECK(
+ [[test-jsonrpc request unix:socket get_schema [\"nonexistent\"]]], [0],
+ [[{"error":null,"id":0,"result":{"details":"get_schema request specifies unknown database nonexistent","error":"unknown database","syntax":"[\"nonexistent\"]"}}
+]], [], [test ! -e pid || kill `cat pid`])
+OVSDB_SERVER_SHUTDOWN
+AT_CLEANUP
+
+AT_SETUP([ovsdb-server/add-db and remove-db])
+AT_KEYWORDS([ovsdb server positive])
+ON_EXIT([kill `cat ovsdb-server.pid`])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema1
+constraint_schema > schema2
+AT_CHECK([ovsdb-tool create db1 schema1], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
+
+# Start ovsdb-server with just a single database - db1.
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db1], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [ordinals
+])
+
+# Add the second database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [constraints
+ordinals
+])
+
+# The databases are responsive.
+AT_CHECK([ovsdb-client list-tables unix:socket constraints], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-client list-tables unix:socket ordinals], [0], [ignore], [ignore])
+
+# Add an already added database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], 2, [], [stderr])
+AT_CHECK([sed 's/(.*)/(...)/' stderr], [0],
+ [I/O error: db2: failed to lock lockfile (...)
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+# Add a non-existing database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db3], 2, [], [stderr])
+AT_CHECK([sed 's/(.*)/(...)/' stderr], [0],
+ [I/O error: open: db3 failed (...)
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+# Add a remote through a db path in db1.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote db:ordinals,ordinals,name], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [db:ordinals,ordinals,name
+punix:socket
+])
+
+# Removing db1 has no effect on its remote.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db ordinals], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [constraints
+])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [db:ordinals,ordinals,name
+punix:socket
+])
+AT_CHECK([ovsdb-client list-tables unix:socket ordinals], [1], [ignore], [ignore])
+
+# Remove db2.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db constraints], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [])
+AT_CHECK([ovsdb-client list-tables unix:socket constraints], [1], [ignore], [ignore])
+
+# Remove a non-existent database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db ordinals], [2],
+ [], [Failed to find the database.
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+# Add a removed database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [constraints
+])
+AT_CHECK([ovsdb-client list-tables unix:socket constraints], [0], [ignore], [ignore])
+AT_CLEANUP
+
+AT_SETUP([ovsdb-server/add-db with --monitor])
+AT_KEYWORDS([ovsdb server positive])
+# Start ovsdb-server, initially with one db.
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db1 schema], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file db1])
+
+# Add the second database.
+constraint_schema > schema2
+AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [constraints
+ordinals
+])
+
+# Kill the daemon process, making it look like a segfault,
+# and wait for a new daemon process to get spawned.
+cp ovsdb-server.pid old.pid
+AT_CHECK([kill -SEGV `cat ovsdb-server.pid`])
+OVS_WAIT_WHILE([kill -0 `cat old.pid`])
+OVS_WAIT_UNTIL(
+ [test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat old.pid`])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [constraints
+ordinals
+])
+AT_CLEANUP
+
+AT_SETUP([ovsdb-server/add-db and remove-db with --monitor])
+AT_KEYWORDS([ovsdb server positive])
+# Start ovsdb-server, initially with one db.
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db1 schema], [0], [ignore], [ignore])
+constraint_schema > schema2
+AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file db1 db2])
+
+# Remove the second database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db constraints])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [ordinals
+])
+
+# Kill the daemon process, making it look like a segfault,
+# and wait for a new daemon process to get spawned.
+cp ovsdb-server.pid old.pid
+AT_CHECK([kill -SEGV `cat ovsdb-server.pid`])
+OVS_WAIT_WHILE([kill -0 `cat old.pid`])
+OVS_WAIT_UNTIL(
+ [test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat old.pid`])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [ordinals
+])
+AT_CLEANUP
+
+AT_SETUP([--remote=db: implementation])
+AT_KEYWORDS([ovsdb server positive])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+AT_DATA([schema],
+ [[{"name": "mydb",
+ "tables": {
+ "Root": {
+ "columns": {
+ "managers": {
+ "type": {
+ "key": "string",
+ "min": 0,
+ "max": "unlimited"}},
+ "manager_options": {
+ "type": {
+ "key": {"type": "uuid", "refTable": "Manager"},
+ "min": 0,
+ "max": "unlimited"}}}},
+ "Manager": {
+ "columns": {
+ "target": {
+ "type": "string"},
+ "is_connected": {
+ "type": {
+ "key": "boolean",
+ "min": 0,
+ "max": 1}}}}}}
+]])
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+AT_CHECK(
+ [[ovsdb-tool transact db \
+ '["mydb",
+ {"op": "insert",
+ "table": "Root",
+ "row": {
+ "managers": "punix:socket1",
+ "manager_options": ["set", [["named-uuid", "x"]]]}},
+ {"op": "insert",
+ "table": "Manager",
+ "uuid-name": "x",
+ "row": {"target": "punix:socket2"}}]']], [0], [ignore], [ignore])
+ON_EXIT([kill `cat ovsdb-server.pid`])
+AT_CHECK([ovsdb-server --enable-dummy --detach --no-chdir --pidfile --remote=db:mydb,Root,managers --remote=db:mydb,Root,manager_options --log-file db], [0], [ignore], [ignore])
+for i in 1 2 3 4 5 6; do ovs-appctl -t ovsdb-server time/warp 1000; done
+AT_CHECK(
+ [[ovsdb-client transact unix:socket1 \
+ '["mydb",
+ {"op": "select",
+ "table": "Root",
+ "where": [],
+ "columns": ["managers"]},
+ {"op": "select",
+ "table": "Manager",
+ "where": [],
+ "columns": ["target", "is_connected"]}]']],
+ [0], [stdout], [ignore])
+AT_CHECK(
+ [${PERL} $srcdir/uuidfilt.pl stdout],
+ [0],
+ [[[{"rows":[{"managers":"punix:socket1"}]},{"rows":[{"is_connected":false,"target":"punix:socket2"}]}]
+]],
+ [ignore])
+AT_CLEANUP
+
+AT_SETUP([ovsdb-server/add-remote and remove-remote])
+AT_KEYWORDS([ovsdb server positive])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile db])
+
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket1])
+OVS_WAIT_UNTIL([test -S socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [punix:socket1
+])
+
+AT_CHECK([test ! -e socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket2])
+OVS_WAIT_UNTIL([test -S socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [punix:socket1
+punix:socket2
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote db:x,y,z], [2],
+ [], ["db:x,y,z": no database named x
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-remote punix:socket1])
+OVS_WAIT_UNTIL([test ! -e socket1])
+AT_CHECK([test -S socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [punix:socket2
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-remote punix:socket2])
+OVS_WAIT_UNTIL([test ! -e socket2])
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes])
+AT_CLEANUP
+
+AT_SETUP([ovsdb-server/add-remote with --monitor])
+AT_KEYWORDS([ovsdb server positive])
+# Start ovsdb-server, initially with no remotes.
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file db])
+
+# Add a remote.
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket1])
+OVS_WAIT_UNTIL([test -S socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [punix:socket1