ovs-vsctl: Add --if-exists options to del-br, del-port commands.
authorBen Pfaff <blp@nicira.com>
Thu, 10 Dec 2009 22:07:33 +0000 (14:07 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 10 Dec 2009 22:07:54 +0000 (14:07 -0800)
These options make it easier to reimplement interface-reconfigure using
ovs-vsctl.

tests/ovs-vsctl.at
utilities/ovs-vsctl.8.in
utilities/ovs-vsctl.c

index a76fd48c81e2537dfd6dc30d6e66703b02f48829..cd4cab3d2c60864b602bf037a1c3c5caaa262652 100644 (file)
@@ -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])
index db0b9b91742f33536d20bcfd9a4808bb8823a6fb..46bbbe288c1571292e6526f520a5020aeb7d675c 100644 (file)
@@ -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"
index b3af98813862362afb622cc8052b1f0b5a576819..3a6ce13b279f3ce463224a276b6f7ed5ab469ffd 100644 (file)
@@ -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, ""},