diff options
author | Ben Pfaff <blp@ovn.org> | 2017-12-22 11:01:52 -0800 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-12-22 11:01:52 -0800 |
commit | 838f9c31043c35a321d2c7cc0042300191ebef9a (patch) | |
tree | 3974fbfe1e1f613f1b18509daa75c2ce5cc76c63 | |
parent | fe0fb88551b4cc5b4bee6814f1027f78c451daa2 (diff) | |
download | openvswitch-838f9c31043c35a321d2c7cc0042300191ebef9a.tar.gz |
ovsdb-client: Add new "query" command.
This is mostly for symmetry with ovsdb-tool, but it might come in handy
from time to time.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Justin Pettit <jpettit@ovn.org>
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | ovsdb/ovsdb-client.1.in | 12 | ||||
-rw-r--r-- | ovsdb/ovsdb-client.c | 67 | ||||
-rw-r--r-- | tests/ovsdb-client.at | 53 |
4 files changed, 121 insertions, 13 deletions
@@ -5,7 +5,7 @@ Post-v2.8.0 * New high-level documentation in ovsdb(7). * New file format documentation for developers in ovsdb(5). * Protocol documentation moved from ovsdb-server(1) to ovsdb-server(7). - * ovsdb-client: New "get-schema-cksum" command. + * ovsdb-client: New "get-schema-cksum" and "query" commands. * ovsdb-client: New "backup" and "restore" commands. * ovsdb-tool: New "db-name" and "schema-name" commands. - OVN: diff --git a/ovsdb/ovsdb-client.1.in b/ovsdb/ovsdb-client.1.in index 7ab452f6d..203d70cfa 100644 --- a/ovsdb/ovsdb-client.1.in +++ b/ovsdb/ovsdb-client.1.in @@ -27,6 +27,8 @@ ovsdb\-client \- command-line interface to \fBovsdb-server\fR(1) .IP "Data Management Commands:" \fBovsdb\-client \fR[\fIoptions\fR] \fBtransact\fI \fR[\fIserver\fR] \fItransaction\fR .br +\fBovsdb\-client \fR[\fIoptions\fR] \fBquery \fR[\fIserver\fR] \fItransaction\fR +.br \fBovsdb\-client \fR[\fIoptions\fR] \fBdump\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR]\fR [\fItable\fR [\fIcolumn\fR...]] .br @@ -137,6 +139,16 @@ which must be a JSON array appropriate for use as the \fBparams\fR to a JSON-RPC \fBtransact\fR request, and prints the received reply on stdout. . +.IP "\fBquery \fR[\fIserver\fR] \fItransaction\fR" +This commands acts like a read-only version of \fBtransact\fR. +It connects to \fIserver\fR, sends it the specified \fItransaction\fR, +which must be a JSON array appropriate for use as the \fBparams\fR to +a JSON-RPC \fBtransact\fR request, and prints the received reply on +stdout. To ensure that the transaction does not modify the database, +this command appends an \fBabort\fR operation to the set of operations +included in \fItransaction\fR before sending it to the database, and +then removes the \fBabort\fR result from the reply (if it is present). +. .IP "\fBdump\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR]\fR [\fItable \fR[\fIcolumn\fR...]]" Connects to \fIserver\fR, retrieves all of the data in \fIdatabase\fR, and prints it on stdout as a series of tables. If \fItable\fR is diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 349bc55d4..974cc0cbc 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -271,8 +271,11 @@ usage(void) "\n list-columns [SERVER] [DATABASE] [TABLE]\n" " list columns in TABLE (or all tables) in DATABASE on SERVER\n" "\n transact [SERVER] TRANSACTION\n" - " run TRANSACTION (a JSON array of operations) on SERVER\n" + " run TRANSACTION (params for \"transact\" request) on SERVER\n" " and print the results as JSON on stdout\n" + "\n query [SERVER] TRANSACTION\n" + " run TRANSACTION (params for \"transact\" request) on SERVER,\n" + " as read-only, and print the results as JSON on stdout\n" "\n monitor [SERVER] [DATABASE] TABLE [COLUMN,...]...\n" " monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n" " COLUMNs may include !initial, !insert, !delete, !modify\n" @@ -370,7 +373,7 @@ static void print_json(struct json *json) { char *string = json_to_string(json, table_style.json_flags); - fputs(string, stdout); + puts(string); free(string); } @@ -536,20 +539,61 @@ do_list_columns(struct jsonrpc *rpc, const char *database, table_destroy(&t); } -static void -do_transact(struct jsonrpc *rpc, const char *database OVS_UNUSED, - int argc OVS_UNUSED, char *argv[]) +static struct json * +do_transact__(struct jsonrpc *rpc, struct json *transaction) { struct jsonrpc_msg *request, *reply; - struct json *transaction; - - transaction = parse_json(argv[0]); request = jsonrpc_create_request("transact", transaction, NULL); check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply); - print_json(reply->result); - putchar('\n'); + struct json *result = json_clone(reply->result); jsonrpc_msg_destroy(reply); + + return result; +} + +static void +do_transact(struct jsonrpc *rpc, const char *database OVS_UNUSED, + int argc OVS_UNUSED, char *argv[]) +{ + print_and_free_json(do_transact__(rpc, parse_json(argv[0]))); +} + +static void +do_query(struct jsonrpc *rpc, const char *database OVS_UNUSED, + int argc OVS_UNUSED, char *argv[]) +{ + struct json *transaction = parse_json(argv[0]); + + if (transaction->type != JSON_ARRAY) { + ovs_fatal(0, "not a valid OVSDB query"); + } + + /* Append an "abort" operation to the query. */ + struct json *abort_op = json_object_create(); + json_object_put_string(abort_op, "op", "abort"); + json_array_add(transaction, abort_op); + size_t abort_idx = transaction->u.array.n - 2; + + /* Run query. */ + struct json *result = do_transact__(rpc, transaction); + + /* If the "abort" operation ended the transaction, remove its result. */ + if (result->type == JSON_ARRAY + && result->u.array.n == abort_idx + 1 + && result->u.array.elems[abort_idx]->type == JSON_OBJECT) { + struct json *op_result = result->u.array.elems[abort_idx]; + struct json *error = shash_find_data(json_object(op_result), "error"); + if (error + && error->type == JSON_STRING + && !strcmp(json_string(error), "aborted")) { + result->u.array.n--; + json_destroy(op_result); + } + } + + /* Print the result. */ + print_and_free_json(result); } /* "monitor" command. */ @@ -1763,7 +1807,6 @@ do_lock(struct jsonrpc *rpc, const char *method, const char *lock) } else if (msg->type == JSONRPC_REPLY && json_equal(msg->id, request_id)) { print_json(msg->result); - putchar('\n'); fflush(stdout); enable_lock_request = true; json_destroy(request_id); @@ -1772,7 +1815,6 @@ do_lock(struct jsonrpc *rpc, const char *method, const char *lock) } else if (msg->type == JSONRPC_NOTIFY) { puts(msg->method); print_json(msg->params); - putchar('\n'); fflush(stdout); } @@ -1831,6 +1873,7 @@ static const struct ovsdb_client_command all_commands[] = { { "list-tables", NEED_DATABASE, 0, 0, do_list_tables }, { "list-columns", NEED_DATABASE, 0, 1, do_list_columns }, { "transact", NEED_RPC, 1, 1, do_transact }, + { "query", NEED_RPC, 1, 1, do_query }, { "monitor", NEED_DATABASE, 1, INT_MAX, do_monitor }, { "monitor-cond", NEED_DATABASE, 2, 3, do_monitor_cond }, { "dump", NEED_DATABASE, 0, INT_MAX, do_dump }, diff --git a/tests/ovsdb-client.at b/tests/ovsdb-client.at index 0aa20df57..ea4755e8a 100644 --- a/tests/ovsdb-client.at +++ b/tests/ovsdb-client.at @@ -118,3 +118,56 @@ dnl Verify that the two dumps are the same. AT_CHECK([sort dump1], [0], [expout]) AT_CLEANUP + +AT_SETUP([ovsdb-client query]) +AT_KEYWORDS([ovsdb client positive]) + +on_exit 'kill `cat *.pid`' + +dnl Create a database. +ordinal_schema > schema +touch .db.~lock~ +AT_CHECK([ovsdb-tool create db schema]) + +dnl Start the database server. +AT_CHECK([ovsdb-server -vfile -vvlog:off --detach --no-chdir --pidfile --log-file --remote=punix:db.sock db], [0]) +AT_CAPTURE_FILE([ovsdb-server.log]) + +dnl Put some data in the database. +dnl Use "query" for some of them, which won't have any effect. +AT_CHECK( + [[for txn in 'transact zero 0' \ + 'query one 1' \ + 'transact two 2' \ + 'query three 3' \ + 'transact four 4' \ + 'query five 5' + do + set -- $txn + ovsdb-client $1 ' + ["ordinals", + {"op": "insert", + "table": "ordinals", + "row": {"name": "'$2'", "number": '$3'}}, + {"op": "comment", + "comment": "add row for '"$pair"'"}]' + done | uuidfilt]], [0], +[[[{"uuid":["uuid","<0>"]},{}] +[{"uuid":["uuid","<1>"]},{}] +[{"uuid":["uuid","<2>"]},{}] +[{"uuid":["uuid","<3>"]},{}] +[{"uuid":["uuid","<4>"]},{}] +[{"uuid":["uuid","<5>"]},{}] +]], [ignore]) + +AT_CHECK([ovsdb-client -f csv dump | sort -t, -k 3 | uuidfilt], [0], [dnl +ordinals table +<0>,zero,0 +<1>,two,2 +<2>,four,4 +_uuid,name,number +]) + +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +AT_CLEANUP |