/*
- * 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.
}
/* 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);
OPT_DRY_RUN,
OPT_PEER_CA_CERT,
OPT_LOCAL,
+ OPT_RETRY,
VLOG_OPTION_ENUMS,
TABLE_OPTION_ENUMS
};
{"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,
options = xmemdup(global_long_options, sizeof global_long_options);
allocated_options = ARRAY_SIZE(global_long_options);
n_options = n_global_long_options;
- for (p = all_commands; p->name; p++) {
+ for (p = get_all_commands(); p->name; p++) {
if (p->options[0]) {
char *save_ptr = NULL;
char *name;
char *equals;
int has_arg;
- assert(name[0] == '-' && name[1] == '-' && name[2]);
+ ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
name += 2;
equals = strchr(name, '=');
o = find_option(name, options, n_options);
if (o) {
- assert(o - options >= n_global_long_options);
- assert(o->has_arg == has_arg);
+ 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);
}
break;
+ case OPT_RETRY:
+ retry = true;
+ break;
+
VLOG_OPTION_HANDLERS
TABLE_OPTION_HANDLERS(&table_style)
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);
}
{
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++) {
/* 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;
+}