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 > >
