vsctl_fatal("'%s' command requires at least %d arguments",
p->name, p->min_args);
} else if (n_arg > p->max_args) {
+ int j;
+
+ for (j = i + 1; j < argc; j++) {
+ if (argv[j][0] == '-') {
+ vsctl_fatal("'%s' command takes at most %d arguments "
+ "(note that options must precede command "
+ "names and follow a \"--\" argument)",
+ p->name, p->max_args);
+ }
+ }
+
vsctl_fatal("'%s' command takes at most %d arguments",
p->name, p->max_args);
} else {
struct ovsrec_controller *ctrl;
};
+static char *
+vsctl_context_to_string(const struct vsctl_context *ctx)
+{
+ const struct shash_node *node;
+ struct svec words;
+ char *s;
+ int i;
+
+ svec_init(&words);
+ SHASH_FOR_EACH (node, &ctx->options) {
+ svec_add(&words, node->name);
+ }
+ for (i = 0; i < ctx->argc; i++) {
+ svec_add(&words, ctx->argv[i]);
+ }
+ svec_terminate(&words);
+
+ s = process_escape_args(words.names);
+
+ svec_destroy(&words);
+
+ return s;
+}
+
static struct vsctl_bridge *
add_bridge(struct vsctl_info *b,
struct ovsrec_bridge *br_cfg, const char *name,
}
static void
-cmd_init(struct vsctl_context *ctx UNUSED)
+cmd_init(struct vsctl_context *ctx OVS_UNUSED)
{
}
static void
cmd_add_br(struct vsctl_context *ctx)
{
- const char *br_name = ctx->argv[1];
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+ const char *br_name, *parent_name;
struct vsctl_info info;
+ int vlan;
+
+ br_name = ctx->argv[1];
+ if (ctx->argc == 2) {
+ parent_name = NULL;
+ vlan = 0;
+ } else if (ctx->argc == 4) {
+ parent_name = ctx->argv[2];
+ vlan = atoi(ctx->argv[3]);
+ if (vlan < 1 || vlan > 4095) {
+ vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
+ }
+ } else {
+ vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
+ ctx->argv[0]);
+ }
get_info(ctx->ovs, &info);
+ if (may_exist) {
+ struct vsctl_bridge *br;
+
+ br = find_bridge(&info, br_name, false);
+ if (br) {
+ if (!parent_name) {
+ if (br->parent) {
+ vsctl_fatal("\"--may-exist add-br %s\" but %s is "
+ "a VLAN bridge for VLAN %d",
+ br_name, br_name, br->vlan);
+ }
+ } else {
+ if (!br->parent) {
+ vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
+ "is not a VLAN bridge",
+ br_name, parent_name, vlan, br_name);
+ } else if (strcmp(br->parent->name, parent_name)) {
+ vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
+ "has the wrong parent %s",
+ br_name, parent_name, vlan,
+ br_name, br->parent->name);
+ } else if (br->vlan != vlan) {
+ vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
+ "is a VLAN bridge for the wrong VLAN %d",
+ br_name, parent_name, vlan, br_name, br->vlan);
+ }
+ }
+ return;
+ }
+ }
check_conflicts(&info, br_name,
xasprintf("cannot create a bridge named %s", br_name));
- if (ctx->argc == 2) {
- struct ovsrec_bridge *br;
+ if (!parent_name) {
struct ovsrec_port *port;
struct ovsrec_interface *iface;
+ struct ovsrec_bridge *br;
iface = ovsrec_interface_insert(ctx->txn);
ovsrec_interface_set_name(iface, br_name);
ovsrec_bridge_set_ports(br, &port, 1);
ovs_insert_bridge(ctx->ovs, br);
- } else if (ctx->argc == 3) {
- 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]);
- struct ovsrec_bridge *br;
+ } else {
struct vsctl_bridge *parent;
struct ovsrec_port *port;
struct ovsrec_interface *iface;
+ struct ovsrec_bridge *br;
int64_t tag = vlan;
- if (vlan < 1 || vlan > 4095) {
- vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
- }
-
parent = find_bridge(&info, parent_name, false);
if (parent && parent->vlan) {
vsctl_fatal("cannot create bridge with fake bridge as parent");
ovsrec_port_set_tag(port, &tag, 1);
bridge_insert_port(br, port);
- } else {
- NOT_REACHED();
}
free_info(&info);
static void
add_port(struct vsctl_context *ctx,
- const char *br_name, const char *port_name, bool fake_iface,
+ const char *br_name, const char *port_name,
+ bool may_exist, bool fake_iface,
char *iface_names[], int n_ifaces)
{
struct vsctl_info info;
size_t i;
get_info(ctx->ovs, &info);
+ if (may_exist) {
+ struct vsctl_port *port;
+
+ port = find_port(&info, port_name, false);
+ if (port) {
+ struct svec want_names, have_names;
+ size_t i;
+
+ svec_init(&want_names);
+ for (i = 0; i < n_ifaces; i++) {
+ svec_add(&want_names, iface_names[i]);
+ }
+ svec_sort(&want_names);
+
+ svec_init(&have_names);
+ for (i = 0; i < port->port_cfg->n_interfaces; i++) {
+ svec_add(&have_names, port->port_cfg->interfaces[i]->name);
+ }
+ svec_sort(&have_names);
+
+ if (strcmp(port->bridge->name, br_name)) {
+ char *command = vsctl_context_to_string(ctx);
+ vsctl_fatal("\"%s\" but %s is actually attached to bridge %s",
+ command, port_name, port->bridge->name);
+ }
+
+ if (!svec_equal(&want_names, &have_names)) {
+ char *have_names_string = svec_join(&have_names, ", ", "");
+ char *command = vsctl_context_to_string(ctx);
+
+ vsctl_fatal("\"%s\" but %s actually has interface(s) %s",
+ command, port_name, have_names_string);
+ }
+
+ svec_destroy(&want_names);
+ svec_destroy(&have_names);
+
+ return;
+ }
+ }
check_conflicts(&info, port_name,
xasprintf("cannot create a port named %s", port_name));
- /* XXX need to check for conflicts on interfaces too */
+ for (i = 0; i < n_ifaces; i++) {
+ check_conflicts(&info, iface_names[i],
+ xasprintf("cannot create an interface named %s",
+ iface_names[i]));
+ }
bridge = find_bridge(&info, br_name, true);
ifaces = xmalloc(n_ifaces * sizeof *ifaces);
static void
cmd_add_port(struct vsctl_context *ctx)
{
- add_port(ctx, ctx->argv[1], ctx->argv[2], false, &ctx->argv[2], 1);
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+
+ add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, false,
+ &ctx->argv[2], 1);
}
static void
cmd_add_bond(struct vsctl_context *ctx)
{
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
bool fake_iface = shash_find(&ctx->options, "--fake-iface");
- add_port(ctx, ctx->argv[1], ctx->argv[2], fake_iface,
+ add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, fake_iface,
&ctx->argv[3], ctx->argc - 3);
}
static void
cmd_create(struct vsctl_context *ctx)
{
- bool force = shash_find(&ctx->options, "--force");
const char *table_name = ctx->argv[1];
const struct vsctl_table_class *table;
const struct ovsdb_idl_row *row;
int i;
- if (!force) {
- vsctl_fatal("\"create\" requires --force");
- }
-
table = get_table(table_name);
row = ovsdb_idl_txn_insert(ctx->txn, table->class);
for (i = 2; i < ctx->argc; i++) {
static void
cmd_destroy(struct vsctl_context *ctx)
{
- bool force = shash_find(&ctx->options, "--force");
bool must_exist = !shash_find(&ctx->options, "--if-exists");
const char *table_name = ctx->argv[1];
const struct vsctl_table_class *table;
int i;
- if (!force) {
- vsctl_fatal("\"destroy\" requires --force");
- }
-
table = get_table(table_name);
for (i = 2; i < ctx->argc; i++) {
const struct ovsdb_idl_row *row;
{"init", 0, 0, cmd_init, NULL, ""},
/* Bridge commands. */
- {"add-br", 1, 3, cmd_add_br, NULL, ""},
+ {"add-br", 1, 3, cmd_add_br, NULL, "--may-exist"},
{"del-br", 1, 1, cmd_del_br, NULL, "--if-exists"},
{"list-br", 0, 0, cmd_list_br, NULL, ""},
{"br-exists", 1, 1, cmd_br_exists, NULL, ""},
/* Port commands. */
{"list-ports", 1, 1, cmd_list_ports, NULL, ""},
- {"add-port", 2, 2, cmd_add_port, NULL, ""},
- {"add-bond", 4, INT_MAX, cmd_add_bond, NULL, "--fake-iface"},
+ {"add-port", 2, 2, cmd_add_port, NULL, "--may-exist"},
+ {"add-bond", 4, INT_MAX, cmd_add_bond, NULL, "--may-exist,--fake-iface"},
{"del-port", 1, 2, cmd_del_port, NULL, "--if-exists"},
{"port-to-br", 1, 1, cmd_port_to_br, NULL, ""},
/* Parameter commands. */
{"get", 3, INT_MAX, cmd_get, NULL, "--if-exists"},
{"list", 1, INT_MAX, cmd_list, NULL, ""},
- {"create", 2, INT_MAX, cmd_create, post_create, "--force"},
- {"destroy", 1, INT_MAX, cmd_destroy, NULL, "--force,--if-exists"},
{"set", 3, INT_MAX, cmd_set, NULL, ""},
{"add", 4, INT_MAX, cmd_add, NULL, ""},
{"remove", 4, INT_MAX, cmd_remove, NULL, ""},
{"clear", 3, INT_MAX, cmd_clear, NULL, ""},
+ {"create", 2, INT_MAX, cmd_create, post_create, ""},
+ {"destroy", 1, INT_MAX, cmd_destroy, NULL, "--if-exists"},
{NULL, 0, 0, NULL, NULL, NULL},
};