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:
parent
7d1af66a70
commit
8b6ea606d9
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue