/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <config.h>
-#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
/* --timeout: Time to wait for a connection to 'db'. */
static int timeout;
+/* --retry: If true, ovs-vsctl will retry connecting to the database forever.
+ * If false and --db says to use an active connection method (e.g. "unix:",
+ * "tcp:", "ssl:"), then ovs-vsctl will try to connect once and exit with an
+ * error if the database server cannot be contacted (e.g. ovsdb-server is not
+ * running).
+ *
+ * Regardless of this setting, --timeout always limits how long ovs-vsctl will
+ * wait. */
+static bool retry;
+
/* Format for table output. */
static struct table_style table_style = TABLE_STYLE_DEFAULT;
/* All supported commands. */
-static const struct vsctl_command_syntax all_commands[];
+static const struct vsctl_command_syntax *get_all_commands(void);
/* The IDL we're using and the current transaction, if any.
* This is for use by vsctl_exit() only, to allow it to clean up.
static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
static char *default_db(void);
static void usage(void) NO_RETURN;
-static void parse_options(int argc, char *argv[]);
+static void parse_options(int argc, char *argv[], struct shash *local_options);
static bool might_write_to_db(char **argv);
static struct vsctl_command *parse_commands(int argc, char *argv[],
+ struct shash *local_options,
size_t *n_commandsp);
-static void parse_command(int argc, char *argv[], struct vsctl_command *);
+static void parse_command(int argc, char *argv[], struct shash *local_options,
+ struct vsctl_command *);
static const struct vsctl_command_syntax *find_command(const char *name);
static void run_prerequisites(struct vsctl_command[], size_t n_commands,
struct ovsdb_idl *);
extern struct vlog_module VLM_reconnect;
struct ovsdb_idl *idl;
struct vsctl_command *commands;
+ struct shash local_options;
unsigned int seqno;
size_t n_commands;
char *args;
VLOG(might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
/* Parse command line. */
- parse_options(argc, argv);
- commands = parse_commands(argc - optind, argv + optind, &n_commands);
+ shash_init(&local_options);
+ parse_options(argc, argv, &local_options);
+ commands = parse_commands(argc - optind, argv + optind, &local_options,
+ &n_commands);
if (timeout) {
time_alarm(timeout);
}
/* Initialize IDL. */
- idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false);
+ idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false, retry);
run_prerequisites(commands, n_commands, idl);
/* Execute the commands.
seqno = ovsdb_idl_get_seqno(idl);
for (;;) {
ovsdb_idl_run(idl);
+ if (!ovsdb_idl_is_alive(idl)) {
+ int retval = ovsdb_idl_get_last_error(idl);
+ vsctl_fatal("%s: database connection failed (%s)",
+ db, ovs_retval_to_string(retval));
+ }
if (seqno != ovsdb_idl_get_seqno(idl)) {
seqno = ovsdb_idl_get_seqno(idl);
}
}
+static struct option *
+find_option(const char *name, struct option *options, size_t n_options)
+{
+ size_t i;
+
+ for (i = 0; i < n_options; i++) {
+ if (!strcmp(options[i].name, name)) {
+ return &options[i];
+ }
+ }
+ return NULL;
+}
+
+static struct option *
+add_option(struct option **optionsp, size_t *n_optionsp,
+ size_t *allocated_optionsp)
+{
+ if (*n_optionsp >= *allocated_optionsp) {
+ *optionsp = x2nrealloc(*optionsp, allocated_optionsp,
+ sizeof **optionsp);
+ }
+ return &(*optionsp)[(*n_optionsp)++];
+}
+
static void
-parse_options(int argc, char *argv[])
+parse_options(int argc, char *argv[], struct shash *local_options)
{
enum {
OPT_DB = UCHAR_MAX + 1,
OPT_NO_WAIT,
OPT_DRY_RUN,
OPT_PEER_CA_CERT,
+ OPT_LOCAL,
+ OPT_RETRY,
VLOG_OPTION_ENUMS,
TABLE_OPTION_ENUMS
};
- static struct option long_options[] = {
+ static const struct option global_long_options[] = {
{"db", required_argument, NULL, OPT_DB},
{"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
{"no-wait", no_argument, NULL, OPT_NO_WAIT},
{"dry-run", no_argument, NULL, OPT_DRY_RUN},
{"oneline", no_argument, NULL, OPT_ONELINE},
{"timeout", required_argument, NULL, 't'},
+ {"retry", no_argument, NULL, OPT_RETRY},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
VLOG_LONG_OPTIONS,
{"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
{NULL, 0, NULL, 0},
};
+ const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
char *tmp, *short_options;
- tmp = long_options_to_short_options(long_options);
+ const struct vsctl_command_syntax *p;
+ struct option *options, *o;
+ size_t allocated_options;
+ size_t n_options;
+ size_t i;
+
+ tmp = long_options_to_short_options(global_long_options);
short_options = xasprintf("+%s", tmp);
free(tmp);
+ /* We want to parse both global and command-specific options here, but
+ * getopt_long() isn't too convenient for the job. We copy our global
+ * options into a dynamic array, then append all of the command-specific
+ * options. */
+ options = xmemdup(global_long_options, sizeof global_long_options);
+ allocated_options = ARRAY_SIZE(global_long_options);
+ n_options = n_global_long_options;
+ for (p = get_all_commands(); p->name; p++) {
+ if (p->options[0]) {
+ char *save_ptr = NULL;
+ char *name;
+ char *s;
+
+ s = xstrdup(p->options);
+ for (name = strtok_r(s, ",", &save_ptr); name != NULL;
+ name = strtok_r(NULL, ",", &save_ptr)) {
+ char *equals;
+ int has_arg;
+
+ ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
+ name += 2;
+
+ equals = strchr(name, '=');
+ if (equals) {
+ has_arg = required_argument;
+ *equals = '\0';
+ } else {
+ has_arg = no_argument;
+ }
+
+ o = find_option(name, options, n_options);
+ if (o) {
+ ovs_assert(o - options >= n_global_long_options);
+ ovs_assert(o->has_arg == has_arg);
+ } else {
+ o = add_option(&options, &n_options, &allocated_options);
+ o->name = xstrdup(name);
+ o->has_arg = has_arg;
+ o->flag = NULL;
+ o->val = OPT_LOCAL;
+ }
+ }
+
+ free(s);
+ }
+ }
+ o = add_option(&options, &n_options, &allocated_options);
+ memset(o, 0, sizeof *o);
+
table_style.format = TF_LIST;
for (;;) {
+ int idx;
int c;
- c = getopt_long(argc, argv, short_options, long_options, NULL);
+ c = getopt_long(argc, argv, short_options, options, &idx);
if (c == -1) {
break;
}
dry_run = true;
break;
+ case OPT_LOCAL:
+ if (shash_find(local_options, options[idx].name)) {
+ vsctl_fatal("'%s' option specified multiple times",
+ options[idx].name);
+ }
+ shash_add_nocopy(local_options,
+ xasprintf("--%s", options[idx].name),
+ optarg ? xstrdup(optarg) : NULL);
+ break;
+
case 'h':
usage();
}
break;
+ case OPT_RETRY:
+ retry = true;
+ break;
+
VLOG_OPTION_HANDLERS
TABLE_OPTION_HANDLERS(&table_style)
if (!db) {
db = default_db();
}
+
+ for (i = n_global_long_options; options[i].name; i++) {
+ free(CONST_CAST(char *, options[i].name));
+ }
+ free(options);
}
static struct vsctl_command *
-parse_commands(int argc, char *argv[], size_t *n_commandsp)
+parse_commands(int argc, char *argv[], struct shash *local_options,
+ size_t *n_commandsp)
{
struct vsctl_command *commands;
size_t n_commands, allocated_commands;
shash_moved(&c->options);
}
}
- parse_command(i - start, &argv[start],
+ parse_command(i - start, &argv[start], local_options,
&commands[n_commands++]);
+ } else if (!shash_is_empty(local_options)) {
+ vsctl_fatal("missing command name (use --help for help)");
}
start = i + 1;
}
}
static void
-parse_command(int argc, char *argv[], struct vsctl_command *command)
+parse_command(int argc, char *argv[], struct shash *local_options,
+ struct vsctl_command *command)
{
const struct vsctl_command_syntax *p;
struct shash_node *node;
int i;
shash_init(&command->options);
+ shash_swap(local_options, &command->options);
for (i = 0; i < argc; i++) {
const char *option = argv[i];
const char *equals;
shash_add_nocopy(&command->options, key, value);
}
if (i == argc) {
- vsctl_fatal("missing command name");
+ vsctl_fatal("missing command name (use --help for help)");
}
p = find_command(argv[i]);
if (shash_is_empty(&commands)) {
const struct vsctl_command_syntax *p;
- for (p = all_commands; p->name; p++) {
+ for (p = get_all_commands(); p->name; p++) {
shash_add_assert(&commands, p->name, p);
}
}
--db=DATABASE connect to DATABASE\n\
(default: %s)\n\
--no-wait do not wait for ovs-vswitchd to reconfigure\n\
+ --retry keep trying to connect to server forever\n\
-t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
--dry-run do not commit changes to database\n\
--oneline print exactly one line of output per command\n",
static void
del_cached_bridge(struct vsctl_context *ctx, struct vsctl_bridge *br)
{
- assert(list_is_empty(&br->ports));
- assert(hmap_is_empty(&br->children));
+ ovs_assert(list_is_empty(&br->ports));
+ ovs_assert(hmap_is_empty(&br->children));
if (br->parent) {
hmap_remove(&br->parent->children, &br->children_node);
}
static void
del_cached_port(struct vsctl_context *ctx, struct vsctl_port *port)
{
- assert(list_is_empty(&port->ifaces));
+ ovs_assert(list_is_empty(&port->ifaces));
list_remove(&port->ports_node);
shash_find_and_delete(&ctx->ports, port->port_cfg->name);
ovsrec_port_delete(port->port_cfg);
{
struct vsctl_bridge *br;
- assert(ctx->cache_valid);
+ ovs_assert(ctx->cache_valid);
br = shash_find_data(&ctx->bridges, name);
if (must_exist && !br) {
{
struct vsctl_port *port;
- assert(ctx->cache_valid);
+ ovs_assert(ctx->cache_valid);
port = shash_find_data(&ctx->ports, name);
if (port && !strcmp(name, port->bridge->name)) {
{
struct vsctl_iface *iface;
- assert(ctx->cache_valid);
+ ovs_assert(ctx->cache_valid);
iface = shash_find_data(&ctx->ifaces, name);
if (iface && !strcmp(name, iface->port->bridge->name)) {
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_mirrors);
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_netflow);
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_sflow);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_ipfix);
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_flood_vlans);
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_other_config);
const struct ovsrec_netflow *nf, *next_nf;
const struct ovsrec_ssl *ssl, *next_ssl;
const struct ovsrec_sflow *sflow, *next_sflow;
+ const struct ovsrec_ipfix *ipfix, *next_ipfix;
+ const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
/* Reset the Open_vSwitch table. */
ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
ovsrec_bridge_set_mirrors(br, NULL, 0);
ovsrec_bridge_set_netflow(br, NULL);
ovsrec_bridge_set_sflow(br, NULL);
+ ovsrec_bridge_set_ipfix(br, NULL);
ovsrec_bridge_set_flood_vlans(br, NULL, 0);
/* We only want to save the "hwaddr" key from other_config. */
ovsrec_sflow_delete(sflow);
}
+ OVSREC_IPFIX_FOR_EACH_SAFE (ipfix, next_ipfix, idl) {
+ ovsrec_ipfix_delete(ipfix);
+ }
+
+ OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset, idl) {
+ ovsrec_flow_sample_collector_set_delete(fscset);
+ }
+
vsctl_context_invalidate_cache(ctx);
}
{
struct vsctl_bridge *child, *next_child;
struct vsctl_port *port, *next_port;
+ const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
HMAP_FOR_EACH_SAFE (child, next_child, children_node, &br->children) {
del_bridge(ctx, child);
del_port(ctx, port);
}
+ OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset,
+ ctx->idl) {
+ if (fscset->bridge == br->br_cfg) {
+ ovsrec_flow_sample_collector_set_delete(fscset);
+ }
+ }
+
del_cached_bridge(ctx, br);
}
{
struct shash_node *node;
struct svec bridges;
+ bool real = shash_find(&ctx->options, "--real");
+ bool fake = shash_find(&ctx->options, "--fake");
+
+ /* If neither fake nor real were requested, return both. */
+ if (!real && !fake) {
+ real = fake = true;
+ }
vsctl_context_populate_cache(ctx);
svec_init(&bridges);
SHASH_FOR_EACH (node, &ctx->bridges) {
struct vsctl_bridge *br = node->data;
- svec_add(&bridges, br->name);
+
+ if (br->parent ? fake : real) {
+ svec_add(&bridges, br->name);
+ }
}
output_sorted(&bridges, &ctx->output);
svec_destroy(&bridges);
{
bool must_exist = !shash_find(&ctx->options, "--if-exists");
bool with_iface = shash_find(&ctx->options, "--with-iface") != NULL;
+ const char *target = ctx->argv[ctx->argc - 1];
struct vsctl_port *port;
vsctl_context_populate_cache(ctx);
- if (!with_iface) {
- port = find_port(ctx, ctx->argv[ctx->argc - 1], must_exist);
+ if (find_bridge(ctx, target, false)) {
+ if (must_exist) {
+ vsctl_fatal("cannot delete port %s because it is the local port "
+ "for bridge %s (deleting this port requires deleting "
+ "the entire bridge)", target, target);
+ }
+ port = NULL;
+ } else if (!with_iface) {
+ port = find_port(ctx, target, must_exist);
} else {
- const char *target = ctx->argv[ctx->argc - 1];
struct vsctl_iface *iface;
port = find_port(ctx, target, false);
static const struct vsctl_table_class tables[] = {
{&ovsrec_table_bridge,
{{&ovsrec_table_bridge, &ovsrec_bridge_col_name, NULL},
- {NULL, NULL, NULL}}},
+ {&ovsrec_table_flow_sample_collector_set, NULL,
+ &ovsrec_flow_sample_collector_set_col_bridge}}},
{&ovsrec_table_controller,
{{&ovsrec_table_bridge,
{{&ovsrec_table_flow_table, &ovsrec_flow_table_col_name, NULL},
{NULL, NULL, NULL}}},
+ {&ovsrec_table_ipfix,
+ {{&ovsrec_table_bridge,
+ &ovsrec_bridge_col_name,
+ &ovsrec_bridge_col_ipfix},
+ {&ovsrec_table_flow_sample_collector_set, NULL,
+ &ovsrec_flow_sample_collector_set_col_ipfix}}},
+
+ {&ovsrec_table_flow_sample_collector_set,
+ {{NULL, NULL, NULL},
+ {NULL, NULL, NULL}}},
+
{NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
};
static const struct ovsdb_idl_row *
get_row (struct vsctl_context *ctx,
- const struct vsctl_table_class *table, const char *record_id)
+ const struct vsctl_table_class *table, const char *record_id,
+ bool must_exist)
{
const struct ovsdb_idl_row *row;
struct uuid uuid;
}
}
}
- return row;
-}
-
-static const struct ovsdb_idl_row *
-must_get_row(struct vsctl_context *ctx,
- const struct vsctl_table_class *table, const char *record_id)
-{
- const struct ovsdb_idl_row *row = get_row(ctx, table, record_id);
- if (!row) {
+ if (must_exist && !row) {
vsctl_fatal("no row \"%s\" in table %s",
record_id, table->class->name);
}
char *column_name;
char *error;
- assert(!(operatorp && !valuep));
+ ovs_assert(!(operatorp && !valuep));
*keyp = NULL;
if (valuep) {
*valuep = NULL;
cmd_get(struct vsctl_context *ctx)
{
const char *id = shash_find_data(&ctx->options, "--id");
- bool if_exists = shash_find(&ctx->options, "--if-exists");
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
const char *table_name = ctx->argv[1];
const char *record_id = ctx->argv[2];
const struct vsctl_table_class *table;
struct ds *out = &ctx->output;
int i;
+ if (id && !must_exist) {
+ vsctl_fatal("--if-exists and --id may not be specified together");
+ }
+
table = get_table(table_name);
- row = must_get_row(ctx, table, record_id);
+ row = get_row(ctx, table, record_id, must_exist);
+ if (!row) {
+ return;
+ }
+
if (id) {
struct ovsdb_symbol *symbol;
bool new;
idx = ovsdb_datum_find_key(datum, &key,
column->type.key.type);
if (idx == UINT_MAX) {
- if (!if_exists) {
+ if (must_exist) {
vsctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
key_string, table->class->name, record_id,
column->name);
{
size_t i;
+ if (!row) {
+ return;
+ }
+
table_add_row(out);
for (i = 0; i < n_columns; i++) {
const struct ovsdb_idl_column *column = columns[i];
cmd_list(struct vsctl_context *ctx)
{
const char *column_names = shash_find_data(&ctx->options, "--columns");
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
const struct ovsdb_idl_column **columns;
const char *table_name = ctx->argv[1];
const struct vsctl_table_class *table;
out = ctx->table = list_make_table(columns, n_columns);
if (ctx->argc > 2) {
for (i = 2; i < ctx->argc; i++) {
- list_record(must_get_row(ctx, table, ctx->argv[i]),
+ list_record(get_row(ctx, table, ctx->argv[i], must_exist),
columns, n_columns, out);
}
} else {
static void
cmd_set(struct vsctl_context *ctx)
{
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
const char *table_name = ctx->argv[1];
const char *record_id = ctx->argv[2];
const struct vsctl_table_class *table;
int i;
table = get_table(table_name);
- row = must_get_row(ctx, table, record_id);
+ row = get_row(ctx, table, record_id, must_exist);
+ if (!row) {
+ return;
+ }
+
for (i = 3; i < ctx->argc; i++) {
set_column(table, row, ctx->argv[i], ctx->symtab);
}
static void
cmd_add(struct vsctl_context *ctx)
{
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
const char *table_name = ctx->argv[1];
const char *record_id = ctx->argv[2];
const char *column_name = ctx->argv[3];
int i;
table = get_table(table_name);
- row = must_get_row(ctx, table, record_id);
die_if_error(get_column(table, column_name, &column));
+ row = get_row(ctx, table, record_id, must_exist);
+ if (!row) {
+ return;
+ }
type = &column->type;
ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
static void
cmd_remove(struct vsctl_context *ctx)
{
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
const char *table_name = ctx->argv[1];
const char *record_id = ctx->argv[2];
const char *column_name = ctx->argv[3];
int i;
table = get_table(table_name);
- row = must_get_row(ctx, table, record_id);
die_if_error(get_column(table, column_name, &column));
+ row = get_row(ctx, table, record_id, must_exist);
+ if (!row) {
+ return;
+ }
type = &column->type;
ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
static void
cmd_clear(struct vsctl_context *ctx)
{
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
const char *table_name = ctx->argv[1];
const char *record_id = ctx->argv[2];
const struct vsctl_table_class *table;
int i;
table = get_table(table_name);
- row = must_get_row(ctx, table, record_id);
+ row = get_row(ctx, table, record_id, must_exist);
+ if (!row) {
+ return;
+ }
+
for (i = 3; i < ctx->argc; i++) {
const struct ovsdb_idl_column *column;
const struct ovsdb_type *type;
struct uuid dummy;
if (!uuid_from_string(&dummy, ds_cstr(&ctx->output))) {
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
real = ovsdb_idl_txn_get_insert_uuid(ctx->txn, &dummy);
if (real) {
for (i = 2; i < ctx->argc; i++) {
const struct ovsdb_idl_row *row;
- row = (must_exist ? must_get_row : get_row)(ctx, table, ctx->argv[i]);
+ row = get_row(ctx, table, ctx->argv[i], must_exist);
if (row) {
ovsdb_idl_txn_delete(row);
}
return ovsdb_datum_includes_all(b, a, type);
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
table = get_table(table_name);
- row = get_row(ctx, table, record_id);
+ row = get_row(ctx, table, record_id, false);
if (!row) {
ctx->try_again = true;
return;
(c->syntax->prerequisites)(&ctx);
vsctl_context_done(&ctx, c);
- assert(!c->output.string);
- assert(!c->table);
+ ovs_assert(!c->output.string);
+ ovs_assert(!c->table);
}
}
}
switch (status) {
case TXN_UNCOMMITTED:
case TXN_INCOMPLETE:
- NOT_REACHED();
+ OVS_NOT_REACHED();
case TXN_ABORTED:
/* Should not happen--we never call ovsdb_idl_txn_abort(). */
vsctl_fatal("database not locked");
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
free(error);
if (txn) {
ovsdb_idl_txn_abort(txn);
ovsdb_idl_txn_destroy(txn);
+ the_idl_txn = NULL;
}
ovsdb_symbol_table_destroy(symtab);
for (c = commands; c < &commands[n_commands]; c++) {
/* Bridge commands. */
{"add-br", 1, 3, pre_get_info, cmd_add_br, NULL, "--may-exist", RW},
{"del-br", 1, 1, pre_get_info, cmd_del_br, NULL, "--if-exists", RW},
- {"list-br", 0, 0, pre_get_info, cmd_list_br, NULL, "", RO},
+ {"list-br", 0, 0, pre_get_info, cmd_list_br, NULL, "--real,--fake", RO},
{"br-exists", 1, 1, pre_get_info, cmd_br_exists, NULL, "", RO},
{"br-to-vlan", 1, 1, pre_get_info, cmd_br_to_vlan, NULL, "", RO},
{"br-to-parent", 1, 1, pre_get_info, cmd_br_to_parent, NULL, "", RO},
/* Manager commands. */
{"get-manager", 0, 0, pre_manager, cmd_get_manager, NULL, "", RO},
- {"del-manager", 0, INT_MAX, pre_manager, cmd_del_manager, NULL, "", RW},
+ {"del-manager", 0, 0, pre_manager, cmd_del_manager, NULL, "", RW},
{"set-manager", 1, INT_MAX, pre_manager, cmd_set_manager, NULL, "", RW},
/* SSL commands. */
/* Database commands. */
{"comment", 0, INT_MAX, NULL, NULL, NULL, "", RO},
{"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},
+ {"list", 1, INT_MAX, pre_cmd_list, cmd_list, NULL,
+ "--if-exists,--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},
- {"clear", 3, INT_MAX, pre_cmd_clear, cmd_clear, NULL, "", RW},
+ {"set", 3, INT_MAX, pre_cmd_set, cmd_set, NULL, "--if-exists", RW},
+ {"add", 4, INT_MAX, pre_cmd_add, cmd_add, NULL, "--if-exists", RW},
+ {"remove", 4, INT_MAX, pre_cmd_remove, cmd_remove, NULL, "--if-exists",
+ RW},
+ {"clear", 3, INT_MAX, pre_cmd_clear, cmd_clear, NULL, "--if-exists", RW},
{"create", 2, INT_MAX, pre_create, cmd_create, post_create, "--id=", RW},
{"destroy", 1, INT_MAX, pre_cmd_destroy, cmd_destroy, NULL,
"--if-exists,--all", RW},
{NULL, 0, 0, NULL, NULL, NULL, NULL, RO},
};
+static const struct vsctl_command_syntax *get_all_commands(void)
+{
+ return all_commands;
+}