m4_foreach([command], [$@], [ovs-vsctl --no-reload --config=conf command
])])
+dnl RUN_OVS_VSCTL_TOGETHER(COMMAND, ...)
+dnl
+dnl Executes each ovs-vsctl COMMAND on a file named "conf" in the
+dnl current directory, in a single run of ovs-vsctl. Creates "conf" if it
+dnl does not already exist.
+m4_define([RUN_OVS_VSCTL_TOGETHER],
+ [: >> conf
+ ovs-vsctl --no-reload --config=conf m4_join([ -- ], $@)])
+
dnl CHECK_BRIDGES([BRIDGE, PARENT, VLAN], ...)
dnl
dnl Verifies that "ovs-vsctl list-br" prints the specified list of bridges,
# 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
+])
+
+ # Check multiple queries in a single run.
+ AT_CHECK([RUN_OVS_VSCTL_TOGETHER([br-to-parent $1], [br-to-vlan $1])], [0],
+[$2
+$3
])])
m4_define([CHECK_BRIDGES],
[dnl Check that the bridges appear on list-br, without --oneline.
AT_SETUP([add-br a b, add-port a a1, add-port b b1, del-br a])
AT_KEYWORDS([ovs-vsctl])
-AT_CHECK([RUN_OVS_VSCTL(
+AT_CHECK([RUN_OVS_VSCTL_TOGETHER(
[add-br a],
[add-br b],
[add-port a a1],
AT_SETUP([add-br a, add-bond a bond0 a1 a2 a3, del-port bond0])
AT_KEYWORDS([ovs-vsctl])
-AT_CHECK([RUN_OVS_VSCTL(
+AT_CHECK([RUN_OVS_VSCTL_TOGETHER(
[add-br a],
[add-bond a bond0 a1 a2 a3],
[del-port bond0])])
.
.SH SYNOPSIS
\fBovs\-vsctl\fR [\fIoptions\fR] \fIcommand \fR[\fIargs\fR\&...]
+[\fB\-\-\fR \fIcommand \fR[\fIargs\fR\&...]]
.
.SH DESCRIPTION
The \fBovs\-vsctl\fR program configures \fBovs\-vswitchd\fR(8), mainly
changes will only take effect when \fBovs\-vswitchd\fR is started.
.PP
By default, each time \fBovs\-vsctl\fR runs, it examines and,
-depending on the requested command, possibly applies changes to an
+depending on the requested command or commands, possibly applies
+changes to an
\fBovs\-vswitchd.conf\fR file. Then, if it applied any changes and if
\fBovs\-vswitchd\fR is running, it tells \fBovs\-vswitchd\fR to reload
the modified configuration file and waits for the reload to complete
changes that it makes to the system log. This option disables this
logging.
.IP "\fB\-\-oneline\fR"
-Modifies the output format so that the output for a command is printed
+Modifies the output format so that the output for each command is printed
on a single line. New-line characters that would otherwise separate
-lines are printed as \fB\\n\fR, and any instances of \fB\\fR that
+lines are printed as \fB\\n\fR, and any instances of \fB\\\fR that
would otherwise appear in the output are doubled.
+Prints a blank line for each command that has no output.
.
.SH COMMANDS
The commands implemented by \fBovs\-vsctl\fR are described in the
.IP "\fBiface\-to\-br \fIiface\fR"
Prints the name of the bridge that contains \fIiface\fR on standard
output.
+.SH "EXAMPLES"
+Create a new bridge named br0 and add port eth0 to it:
+.IP
+.B "ovs-vsctl add\-br br0"
+.br
+.B "ovs-vsctl add\-port br0 eth0"
+.PP
+Alternatively, perform both operations in a single atomic transaction:
+.IP
+.B "ovs-vsctl add\-br br0 \-\- add\-port br0 eth0"
.
.SH "EXIT STATUS"
.IP "0"
parent, vlan = find_bridge(cfg, bridge)
return (parent,)
+cmdTable = {'add-br': (cmd_add_br, True, lambda n: n == 1 or n == 3),
+ 'del-br': (cmd_del_br, True, 1),
+ 'list-br': (cmd_list_br, False, 0),
+ 'br-exists': (cmd_br_exists, False, 1),
+ 'list-ports': (cmd_list_ports, False, 1),
+ 'add-port': (cmd_add_port, True, 2),
+ 'add-bond': (cmd_add_bond, True, lambda n: n >= 4),
+ 'del-port': (cmd_del_port, True, lambda n: n == 1 or n == 2),
+ 'port-to-br': (cmd_port_to_br, False, 1),
+ 'br-to-vlan': (cmd_br_to_vlan, False, 1),
+ 'br-to-parent': (cmd_br_to_parent, False, 1),
+ 'list-ifaces': (cmd_list_ifaces, False, 1),
+ 'iface-to-br': (cmd_iface_to_br, False, 1)}
+
+# Break up commands at -- boundaries.
+def split_commands(args):
+ commands = []
+ command = []
+ for arg in args:
+ if arg == '--':
+ if command:
+ commands.append(command)
+ command = []
+ else:
+ command.append(arg)
+ if command:
+ commands.append(command)
+ return commands
+
+def check_command(args):
+ command, args = args[0], args[1:]
+ if command not in cmdTable:
+ sys.stderr.write("%s: unknown command '%s' (use --help for help)\n"
+ % (argv0, command))
+ sys.exit(1)
+
+ function, is_mutator, nargs = cmdTable[command]
+ if callable(nargs) and not nargs(len(args)):
+ sys.stderr.write("%s: '%s' command does not accept %d arguments (use --help for help)\n" % (argv0, command, len(args)))
+ sys.exit(1)
+ elif not callable(nargs) and len(args) != nargs:
+ sys.stderr.write("%s: '%s' command takes %d arguments but %d were supplied (use --help for help)\n" % (argv0, command, nargs, len(args)))
+ sys.exit(1)
+
+def run_command(cfg, args):
+ command, args = args[0], args[1:]
+ function, need_lock, nargs = cmdTable[command]
+ return function(cfg, *args)
+
def main():
# Parse command line.
try:
- options, args = getopt.gnu_getopt(sys.argv[1:], "c:t:hV",
- ["config=",
- "target=",
- "no-reload",
- "no-syslog",
- "oneline",
- "help",
- "version"])
+ options, args = getopt.getopt(sys.argv[1:], "c:t:hV",
+ ["config=",
+ "target=",
+ "no-reload",
+ "no-syslog",
+ "oneline",
+ "help",
+ "version"])
except getopt.GetoptError, msg:
sys.stderr.write("%s: %s (use --help for help)\n" % (argv0, msg))
sys.exit(1)
syslog.openlog("ovs-vsctl")
log("Called as %s" % ' '.join(sys.argv[1:]))
- # Execute commands.
- if not args:
+ # Break arguments into a series of commands.
+ commands = split_commands(args)
+ if not commands:
sys.stderr.write("%s: missing command name (use --help for help)\n"
% argv0)
sys.exit(1)
- commands = {'add-br': (cmd_add_br, True, lambda n: n == 1 or n == 3),
- 'del-br': (cmd_del_br, True, 1),
- 'list-br': (cmd_list_br, False, 0),
- 'br-exists': (cmd_br_exists, False, 1),
- 'list-ports': (cmd_list_ports, False, 1),
- 'add-port': (cmd_add_port, True, 2),
- 'add-bond': (cmd_add_bond, True, lambda n: n >= 4),
- 'del-port': (cmd_del_port, True, lambda n: n == 1 or n == 2),
- 'port-to-br': (cmd_port_to_br, False, 1),
- 'br-to-vlan': (cmd_br_to_vlan, False, 1),
- 'br-to-parent': (cmd_br_to_parent, False, 1),
- 'list-ifaces': (cmd_list_ifaces, False, 1),
- 'iface-to-br': (cmd_iface_to_br, False, 1)}
- command = args[0]
- args = args[1:]
- if command not in commands:
- sys.stderr.write("%s: unknown command '%s' (use --help for help)\n"
- % (argv0, command))
- sys.exit(1)
+ # Check command syntax.
+ need_lock = False
+ for command in commands:
+ check_command(command)
+ if cmdTable[command[0]][1]:
+ need_lock = True
- function, is_mutator, nargs = commands[command]
- if callable(nargs) and not nargs(len(args)):
- sys.stderr.write("%s: '%s' command does not accept %d arguments (use --help for help)\n" % (argv0, command, len(args)))
- sys.exit(1)
- elif not callable(nargs) and len(args) != nargs:
- sys.stderr.write("%s: '%s' command takes %d arguments but %d were supplied (use --help for help)\n" % (argv0, command, nargs, len(args)))
- sys.exit(1)
- else:
- cfg = cfg_read(VSWITCHD_CONF, is_mutator)
- output = function(cfg, *args)
- if output != None:
- if oneline:
- print '\\n'.join([str(s).replace('\\', '\\\\')
- for s in output])
- else:
- for line in output:
- print line
- if is_mutator:
- cfg_save(cfg, VSWITCHD_CONF)
- sys.exit(0)
+ # Execute commands.
+ cfg = cfg_read(VSWITCHD_CONF, need_lock)
+ for command in commands:
+ output = run_command(cfg, command)
+ if oneline:
+ if output == None:
+ output = ()
+ print '\\n'.join([str(s).replace('\\', '\\\\')
+ for s in output])
+ elif output != None:
+ for line in output:
+ print line
+ if need_lock:
+ cfg_save(cfg, VSWITCHD_CONF)
+ sys.exit(0)
if __name__ == "__main__":
try: