I had to apply a small interdiff to pass the documentation tests:

diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py
index 0c9bc6d..9d0877f 100644
--- a/lib/hypervisor/hv_lxc.py
+++ b/lib/hypervisor/hv_lxc.py
@@ -871,11 +871,11 @@ class LXCHypervisor(hv_base.BaseHypervisor):

     Version information will be retrieved by command specified by from_cmd.

-    @param from_cmd: the lxc command used to retrieve a version information
+    @param from_cmd: the lxc command used to retrieve version information
     @type from_cmd: string
-    @rtype L{LXCVersion}
-    @return a version object which represents the version retrieved from
the
-      command
+    @rtype: L{LXCVersion}
+    @return: a version object which represents the version retrieved from
the
+             command

     """
     result = utils.RunCmd([from_cmd, "--version"])

On Tue, Oct 7, 2014 at 5:22 PM, Hrvoje Ribicic <[email protected]> wrote:

> LGTM, thanks
>
> On Mon, Oct 6, 2014 at 8:09 PM, Yuto KAWAMURA(kawamuray) <
> [email protected]> wrote:
>
>> This patch adds the class LXCVersion and the function _GetLXCVersion
>> which can be used to obtain version information from an LXC command.
>> _VerifyLXCCommands has been changed to use this function instead of
>> calling commands directly, and adjust unit tests for changes made.
>>
>> Signed-off-by: Yuto KAWAMURA(kawamuray) <[email protected]>
>> ---
>>  lib/hypervisor/hv_lxc.py                     | 89
>> ++++++++++++++++++++--------
>>  test/py/ganeti.hypervisor.hv_lxc_unittest.py | 18 +++---
>>  2 files changed, 74 insertions(+), 33 deletions(-)
>>
>> diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py
>> index 4981c9e..0c9bc6d 100644
>> --- a/lib/hypervisor/hv_lxc.py
>> +++ b/lib/hypervisor/hv_lxc.py
>> @@ -62,6 +62,40 @@ def _CreateBlankFile(path, mode):
>>      raise HypervisorError("Failed to create file %s: %s" % (path, err))
>>
>>
>> +class LXCVersion(tuple): # pylint: disable=R0924
>> +  """LXC version class.
>> +
>> +  """
>> +  # Let beta version following micro version, but don't care about it
>> +  _VERSION_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)")
>> +
>> +  @classmethod
>> +  def _Parse(cls, version_string):
>> +    """Parse a passed string as an LXC version string.
>> +
>> +    @param version_string: a valid LXC version string
>> +    @type version_string: string
>> +    @raise ValueError: if version_string is an invalid LXC version string
>> +    @rtype tuple(int, int, int)
>> +    @return (major_num, minor_num, micro_num)
>> +
>> +    """
>> +    match = cls._VERSION_RE.match(version_string)
>> +    if match:
>> +      return tuple(map(int, match.groups()))
>> +    else:
>> +      raise ValueError("'%s' is not a valid LXC version string" %
>> +                       version_string)
>> +
>> +  def __new__(cls, version_string):
>> +    version = super(LXCVersion, cls).__new__(cls,
>> cls._Parse(version_string))
>> +    version.original_string = version_string
>> +    return version
>> +
>> +  def __str__(self):
>> +    return self.original_string
>> +
>> +
>>  class LXCHypervisor(hv_base.BaseHypervisor):
>>    """LXC-based virtualization.
>>
>> @@ -93,7 +127,7 @@ class LXCHypervisor(hv_base.BaseHypervisor):
>>    _PROC_CGROUPS_FILE = "/proc/cgroups"
>>    _PROC_SELF_CGROUP_FILE = "/proc/self/cgroup"
>>
>> -  _LXC_MIN_VERSION_REQUIRED = "1.0.0"
>> +  _LXC_MIN_VERSION_REQUIRED = LXCVersion("1.0.0")
>>    _LXC_COMMANDS_REQUIRED = [
>>      "lxc-console",
>>      "lxc-ls",
>> @@ -115,8 +149,6 @@ class LXCHypervisor(hv_base.BaseHypervisor):
>>      constants.HV_LXC_STARTUP_WAIT: hv_base.OPT_NONNEGATIVE_INT_CHECK,
>>      }
>>
>> -  # Let beta version following micro version, but don't care about it
>> -  _LXC_VERSION_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)")
>>    _REBOOT_TIMEOUT = 120 # secs
>>    _REQUIRED_CGROUP_SUBSYSTEMS = [
>>      "cpuset",
>> @@ -834,15 +866,28 @@ class LXCHypervisor(hv_base.BaseHypervisor):
>>                                     command=["lxc-console", "-n",
>> instance.name])
>>
>>    @classmethod
>> -  def _ParseLXCVersion(cls, version_string):
>> -    """Return a parsed result of lxc version string.
>> +  def _GetLXCVersionFromCmd(cls, from_cmd):
>> +    """Return the LXC version currently used in the system.
>> +
>> +    Version information will be retrieved by command specified by
>> from_cmd.
>>
>> -    @return: tuple of major, minor and micro version number
>> -    @rtype: tuple(int, int, int)
>> +    @param from_cmd: the lxc command used to retrieve a version
>> information
>> +    @type from_cmd: string
>> +    @rtype L{LXCVersion}
>> +    @return a version object which represents the version retrieved from
>> the
>> +      command
>>
>>      """
>> -    match = cls._LXC_VERSION_RE.match(version_string)
>> -    return tuple(map(int, match.groups())) if match else None
>> +    result = utils.RunCmd([from_cmd, "--version"])
>> +    if result.failed:
>> +      raise HypervisorError("Failed to get version info from command %s:
>> %s" %
>> +                            (from_cmd, result.output))
>> +
>> +    try:
>> +      return LXCVersion(result.stdout.strip())
>> +    except ValueError, err:
>> +      raise HypervisorError("Can't parse LXC version from %s: %s" %
>> +                            (from_cmd, err))
>>
>>    @classmethod
>>    def _VerifyLXCCommands(cls):
>> @@ -853,7 +898,6 @@ class LXCHypervisor(hv_base.BaseHypervisor):
>>               there is no problem.
>>
>>      """
>> -    version_required =
>> cls._ParseLXCVersion(cls._LXC_MIN_VERSION_REQUIRED)
>>      msgs = []
>>      for cmd in cls._LXC_COMMANDS_REQUIRED:
>>        try:
>> @@ -868,21 +912,16 @@ class LXCHypervisor(hv_base.BaseHypervisor):
>>              msgs.append("The python version of 'lxc-ls' is required."
>>                          " Maybe lxc was installed without
>> --enable-python")
>>          else:
>> -          result = utils.RunCmd([cmd, "--version"])
>> -          if result.failed:
>> -            msgs.append("Can't get version info from %s: %s" %
>> -                        (cmd, result.output))
>> -          else:
>> -            version_str = result.stdout.strip()
>> -            version = cls._ParseLXCVersion(version_str)
>> -            if version:
>> -              if version < version_required:
>> -                msgs.append("LXC version >= %s is required but command
>> %s has"
>> -                            " version %s" %
>> -                            (cls._LXC_MIN_VERSION_REQUIRED, cmd,
>> version_str))
>> -            else:
>> -              msgs.append("Can't parse version info from %s output: %s" %
>> -                          (cmd, version_str))
>> +          try:
>> +            version = cls._GetLXCVersionFromCmd(cmd)
>> +          except HypervisorError, err:
>> +            msgs.append(str(err))
>> +            continue
>> +
>> +          if version < cls._LXC_MIN_VERSION_REQUIRED:
>> +            msgs.append("LXC version >= %s is required but command %s
>> has"
>> +                        " version %s" %
>> +                        (cls._LXC_MIN_VERSION_REQUIRED, cmd, version))
>>        except errors.OpExecError:
>>          msgs.append("Required command %s not found" % cmd)
>>
>> diff --git a/test/py/ganeti.hypervisor.hv_lxc_unittest.py b/test/py/
>> ganeti.hypervisor.hv_lxc_unittest.py
>> index 8cd08c7..208ddcf 100755
>> --- a/test/py/ganeti.hypervisor.hv_lxc_unittest.py
>> +++ b/test/py/ganeti.hypervisor.hv_lxc_unittest.py
>> @@ -40,7 +40,7 @@ from ganeti import utils
>>
>>  from ganeti.hypervisor import hv_base
>>  from ganeti.hypervisor import hv_lxc
>> -from ganeti.hypervisor.hv_lxc import LXCHypervisor
>> +from ganeti.hypervisor.hv_lxc import LXCHypervisor, LXCVersion
>>
>>  import mock
>>  import os
>> @@ -67,6 +67,14 @@ def RunResultOk(stdout):
>>    return utils.RunResult(0, None, stdout, "", [], None, None)
>>
>>
>> +class TestLXCVersion(unittest.TestCase):
>> +  def testParseLXCVersion(self):
>> +    self.assertEqual(LXCVersion("1.0.0"), (1, 0, 0))
>> +    self.assertEqual(LXCVersion("1.0.0.alpha1"), (1, 0, 0))
>> +    self.assertRaises(ValueError, LXCVersion, "1.0")
>> +    self.assertRaises(ValueError, LXCVersion, "1.2a.0")
>> +
>> +
>>  class LXCHypervisorTestCase(unittest.TestCase):
>>    """Used to test classes instantiating the LXC hypervisor class.
>>
>> @@ -208,7 +216,7 @@ class TestVerifyLXCCommands(unittest.TestCase):
>>      self.RunCmdPatch = patch_object(utils, "RunCmd", runcmd_mock)
>>      self.RunCmdPatch.start()
>>      version_patch = patch_object(LXCHypervisor,
>> "_LXC_MIN_VERSION_REQUIRED",
>> -                                 "1.2.3")
>> +                                 LXCVersion("1.2.3"))
>>      self._LXC_MIN_VERSION_REQUIRED_Patch = version_patch
>>      self._LXC_MIN_VERSION_REQUIRED_Patch.start()
>>      self.hvc = LXCHypervisor
>> @@ -217,12 +225,6 @@ class TestVerifyLXCCommands(unittest.TestCase):
>>      self.RunCmdPatch.stop()
>>      self._LXC_MIN_VERSION_REQUIRED_Patch.stop()
>>
>> -  def testParseLXCVersion(self):
>> -    self.assertEqual(self.hvc._ParseLXCVersion("1.0.0"), (1, 0, 0))
>> -    self.assertEqual(self.hvc._ParseLXCVersion("1.0.0.alpha1"), (1, 0,
>> 0))
>> -    self.assertEqual(self.hvc._ParseLXCVersion("1.0"), None)
>> -    self.assertEqual(self.hvc._ParseLXCVersion("1.2a.0"), None)
>> -
>>    @patch_object(LXCHypervisor, "_LXC_COMMANDS_REQUIRED", ["lxc-stop"])
>>    def testCommandVersion(self):
>>      utils.RunCmd.return_value = RunResultOk("1.2.3\n")
>> --
>> 2.0.4
>>
>>
>


Hrvoje Ribicic
Ganeti Engineering
Google Germany GmbH
Dienerstr. 12, 80331, München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores
Steuernummer: 48/725/00206
Umsatzsteueridentifikationsnummer: DE813741370

Reply via email to