From 90c4bd001ae4a0f6b091db2af6fc664b110aafea Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 27 Jan 2010 11:30:59 -0800 Subject: [PATCH] ovs-vsctl: Add "remove" and "clear" commands. --- utilities/ovs-vsctl.8.in | 20 ++++++++++ utilities/ovs-vsctl.c | 86 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index a206a3bb6..d05b809f4 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -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 diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index c5864b7ee..f4b2c25af 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -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); + } +} 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; -- 2.43.0