From 460aad80489c8f4d253dc4a22117e81a103eb611 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 10 Dec 2009 14:07:33 -0800 Subject: [PATCH] ovs-vsctl: Add --if-exists options to del-br, del-port commands. These options make it easier to reimplement interface-reconfigure using ovs-vsctl. --- tests/ovs-vsctl.at | 37 +++++++++++++++------- utilities/ovs-vsctl.8.in | 34 +++++++++++++++++--- utilities/ovs-vsctl.c | 67 +++++++++++++++++++++++----------------- 3 files changed, 93 insertions(+), 45 deletions(-) diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index a76fd48c..cd4cab3d 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -23,14 +23,18 @@ dnl RUN_OVS_VSCTL(COMMAND, ...) dnl dnl Executes each ovs-vsctl COMMAND. m4_define([RUN_OVS_VSCTL], - [m4_foreach([command], [$@], [ovs-vsctl -vreconnect:ANY:emer --db=unix:socket command + [m4_foreach([command], [$@], [ovs-vsctl -vreconnect:ANY:emer --db=unix:socket -- command +])]) +m4_define([RUN_OVS_VSCTL_ONELINE], + [m4_foreach([command], [$@], [ovs-vsctl -vreconnect:ANY:emer --db=unix:socket --oneline -- command ])]) dnl RUN_OVS_VSCTL_TOGETHER(COMMAND, ...) dnl dnl Executes each ovs-vsctl COMMAND in a single run of ovs-vsctl. m4_define([RUN_OVS_VSCTL_TOGETHER], - [ovs-vsctl -vreconnect:ANY:emer --db=unix:socket m4_join([ -- ], $@)]) + [ovs-vsctl -vreconnect:ANY:emer --db=unix:socket --oneline dnl +m4_foreach([command], [$@], [ -- command])]) dnl CHECK_BRIDGES([BRIDGE, PARENT, VLAN], ...) dnl @@ -48,7 +52,7 @@ m4_define([_CHECK_BRIDGE], # (This particular test is interesting with --oneline because it returns # an integer instead of a string and that can cause type mismatches inside # python if not done carefully.) - AT_CHECK([RUN_OVS_VSCTL([--oneline br-to-vlan $1])], [0], [$3 + AT_CHECK([RUN_OVS_VSCTL_ONELINE([br-to-vlan $1])], [0], [$3 ], [], [OVS_VSCTL_CLEANUP]) # Check multiple queries in a single run. @@ -68,7 +72,7 @@ m4_define([CHECK_BRIDGES], dnl Check that the bridges appear on list-br, with --oneline. AT_CHECK( - [RUN_OVS_VSCTL([--oneline list-br])], + [RUN_OVS_VSCTL_ONELINE([list-br])], [0], [m4_join([\n], m4_foreach([brinfo], [$@], [m4_car(brinfo),])) ], @@ -104,7 +108,7 @@ m4_define([CHECK_PORTS], dnl Check ports with --oneline. AT_CHECK( - [RUN_OVS_VSCTL([--oneline list-ports $1])], + [RUN_OVS_VSCTL_ONELINE([list-ports $1])], [0], [m4_join([\n], m4_shift($@)) ], @@ -195,6 +199,7 @@ AT_KEYWORDS([ovs-vsctl]) OVS_VSCTL_SETUP AT_CHECK([RUN_OVS_VSCTL( [add-br a], + [--if-exists del-br b], [add-port a a1], [add-port a a2])], [0], [], [], [OVS_VSCTL_CLEANUP]) CHECK_BRIDGES([a, a, 0]) @@ -223,7 +228,14 @@ AT_CHECK([RUN_OVS_VSCTL_TOGETHER( [add-br b], [add-port a a1], [add-port b b1], - [del-br a])], [0], [], [], [OVS_VSCTL_CLEANUP]) + [--if-exists del-port b b2], + [del-br a])], [0], [ + + + + + +], [], [OVS_VSCTL_CLEANUP]) CHECK_BRIDGES([b, b, 0]) CHECK_PORTS([b], [b1]) CHECK_IFACES([b], [b1]) @@ -265,7 +277,10 @@ OVS_VSCTL_SETUP AT_CHECK([RUN_OVS_VSCTL_TOGETHER( [add-br a], [add-bond a bond0 a1 a2 a3], - [del-port bond0])], [0], [], [], [OVS_VSCTL_CLEANUP]) + [del-port bond0])], [0], [ + + +], [], [OVS_VSCTL_CLEANUP]) CHECK_BRIDGES([a, a, 0]) CHECK_PORTS([a]) OVS_VSCTL_CLEANUP @@ -275,7 +290,7 @@ AT_SETUP([external IDs]) AT_KEYWORDS([ovs-vsctl]) OVS_VSCTL_SETUP AT_CHECK([RUN_OVS_VSCTL_TOGETHER( - [--oneline add-br a], + [add-br a], [add-port a a1], [add-bond a bond0 a2 a3], [br-set-external-id a key0 value0], @@ -312,7 +327,7 @@ key2=value2\nkey3=value3 key4=value4 ], [], [OVS_VSCTL_CLEANUP]) AT_CHECK([RUN_OVS_VSCTL_TOGETHER( - [--oneline br-get-external-id a], + [br-get-external-id a], [port-get-external-id a1], [iface-get-external-id a2], [iface-get-external-id a3])], [0], @@ -376,7 +391,7 @@ AT_KEYWORDS([ovs-vsctl fake-bridge]) OVS_VSCTL_SETUP OVS_VSCTL_SETUP_SIMPLE_FAKE_CONF AT_CHECK([RUN_OVS_VSCTL_TOGETHER( - [--oneline br-set-external-id xenbr0 key0 value0], + [br-set-external-id xenbr0 key0 value0], [br-set-external-id xapi1 key1 value1], [br-get-external-id xenbr0], [br-get-external-id xenbr0 key0], @@ -421,7 +436,7 @@ AT_SETUP([fake bridge on bond + del-br fake bridge]) AT_KEYWORDS([ovs-vsctl fake-bridge]) OVS_VSCTL_SETUP OVS_VSCTL_SETUP_BOND_FAKE_CONF -AT_CHECK([RUN_OVS_VSCTL([--oneline del-br xapi2])], [0], [ +AT_CHECK([RUN_OVS_VSCTL_ONELINE([del-br xapi2])], [0], [ ], [], [OVS_VSCTL_CLEANUP]) CHECK_BRIDGES([xapi1, xapi1, 0]) CHECK_PORTS([xapi1], [bond0]) diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index db0b9b91..46bbbe28 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -11,7 +11,7 @@ ovs\-vsctl \- utility for querying and configuring \fBovs\-vswitchd\fR . .SH SYNOPSIS -\fBovs\-vsctl\fR [\fIoptions\fR] \fIcommand \fR[\fIargs\fR\&...] +\fBovs\-vsctl\fR [\fIoptions\fR] [\fB\-\-\fR] \fIcommand \fR[\fIargs\fR\&...] [\fB\-\-\fR \fIcommand \fR[\fIargs\fR\&...]] . .SH DESCRIPTION @@ -29,6 +29,10 @@ configuration database. Using this connection, it queries and possibly applies changes to the database, depending on the supplied commands. Then, if it applied any changes, it waits until \fBovs\-vswitchd\fR has finished reconfiguring itself before it exits. +.PP +\fBovs\-vsctl\fR can perform any number of commands in a single run, +implemented as a single atomic transaction against the database. +Commands are separated on the command line by \fB\-\-\fR arguments. . .SS "Linux VLAN Bridging Compatibility" The \fBovs\-vsctl\fR program supports the model of a bridge @@ -51,8 +55,11 @@ they are members. . .SH OPTIONS . -The following options affect the general outline of \fBovs\-vsctl\fR's -activities: +The following options affect the behavior \fBovs\-vsctl\fR as a whole. +Some individual commands also accept their own options, which are +given just before the command name. If the first command on the +command line has options, then those options must be separated from +the global options by \fB\-\-\fR. . .IP "\fB\-\-db=\fIserver\fR" Sets \fIserver\fR as the database server that \fBovs\-vsctl\fR @@ -109,10 +116,14 @@ 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 "\fBdel\-br \fIbridge\fR" +.IP "[\fB\-\-if\-exists\fR] \fBdel\-br \fIbridge\fR" Deletes \fIbridge\fR and all of its ports. If \fIbridge\fR is a real bridge, this command also deletes any fake bridges that were created with \fIbridge\fR as parent, including all of their ports. +.IP +Without \fB\-\-if\-exists\fR, attempting to delete a bridge that does +not exist is an error. With \fB\-\-if\-exists\fR, attempting to +delete a bridge that does not exist has no effect. . .IP "\fBlist\-br\fR" Lists all existing real and fake bridges on standard output, one per @@ -168,10 +179,14 @@ Creates on \fIbridge\fR a new port named \fIport\fR that bonds together the network devices given as each \fIiface\fR. At least two interfaces must be named. . -.IP "\fBdel\-port \fR[\fIbridge\fR] \fIport\fR" +.IP "[\fB\-\-if\-exists\fR] \fBdel\-port \fR[\fIbridge\fR] \fIport\fR" Deletes \fIport\fR. If \fIbridge\fR is omitted, \fIport\fR is removed from whatever bridge contains it; if \fIbridge\fR is specified, it must be the real or fake bridge that contains \fIport\fR. +.IP +Without \fB\-\-if\-exists\fR, attempting to delete a port that does +not exist is an error. With \fB\-\-if\-exists\fR, attempting to +delete a port that does not exist has no effect. . .IP "\fBport\-to\-br \fIport\fR" Prints the name of the bridge that contains \fIport\fR on standard @@ -240,6 +255,15 @@ Create a new bridge named br0 and add port eth0 to it: Alternatively, perform both operations in a single atomic transaction: .IP .B "ovs-vsctl add\-br br0 \-\- add\-port br0 eth0" +.PP +Delete bridge \fBbr0\fR, reporting an error if it does not exist: +.IP +.B "ovs\-vsctl del\-br br0" +.PP +Delete bridge \fBbr0\fR if it exists (the \fB\-\-\fR is required to +separate \fBdel\-br\fR's options from the global options): +.IP +.B "ovs\-vsctl \-\- \-\-if\-exists del\-br br0" . .SH "EXIT STATUS" .IP "0" diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index b3af9881..3a6ce13b 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -514,7 +514,7 @@ static struct vsctl_port * find_port(struct vsctl_info *info, const char *name, bool must_exist) { struct vsctl_port *port = shash_find_data(&info->ports, name); - if (!strcmp(name, port->bridge->name)) { + if (port && !strcmp(name, port->bridge->name)) { port = NULL; } if (must_exist && !port) { @@ -527,7 +527,7 @@ static struct vsctl_iface * find_iface(struct vsctl_info *info, const char *name, bool must_exist) { struct vsctl_iface *iface = shash_find_data(&info->ifaces, name); - if (!strcmp(name, iface->port->bridge->name)) { + if (iface && !strcmp(name, iface->port->bridge->name)) { iface = NULL; } if (must_exist && !iface) { @@ -690,22 +690,26 @@ del_port(struct vsctl_info *info, struct vsctl_port *port) 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], true); - 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); } @@ -954,25 +958,30 @@ cmd_add_bond(struct vsctl_context *ctx) 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], true); - del_port(&info, port); + struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist); + if (port) { + del_port(&info, port); + } } 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], true); - - if (port->bridge == bridge) { - 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]); + 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) { + 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]); + } } } free_info(&info); @@ -1242,7 +1251,7 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) static const struct vsctl_command all_commands[] = { /* 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, ""}, @@ -1254,7 +1263,7 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) {"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, ""}, -- 2.30.2