ovs-vsctl: Add new "find" command.
authorBen Pfaff <blp@nicira.com>
Tue, 8 Feb 2011 18:21:59 +0000 (10:21 -0800)
committerBen Pfaff <blp@nicira.com>
Wed, 9 Feb 2011 00:01:28 +0000 (16:01 -0800)
This allows listing records that match specified criteria, instead
of just records that have specific names.

This will be used in an upcoming patch, along with --columns, to
list all of the interfaces whose type is 'internal'.

tests/ovs-vsctl.at
utilities/ovs-vsctl.8.in
utilities/ovs-vsctl.c

index a6f0dbf..7488e3d 100644 (file)
@@ -565,6 +565,23 @@ AT_CHECK(
 name                : "br0"
 datapath_type       : ""
 ]], [ignore], [test ! -e pid || kill `cat pid`])
+AT_CHECK(
+  [RUN_OVS_VSCTL([--columns=fail_mode,name,datapath_type find b])],
+  [0],
+  [[fail_mode           : []
+name                : "br0"
+datapath_type       : ""
+]], [ignore], [test ! -e pid || kill `cat pid`])
+AT_CHECK([RUN_OVS_VSCTL([create b name=br1 datapath_type="foo"],
+                        [create b name=br2 external-ids:bar=quux])],
+  [0], [stdout], [], [OVS_VSCTL_CLEANUP])
+AT_CHECK(
+  [RUN_OVS_VSCTL([--columns=name find b datapath_type!=foo])], [0], [stdout],
+  [ignore], [test ! -e pid || kill `cat pid`])
+AT_CHECK([sed -n '/./p' stdout | sort], [0],
+  [[name                : "br0"
+name                : "br2"
+]])
 AT_CHECK(
   [RUN_OVS_VSCTL(
     [set bridge br0 \
@@ -589,7 +606,9 @@ AT_CHECK([RUN_OVS_VSCTL([remove br br0 other_config 'datapath_id="0123456789ab"'
 AT_CHECK([RUN_OVS_VSCTL([clear br br0 external-ids -- get br br0 external_ids])], 
   [0], [{}
 ], [], [OVS_VSCTL_CLEANUP])
-AT_CHECK([RUN_OVS_VSCTL([destroy b br0])], 
+AT_CHECK([RUN_OVS_VSCTL_TOGETHER([destroy b br0],
+                                 [destroy b br1],
+                                 [destroy b br2])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
 AT_CHECK([RUN_OVS_VSCTL([list b])], 
   [0], [], [], [OVS_VSCTL_CLEANUP])
index 79a1486..553985b 100644 (file)
@@ -551,6 +551,18 @@ If \fB\-\-columns\fR is specified, only the requested columns are
 listed, in the specified order.  Otherwise, all columns are listed, in
 alphabetical order by column name.
 .
+.IP "[\fB\-\-columns=\fIcolumn\fR[\fB,\fIcolumn\fR]...] \fBfind \fItable \fR[\fIcolumn\fR[\fB:\fIkey\fR]\fB=\fIvalue\fR]..."
+Lists the data in each record in \fItable\fR whose \fIcolumn\fR equals
+\fIvalue\fR or, if \fIkey\fR is specified, whose \fIcolumn\fR contains
+a \fIkey\fR with the specified \fIvalue\fR.  Any of the operators
+\fB!=\fR, \fB<\fR, \fB>\fR, \fB<=\fR, or \fB>=\fR may be substituted
+for \fB=\fR to test for inequality, less than, greater than, less than
+or equal to, or greater than or equal to, respectively.  (Don't forget
+to escape \fB<\fR or \fB>\fR from interpretation by the shell.)
+.IP
+If \fB\-\-columns\fR is specified, only the requested columns are
+listed, in the specified order.  Otherwise all columns are listed, in
+alphabetical order by column name.
 .IP
 The UUIDs shown for rows created in the same \fBovs\-vsctl\fR
 invocation will be wrong.
index 18bf63b..66ba418 100644 (file)
@@ -138,6 +138,11 @@ static void set_column(const struct vsctl_table_class *,
                        const struct ovsdb_idl_row *, const char *arg,
                        struct ovsdb_symbol_table *);
 
+static bool is_condition_satisfied(const struct vsctl_table_class *,
+                                   const struct ovsdb_idl_row *,
+                                   const char *arg,
+                                   struct ovsdb_symbol_table *);
+
 int
 main(int argc, char *argv[])
 {
@@ -508,6 +513,7 @@ Switch commands:\n\
 \n\
 Database commands:\n\
   list TBL [REC]              list RECord (or all records) in TBL\n\
+  find TBL CONDITION...       list records satisfying CONDITION in TBL\n\
   get TBL REC COL[:KEY]       print values of COLumns in RECord in TBL\n\
   set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
   add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
@@ -2790,6 +2796,54 @@ cmd_list(struct vsctl_context *ctx)
     free(columns);
 }
 
+static void
+pre_cmd_find(struct vsctl_context *ctx)
+{
+    const char *column_names = shash_find_data(&ctx->options, "--columns");
+    const char *table_name = ctx->argv[1];
+    const struct vsctl_table_class *table;
+    int i;
+
+    table = pre_get_table(ctx, table_name);
+    pre_list_columns(ctx, table, column_names);
+    for (i = 2; i < ctx->argc; i++) {
+        pre_parse_column_key_value(ctx, ctx->argv[i], table);
+    }
+}
+
+static void
+cmd_find(struct vsctl_context *ctx)
+{
+    const char *column_names = shash_find_data(&ctx->options, "--columns");
+    const struct ovsdb_idl_column **columns;
+    const char *table_name = ctx->argv[1];
+    const struct vsctl_table_class *table;
+    const struct ovsdb_idl_row *row;
+    struct ds *out = &ctx->output;
+    size_t n_columns;
+
+    table = get_table(table_name);
+    parse_column_names(column_names, table, &columns, &n_columns);
+
+    for (row = ovsdb_idl_first_row(ctx->idl, table->class); row;
+         row = ovsdb_idl_next_row(row)) {
+        int i;
+
+        for (i = 2; i < ctx->argc; i++) {
+            if (!is_condition_satisfied(table, row, ctx->argv[i],
+                                        ctx->symtab)) {
+                goto next_row;
+            }
+        }
+        if (out->length) {
+            ds_put_char(out, '\n');
+        }
+        list_record(row, columns, n_columns, out);
+
+    next_row: ;
+    }
+}
+
 static void
 pre_cmd_set(struct vsctl_context *ctx)
 {
@@ -3494,6 +3548,7 @@ static const struct vsctl_command_syntax all_commands[] = {
     /* Parameter commands. */
     {"get", 2, INT_MAX, pre_cmd_get, cmd_get, NULL, "--if-exists,--id=", RO},
     {"list", 1, INT_MAX, pre_cmd_list, cmd_list, NULL, "--columns=", RO},
+    {"find", 1, INT_MAX, pre_cmd_find, cmd_find, NULL, "--columns=", RO},
     {"set", 3, INT_MAX, pre_cmd_set, cmd_set, NULL, "", RW},
     {"add", 4, INT_MAX, pre_cmd_add, cmd_add, NULL, "", RW},
     {"remove", 4, INT_MAX, pre_cmd_remove, cmd_remove, NULL, "", RW},