From aeee85aab0f50f0408672a3150a41caf0a89cc3d Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 9 Feb 2010 11:03:14 -0800 Subject: [PATCH] ovs-vsctl: Add --may-exist option for add-br command. This will be used in the XenServer interface-reconfigure script. --- tests/ovs-vsctl.at | 15 +++++++++ utilities/ovs-vsctl.8.in | 13 ++++++-- utilities/ovs-vsctl.c | 69 ++++++++++++++++++++++++++++++---------- 3 files changed, 79 insertions(+), 18 deletions(-) diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index b140f025..e6e209df 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -167,6 +167,10 @@ AT_KEYWORDS([ovs-vsctl]) OVS_VSCTL_SETUP AT_CHECK([RUN_OVS_VSCTL([add-br a], [add-br b])], [0], [], [], [OVS_VSCTL_CLEANUP]) +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br a b 9])], [1], [], + [ovs-vsctl: "--may-exist add-br a b 9" but a is not a VLAN bridge +], + [OVS_VSCTL_CLEANUP]) CHECK_BRIDGES([a, a, 0], [b, b, 0]) CHECK_PORTS([a]) CHECK_IFACES([a]) @@ -341,8 +345,10 @@ m4_define([OVS_VSCTL_SETUP_SIMPLE_FAKE_CONF], [AT_CHECK( [RUN_OVS_VSCTL( [add-br xenbr0], + [--may-exist add-br xenbr0], [add-port xenbr0 eth0], [add-br xapi1 xenbr0 9], + [--may-exist add-br xapi1 xenbr0 9], [add-port xapi1 eth0.9])], [0], [], [], [OVS_VSCTL_CLEANUP])]) @@ -350,6 +356,15 @@ AT_SETUP([simple fake bridge]) AT_KEYWORDS([ovs-vsctl fake-bridge]) OVS_VSCTL_SETUP OVS_VSCTL_SETUP_SIMPLE_FAKE_CONF +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br xapi1])], [1], [], + [ovs-vsctl: "--may-exist add-br xapi1" but xapi1 is a VLAN bridge for VLAN 9 +], [OVS_VSCTL_CLEANUP]) +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br xapi1 xxx 9])], [1], [], + [ovs-vsctl: "--may-exist add-br xapi1 xxx 9" but xapi1 has the wrong parent xenbr0 +], [OVS_VSCTL_CLEANUP]) +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br xapi1 xenbr0 10])], [1], [], + [ovs-vsctl: "--may-exist add-br xapi1 xenbr0 10" but xapi1 is a VLAN bridge for the wrong VLAN 9 +], [OVS_VSCTL_CLEANUP]) CHECK_BRIDGES([xapi1, xenbr0, 9], [xenbr0, xenbr0, 0]) CHECK_PORTS([xenbr0], [eth0]) CHECK_IFACES([xenbr0], [eth0]) diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index 81daf719..723a3af0 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -132,16 +132,25 @@ initialize the database without executing any other command. .SS "Bridge Commands" These commands examine and manipulate Open vSwitch bridges. . -.IP "\fBadd\-br \fIbridge\fR" +.IP "[\fB\-\-may\-exist\fR] \fBadd\-br \fIbridge\fR" Creates a new bridge named \fIbridge\fR. Initially the bridge will have no ports (other than \fIbridge\fR itself). +.IP +Without \fB\-\-may\-exist\fR, attempting to create a bridge that +exists is an error. With \fB\-\-may\-exist\fR, \fIbridge\fR may +already exist (but it must be a real bridge, not a VLAN bridge). . -.IP "\fBadd\-br \fIbridge parent vlan\fR" +.IP "[\fB\-\-may\-exist\fR] \fBadd\-br \fIbridge parent vlan\fR" Creates a ``fake bridge'' named \fIbridge\fR within the existing Open vSwitch bridge \fIparent\fR, which must already exist and must not itself be a fake bridge. The new fake bridge will be on 802.1Q VLAN \fIvlan\fR, which must be an integer between 1 and 4095. Initially \fIbridge\fR will have no ports (other than \fIbridge\fR itself). +.IP +Without \fB\-\-may\-exist\fR, attempting to create a bridge that +exists is an error. With \fB\-\-may\-exist\fR, \fIbridge\fR may +already exist (but it must have the specified \fIvlan\fR and +\fIparent\fR). . .IP "[\fB\-\-if\-exists\fR] \fBdel\-br \fIbridge\fR" Deletes \fIbridge\fR and all of its ports. If \fIbridge\fR is a real diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 18f3fd64..98b7cea7 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -807,17 +807,65 @@ cmd_init(struct vsctl_context *ctx UNUSED) static void cmd_add_br(struct vsctl_context *ctx) { + bool may_exist = shash_find(&ctx->options, "--may-exist") != 0; const char *br_name = ctx->argv[1]; + const char *parent_name = ctx->argc > 2 ? ctx->argv[2] : NULL; + int vlan = ctx->argc > 3 ? atoi(ctx->argv[3]) : 0; struct vsctl_info info; + 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); @@ -831,22 +879,13 @@ cmd_add_br(struct vsctl_context *ctx) 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"); @@ -867,8 +906,6 @@ cmd_add_br(struct vsctl_context *ctx) ovsrec_port_set_tag(port, &tag, 1); bridge_insert_port(br, port); - } else { - NOT_REACHED(); } free_info(&info); @@ -2362,7 +2399,7 @@ static const struct vsctl_command_syntax all_commands[] = { {"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, ""}, -- 2.30.2