/* --oneline: Write each command's output as a single line? */
static bool oneline;
+/* --dry-run: Do not commit any changes. */
+static bool dry_run;
+
+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[]);
}
}
if (!n_commands) {
- ovs_fatal(0, "missing command name (use --help for help)");
+ vsctl_fatal("missing command name (use --help for help)");
}
- /* Now execut the commands. */
+ /* Now execute the commands. */
idl = ovsdb_idl_create(db, &ovsrec_idl_class);
seqno = ovsdb_idl_get_seqno(idl);
trials = 0;
new_seqno = ovsdb_idl_get_seqno(idl);
if (new_seqno != seqno) {
if (++trials > 5) {
- ovs_fatal(0, "too many database inconsistency failures");
+ vsctl_fatal("too many database inconsistency failures");
}
do_vsctl(argc - optind, argv + optind, idl);
seqno = new_seqno;
}
}
+static void
+vsctl_fatal(const char *format, ...)
+{
+ char *message;
+ va_list args;
+
+ va_start(args, format);
+ message = xvasprintf(format, args);
+ va_end(args);
+
+ vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
+ VLOG_ERR("%s", message);
+ ovs_fatal(0, "%s", message);
+}
+
static void
parse_options(int argc, char *argv[])
{
enum {
OPT_DB = UCHAR_MAX + 1,
OPT_ONELINE,
- OPT_NO_SYSLOG
+ OPT_NO_SYSLOG,
+ OPT_NO_WAIT,
+ OPT_DRY_RUN
};
static struct option long_options[] = {
{"db", required_argument, 0, OPT_DB},
{"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
+ {"no-wait", no_argument, 0, OPT_NO_WAIT},
+ {"dry-run", no_argument, 0, OPT_DRY_RUN},
{"oneline", no_argument, 0, OPT_ONELINE},
{"verbose", optional_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
break;
+ case OPT_NO_WAIT:
+ /* XXX not yet implemented */
+ break;
+
+ case OPT_DRY_RUN:
+ dry_run = true;
+ break;
+
case 'h':
usage();
struct vsctl_port *port;
if (shash_find(&info->bridges, name)) {
- ovs_fatal(0, "%s because a bridge named %s already exists", msg, name);
+ vsctl_fatal("%s because a bridge named %s already exists",
+ msg, name);
}
port = shash_find_data(&info->ports, name);
if (port) {
- ovs_fatal(0, "%s because a port named %s already exists on bridge %s",
- msg, name, port->bridge->name);
+ vsctl_fatal("%s because a port named %s already exists on "
+ "bridge %s", msg, name, port->bridge->name);
}
iface = shash_find_data(&info->ifaces, name);
if (iface) {
- ovs_fatal(0, "%s because an interface named %s already exists "
- "on bridge %s", msg, name, iface->port->bridge->name);
+ vsctl_fatal("%s because an interface named %s already exists "
+ "on bridge %s", msg, name, iface->port->bridge->name);
}
free(msg);
}
static struct vsctl_bridge *
-find_bridge(struct vsctl_info *info, const char *name)
+find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
{
struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
- if (!br) {
- ovs_fatal(0, "no bridge named %s", name);
+ if (must_exist && !br) {
+ vsctl_fatal("no bridge named %s", name);
}
return br;
}
static struct vsctl_port *
-find_port(struct vsctl_info *info, const char *name)
+find_port(struct vsctl_info *info, const char *name, bool must_exist)
{
struct vsctl_port *port = shash_find_data(&info->ports, name);
- if (!port || !strcmp(name, port->bridge->name)) {
- ovs_fatal(0, "no port named %s", name);
+ if (port && !strcmp(name, port->bridge->name)) {
+ port = NULL;
+ }
+ if (must_exist && !port) {
+ vsctl_fatal("no port named %s", name);
}
return port;
}
static struct vsctl_iface *
-find_iface(struct vsctl_info *info, const char *name)
+find_iface(struct vsctl_info *info, const char *name, bool must_exist)
{
struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
- if (!iface || !strcmp(name, iface->port->bridge->name)) {
- ovs_fatal(0, "no interface named %s", name);
+ if (iface && !strcmp(name, iface->port->bridge->name)) {
+ iface = NULL;
+ }
+ if (must_exist && !iface) {
+ vsctl_fatal("no interface named %s", name);
}
return iface;
}
free(bridges);
}
+static void
+cmd_init(struct vsctl_context *ctx UNUSED)
+{
+}
+
static void
cmd_add_br(struct vsctl_context *ctx)
{
ovs_insert_bridge(ctx->ovs, br);
} else if (ctx->argc == 3) {
- ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", ctx->argv[0]);
+ vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
+ ctx->argv[0]);
} else if (ctx->argc == 4) {
const char *parent_name = ctx->argv[2];
int vlan = atoi(ctx->argv[3]);
int64_t tag = vlan;
if (vlan < 1 || vlan > 4095) {
- ovs_fatal(0, "%s: vlan must be between 1 and 4095", ctx->argv[0]);
+ vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
}
- parent = shash_find_data(&info.bridges, parent_name);
+ parent = find_bridge(&info, parent_name, false);
if (parent && parent->vlan) {
- ovs_fatal(0, "cannot create brdige with fake bridge as parent");
+ vsctl_fatal("cannot create brdige with fake bridge as parent");
}
if (!parent) {
- ovs_fatal(0, "parent bridge %s does not exist", parent_name);
+ vsctl_fatal("parent bridge %s does not exist", parent_name);
}
br = parent->br_cfg;
static void
cmd_del_br(struct vsctl_context *ctx)
{
- struct shash_node *node;
- struct vsctl_info info;
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
struct vsctl_bridge *bridge;
+ struct vsctl_info info;
get_info(ctx->ovs, &info);
- bridge = find_bridge(&info, ctx->argv[1]);
- SHASH_FOR_EACH (node, &info.ports) {
- struct vsctl_port *port = node->data;
- if (port->bridge == bridge
- || !strcmp(port->port_cfg->name, bridge->name)) {
- del_port(&info, port);
+ bridge = find_bridge(&info, ctx->argv[1], must_exist);
+ if (bridge) {
+ struct shash_node *node;
+
+ SHASH_FOR_EACH (node, &info.ports) {
+ struct vsctl_port *port = node->data;
+ if (port->bridge == bridge
+ || !strcmp(port->port_cfg->name, bridge->name)) {
+ del_port(&info, port);
+ }
+ }
+ if (bridge->br_cfg) {
+ ovsrec_bridge_delete(bridge->br_cfg);
+ ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
}
- }
- if (bridge->br_cfg) {
- ovsrec_bridge_delete(bridge->br_cfg);
- ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
}
free_info(&info);
}
struct vsctl_info info;
get_info(ctx->ovs, &info);
- if (!shash_find_data(&info.bridges, ctx->argv[1])) {
+ if (!find_bridge(&info, ctx->argv[1], false)) {
exit(2);
}
free_info(&info);
size_t n;
get_info(ctx->ovs, &info);
- bridge = find_bridge(&info, ctx->argv[1]);
+ bridge = find_bridge(&info, ctx->argv[1], true);
if (bridge->br_cfg) {
set_external_id(bridge->br_cfg->key_external_ids,
bridge->br_cfg->value_external_ids,
struct vsctl_bridge *bridge;
get_info(ctx->ovs, &info);
- bridge = find_bridge(&info, ctx->argv[1]);
+ bridge = find_bridge(&info, ctx->argv[1], true);
if (bridge->br_cfg) {
get_external_id(bridge->br_cfg->key_external_ids,
bridge->br_cfg->value_external_ids,
struct svec ports;
get_info(ctx->ovs, &info);
- br = find_bridge(&info, ctx->argv[1]);
+ br = find_bridge(&info, ctx->argv[1], true);
svec_init(&ports);
SHASH_FOR_EACH (node, &info.ports) {
check_conflicts(&info, port_name,
xasprintf("cannot create a port named %s", port_name));
/* XXX need to check for conflicts on interfaces too */
- bridge = find_bridge(&info, br_name);
+ bridge = find_bridge(&info, br_name, true);
ifaces = xmalloc(n_ifaces * sizeof *ifaces);
for (i = 0; i < n_ifaces; i++) {
static void
cmd_del_port(struct vsctl_context *ctx)
{
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
struct vsctl_info info;
get_info(ctx->ovs, &info);
if (ctx->argc == 2) {
- struct vsctl_port *port = find_port(&info, ctx->argv[1]);
- del_port(&info, port);
- } else if (ctx->argc == 3) {
- struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1]);
- struct vsctl_port *port = find_port(&info, ctx->argv[2]);
-
- if (port->bridge == bridge) {
+ struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
+ if (port) {
del_port(&info, port);
- } else if (port->bridge->parent == bridge) {
- ovs_fatal(0, "bridge %s does not have a port %s (although its "
- "parent bridge %s does)",
- ctx->argv[1], ctx->argv[2], bridge->parent->name);
- } else {
- ovs_fatal(0, "bridge %s does not have a port %s",
- ctx->argv[1], ctx->argv[2]);
+ }
+ } else if (ctx->argc == 3) {
+ struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
+ struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
+
+ if (port) {
+ if (port->bridge == bridge) {
+ del_port(&info, port);
+ } else if (port->bridge->parent == bridge) {
+ vsctl_fatal("bridge %s does not have a port %s (although its "
+ "parent bridge %s does)",
+ ctx->argv[1], ctx->argv[2], bridge->parent->name);
+ } else {
+ vsctl_fatal("bridge %s does not have a port %s",
+ ctx->argv[1], ctx->argv[2]);
+ }
}
}
free_info(&info);
struct vsctl_info info;
get_info(ctx->ovs, &info);
- port = find_port(&info, ctx->argv[1]);
+ port = find_port(&info, ctx->argv[1], true);
ds_put_format(&ctx->output, "%s\n", port->bridge->name);
free_info(&info);
}
size_t n;
get_info(ctx->ovs, &info);
- port = find_port(&info, ctx->argv[1]);
+ port = find_port(&info, ctx->argv[1], true);
set_external_id(port->port_cfg->key_external_ids,
port->port_cfg->value_external_ids,
port->port_cfg->n_external_ids,
struct vsctl_port *port;
get_info(ctx->ovs, &info);
- port = find_port(&info, ctx->argv[1]);
+ port = find_port(&info, ctx->argv[1], true);
get_external_id(port->port_cfg->key_external_ids,
port->port_cfg->value_external_ids,
port->port_cfg->n_external_ids,
struct vsctl_info info;
get_info(ctx->ovs, &info);
- bridge = find_bridge(&info, ctx->argv[1]);
+ bridge = find_bridge(&info, ctx->argv[1], true);
ds_put_format(&ctx->output, "%d\n", bridge->vlan);
free_info(&info);
}
struct vsctl_info info;
get_info(ctx->ovs, &info);
- bridge = find_bridge(&info, ctx->argv[1]);
+ bridge = find_bridge(&info, ctx->argv[1], true);
if (bridge->parent) {
bridge = bridge->parent;
}
struct svec ifaces;
get_info(ctx->ovs, &info);
- br = find_bridge(&info, ctx->argv[1]);
+ br = find_bridge(&info, ctx->argv[1], true);
svec_init(&ifaces);
SHASH_FOR_EACH (node, &info.ifaces) {
struct vsctl_info info;
get_info(ctx->ovs, &info);
- iface = find_iface(&info, ctx->argv[1]);
+ iface = find_iface(&info, ctx->argv[1], true);
ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
free_info(&info);
}
size_t n;
get_info(ctx->ovs, &info);
- iface = find_iface(&info, ctx->argv[1]);
+ iface = find_iface(&info, ctx->argv[1], true);
set_external_id(iface->iface_cfg->key_external_ids,
iface->iface_cfg->value_external_ids,
iface->iface_cfg->n_external_ids,
struct vsctl_iface *iface;
get_info(ctx->ovs, &info);
- iface = find_iface(&info, ctx->argv[1]);
+ iface = find_iface(&info, ctx->argv[1], true);
get_external_id(iface->iface_cfg->key_external_ids,
iface->iface_cfg->value_external_ids,
iface->iface_cfg->n_external_ids,
int n_output;
int i, start;
+ txn = ovsdb_idl_txn_create(idl);
+ if (dry_run) {
+ ovsdb_idl_txn_set_dry_run(txn);
+ }
+
ovs = ovsrec_open_vswitch_first(idl);
if (!ovs) {
- /* XXX it would be more user-friendly to create a record ourselves
- * (while verifying that the table is empty before doing so). */
- ovs_fatal(0, "%s: database does not contain any Open vSwitch "
- "configuration", db);
+ /* XXX add verification that table is empty */
+ ovs = ovsrec_open_vswitch_insert(txn);
}
- txn = ovsdb_idl_txn_create(idl);
output = xmalloc(argc * sizeof *output);
n_output = 0;
for (start = i = 0; i <= argc; i++) {
case TXN_ABORTED:
/* Should not happen--we never call ovsdb_idl_txn_abort(). */
- ovs_fatal(0, "transaction aborted");
+ vsctl_fatal("transaction aborted");
case TXN_SUCCESS:
break;
return;
case TXN_ERROR:
- ovs_fatal(0, "transaction error");
+ vsctl_fatal("transaction error");
default:
NOT_REACHED();
get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
{
static const struct vsctl_command all_commands[] = {
+ /* Open vSwitch commands. */
+ {"init", 0, 0, cmd_init, ""},
+
/* Bridge commands. */
{"add-br", 1, 3, cmd_add_br, ""},
- {"del-br", 1, 1, cmd_del_br, ""},
+ {"del-br", 1, 1, cmd_del_br, "--if-exists"},
{"list-br", 0, 0, cmd_list_br, ""},
{"br-exists", 1, 1, cmd_br_exists, ""},
{"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
{"list-ports", 1, 1, cmd_list_ports, ""},
{"add-port", 2, 2, cmd_add_port, ""},
{"add-bond", 4, INT_MAX, cmd_add_bond, ""},
- {"del-port", 1, 2, cmd_del_port, ""},
+ {"del-port", 1, 2, cmd_del_port, "--if-exists"},
{"port-to-br", 1, 1, cmd_port_to_br, ""},
{"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
{"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
break;
}
if (!shash_add_once(&ctx->options, argv[i], NULL)) {
- ovs_fatal(0, "'%s' option specified multiple times", argv[i]);
+ vsctl_fatal("'%s' option specified multiple times", argv[i]);
}
}
if (i == argc) {
- ovs_fatal(0, "missing command name");
+ vsctl_fatal("missing command name");
}
for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
const char *s = strstr(p->options, node->name);
int end = s ? s[strlen(node->name)] : EOF;
if (end != ',' && end != ' ' && end != '\0') {
- ovs_fatal(0, "'%s' command has no '%s' option",
- argv[i], node->name);
+ vsctl_fatal("'%s' command has no '%s' option",
+ argv[i], node->name);
}
}
n_arg = argc - i - 1;
if (n_arg < p->min_args) {
- ovs_fatal(0, "'%s' command requires at least %d arguments",
- p->name, p->min_args);
+ vsctl_fatal("'%s' command requires at least %d arguments",
+ p->name, p->min_args);
} else if (n_arg > p->max_args) {
- ovs_fatal(0, "'%s' command takes at most %d arguments",
- p->name, p->max_args);
+ vsctl_fatal("'%s' command takes at most %d arguments",
+ p->name, p->max_args);
} else {
ctx->argc = n_arg + 1;
ctx->argv = &argv[i];
}
}
- ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
+ vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
}
static void