[ovs-dev] [PATCH 3/3] ovs-vsctl: Add the ability to perform multiple operations in a single run.

Ben Pfaff blp at nicira.com
Fri Oct 16 16:45:13 UTC 2009


<reid at nicira.com> writes:

> One other note regarding the oneline output option with multiple commands.
> It seems as though it might be useful for parsing this output if commands
> which do not have output (i.e.: return None) have a blank line or some
> other marker printed, to save the parsing user the trouble of determining
> which commands were supposed to have output and which weren't.  

I was wavering on that myself, and your opinion pushed me over
the end.

I've changed it to print a line of output for every command with
--oneline, which is blank if the command had no output.

> In the interactive command-line case I can see that this would
> probably just be more clutter or confusion - defaulting off,
> with a command line option to turn this on would probably be
> preferable.
>
>   -Reid
>
> On Thu, 15 Oct 2009 22:50:32 -0400, <reid at nicira.com> wrote:
>> Looks useful =).  Prefer append in split_commands.  I assume that
> removing
>> the final sys.exit(0) was deliberate.
>> 
>> On Thu, 15 Oct 2009 15:38:51 -0700, Ben Pfaff <blp at nicira.com> wrote:
>>> CC: Ian Campbell <Ian.Campbell at citrix.com>
>>> ---
>>>  tests/ovs-vsctl.at       |   19 +++++++-
>>>  utilities/ovs-vsctl.8.in |   16 ++++++-
>>>  utilities/ovs-vsctl.in   |  114
>>> +++++++++++++++++++++++++++++-----------------
>>>  3 files changed, 103 insertions(+), 46 deletions(-)
>>>
>>> diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
>>> index 834ecc6..5f19665 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 bc4cb11..9968ebe 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
>>> @@ -101,7 +103,7 @@ logging.
>>>  .IP "\fB\-\-oneline\fR"
>>>  Modifies the output format so that the output for a 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.
>>>  .
>>>  .SH COMMANDS
>>> @@ -185,6 +187,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 012ce4e..a419149 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 += [command]
>>> +            command = []
>>> +        else:
>>> +            command += [arg]
>>> +    if command:
>>> +        commands += [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,51 +574,32 @@ def main():
>>>          syslog.openlog("ovs-vsctl")
>>>          log("Called as " + ' '.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)
>>> +    # Execute commands.
>>> +    cfg = cfg_read(VSWITCHD_CONF, need_lock)
>>> +    for command in commands:
>>> +        output = run_command(cfg, command)
>>>          if output != None:
>>>              if oneline:
>>>                  print '\\n'.join([s.replace('\\', '\\\\') for s in
>>> output])
>>>              else:
>>>                  for line in output:
>>>                      print line
>>> -        if is_mutator:
>>> -            cfg_save(cfg, VSWITCHD_CONF)
>>> -        sys.exit(0)
>>> +    if need_lock:
>>> +        cfg_save(cfg, VSWITCHD_CONF)
>>>
>>>  if __name__ == "__main__":
>>>      try:
>>> --
>>> 1.6.3.3
>>>
>>>
>>> _______________________________________________
>>> dev mailing list
>>> dev at openvswitch.org
>>> http://openvswitch.org/mailman/listinfo/dev_openvswitch.org
>> 
>> 
>> _______________________________________________
>> dev mailing list
>> dev at openvswitch.org
>> http://openvswitch.org/mailman/listinfo/dev_openvswitch.org




More information about the dev mailing list