virt: force TCG with libguestfs unless KVM is enabled in libvirt

If the libvirt driver has not been configured to use KVM, then
the libguestfs module should be forced to use TCG. This is
particularly important when running Nova inside a VM, which
might claim to have VMX/SVM support when it is in fact broken.
This will avoid libguestfs hanging in such scenarios.

Resolves-bug: #1286256
Change-Id: I9316dcedd65244c60d468b270311f032b45b051f
This commit is contained in:
Daniel P. Berrange 2014-07-02 18:06:30 +01:00
parent 7d1af66a70
commit 8b6ea606d9
4 changed files with 58 additions and 2 deletions

View File

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

View File

@ -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")

View File

@ -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()

View File

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