ovs-vsctl: Add "remove" and "clear" commands.
authorBen Pfaff <blp@nicira.com>
Wed, 27 Jan 2010 19:30:59 +0000 (11:30 -0800)
committerBen Pfaff <blp@nicira.com>
Wed, 27 Jan 2010 21:51:52 +0000 (13:51 -0800)
utilities/ovs-vsctl.8.in
utilities/ovs-vsctl.c

index a206a3bb64a6ad6912f35d9368dea9cd04101dfb..d05b809f439c408d72104da9ae62b7f103eed75a 100644 (file)
@@ -497,6 +497,26 @@ Adds the specified value or key-value pair to \fIcolumn\fR in
 is required, otherwise it is prohibited.  If \fIkey\fR already exists
 in a map column, then the current \fIvalue\fR is not replaced (use the
 \fBset\fR command to replace an existing value).
+.
+.IP "\fBremove \fItable record column \fR\fIvalue\fR..."
+.IQ "\fBremove \fItable record column \fR\fIkey\fR..."
+.IQ "\fBremove \fItable record column \fR\fIkey\fB=\fR\fIvalue\fR..."
+Removes the specified values or key-value pairs from \fIcolumn\fR in
+\fIrecord\fR in \fItable\fR.  The first form applies to columns that
+are not maps: each specified \fIvalue\fR is removed from the column.
+The second and third forms apply to map columns: if only a \fIkey\fR
+is specified, then any key-value pair with the given \fIkey\fR is
+removed, regardless of its value; if a \fIvalue\fR is given then a
+pair is removed only if both key and value match.
+.IP
+It is not an error if the column does not contain the specified key or
+value or pair.
+.
+.IP "\fBclear \fItable record column\fR..."
+Sets each \fIcolumn\fR in \fIrecord\fR in \fItable\fR to the empty set
+or empty map, as appropriate.  This command applies only to columns
+that are allowed to be empty.
+.
 .SH "EXAMPLES"
 Create a new bridge named br0 and add port eth0 to it:
 .IP
index c5864b7ee7f8227df038ba2d0af33f528bc6413f..f4b2c25afbf3f7557a259d0c34d1f3569731a649 100644 (file)
@@ -2227,6 +2227,89 @@ cmd_add(struct vsctl_context *ctx)
     }
     ovsdb_idl_txn_write(row, column->idl, &old);
 }
+
+static void
+cmd_remove(struct vsctl_context *ctx)
+{
+    const char *table_name = ctx->argv[1];
+    const char *record_id = ctx->argv[2];
+    const char *column_name = ctx->argv[3];
+    const struct vsctl_table_class *table;
+    const struct vsctl_column *column;
+    const struct ovsdb_idl_row *row;
+    const struct ovsdb_type *type;
+    struct ovsdb_datum old;
+    int i;
+
+    table = get_table(table_name);
+    row = get_row(ctx, table, record_id);
+    die_if_error(get_column(table, column_name, &column));
+    type = &column->idl->type;
+    ovsdb_idl_txn_read(row, column->idl, &old);
+    for (i = 4; i < ctx->argc; i++) {
+        struct ovsdb_type rm_type;
+        struct ovsdb_datum rm;
+        char *error;
+
+        if (column->flags & VSCF_READONLY) {
+            ovs_fatal(0, "%s: cannot modify read-only column %s in table %s",
+                      ctx->argv[i], column->idl->name, table_name);
+        }
+
+        rm_type = *type;
+        rm_type.n_min = 1;
+        rm_type.n_max = UINT_MAX;
+        error = ovsdb_datum_from_string(&rm, &rm_type, ctx->argv[i]);
+        if (error && ovsdb_type_is_map(&rm_type)) {
+            free(error);
+            rm_type.value_type = OVSDB_TYPE_VOID;
+            die_if_error(ovsdb_datum_from_string(&rm, &rm_type, ctx->argv[i]));
+        }
+        ovsdb_datum_subtract(&old, type, &rm, &rm_type);
+        ovsdb_datum_destroy(&rm, &rm_type);
+    }
+    if (old.n < type->n_min) {
+        ovs_fatal(0, "\"remove\" operation would put %u %s in column %s of "
+                  "table %s but at least %u are required",
+                  old.n,
+                  type->value_type == OVSDB_TYPE_VOID ? "values" : "pairs",
+                  column->idl->name, table_name, type->n_min);
+    }
+    ovsdb_idl_txn_write(row, column->idl, &old);
+}
+
+static void
+cmd_clear(struct vsctl_context *ctx)
+{
+    const char *table_name = ctx->argv[1];
+    const char *record_id = ctx->argv[2];
+    const struct vsctl_table_class *table;
+    const struct ovsdb_idl_row *row;
+    int i;
+
+    table = get_table(table_name);
+    row = get_row(ctx, table, record_id);
+    for (i = 3; i < ctx->argc; i++) {
+        const struct vsctl_column *column;
+        const struct ovsdb_type *type;
+        struct ovsdb_datum datum;
+
+        die_if_error(get_column(table, ctx->argv[i], &column));
+
+        type = &column->idl->type;
+        if (column->flags & VSCF_READONLY) {
+            ovs_fatal(0, "%s: cannot modify read-only column %s in table %s",
+                      ctx->argv[i], column->idl->name, table_name);
+        } else if (type->n_min > 0) {
+            ovs_fatal(0, "\"clear\" operation cannot be applied to column %s "
+                      "of table %s, which is not allowed to be empty",
+                      column->idl->name, table_name);
+        }
+
+        ovsdb_datum_init_empty(&datum);
+        ovsdb_idl_txn_write(row, column->idl, &datum);
+    }
+}
 \f
 typedef void vsctl_handler_func(struct vsctl_context *);
 
@@ -2437,11 +2520,8 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
         {"list", 1, INT_MAX, cmd_list, ""},
         {"set", 3, INT_MAX, cmd_set, ""},
         {"add", 4, INT_MAX, cmd_add, ""},
-#if 0
-        /* XXX Not yet implemented. */
         {"remove", 4, INT_MAX, cmd_remove, ""},
         {"clear", 3, INT_MAX, cmd_clear, ""},
-#endif
     };
 
     const struct vsctl_command *p;