Improve cfg's argparse sub-parsers support

In order for sub-parsers to be useful, you need some way of knowing
which sub-parser was chosen during argument parsing. It's pretty obvious
from the current sub-parsers test case that we don't have a convenient
interface for this.

One way of doing it is to use the 'dest' argument when adding
sub-parsers:

  >>> subparsers = parser.add_subparsers(dest='cmd')
  >>> subparsers.add_parser('a')
  >>> subparsers.add_parser('b')
  >>> parser.parse_args(['a'])
  Namespace(cmd='a')

The most sensible way to map this into cfg concepts is to register
sub-parsers as an Opt. This way, we can make name and argument values
of the sub-parser as an attribute on the ConfigOpts object:

  >>> def add_parsers(subparsers):
  ...     a = subparsers.add_parser('a')
  ...     a.add_argument('id')
  ...     b = subparsers.add_parser('b')
  ...
  >>> CONF.register_cli_opt(SubCommandOpt('cmd', handler=add_parsers))
  True
  >>> CONF(['a', '10'])
  >>> CONF.cmd.name, CONF.cmd.id
  ('a', '10')

The handler method is a bit awkward, but each time cfg is to parse
command line args it takes all the registered opts and creates a new
argparse parser. So we need to be able to re-add the sub-parsers each
time.

Change-Id: I01bfd01bf8853cf57a9248b1663eb3da142366a4
Add a CLI argument validation utility

blueprint oslo-cliutils

In nova-manage and cinder-manage, we allow command arguments to be
passed as optional or positional arguments.

e.g.

  $> nova-manage floating create 10.0.0.1/28
  $> nova-manage floating create --ip_range 10.0.0.1/28

are equivalent.

Once nova-manage has collected those arguments, it calls the
appropriate command function with them as positional and keyword
arguments. If the user forgets to supply a required argument, they
merely get a TypeError with little useful information.

Improve the usability of these commands using a new utility function
to check that the required arguments have been supplied and raise a
useful exception if not.

Change-Id: If6e4a9f222a30472bbfbcd06859865bd4e37e139
Fixes import nit in test_zmq

Fixes bug #1084821

Change-Id: I1199d264b911036d142c6d1b58a41d740d795dd5
Rename utils.py to strutils.py

Fixes bug #1083956

Change-Id: I681227e9428778adb7824a1930a33cfa5ffa13a1
Fixes update.py issue with EOL style on Windows

Fixes Bug #1075230

Files are saved with the OS EOL conversion unless "b" is specified
in open(...). In this case we want to preserve the original EOL
convention.

Change-Id: Id756174d03c3e95db055d512ec4aa5a0eeb768b8
Fix set_default() with boolean CLI options

Porting to argparse broke set_default() with boolean CLI options. The
new test case shows this borkage.

The issue is that, by default, argparse differs subtly from optparse in
its handling of defaults for boolean options. Compare:

  >>> p = optparse.OptionParser()
  >>> p.add_option('--foo', action='store_true')
  >>> p.add_option('--bar', action='store_true', default=False)
  >>> p.parse_args([])
  (<Values at 0x7f28aba066c8: {'foo': None, 'bar': False}>, [])

to:

  >>> p = argparse.ArgumentParser()
  >>> p.add_argument('--foo', action='store_true')
  >>> p.add_argument('--bar', action='store_true', default=False)
  >>> p.add_argument('--blaa', action='store_true', default=None)
  >>> p.parse_args([])
  Namespace(bar=False, blaa=None, foo=False)

i.e. unless you specify a default for a boolean option, optparse
defaults to None whereas argparse defaults to False. To get the
same optparse behaviour with argparse, you need default=None.

Change-Id: Ifc92a834c4ba59e939d80ac5de24d7051232f5b5
Merge "Fixes import nit in test_zmq"
Merge "Fixes update.py issue with EOL style on Windows"
Merge "Rename utils.py to strutils.py"
Merge "Improve cfg's argparse sub-parsers support"
Merge "Fix set_default() with boolean CLI options"
Fixing modulename so eventlet will log properly.

Fixes bug 1086063

Change-Id: I1ebc3243b6db242279b05424c99013dbcf703703
Merge "Fixing modulename so eventlet will log properly."
Merge "Add a CLI argument validation utility"
Fix import order in openstack/common/lockutils.py

Change-Id: Ia1dfa85a81bae6620c2c24c0c28a589d46ed3b04