From 4d14e30f80e2e2d72fcf3aba840fa55eaed1121f Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 16 Oct 2009 09:42:21 -0700 Subject: [PATCH] ovs-vsctl: Add the ability to perform multiple operations in a single run. CC: Ian Campbell --- tests/ovs-vsctl.at | 19 +++++- utilities/ovs-vsctl.8.in | 19 +++++- utilities/ovs-vsctl.in | 130 ++++++++++++++++++++++++--------------- 3 files changed, 114 insertions(+), 54 deletions(-) diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index 834ecc6c..5f19665f 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -7,6 +7,15 @@ m4_define([RUN_OVS_VSCTL], 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, @@ -24,6 +33,12 @@ m4_define([_CHECK_BRIDGE], # 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. @@ -152,7 +167,7 @@ AT_CLEANUP 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], @@ -206,7 +221,7 @@ AT_CLEANUP 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])]) diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index bc4cb11a..7f6326e9 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -12,6 +12,7 @@ ovs\-vsctl \- utility for querying and configuring \fBovs\-vswitchd\fR . .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 @@ -22,7 +23,8 @@ when \fBovs\-vswitchd\fR is running, but it can also be used when 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 @@ -99,10 +101,11 @@ By default, \fBovs\-vsctl\fR logs its arguments and the details of any 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 @@ -185,6 +188,16 @@ list. .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" diff --git a/utilities/ovs-vsctl.in b/utilities/ovs-vsctl.in index d8b44045..cc9f52b3 100755 --- a/utilities/ovs-vsctl.in +++ b/utilities/ovs-vsctl.in @@ -480,17 +480,66 @@ def cmd_br_to_parent(cfg, bridge): 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) @@ -525,52 +574,35 @@ def main(): 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: -- 2.30.2