usage();
case 'V':
- OVS_PRINT_VERSION(0, 0);
+ ovs_print_version(0, 0);
exit(EXIT_SUCCESS);
case 't':
message = xvasprintf(format, args);
va_end(args);
- vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_EMER);
+ vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_OFF);
VLOG_ERR("%s", message);
ovs_error(0, "%s", message);
vsctl_exit(EXIT_FAILURE);
\n\
Open vSwitch commands:\n\
init initialize database, if not yet initialized\n\
+ show print overview of database contents\n\
emer-reset reset configuration to clean state\n\
\n\
Bridge commands:\n\
struct ovsrec_port *port_cfg = br_cfg->ports[j];
if (!sset_add(&ports, port_cfg->name)) {
- VLOG_WARN("%s: database contains duplicate port name",
- port_cfg->name);
+ /* Duplicate port name. (We will warn about that later.) */
continue;
}
sset_destroy(&ports);
sset_init(&bridges);
- sset_init(&ports);
for (i = 0; i < ovs->n_bridges; i++) {
struct ovsrec_bridge *br_cfg = ovs->bridges[i];
struct vsctl_bridge *br;
struct vsctl_port *port;
size_t k;
- if (!sset_add(&ports, port_cfg->name)) {
+ port = shash_find_data(&info->ports, port_cfg->name);
+ if (port) {
+ if (port_cfg == port->port_cfg) {
+ VLOG_WARN("%s: port is in multiple bridges (%s and %s)",
+ port_cfg->name, br->name, port->bridge->name);
+ } else {
+ /* Log as an error because this violates the database's
+ * uniqueness constraints, so the database server shouldn't
+ * have allowed it. */
+ VLOG_ERR("%s: database contains duplicate port name",
+ port_cfg->name);
+ }
continue;
}
struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
struct vsctl_iface *iface;
- if (shash_find(&info->ifaces, iface_cfg->name)) {
- VLOG_WARN("%s: database contains duplicate interface name",
- iface_cfg->name);
+ iface = shash_find_data(&info->ifaces, iface_cfg->name);
+ if (iface) {
+ if (iface_cfg == iface->iface_cfg) {
+ VLOG_WARN("%s: interface is in multiple ports "
+ "(%s and %s)",
+ iface_cfg->name,
+ iface->port->port_cfg->name,
+ port->port_cfg->name);
+ } else {
+ /* Log as an error because this violates the database's
+ * uniqueness constraints, so the database server
+ * shouldn't have allowed it. */
+ VLOG_ERR("%s: database contains duplicate interface "
+ "name", iface_cfg->name);
+ }
continue;
}
}
}
sset_destroy(&bridges);
- sset_destroy(&ports);
}
static void
{
}
+struct cmd_show_table {
+ const struct ovsdb_idl_table_class *table;
+ const struct ovsdb_idl_column *name_column;
+ const struct ovsdb_idl_column *columns[3];
+ bool recurse;
+};
+
+static struct cmd_show_table cmd_show_tables[] = {
+ {&ovsrec_table_open_vswitch,
+ NULL,
+ {&ovsrec_open_vswitch_col_manager_options,
+ &ovsrec_open_vswitch_col_bridges,
+ &ovsrec_open_vswitch_col_ovs_version},
+ false},
+
+ {&ovsrec_table_bridge,
+ &ovsrec_bridge_col_name,
+ {&ovsrec_bridge_col_controller,
+ &ovsrec_bridge_col_fail_mode,
+ &ovsrec_bridge_col_ports},
+ false},
+
+ {&ovsrec_table_port,
+ &ovsrec_port_col_name,
+ {&ovsrec_port_col_tag,
+ &ovsrec_port_col_trunks,
+ &ovsrec_port_col_interfaces},
+ false},
+
+ {&ovsrec_table_interface,
+ &ovsrec_interface_col_name,
+ {&ovsrec_interface_col_type,
+ &ovsrec_interface_col_options,
+ NULL},
+ false},
+
+ {&ovsrec_table_controller,
+ &ovsrec_controller_col_target,
+ {&ovsrec_controller_col_is_connected,
+ NULL,
+ NULL},
+ false},
+
+ {&ovsrec_table_manager,
+ &ovsrec_manager_col_target,
+ {&ovsrec_manager_col_is_connected,
+ NULL,
+ NULL},
+ false},
+};
+
+static void
+pre_cmd_show(struct vsctl_context *ctx)
+{
+ struct cmd_show_table *show;
+
+ for (show = cmd_show_tables;
+ show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
+ show++) {
+ size_t i;
+
+ ovsdb_idl_add_table(ctx->idl, show->table);
+ if (show->name_column) {
+ ovsdb_idl_add_column(ctx->idl, show->name_column);
+ }
+ for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
+ const struct ovsdb_idl_column *column = show->columns[i];
+ if (column) {
+ ovsdb_idl_add_column(ctx->idl, column);
+ }
+ }
+ }
+}
+
+static struct cmd_show_table *
+cmd_show_find_table_by_row(const struct ovsdb_idl_row *row)
+{
+ struct cmd_show_table *show;
+
+ for (show = cmd_show_tables;
+ show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
+ show++) {
+ if (show->table == row->table->class) {
+ return show;
+ }
+ }
+ return NULL;
+}
+
+static struct cmd_show_table *
+cmd_show_find_table_by_name(const char *name)
+{
+ struct cmd_show_table *show;
+
+ for (show = cmd_show_tables;
+ show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
+ show++) {
+ if (!strcmp(show->table->name, name)) {
+ return show;
+ }
+ }
+ return NULL;
+}
+
+static void
+cmd_show_row(struct vsctl_context *ctx, const struct ovsdb_idl_row *row,
+ int level)
+{
+ struct cmd_show_table *show = cmd_show_find_table_by_row(row);
+ size_t i;
+
+ ds_put_char_multiple(&ctx->output, ' ', level * 4);
+ if (show && show->name_column) {
+ const struct ovsdb_datum *datum;
+
+ ds_put_format(&ctx->output, "%s ", show->table->name);
+ datum = ovsdb_idl_read(row, show->name_column);
+ ovsdb_datum_to_string(datum, &show->name_column->type, &ctx->output);
+ } else {
+ ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
+ }
+ ds_put_char(&ctx->output, '\n');
+
+ if (!show || show->recurse) {
+ return;
+ }
+
+ show->recurse = true;
+ for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
+ const struct ovsdb_idl_column *column = show->columns[i];
+ const struct ovsdb_datum *datum;
+
+ if (!column) {
+ break;
+ }
+
+ datum = ovsdb_idl_read(row, column);
+ if (column->type.key.type == OVSDB_TYPE_UUID &&
+ column->type.key.u.uuid.refTableName) {
+ struct cmd_show_table *ref_show;
+ size_t j;
+
+ ref_show = cmd_show_find_table_by_name(
+ column->type.key.u.uuid.refTableName);
+ if (ref_show) {
+ for (j = 0; j < datum->n; j++) {
+ const struct ovsdb_idl_row *ref_row;
+
+ ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
+ ref_show->table,
+ &datum->keys[j].uuid);
+ if (ref_row) {
+ cmd_show_row(ctx, ref_row, level + 1);
+ }
+ }
+ continue;
+ }
+ }
+
+ if (!ovsdb_datum_is_default(datum, &column->type)) {
+ ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
+ ds_put_format(&ctx->output, "%s: ", column->name);
+ ovsdb_datum_to_string(datum, &column->type, &ctx->output);
+ ds_put_char(&ctx->output, '\n');
+ }
+ }
+ show->recurse = false;
+}
+
+static void
+cmd_show(struct vsctl_context *ctx)
+{
+ const struct ovsdb_idl_row *row;
+
+ for (row = ovsdb_idl_first_row(ctx->idl, cmd_show_tables[0].table);
+ row; row = ovsdb_idl_next_row(row)) {
+ cmd_show_row(ctx, row, 0);
+ }
+}
+
static void
pre_cmd_emer_reset(struct vsctl_context *ctx)
{
{{&ovsrec_table_port, &ovsrec_port_col_name, &ovsrec_port_col_qos},
{NULL, NULL, NULL}}},
- {&ovsrec_table_monitor,
- {{&ovsrec_table_interface,
- &ovsrec_interface_col_name,
- &ovsrec_interface_col_monitor},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_maintenance_point,
- {{NULL, NULL, NULL},
- {NULL, NULL, NULL}}},
-
{&ovsrec_table_queue,
{{NULL, NULL, NULL},
{NULL, NULL, NULL}}},
struct vsctl_context ctx;
vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
- (c->syntax->run)(&ctx);
+ if (c->syntax->run) {
+ (c->syntax->run)(&ctx);
+ }
vsctl_context_done(&ctx, c);
if (ctx.try_again) {
txn = the_idl_txn = NULL;
switch (status) {
+ case TXN_UNCOMMITTED:
case TXN_INCOMPLETE:
NOT_REACHED();
case TXN_ERROR:
vsctl_fatal("transaction error: %s", error);
+ case TXN_NOT_LOCKED:
+ /* Should not happen--we never call ovsdb_idl_set_lock(). */
+ vsctl_fatal("database not locked");
+
default:
NOT_REACHED();
}
static const struct vsctl_command_syntax all_commands[] = {
/* Open vSwitch commands. */
{"init", 0, 0, NULL, cmd_init, NULL, "", RW},
+ {"show", 0, 0, pre_cmd_show, cmd_show, NULL, "", RO},
/* Bridge commands. */
{"add-br", 1, 3, pre_get_info, cmd_add_br, NULL, "--may-exist", RW},
/* Switch commands. */
{"emer-reset", 0, 0, pre_cmd_emer_reset, cmd_emer_reset, NULL, "", RW},
- /* Parameter 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},
{"find", 1, INT_MAX, pre_cmd_find, cmd_find, NULL, "--columns=", RO},