#include "table.h"
#include "timeval.h"
#include "util.h"
+#include "vconn.h"
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(vsctl);
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 *);
-static void do_vsctl(const char *args,
- struct vsctl_command *, size_t n_commands,
- struct ovsdb_idl *);
+static enum ovsdb_idl_txn_status do_vsctl(const char *args,
+ struct vsctl_command *, size_t n,
+ struct ovsdb_idl *);
static const struct vsctl_table_class *get_table(const char *table_name);
static void set_column(const struct vsctl_table_class *,
main(int argc, char *argv[])
{
extern struct vlog_module VLM_reconnect;
+ enum ovsdb_idl_txn_status status;
struct ovsdb_idl *idl;
struct vsctl_command *commands;
size_t n_commands;
run_prerequisites(commands, n_commands, idl);
/* Now execute the commands. */
+ status = TXN_AGAIN_WAIT;
for (;;) {
- if (ovsdb_idl_run(idl)) {
- do_vsctl(args, commands, n_commands, idl);
+ if (ovsdb_idl_run(idl) || status == TXN_AGAIN_NOW) {
+ status = do_vsctl(args, commands, n_commands, idl);
}
- ovsdb_idl_wait(idl);
- poll_block();
+ if (status != TXN_AGAIN_NOW) {
+ ovsdb_idl_wait(idl);
+ poll_block();
+ }
}
}
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);
iface-to-br IFACE print name of bridge that contains IFACE\n\
\n\
Controller commands:\n\
- get-controller BRIDGE print the controller for BRIDGE\n\
- del-controller BRIDGE delete the controller for BRIDGE\n\
- set-controller BRIDGE TARGET set the controller for BRIDGE to TARGET\n\
+ get-controller BRIDGE print the controllers for BRIDGE\n\
+ del-controller BRIDGE delete the controllers for BRIDGE\n\
+ set-controller BRIDGE TARGET... set the controllers for BRIDGE\n\
get-fail-mode BRIDGE print the fail-mode for BRIDGE\n\
del-fail-mode BRIDGE delete the fail-mode for BRIDGE\n\
set-fail-mode BRIDGE MODE set the fail-mode for BRIDGE to MODE\n\
\n\
Manager commands:\n\
- get-manager print all manager(s)\n\
- del-manager delete all manager(s)\n\
- set-manager TARGET... set the list of manager(s) to TARGET(s)\n\
+ get-manager print the managers\n\
+ del-manager delete the managers\n\
+ set-manager TARGET... set the list of managers to TARGET...\n\
\n\
SSL commands:\n\
get-ssl print the SSL configuration\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
controllers = xmalloc(n * sizeof *controllers);
for (i = 0; i < n; i++) {
+ if (vconn_verify_name(targets[i]) && pvconn_verify_name(targets[i])) {
+ VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
+ }
controllers[i] = ovsrec_controller_insert(txn);
ovsrec_controller_set_target(controllers[i], targets[i]);
}
/* Insert each manager in a new row in Manager table. */
managers = xmalloc(n * sizeof *managers);
for (i = 0; i < n; i++) {
+ if (stream_verify_name(targets[i]) && pstream_verify_name(targets[i])) {
+ VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
+ }
managers[i] = ovsrec_manager_insert(ctx->txn);
ovsrec_manager_set_target(managers[i], targets[i]);
}
}
}
-static void
+static enum ovsdb_idl_txn_status
do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
struct ovsdb_idl *idl)
{
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) {
+ status = TXN_AGAIN_WAIT;
goto try_again;
}
}
txn = the_idl_txn = NULL;
switch (status) {
+ case TXN_UNCOMMITTED:
case TXN_INCOMPLETE:
NOT_REACHED();
case TXN_SUCCESS:
break;
- case TXN_TRY_AGAIN:
+ case TXN_AGAIN_WAIT:
+ case TXN_AGAIN_NOW:
goto try_again;
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();
}
free(c->table);
}
free(error);
+
+ return status;
}
static const struct vsctl_command_syntax all_commands[] = {
/* 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},