From patchwork Tue Dec 1 00:21:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bert Vermeulen X-Patchwork-Id: 550565 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id 407291401B5 for ; Tue, 1 Dec 2015 11:22:39 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 822071059E; Mon, 30 Nov 2015 16:22:38 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 3EBC8101F9 for ; Mon, 30 Nov 2015 16:22:37 -0800 (PST) Received: from bar3.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id C66B5161BDD for ; Mon, 30 Nov 2015 17:22:36 -0700 (MST) X-ASG-Debug-ID: 1448929355-03dd7b0fba50c0d0001-byXFYA Received: from mx3-pf2.cudamail.com ([192.168.14.1]) by bar3.cudamail.com with ESMTP id sji6n22XAQ9TIMnq (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 30 Nov 2015 17:22:35 -0700 (MST) X-Barracuda-Envelope-From: bert@biot.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.1 Received: from unknown (HELO kiutl.biot.com) (31.172.244.210) by mx3-pf2.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 1 Dec 2015 00:22:28 -0000 Received-SPF: pass (mx3-pf2.cudamail.com: SPF record at biot.com designates 31.172.244.210 as permitted sender) X-Barracuda-Apparent-Source-IP: 31.172.244.210 X-Barracuda-RBL-IP: 31.172.244.210 Received: from spamd by kiutl.biot.com with sa-checked (Exim 4.83) (envelope-from ) id 1a3Yi8-0001Q8-SS for dev@openvswitch.org; Tue, 01 Dec 2015 01:22:26 +0100 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on kiutl.biot.com X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, FSL_HELO_NON_FQDN_1, SPF_FAIL,TVD_RCVD_IP autolearn=no autolearn_force=no version=3.4.0 Received: from 85.234.217.28.static.edpnet.net ([85.234.217.28] helo=flake) by kiutl.biot.com with esmtps (TLSv1.2:AES128-GCM-SHA256:128) (Exim 4.83) (envelope-from ) id 1a3Yi8-0001Q4-5i; Tue, 01 Dec 2015 01:22:24 +0100 Received: from bert by flake with local (Exim 4.86) (envelope-from ) id 1a3Yi7-0001Oz-Oc; Tue, 01 Dec 2015 01:22:23 +0100 X-CudaMail-Envelope-Sender: bert@biot.com From: Bert Vermeulen To: dev@openvswitch.org X-CudaMail-MID: CM-V2-1129075730 X-CudaMail-DTE: 113015 X-CudaMail-Originating-IP: 31.172.244.210 Date: Tue, 1 Dec 2015 01:21:54 +0100 X-ASG-Orig-Subj: [##CM-V2-1129075730##][PATCH v2] ovsdb-client: Add optional table and columns to dump command Message-Id: <1448929314-5351-1-git-send-email-bert@biot.com> X-Mailer: git-send-email 2.5.0 X-Barracuda-Connect: UNKNOWN[192.168.14.1] X-Barracuda-Start-Time: 1448929355 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.24863 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: Bert Vermeulen Subject: [ovs-dev] [PATCH v2] ovsdb-client: Add optional table and columns to dump command X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Adding a table to the dump command's arguments retrieves only that table. One or more columns after the table retrieve only those columns. Default behavior is unchanged. Signed-off-by: Bert Vermeulen --- Changes in v2: coding style fixes, also fixed a regression. ovsdb/ovsdb-client.1.in | 7 ++++-- ovsdb/ovsdb-client.c | 67 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/ovsdb/ovsdb-client.1.in b/ovsdb/ovsdb-client.1.in index fbb7148..909a739 100644 --- a/ovsdb/ovsdb-client.1.in +++ b/ovsdb/ovsdb-client.1.in @@ -25,7 +25,8 @@ ovsdb\-client \- command-line interface to \fBovsdb-server\fR(1) .br \fBovsdb\-client \fR[\fIoptions\fR] \fBtransact\fI \fR[\fIserver\fR] \fItransaction\fR .br -\fBovsdb\-client \fR[\fIoptions\fR] \fBdump\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR]\fR +\fBovsdb\-client \fR[\fIoptions\fR] \fBdump\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR]\fR [\fItable\fR] +[\fIcolumn\fR[\fB,\fIcolumn\fR]...]... .br \fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]... @@ -102,7 +103,9 @@ operations, and prints the received reply on stdout. . .IP "\fBdump\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR]\fR" Connects to \fIserver\fR, retrieves all of the data in \fIdatabase\fR, -and prints it on stdout as a series of tables. +and prints it on stdout as a series of tables. If a table is specified, only +that table is retrieved. If at least one \fIcolumn\fR is specified, only those +columns are retrieved. . .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..." Connects to \fIserver\fR and monitors the contents of \fItable\fR in diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index b59388f..ce6591d 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -963,7 +963,8 @@ compare_columns(const void *a_, const void *b_) } static void -dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows) +dump_table(const char *table_name, const struct shash *cols, + struct json_array *rows) { const struct ovsdb_column **columns; size_t n_columns; @@ -976,9 +977,9 @@ dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows) size_t x, y; /* Sort columns by name, for reproducibility. */ - columns = xmalloc(shash_count(&ts->columns) * sizeof *columns); + columns = xmalloc(shash_count(cols) * sizeof *columns); n_columns = 0; - SHASH_FOR_EACH (node, &ts->columns) { + SHASH_FOR_EACH (node, cols) { struct ovsdb_column *column = node->data; if (strcmp(column->name, "_version")) { columns[n_columns++] = column; @@ -993,7 +994,7 @@ dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows) if (rows->elems[y]->type != JSON_OBJECT) { ovs_fatal(0, "row %"PRIuSIZE" in table %s response is not a JSON object: " - "%s", y, ts->name, json_to_string(rows->elems[y], 0)); + "%s", y, table_name, json_to_string(rows->elems[y], 0)); } row = json_object(rows->elems[y]); @@ -1002,7 +1003,7 @@ dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows) const struct json *json = shash_find_data(row, columns[x]->name); if (!json) { ovs_fatal(0, "row %"PRIuSIZE" in table %s response lacks %s column", - y, ts->name, columns[x]->name); + y, table_name, columns[x]->name); } check_ovsdb_error(ovsdb_datum_from_json(&data[y][x], @@ -1019,7 +1020,7 @@ dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows) /* Add column headings. */ table_init(&t); - table_set_caption(&t, xasprintf("%s table", ts->name)); + table_set_caption(&t, xasprintf("%s table", table_name)); for (x = 0; x < n_columns; x++) { table_add_column(&t, "%s", columns[x]->name); } @@ -1044,34 +1045,59 @@ dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows) static void do_dump(struct jsonrpc *rpc, const char *database, - int argc OVS_UNUSED, char *argv[] OVS_UNUSED) + int argc, char *argv[]) { struct jsonrpc_msg *request, *reply; struct ovsdb_schema *schema; struct json *transaction; - const struct shash_node **tables; + const struct shash_node *node, **tables; size_t n_tables; + struct ovsdb_table_schema *tschema; + const struct shash *columns; + struct shash custom_columns; size_t i; + shash_init(&custom_columns); schema = fetch_schema(rpc, database); - tables = shash_sort(&schema->tables); - n_tables = shash_count(&schema->tables); + if (argc) { + node = shash_find(&schema->tables, argv[0]); + if (!node) { + ovs_fatal(0, "No table \"%s\" found.", argv[0]); + } + tables = xmemdup(&node, sizeof(&node)); + n_tables = 1; + tschema = tables[0]->data; + for (i = 1; i < argc; i++) { + node = shash_find(&tschema->columns, argv[i]); + if (!node) { + ovs_fatal(0, "Table \"%s\" has no column %s.", argv[0], argv[1]); + } + shash_add(&custom_columns, argv[1], node->data); + } + } else { + tables = shash_sort(&schema->tables); + n_tables = shash_count(&schema->tables); + } /* Construct transaction to retrieve entire database. */ transaction = json_array_create_1(json_string_create(database)); for (i = 0; i < n_tables; i++) { const struct ovsdb_table_schema *ts = tables[i]->data; - struct json *op, *columns; - struct shash_node *node; + struct json *op, *jcolumns; - columns = json_array_create_empty(); - SHASH_FOR_EACH (node, &ts->columns) { + if (argc > 1) { + columns = &custom_columns; + } else { + columns = &ts->columns; + } + jcolumns = json_array_create_empty(); + SHASH_FOR_EACH (node, columns) { const struct ovsdb_column *column = node->data; if (strcmp(column->name, "_version")) { - json_array_add(columns, json_string_create(column->name)); + json_array_add(jcolumns, json_string_create(column->name)); } } @@ -1079,7 +1105,7 @@ do_dump(struct jsonrpc *rpc, const char *database, json_object_put_string(op, "op", "select"); json_object_put_string(op, "table", tables[i]->name); json_object_put(op, "where", json_array_create_empty()); - json_object_put(op, "columns", columns); + json_object_put(op, "columns", jcolumns); json_array_add(transaction, op); } @@ -1106,10 +1132,15 @@ do_dump(struct jsonrpc *rpc, const char *database, ts->name, json_to_string(op_result, 0)); } - dump_table(ts, &rows->u.array); + if (argc > 1) { + dump_table(tables[i]->name, &custom_columns, &rows->u.array); + } else { + dump_table(tables[i]->name, &ts->columns, &rows->u.array); + } } jsonrpc_msg_destroy(reply); + shash_destroy(&custom_columns); free(tables); ovsdb_schema_destroy(schema); } @@ -1136,7 +1167,7 @@ static const struct ovsdb_client_command all_commands[] = { { "list-columns", NEED_DATABASE, 0, 1, do_list_columns }, { "transact", NEED_RPC, 1, 1, do_transact }, { "monitor", NEED_DATABASE, 1, INT_MAX, do_monitor }, - { "dump", NEED_DATABASE, 0, 0, do_dump }, + { "dump", NEED_DATABASE, 0, INT_MAX, do_dump }, { "help", NEED_NONE, 0, INT_MAX, do_help },