libvirt: enable hyperv enlightenments for windows guests
All windows guests (ie os_type=windows) now get the following enabled <features> <hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='8191'/> </hyperv> <features/> if running a new enough libvirt and QEMU Closes-bug: #1400315 Change-Id: Icd0fe9bda6402d9bf7a4bab8077f0ce755703999
This commit is contained in:
parent
31d91d9de3
commit
12cf893fd9
|
@ -1598,6 +1598,90 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
self.assertEqual("hypervclock", cfg.clock.timers[3].name)
|
||||
self.assertTrue(cfg.clock.timers[3].present)
|
||||
|
||||
self.assertEqual(3, len(cfg.features))
|
||||
self.assertIsInstance(cfg.features[0],
|
||||
vconfig.LibvirtConfigGuestFeatureACPI)
|
||||
self.assertIsInstance(cfg.features[1],
|
||||
vconfig.LibvirtConfigGuestFeatureAPIC)
|
||||
self.assertIsInstance(cfg.features[2],
|
||||
vconfig.LibvirtConfigGuestFeatureHyperV)
|
||||
|
||||
@mock.patch.object(host.Host, 'has_min_version')
|
||||
@mock.patch.object(objects.Flavor, 'get_by_id')
|
||||
def test_get_guest_config_windows_hyperv_feature1(self,
|
||||
mock_flavor,
|
||||
mock_version):
|
||||
def fake_version(lv_ver=None, hv_ver=None, hv_type=None):
|
||||
if lv_ver == (1, 0, 0) and hv_ver == (1, 1, 0):
|
||||
return True
|
||||
return False
|
||||
|
||||
mock_version.side_effect = fake_version
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
instance_ref['os_type'] = 'windows'
|
||||
flavor = instance_ref.get_flavor()
|
||||
flavor.extra_specs = {}
|
||||
mock_flavor.return_value = flavor
|
||||
|
||||
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
|
||||
instance_ref)
|
||||
cfg = conn._get_guest_config(instance_ref,
|
||||
_fake_network_info(self.stubs, 1),
|
||||
{}, disk_info)
|
||||
|
||||
self.assertIsInstance(cfg.clock,
|
||||
vconfig.LibvirtConfigGuestClock)
|
||||
self.assertEqual(cfg.clock.offset, "localtime")
|
||||
|
||||
self.assertEqual(3, len(cfg.features))
|
||||
self.assertIsInstance(cfg.features[0],
|
||||
vconfig.LibvirtConfigGuestFeatureACPI)
|
||||
self.assertIsInstance(cfg.features[1],
|
||||
vconfig.LibvirtConfigGuestFeatureAPIC)
|
||||
self.assertIsInstance(cfg.features[2],
|
||||
vconfig.LibvirtConfigGuestFeatureHyperV)
|
||||
|
||||
self.assertTrue(cfg.features[2].relaxed)
|
||||
self.assertFalse(cfg.features[2].spinlocks)
|
||||
self.assertFalse(cfg.features[2].vapic)
|
||||
|
||||
@mock.patch.object(host.Host, 'has_min_version')
|
||||
@mock.patch.object(objects.Flavor, 'get_by_id')
|
||||
def test_get_guest_config_windows_hyperv_feature2(self,
|
||||
mock_flavor,
|
||||
mock_version):
|
||||
mock_version.return_value = True
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
instance_ref['os_type'] = 'windows'
|
||||
flavor = instance_ref.get_flavor()
|
||||
flavor.extra_specs = {}
|
||||
mock_flavor.return_value = flavor
|
||||
|
||||
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
|
||||
instance_ref)
|
||||
cfg = conn._get_guest_config(instance_ref,
|
||||
_fake_network_info(self.stubs, 1),
|
||||
{}, disk_info)
|
||||
|
||||
self.assertIsInstance(cfg.clock,
|
||||
vconfig.LibvirtConfigGuestClock)
|
||||
self.assertEqual(cfg.clock.offset, "localtime")
|
||||
|
||||
self.assertEqual(3, len(cfg.features))
|
||||
self.assertIsInstance(cfg.features[0],
|
||||
vconfig.LibvirtConfigGuestFeatureACPI)
|
||||
self.assertIsInstance(cfg.features[1],
|
||||
vconfig.LibvirtConfigGuestFeatureAPIC)
|
||||
self.assertIsInstance(cfg.features[2],
|
||||
vconfig.LibvirtConfigGuestFeatureHyperV)
|
||||
|
||||
self.assertTrue(cfg.features[2].relaxed)
|
||||
self.assertTrue(cfg.features[2].spinlocks)
|
||||
self.assertEqual(8191, cfg.features[2].spinlock_retries)
|
||||
self.assertTrue(cfg.features[2].vapic)
|
||||
|
||||
@mock.patch.object(objects.Flavor, 'get_by_id')
|
||||
def test_get_guest_config_with_two_nics(self, mock_flavor):
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
|
|
|
@ -365,6 +365,10 @@ MIN_LIBVIRT_FSFREEZE_VERSION = (1, 2, 5)
|
|||
MIN_LIBVIRT_HYPERV_TIMER_VERSION = (1, 2, 2)
|
||||
MIN_QEMU_HYPERV_TIMER_VERSION = (2, 0, 0)
|
||||
|
||||
MIN_LIBVIRT_HYPERV_FEATURE_VERSION = (1, 0, 0)
|
||||
MIN_LIBVIRT_HYPERV_FEATURE_EXTRA_VERSION = (1, 1, 0)
|
||||
MIN_QEMU_HYPERV_FEATURE_VERSION = (1, 1, 0)
|
||||
|
||||
|
||||
class LibvirtDriver(driver.ComputeDriver):
|
||||
|
||||
|
@ -3665,7 +3669,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
tmhyperv.present = True
|
||||
clk.add_timer(tmhyperv)
|
||||
|
||||
def _set_features(self, guest, caps, virt_type):
|
||||
def _set_features(self, guest, os_type, caps, virt_type):
|
||||
if virt_type == "xen":
|
||||
# PAE only makes sense in X86
|
||||
if caps.host.cpu.arch in (arch.I686, arch.X86_64):
|
||||
|
@ -3675,6 +3679,23 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
guest.features.append(vconfig.LibvirtConfigGuestFeatureACPI())
|
||||
guest.features.append(vconfig.LibvirtConfigGuestFeatureAPIC())
|
||||
|
||||
if (virt_type in ("qemu", "kvm") and
|
||||
os_type == 'windows' and
|
||||
self._host.has_min_version(MIN_LIBVIRT_HYPERV_FEATURE_VERSION,
|
||||
MIN_QEMU_HYPERV_FEATURE_VERSION)):
|
||||
hv = vconfig.LibvirtConfigGuestFeatureHyperV()
|
||||
hv.relaxed = True
|
||||
|
||||
if self._host.has_min_version(
|
||||
MIN_LIBVIRT_HYPERV_FEATURE_EXTRA_VERSION):
|
||||
hv.spinlocks = True
|
||||
# Increase spinlock retries - value recommended by
|
||||
# KVM maintainers who certify Windows guests
|
||||
# with Microsoft
|
||||
hv.spinlock_retries = 8191
|
||||
hv.vapic = True
|
||||
guest.features.append(hv)
|
||||
|
||||
def _create_serial_console_devices(self, guest, instance, flavor,
|
||||
image_meta):
|
||||
if CONF.serial_console.enabled:
|
||||
|
@ -3870,7 +3891,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
else:
|
||||
guest.os_boot_dev = blockinfo.get_boot_order(disk_info)
|
||||
|
||||
self._set_features(guest, caps, virt_type)
|
||||
self._set_features(guest, instance.os_type, caps, virt_type)
|
||||
self._set_clock(guest, instance.os_type, image_meta, virt_type)
|
||||
|
||||
storage_configs = self._get_guest_storage_config(
|
||||
|
|
Loading…
Reference in New Issue