Commit 59d81cb3 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Merge branch 'devel-2.5'



* devel-2.5:
  Fix wrong option names in QA and cluster-merge
  Bump version to 2.5.0~rc5, update NEWS
  Add UnescapeAndSplit unittest for multi-escapes
  Fix a bug in command line option parsing code
  cli: Disable abbreviation matching for options
  Bump version to 2.5.0~rc5, update NEWS
  Add UnescapeAndSplit unittest for multi-escapes
  Fix a bug in command line option parsing code

Conflicts:
	lib/cli.py: Trivial
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parents f356202a 431f2a80
......@@ -14,19 +14,7 @@ Version 2.6.0 beta1
Version 2.5.0 rc5
-----------------
*(unreleased)*
Improvements and bugfixes
~~~~~~~~~~~~~~~~~~~~~~~~~
- Support for kvm version 1.0, that changed the version reporting format
(from 3 to 2 digits).
Version 2.5.0 rc4
-----------------
*(Released Thu, 27 Oct 2011)*
*(Released Mon, 9 Jan 2012)*
Incompatible/important changes and bugfixes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -60,6 +48,9 @@ Incompatible/important changes and bugfixes
- :doc:`New iallocator modes <design-multi-reloc>` have been added to
support operations involving multiple node groups.
- Offline nodes are ignored when failing over an instance.
- Support for KVM version 1.0, which changed the version reporting format
from 3 to 2 digits.
- Includes all bugfixes made in the 2.4 series
New features
~~~~~~~~~~~~
......@@ -153,6 +144,14 @@ Misc
- DRBD metadata volumes are overwritten with zeros during disk creation.
Version 2.5.0 rc4
-----------------
*(Released Thu, 27 Oct 2011)*
This was the fourth release candidate of the 2.5 series.
Version 2.5.0 rc3
-----------------
......
......@@ -2,7 +2,7 @@
m4_define([gnt_version_major], [2])
m4_define([gnt_version_minor], [5])
m4_define([gnt_version_revision], [0])
m4_define([gnt_version_suffix], [~rc4])
m4_define([gnt_version_suffix], [~rc5])
m4_define([gnt_version_full],
m4_format([%d.%d.%d%s],
gnt_version_major, gnt_version_minor,
......
......@@ -30,6 +30,7 @@ import logging
import errno
import itertools
import shlex
import optparse
from cStringIO import StringIO
from ganeti import utils
......@@ -44,7 +45,7 @@ from ganeti import compat
from ganeti import netutils
from ganeti import qlang
from optparse import (OptionParser, TitledHelpFormatter,
from optparse import (TitledHelpFormatter,
Option, OptionValueError)
......@@ -1480,10 +1481,10 @@ def _ParseArgs(argv, commands, aliases, env_override):
argv = utils.InsertAtPos(argv, 1, shlex.split(env_args))
func, args_def, parser_opts, usage, description = commands[cmd]
parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
description=description,
formatter=TitledHelpFormatter(),
usage="%%prog %s %s" % (cmd, usage))
parser = CustomOptionParser(option_list=parser_opts + COMMON_OPTS,
description=description,
formatter=TitledHelpFormatter(),
usage="%%prog %s %s" % (cmd, usage))
parser.disable_interspersed_args()
options, args = parser.parse_args(args=argv[1:])
......@@ -1493,6 +1494,21 @@ def _ParseArgs(argv, commands, aliases, env_override):
return func, options, args
class CustomOptionParser(optparse.OptionParser):
def _match_long_opt(self, opt):
"""Override C{OptionParser}'s function for matching long options.
The default implementation does prefix-based abbreviation matching. We
disable such behaviour as it can can lead to confusing conflicts (e.g.
C{--force} and C{--force-multi}).
"""
if opt in self._long_opt:
return opt
else:
raise optparse.BadOptionError(opt)
def _CheckArguments(cmd, args_def, args):
"""Verifies the arguments using the argument definition.
......
......@@ -387,10 +387,12 @@ def UnescapeAndSplit(text, sep=","):
num_b = len(e1) - len(e1.rstrip("\\"))
if num_b % 2 == 1 and slist:
e2 = slist.pop(0)
# here the backslashes remain (all), and will be reduced in
# the next step
rlist.append(e1 + sep + e2)
# Merge the two elements and push the result back to the source list for
# revisiting. If e2 ended with backslashes, further merging may need to
# be done.
slist.insert(0, e1 + sep + e2)
continue
# here the backslashes remain (all), and will be reduced in the next step
rlist.append(e1)
# finally, replace backslash-something with something
rlist = [re.sub(r"\\(.)", r"\1", v) for v in rlist]
......
......@@ -205,7 +205,7 @@ def TestClusterEpo():
# Assert that OOB is unavailable for all nodes
result_output = GetCommandOutput(master["primary"],
"gnt-node list --verbose --no-header -o"
"gnt-node list --verbose --no-headers -o"
" powered")
AssertEqual(compat.all(powered == "(unavail)"
for powered in result_output.splitlines()), True)
......@@ -223,7 +223,7 @@ def TestClusterEpo():
# All instances should have been stopped now
result_output = GetCommandOutput(master["primary"],
"gnt-instance list --no-header -o status")
"gnt-instance list --no-headers -o status")
AssertEqual(compat.all(status == "ADMIN_down"
for status in result_output.splitlines()), True)
......@@ -232,7 +232,7 @@ def TestClusterEpo():
# All instances should have been started now
result_output = GetCommandOutput(master["primary"],
"gnt-instance list --no-header -o status")
"gnt-instance list --no-headers -o status")
AssertEqual(compat.all(status == "running"
for status in result_output.splitlines()), True)
......
......@@ -112,7 +112,7 @@ def TestInstanceReboot(instance):
AssertCommand(["gnt-instance", "reboot", name])
master = qa_config.GetMasterNode()
cmd = ["gnt-instance", "list", "--no-header", "-o", "status", name]
cmd = ["gnt-instance", "list", "--no-headers", "-o", "status", name]
result_output = qa_utils.GetCommandOutput(master["primary"],
utils.ShellQuoteArgs(cmd))
AssertEqual(result_output.strip(), constants.INSTST_RUNNING)
......
......@@ -400,7 +400,7 @@ def _List(listcmd, fields, names):
"""
master = qa_config.GetMasterNode()
cmd = [listcmd, "list", "--separator=|", "--no-header",
cmd = [listcmd, "list", "--separator=|", "--no-headers",
"--output", ",".join(fields)]
if names:
......
......@@ -408,6 +408,12 @@ class TestUnescapeAndSplit(unittest.TestCase):
b = [sep, sep, "c", "d.moo\\"]
self.assertEqual(utils.UnescapeAndSplit("%s\\" % sep.join(a), sep=sep), b)
def testMultipleEscapes(self):
for sep in self._seps:
a = ["a", "b\\" + sep + "c", "d\\" + sep + "e\\" + sep + "f", "g"]
b = ["a", "b" + sep + "c", "d" + sep + "e" + sep + "f", "g"]
self.failUnlessEqual(utils.UnescapeAndSplit(sep.join(a), sep=sep), b)
class TestCommaJoin(unittest.TestCase):
def test(self):
......
......@@ -192,7 +192,7 @@ class Merger(object):
utils.WriteFile(key_path, mode=0600, data=result.stdout)
result = self._RunCmd(cluster, "gnt-node list -o name,offline"
" --no-header --separator=,", private_key=key_path)
" --no-headers --separator=,", private_key=key_path)
if result.failed:
raise errors.RemoteError("Unable to retrieve list of nodes from %s."
" Fail reason: %s; output: %s" %
......@@ -201,7 +201,7 @@ class Merger(object):
nodes = [node_status[0] for node_status in nodes_statuses
if node_status[1] == "N"]
result = self._RunCmd(cluster, "gnt-instance list -o name --no-header",
result = self._RunCmd(cluster, "gnt-instance list -o name --no-headers",
private_key=key_path)
if result.failed:
raise errors.RemoteError("Unable to retrieve list of instances from"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment