diff --git a/nova/tests/fakeguestfs.py b/nova/tests/fakeguestfs.py index c8424282d51c..7a3b33039c25 100644 --- a/nova/tests/fakeguestfs.py +++ b/nova/tests/fakeguestfs.py @@ -27,6 +27,7 @@ class GuestFS(object): self.files = {} self.auginit = False self.root_mounted = False + self.backend_settings = None def launch(self): self.running = True @@ -36,6 +37,9 @@ class GuestFS(object): self.mounts = [] self.drives = [] + def set_backend_settings(self, settings): + self.backend_settings = settings + def close(self): self.closed = True diff --git a/nova/tests/virt/test_virt_disk_vfs_guestfs.py b/nova/tests/virt/test_virt_disk_vfs_guestfs.py index 353319b9887d..692576cdc0cb 100644 --- a/nova/tests/virt/test_virt_disk_vfs_guestfs.py +++ b/nova/tests/virt/test_virt_disk_vfs_guestfs.py @@ -27,12 +27,23 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): sys.modules['guestfs'] = fakeguestfs vfsimpl.guestfs = fakeguestfs - def test_appliance_setup_inspect(self): + def _do_test_appliance_setup_inspect(self, forcetcg): + if forcetcg: + vfsimpl.force_tcg() + else: + vfsimpl.force_tcg(False) + vfs = vfsimpl.VFSGuestFS(imgfile="/dummy.qcow2", imgfmt="qcow2", partition=-1) vfs.setup() + if forcetcg: + self.assertEqual(vfs.handle.backend_settings, "force_tcg") + vfsimpl.force_tcg(False) + else: + self.assertIsNone(vfs.handle.backend_settings) + self.assertEqual(vfs.handle.running, True) self.assertEqual(len(vfs.handle.mounts), 3) self.assertEqual(vfs.handle.mounts[0][1], @@ -52,6 +63,12 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): self.assertEqual(handle.closed, True) self.assertEqual(len(handle.mounts), 0) + def test_appliance_setup_inspect_auto(self): + self._do_test_appliance_setup_inspect(False) + + def test_appliance_setup_inspect_tcg(self): + self._do_test_appliance_setup_inspect(True) + def test_appliance_setup_inspect_no_root_raises(self): vfs = vfsimpl.VFSGuestFS(imgfile="/dummy.qcow2", imgfmt="qcow2", @@ -59,6 +76,8 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): # call setup to init the handle so we can stub it vfs.setup() + self.assertIsNone(vfs.handle.backend_settings) + def fake_inspect_os(): return [] @@ -72,6 +91,8 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): # call setup to init the handle so we can stub it vfs.setup() + self.assertIsNone(vfs.handle.backend_settings) + def fake_inspect_os(): return ['fake1', 'fake2'] @@ -84,6 +105,7 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): partition=None) vfs.setup() + self.assertIsNone(vfs.handle.backend_settings) self.assertEqual(vfs.handle.running, True) self.assertEqual(len(vfs.handle.mounts), 1) self.assertEqual(vfs.handle.mounts[0][1], "/dev/sda") @@ -103,6 +125,7 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): partition=2) vfs.setup() + self.assertIsNone(vfs.handle.backend_settings) self.assertEqual(vfs.handle.running, True) self.assertEqual(len(vfs.handle.mounts), 1) self.assertEqual(vfs.handle.mounts[0][1], "/dev/sda2") diff --git a/nova/virt/disk/vfs/guestfs.py b/nova/virt/disk/vfs/guestfs.py index a65f649ab3f7..fabfde5ba415 100644 --- a/nova/virt/disk/vfs/guestfs.py +++ b/nova/virt/disk/vfs/guestfs.py @@ -15,7 +15,7 @@ from eventlet import tpool from nova import exception -from nova.i18n import _ +from nova.i18n import _, _LI from nova.openstack.common import importutils from nova.openstack.common import log as logging from nova.virt.disk.vfs import api as vfs @@ -24,6 +24,18 @@ from nova.virt.disk.vfs import api as vfs LOG = logging.getLogger(__name__) guestfs = None +forceTCG = False + + +def force_tcg(force=True): + """Prevent libguestfs trying to use KVM acceleration + + It is a good idea to call this if it is known that + KVM is not desired, even if technically available. + """ + + global forceTCG + forceTCG = force class VFSGuestFS(vfs.VFS): @@ -116,6 +128,16 @@ class VFSGuestFS(vfs.VFS): else: raise + try: + if forceTCG: + self.handle.set_backend_settings("force_tcg") + except AttributeError as ex: + # set_backend_settings method doesn't exist in older + # libguestfs versions, so nothing we can do but ignore + LOG.info(_LI("Unable to force TCG mode, libguestfs too old?"), + ex) + pass + try: self.handle.add_drive_opts(self.imgfile, format=self.imgfmt) self.handle.launch() diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 7759b940fbfd..16c4e695cdf3 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -81,6 +81,7 @@ from nova import version from nova.virt import block_device as driver_block_device from nova.virt import configdrive from nova.virt.disk import api as disk +from nova.virt.disk.vfs import guestfs from nova.virt import driver from nova.virt import event as virtevent from nova.virt import firewall @@ -631,6 +632,12 @@ class LibvirtDriver(driver.ComputeDriver): libvirt.virEventRegisterDefaultImpl() self._do_quality_warnings() + # Stop libguestfs using KVM unless we're also configured + # to use this. This solves problem where people need to + # stop Nova use of KVM because nested-virt is broken + if CONF.libvirt.virt_type != "kvm": + guestfs.force_tcg() + if not self._has_min_version(MIN_LIBVIRT_VERSION): major = MIN_LIBVIRT_VERSION[0] minor = MIN_LIBVIRT_VERSION[1]