On Fri, Jan 7, 2011 at 1:42 PM, Michael Hanselmann <[email protected]> wrote:
> This makes use of the new way of returning console information from the
> master daemon. Unittests are included.
>
> Signed-off-by: Michael Hanselmann <[email protected]>
> ---
>  Makefile.am                                  |    4 ++
>  lib/cmdlib.py                                |    9 +---
>  lib/hypervisor/hv_base.py                    |    4 +-
>  lib/hypervisor/hv_chroot.py                  |   20 ++++++---
>  lib/hypervisor/hv_fake.py                    |   10 +++-
>  lib/hypervisor/hv_kvm.py                     |   38 ++++++++++--------
>  lib/hypervisor/hv_lxc.py                     |    9 +++-
>  lib/hypervisor/hv_xen.py                     |   10 +++-
>  test/ganeti.hypervisor.hv_chroot_unittest.py |   54 
> ++++++++++++++++++++++++++
>  test/ganeti.hypervisor.hv_fake_unittest.py   |   44 +++++++++++++++++++++
>  test/ganeti.hypervisor.hv_kvm_unittest.py    |   46 +++++++++++++++++++++-
>  test/ganeti.hypervisor.hv_lxc_unittest.py    |   46 ++++++++++++++++++++++
>  test/ganeti.hypervisor.hv_xen_unittest.py    |   48 +++++++++++++++++++++++
>  13 files changed, 300 insertions(+), 42 deletions(-)
>  create mode 100755 test/ganeti.hypervisor.hv_chroot_unittest.py
>  create mode 100755 test/ganeti.hypervisor.hv_fake_unittest.py
>  create mode 100755 test/ganeti.hypervisor.hv_lxc_unittest.py
>  create mode 100755 test/ganeti.hypervisor.hv_xen_unittest.py
>
> diff --git a/Makefile.am b/Makefile.am
> index 6c25dca..612a98a 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -449,7 +449,11 @@ python_tests = \
>        test/ganeti.ht_unittest.py \
>        test/ganeti.http_unittest.py \
>        test/ganeti.hypervisor_unittest.py \
> +       test/ganeti.hypervisor.hv_chroot_unittest.py \
> +       test/ganeti.hypervisor.hv_fake_unittest.py \
>        test/ganeti.hypervisor.hv_kvm_unittest.py \
> +       test/ganeti.hypervisor.hv_lxc_unittest.py \
> +       test/ganeti.hypervisor.hv_xen_unittest.py \
>        test/ganeti.impexpd_unittest.py \
>        test/ganeti.jqueue_unittest.py \
>        test/ganeti.locking_unittest.py \
> diff --git a/lib/cmdlib.py b/lib/cmdlib.py
> index 996489e..5a4a08f 100644
> --- a/lib/cmdlib.py
> +++ b/lib/cmdlib.py
> @@ -7691,14 +7691,9 @@ class LUConnectConsole(NoHooksLU):
>     # instance and then saving the defaults in the instance itself.
>     hvparams = cluster.FillHV(instance)
>     beparams = cluster.FillBE(instance)
> -    console_cmd = hyper.GetShellCommandForConsole(instance, hvparams, 
> beparams)
> -
> -    console = objects.InstanceConsole(instance=instance.name,
> -                                      kind=constants.CONS_SSH,
> -                                      host=node,
> -                                      user="root",
> -                                      command=console_cmd)
> +    console = hyper.GetInstanceConsole(instance, hvparams, beparams)
>
> +    assert console.instance == instance.name
>     assert console.Validate()
>
>     return console.ToDict()
> diff --git a/lib/hypervisor/hv_base.py b/lib/hypervisor/hv_base.py
> index 80675ee..ec47400 100644
> --- a/lib/hypervisor/hv_base.py
> +++ b/lib/hypervisor/hv_base.py
> @@ -206,8 +206,8 @@ class BaseHypervisor(object):
>     raise NotImplementedError
>
>   @classmethod
> -  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
> -    """Return a command for connecting to the console of an instance.
> +  def GetInstanceConsole(cls, instance, hvparams, beparams):
> +    """Return information for connecting to the console of an instance.
>
>     """
>     raise NotImplementedError
> diff --git a/lib/hypervisor/hv_chroot.py b/lib/hypervisor/hv_chroot.py
> index f33fed2..bf679e7 100644
> --- a/lib/hypervisor/hv_chroot.py
> +++ b/lib/hypervisor/hv_chroot.py
> @@ -31,6 +31,7 @@ import logging
>  from ganeti import constants
>  from ganeti import errors # pylint: disable-msg=W0611
>  from ganeti import utils
> +from ganeti import objects
>  from ganeti.hypervisor import hv_base
>  from ganeti.errors import HypervisorError
>
> @@ -246,15 +247,20 @@ class ChrootManager(hv_base.BaseHypervisor):
>     return self.GetLinuxNodeInfo()
>
>   @classmethod
> -  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
> -    """Return a command for connecting to the console of an instance.
> +  def GetInstanceConsole(cls, instance, hvparams, beparams, root_dir=None):
> +    """Return information for connecting to the console of an instance.
>
>     """
> -    root_dir = cls._InstanceDir(instance.name)
> -    if not os.path.ismount(root_dir):
> -      raise HypervisorError("Instance %s is not running" % instance.name)
> -
> -    return "chroot %s" % root_dir
> +    if root_dir is None:
> +      root_dir = cls._InstanceDir(instance.name)
> +      if not os.path.ismount(root_dir):
> +        raise HypervisorError("Instance %s is not running" % instance.name)
> +
> +    return objects.InstanceConsole(instance=instance.name,
> +                                   kind=constants.CONS_SSH,
> +                                   host=instance.primary_node,
> +                                   user=constants.GANETI_RUNAS,
> +                                   command=["chroot", root_dir])
>
>   def Verify(self):
>     """Verify the hypervisor.
> diff --git a/lib/hypervisor/hv_fake.py b/lib/hypervisor/hv_fake.py
> index 2d386d2..9e5f96e 100644
> --- a/lib/hypervisor/hv_fake.py
> +++ b/lib/hypervisor/hv_fake.py
> @@ -30,6 +30,7 @@ import logging
>  from ganeti import utils
>  from ganeti import constants
>  from ganeti import errors
> +from ganeti import objects
>  from ganeti.hypervisor import hv_base
>
>
> @@ -204,11 +205,14 @@ class FakeHypervisor(hv_base.BaseHypervisor):
>     return result
>
>   @classmethod
> -  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
> -    """Return a command for connecting to the console of an instance.
> +  def GetInstanceConsole(cls, instance, hvparams, beparams):
> +    """Return information for connecting to the console of an instance.
>
>     """
> -    return "echo Console not available for fake hypervisor"
> +    return objects.InstanceConsole(instance=instance.name,
> +                                   kind=constants.CONS_MESSAGE,
> +                                   message=("Console not available for fake"
> +                                            " hypervisor"))
>
>   def Verify(self):
>     """Verify the hypervisor.
> diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py
> index 0538ffb..46f41c5 100644
> --- a/lib/hypervisor/hv_kvm.py
> +++ b/lib/hypervisor/hv_kvm.py
> @@ -1035,28 +1035,33 @@ class KVMHypervisor(hv_base.BaseHypervisor):
>     return self.GetLinuxNodeInfo()
>
>   @classmethod
> -  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
> +  def GetInstanceConsole(cls, instance, hvparams, beparams):
>     """Return a command for connecting to the console of an instance.
>
>     """
>     if hvparams[constants.HV_SERIAL_CONSOLE]:
> -      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
> -                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
> -                        
> utils.ShellQuote(cls._InstanceSerial(instance.name))))
> -    else:
> -      shell_command = "echo 'No serial shell for instance %s'" % 
> instance.name
> +      cmd = [constants.SOCAT_PATH,
> +             "STDIO,%s" % cls._SocatUnixConsoleParams(),
> +             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
> +      return objects.InstanceConsole(instance=instance.name,
> +                                     kind=constants.CONS_SSH,
> +                                     host=instance.primary_node,
> +                                     user=constants.GANETI_RUNAS,
> +                                     command=cmd)
>
>     vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
> -    if vnc_bind_address:
> -      if instance.network_port > constants.VNC_BASE_PORT:
> -        display = instance.network_port - constants.VNC_BASE_PORT
> -        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
> -                       " (display: %d)'" % (vnc_bind_address,
> -                                            instance.network_port,
> -                                            display))
> -        shell_command = "%s; %s" % (vnc_command, shell_command)
> -
> -    return shell_command
> +    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
> +      display = instance.network_port - constants.VNC_BASE_PORT
> +      return objects.InstanceConsole(instance=instance.name,
> +                                     kind=constants.CONS_VNC,
> +                                     host=vnc_bind_address,
> +                                     port=instance.network_port,
> +                                     display=display)
> +
> +    return objects.InstanceConsole(instance=instance.name,
> +                                   kind=constants.CONS_MESSAGE,
> +                                   message=("No serial shell for instance 
> %s" %
> +                                            instance.name))
>
>   def Verify(self):
>     """Verify the hypervisor.
> @@ -1069,7 +1074,6 @@ class KVMHypervisor(hv_base.BaseHypervisor):
>     if not os.path.exists(constants.SOCAT_PATH):
>       return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
>
> -
>   @classmethod
>   def CheckParameterSyntax(cls, hvparams):
>     """Check the given parameters for validity.
> diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py
> index 3779a68..78c1f34 100644
> --- a/lib/hypervisor/hv_lxc.py
> +++ b/lib/hypervisor/hv_lxc.py
> @@ -31,6 +31,7 @@ import logging
>  from ganeti import constants
>  from ganeti import errors # pylint: disable-msg=W0611
>  from ganeti import utils
> +from ganeti import objects
>  from ganeti.hypervisor import hv_base
>  from ganeti.errors import HypervisorError
>
> @@ -374,11 +375,15 @@ class LXCHypervisor(hv_base.BaseHypervisor):
>     return self.GetLinuxNodeInfo()
>
>   @classmethod
> -  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
> +  def GetInstanceConsole(cls, instance, hvparams, beparams):
>     """Return a command for connecting to the console of an instance.
>
>     """
> -    return "lxc-console -n %s" % instance.name
> +    return objects.InstanceConsole(instance=instance.name,
> +                                   kind=constants.CONS_SSH,
> +                                   host=instance.primary_node,
> +                                   user=constants.GANETI_RUNAS,
> +                                   command=["lxc-console", "-n", 
> instance.name])
>
>   def Verify(self):
>     """Verify the hypervisor.
> diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
> index 5d6de5c..8d36e20 100644
> --- a/lib/hypervisor/hv_xen.py
> +++ b/lib/hypervisor/hv_xen.py
> @@ -31,6 +31,7 @@ from ganeti import errors
>  from ganeti import utils
>  from ganeti.hypervisor import hv_base
>  from ganeti import netutils
> +from ganeti import objects
>
>
>  class XenHypervisor(hv_base.BaseHypervisor):
> @@ -294,12 +295,15 @@ class XenHypervisor(hv_base.BaseHypervisor):
>     return result
>
>   @classmethod
> -  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
> +  def GetInstanceConsole(cls, instance, hvparams, beparams):
>     """Return a command for connecting to the console of an instance.
>
>     """
> -    return "xm console %s" % instance.name
> -
> +    return objects.InstanceConsole(instance=instance.name,
> +                                   kind=constants.CONS_SSH,
> +                                   host=instance.primary_node,
> +                                   user=constants.GANETI_RUNAS,
> +                                   command=["xm", "console", instance.name])
>
>   def Verify(self):
>     """Verify the hypervisor.
> diff --git a/test/ganeti.hypervisor.hv_chroot_unittest.py 
> b/test/ganeti.hypervisor.hv_chroot_unittest.py
> new file mode 100755
> index 0000000..233808c
> --- /dev/null
> +++ b/test/ganeti.hypervisor.hv_chroot_unittest.py
> @@ -0,0 +1,54 @@
> +#!/usr/bin/python
> +#
> +
> +# Copyright (C) 2011 Google Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +# 02110-1301, USA.
> +
> +
> +"""Script for testing ganeti.hypervisor.hv_chroot"""
> +
> +import unittest
> +import tempfile
> +import shutil
> +
> +from ganeti import constants
> +from ganeti import objects
> +from ganeti import hypervisor
> +
> +from ganeti.hypervisor import hv_chroot
> +
> +import testutils
> +
> +
> +class TestConsole(unittest.TestCase):
> +  def setUp(self):
> +    self.tmpdir = tempfile.mkdtemp()
> +
> +  def tearDown(self):
> +    shutil.rmtree(self.tmpdir)
> +
> +  def test(self):
> +    instance = objects.Instance(name="fake.example.com", 
> primary_node="node837")
> +    cons = hv_chroot.ChrootManager.GetInstanceConsole(instance, {}, {},
> +                                                      root_dir=self.tmpdir)
> +    self.assertTrue(cons.Validate())
> +    self.assertEqual(cons.kind, constants.CONS_SSH)
> +    self.assertEqual(cons.host, instance.primary_node)
> +
> +
> +if __name__ == "__main__":
> +  testutils.GanetiTestProgram()
> diff --git a/test/ganeti.hypervisor.hv_fake_unittest.py 
> b/test/ganeti.hypervisor.hv_fake_unittest.py
> new file mode 100755
> index 0000000..e0c4240
> --- /dev/null
> +++ b/test/ganeti.hypervisor.hv_fake_unittest.py
> @@ -0,0 +1,44 @@
> +#!/usr/bin/python
> +#
> +
> +# Copyright (C) 2011 Google Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +# 02110-1301, USA.
> +
> +
> +"""Script for testing ganeti.hypervisor.hv_fake"""
> +
> +import unittest
> +
> +from ganeti import constants
> +from ganeti import objects
> +from ganeti import hypervisor
> +
> +from ganeti.hypervisor import hv_fake
> +
> +import testutils
> +
> +
> +class TestConsole(unittest.TestCase):
> +  def test(self):
> +    instance = objects.Instance(name="fake.example.com")
> +    cons = hv_fake.FakeHypervisor.GetInstanceConsole(instance, {}, {})
> +    self.assertTrue(cons.Validate())
> +    self.assertEqual(cons.kind, constants.CONS_MESSAGE)
> +
> +
> +if __name__ == "__main__":
> +  testutils.GanetiTestProgram()
> diff --git a/test/ganeti.hypervisor.hv_kvm_unittest.py 
> b/test/ganeti.hypervisor.hv_kvm_unittest.py
> index 28a936b..c2a964f 100755
> --- a/test/ganeti.hypervisor.hv_kvm_unittest.py
> +++ b/test/ganeti.hypervisor.hv_kvm_unittest.py
> @@ -1,7 +1,7 @@
>  #!/usr/bin/python
>  #
>
> -# Copyright (C) 2010 Google Inc.
> +# Copyright (C) 2010, 2011 Google Inc.
>  #
>  # This program is free software; you can redistribute it and/or modify
>  # it under the terms of the GNU General Public License as published by
> @@ -80,5 +80,49 @@ class TestWriteNetScript(unittest.TestCase):
>                       inst, nic, 2)
>
>
> +class TestConsole(unittest.TestCase):
> +  def _Test(self, instance, hvparams):
> +    cons = hv_kvm.KVMHypervisor.GetInstanceConsole(instance, hvparams, {})
> +    self.assertTrue(cons.Validate())
> +    return cons
> +
> +  def testSerial(self):
> +    instance = objects.Instance(name="kvm.example.com",
> +                                primary_node="node6017")
> +    hvparams = {
> +      constants.HV_SERIAL_CONSOLE: True,
> +      constants.HV_VNC_BIND_ADDRESS: None,
> +      }
> +    cons = self._Test(instance, hvparams)
> +    self.assertEqual(cons.kind, constants.CONS_SSH)
> +    self.assertEqual(cons.host, instance.primary_node)
> +    self.assertEqual(cons.command[0], constants.SOCAT_PATH)
> +
> +  def testVnc(self):
> +    instance = objects.Instance(name="kvm.example.com",
> +                                primary_node="node7235",
> +                                network_port=constants.VNC_BASE_PORT + 10)
> +    hvparams = {
> +      constants.HV_SERIAL_CONSOLE: False,
> +      constants.HV_VNC_BIND_ADDRESS: "192.0.2.1",
> +      }
> +    cons = self._Test(instance, hvparams)
> +    self.assertEqual(cons.kind, constants.CONS_VNC)
> +    self.assertEqual(cons.host, "192.0.2.1")
> +    self.assertEqual(cons.port, constants.VNC_BASE_PORT + 10)
> +    self.assertEqual(cons.display, 10)
> +
> +  def testNoConsole(self):
> +    instance = objects.Instance(name="kvm.example.com",
> +                                primary_node="node24325",
> +                                network_port=0)
> +    hvparams = {
> +      constants.HV_SERIAL_CONSOLE: False,
> +      constants.HV_VNC_BIND_ADDRESS: None,
> +      }
> +    cons = self._Test(instance, hvparams)
> +    self.assertEqual(cons.kind, constants.CONS_MESSAGE)
> +
> +
>  if __name__ == "__main__":
>   testutils.GanetiTestProgram()
> diff --git a/test/ganeti.hypervisor.hv_lxc_unittest.py 
> b/test/ganeti.hypervisor.hv_lxc_unittest.py
> new file mode 100755
> index 0000000..9d9e441
> --- /dev/null
> +++ b/test/ganeti.hypervisor.hv_lxc_unittest.py
> @@ -0,0 +1,46 @@
> +#!/usr/bin/python
> +#
> +
> +# Copyright (C) 2011 Google Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +# 02110-1301, USA.
> +
> +
> +"""Script for testing ganeti.hypervisor.hv_lxc"""
> +
> +import unittest
> +
> +from ganeti import constants
> +from ganeti import objects
> +from ganeti import hypervisor
> +
> +from ganeti.hypervisor import hv_lxc
> +
> +import testutils
> +
> +
> +class TestConsole(unittest.TestCase):
> +  def test(self):
> +    instance = objects.Instance(name="lxc.example.com", 
> primary_node="node199")
> +    cons = hv_lxc.LXCHypervisor.GetInstanceConsole(instance, {}, {})
> +    self.assertTrue(cons.Validate())
> +    self.assertEqual(cons.kind, constants.CONS_SSH)
> +    self.assertEqual(cons.host, instance.primary_node)
> +    self.assertEqual(cons.command[-1], instance.name)
> +
> +
> +if __name__ == "__main__":
> +  testutils.GanetiTestProgram()
> diff --git a/test/ganeti.hypervisor.hv_xen_unittest.py 
> b/test/ganeti.hypervisor.hv_xen_unittest.py
> new file mode 100755
> index 0000000..dc86839
> --- /dev/null
> +++ b/test/ganeti.hypervisor.hv_xen_unittest.py
> @@ -0,0 +1,48 @@
> +#!/usr/bin/python
> +#
> +
> +# Copyright (C) 2011 Google Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +# 02110-1301, USA.
> +
> +
> +"""Script for testing ganeti.hypervisor.hv_lxc"""
> +
> +import unittest
> +
> +from ganeti import constants
> +from ganeti import objects
> +from ganeti import hypervisor
> +
> +from ganeti.hypervisor import hv_xen
> +
> +import testutils
> +
> +
> +class TestConsole(unittest.TestCase):
> +  def test(self):
> +    for cls in [hv_xen.XenPvmHypervisor, hv_xen.XenHvmHypervisor]:
> +      instance = objects.Instance(name="xen.example.com",
> +                                  primary_node="node24828")
> +      cons = cls.GetInstanceConsole(instance, {}, {})
> +      self.assertTrue(cons.Validate())
> +      self.assertEqual(cons.kind, constants.CONS_SSH)
> +      self.assertEqual(cons.host, instance.primary_node)
> +      self.assertEqual(cons.command[-1], instance.name)
> +
> +
> +if __name__ == "__main__":
> +  testutils.GanetiTestProgram()
> --
> 1.7.3.1

LGTM

>
>

Reply via email to