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
# (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.
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),]))
],
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($@))
],
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])
[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])
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
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],
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],
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],
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])
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
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
.
.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
\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
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
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"
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) {
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) {
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);
}
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);
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, ""},
{"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, ""},