libvirt: check qemu version for NUMA & hugepage support
In commit 945ab28
the libvirt driver was modified to validate the
libvirt version before enabling NUMA and hugepage support.
While good, it's not sufficient. We also need to check the qemu
version since NUMA hugepage support wasn't added until version 2.1.
(See http://wiki.qemu.org/ChangeLog/2.1#x86, specifically the
memory-backend-* objects.)
We know that qemu on the s390x doesn't support NUMA or hugepages.
Support for ppc64 is possible but not yet determined...we can
update the supported list once we find out for sure.
Change-Id: Ib31c4f806e30a8b33669d5a15bd1578050c7e352
Closes-Bug: #1422775
This commit is contained in:
parent
f0ddb9f9a9
commit
7f4d7e0b67
|
@ -127,6 +127,7 @@ class NUMAServersTest(ServersTestBase):
|
|||
cpu_threads=2, kB_mem=15740000)
|
||||
fake_connection = fakelibvirt.Connection('qemu:///system',
|
||||
version=1002007,
|
||||
hv_version=2001000,
|
||||
host_info=host_info)
|
||||
|
||||
# Create a flavor
|
||||
|
|
|
@ -743,7 +743,8 @@ class DomainSnapshot(object):
|
|||
|
||||
|
||||
class Connection(object):
|
||||
def __init__(self, uri=None, readonly=False, version=9011, host_info=None):
|
||||
def __init__(self, uri=None, readonly=False, version=9011,
|
||||
hv_version=1001000, host_info=None):
|
||||
if not uri or uri == '':
|
||||
if allow_default_uri_connection:
|
||||
uri = 'qemu:///session'
|
||||
|
@ -775,7 +776,7 @@ class Connection(object):
|
|||
self._nodedevs = {}
|
||||
self._event_callbacks = {}
|
||||
self.fakeLibVersion = version
|
||||
self.fakeVersion = version
|
||||
self.fakeVersion = hv_version
|
||||
self.host_info = host_info or HostInfo()
|
||||
|
||||
def _add_filter(self, nwfilter):
|
||||
|
|
|
@ -1338,13 +1338,17 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(0, len(cfg.cputune.vcpupin))
|
||||
self.assertIsNone(cfg.cpu.numa)
|
||||
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getType')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
@mock.patch.object(host.Host, 'get_capabilities')
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver, '_set_host_enabled')
|
||||
def _test_get_guest_config_numa_unsupported(self, fake_version,
|
||||
exception_class, pagesize,
|
||||
mock_host,
|
||||
mock_caps, mock_version):
|
||||
def _test_get_guest_config_numa_unsupported(self, fake_lib_version,
|
||||
fake_version, fake_type,
|
||||
fake_arch, exception_class,
|
||||
pagesize, mock_host,
|
||||
mock_caps, mock_lib_version,
|
||||
mock_version, mock_type):
|
||||
instance_topology = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0]),
|
||||
|
@ -1360,10 +1364,12 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
caps = vconfig.LibvirtConfigCaps()
|
||||
caps.host = vconfig.LibvirtConfigCapsHost()
|
||||
caps.host.cpu = vconfig.LibvirtConfigCPU()
|
||||
caps.host.cpu.arch = "x86_64"
|
||||
caps.host.cpu.arch = fake_arch
|
||||
caps.host.topology = self._fake_caps_numa_topology()
|
||||
|
||||
mock_type.return_value = fake_type
|
||||
mock_version.return_value = fake_version
|
||||
mock_lib_version.return_value = fake_lib_version
|
||||
mock_caps.return_value = caps
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
|
@ -1375,12 +1381,42 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
drvr._get_guest_config,
|
||||
instance_ref, [], {}, disk_info)
|
||||
|
||||
def test_get_guest_config_numa_old_version(self):
|
||||
def test_get_guest_config_numa_old_version_libvirt(self):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
|
||||
self._test_get_guest_config_numa_unsupported(
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_NUMA_VERSION) - 1,
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION),
|
||||
libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE,
|
||||
arch.X86_64,
|
||||
exception.NUMATopologyUnsupported,
|
||||
None)
|
||||
|
||||
def test_get_guest_config_numa_old_version_qemu(self):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
|
||||
self._test_get_guest_config_numa_unsupported(
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_NUMA_VERSION),
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION) - 1,
|
||||
libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE,
|
||||
arch.X86_64,
|
||||
exception.NUMATopologyUnsupported,
|
||||
None)
|
||||
|
||||
def test_get_guest_config_numa_other_arch_qemu(self):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
|
||||
self._test_get_guest_config_numa_unsupported(
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_NUMA_VERSION),
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION),
|
||||
libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE,
|
||||
arch.PPC64,
|
||||
exception.NUMATopologyUnsupported,
|
||||
None)
|
||||
|
||||
|
@ -1390,18 +1426,38 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
self._test_get_guest_config_numa_unsupported(
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_NUMA_VERSION),
|
||||
utils.convert_version_to_int((4, 5, 0)),
|
||||
'XEN',
|
||||
arch.X86_64,
|
||||
exception.NUMATopologyUnsupported,
|
||||
None)
|
||||
|
||||
def test_get_guest_config_numa_old_pages(self):
|
||||
def test_get_guest_config_numa_old_pages_libvirt(self):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
|
||||
self._test_get_guest_config_numa_unsupported(
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_HUGEPAGE_VERSION) - 1,
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION),
|
||||
libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE,
|
||||
arch.X86_64,
|
||||
exception.MemoryPagesUnsupported,
|
||||
2048)
|
||||
|
||||
def test_get_guest_config_numa_old_pages_qemu(self):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
|
||||
self._test_get_guest_config_numa_unsupported(
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_HUGEPAGE_VERSION),
|
||||
utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION) - 1,
|
||||
libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE,
|
||||
arch.X86_64,
|
||||
exception.NUMATopologyUnsupported,
|
||||
2048)
|
||||
|
||||
def test_get_guest_config_numa_host_instance_fit_w_cpu_pinset(self):
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
image_meta = {}
|
||||
|
@ -8816,6 +8872,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
def _test_get_host_numa_topology(self, mempages):
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
caps.host = vconfig.LibvirtConfigCapsHost()
|
||||
caps.host.cpu = vconfig.LibvirtConfigCPU()
|
||||
caps.host.cpu.arch = arch.X86_64
|
||||
caps.host.topology = self._fake_caps_numa_topology()
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
@ -8873,17 +8931,24 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
def test_get_host_numa_topology(self, mock_version):
|
||||
self._test_get_host_numa_topology(mempages=True)
|
||||
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getType')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
def test_get_host_numa_topology_no_mempages(self, mock_version):
|
||||
def test_get_host_numa_topology_no_mempages(self, mock_lib_version,
|
||||
mock_version, mock_type):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
|
||||
mock_version.return_value = utils.convert_version_to_int(
|
||||
mock_lib_version.return_value = utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_HUGEPAGE_VERSION) - 1
|
||||
mock_version.return_value = utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION)
|
||||
mock_type.return_value = libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE
|
||||
self._test_get_host_numa_topology(mempages=False)
|
||||
|
||||
def test_get_host_numa_topology_empty(self):
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
caps.host = vconfig.LibvirtConfigCapsHost()
|
||||
caps.host.cpu = vconfig.LibvirtConfigCPU()
|
||||
caps.host.cpu.arch = arch.X86_64
|
||||
caps.host.topology = None
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
@ -8893,22 +8958,36 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
return_value=caps)
|
||||
) as (has_min_version, get_caps):
|
||||
self.assertIsNone(drvr._get_host_numa_topology())
|
||||
get_caps.assert_called_once_with()
|
||||
self.assertEqual(2, get_caps.call_count)
|
||||
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getType')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
def test_get_host_numa_topology_old_version(self, mock_version):
|
||||
def test_get_host_numa_topology_old_version(self, mock_lib_version,
|
||||
mock_version, mock_type):
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
||||
mock_version.side_effect = utils.convert_version_to_int(
|
||||
mock_lib_version.return_value = utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_NUMA_VERSION) - 1
|
||||
mock_version.return_value = utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION)
|
||||
mock_type.return_value = libvirt_driver.REQ_HYPERVISOR_NUMA_HUGEPAGE
|
||||
self.assertIsNone(drvr._get_host_numa_topology())
|
||||
|
||||
@mock.patch.object(host.Host, 'has_min_version', return_value=True)
|
||||
def test_get_host_numa_topology_xen(self, mock_version):
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getType')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getVersion')
|
||||
@mock.patch.object(fakelibvirt.Connection, 'getLibVersion')
|
||||
def test_get_host_numa_topology_xen(self, mock_lib_version,
|
||||
mock_version, mock_type):
|
||||
self.flags(virt_type='xen', group='libvirt')
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
||||
mock_lib_version.return_value = utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_NUMA_VERSION)
|
||||
mock_version.return_value = utils.convert_version_to_int(
|
||||
libvirt_driver.MIN_QEMU_NUMA_HUGEPAGE_VERSION)
|
||||
mock_type.return_value = 'xen'
|
||||
self.assertIsNone(drvr._get_host_numa_topology())
|
||||
|
||||
def test_diagnostic_vcpus_exception(self):
|
||||
|
@ -11160,7 +11239,7 @@ class HostStateTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(stats["memory_mb_used"], 88)
|
||||
self.assertEqual(stats["local_gb_used"], 20)
|
||||
self.assertEqual(stats["hypervisor_type"], 'QEMU')
|
||||
self.assertEqual(stats["hypervisor_version"], 9011)
|
||||
self.assertEqual(stats["hypervisor_version"], 1001000)
|
||||
self.assertEqual(stats["hypervisor_hostname"], 'compute1')
|
||||
cpu_info = jsonutils.loads(stats["cpu_info"])
|
||||
self.assertEqual(cpu_info,
|
||||
|
|
|
@ -364,6 +364,11 @@ MIN_LIBVIRT_NUMA_VERSION = (1, 2, 7)
|
|||
MIN_LIBVIRT_HUGEPAGE_VERSION = (1, 2, 8)
|
||||
# missing libvirt cpu pinning support
|
||||
BAD_LIBVIRT_CPU_POLICY_VERSIONS = [(1, 2, 9, 2), (1, 2, 10)]
|
||||
# qemu 2.1 introduces support for pinning memory on host
|
||||
# NUMA nodes, along with the ability to specify hugepage
|
||||
# sizes per guest NUMA node
|
||||
MIN_QEMU_NUMA_HUGEPAGE_VERSION = (2, 1, 0)
|
||||
REQ_HYPERVISOR_NUMA_HUGEPAGE = "QEMU"
|
||||
# fsFreeze/fsThaw requirement
|
||||
MIN_LIBVIRT_FSFREEZE_VERSION = (1, 2, 5)
|
||||
|
||||
|
@ -4741,22 +4746,24 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
return jsonutils.dumps(pci_info)
|
||||
|
||||
def _has_numa_support(self):
|
||||
if not self._host.has_min_version(MIN_LIBVIRT_NUMA_VERSION):
|
||||
return False
|
||||
|
||||
if CONF.libvirt.virt_type not in ['qemu', 'kvm']:
|
||||
return False
|
||||
|
||||
return True
|
||||
# This means that the host can support LibvirtConfigGuestNUMATune
|
||||
# and the nodeset field in LibvirtConfigGuestMemoryBackingPage
|
||||
supported_archs = [arch.I686, arch.X86_64]
|
||||
caps = self._host.get_capabilities()
|
||||
return ((caps.host.cpu.arch in supported_archs) and
|
||||
self._host.has_min_version(MIN_LIBVIRT_NUMA_VERSION,
|
||||
MIN_QEMU_NUMA_HUGEPAGE_VERSION,
|
||||
REQ_HYPERVISOR_NUMA_HUGEPAGE))
|
||||
|
||||
def _has_hugepage_support(self):
|
||||
if not self._host.has_min_version(MIN_LIBVIRT_HUGEPAGE_VERSION):
|
||||
return False
|
||||
|
||||
if CONF.libvirt.virt_type not in ['qemu', 'kvm']:
|
||||
return False
|
||||
|
||||
return True
|
||||
# This means that the host can support multiple values for the size
|
||||
# field in LibvirtConfigGuestMemoryBackingPage
|
||||
supported_archs = [arch.I686, arch.X86_64]
|
||||
caps = self._host.get_capabilities()
|
||||
return ((caps.host.cpu.arch in supported_archs) and
|
||||
self._host.has_min_version(MIN_LIBVIRT_HUGEPAGE_VERSION,
|
||||
MIN_QEMU_NUMA_HUGEPAGE_VERSION,
|
||||
REQ_HYPERVISOR_NUMA_HUGEPAGE))
|
||||
|
||||
def _get_host_numa_topology(self):
|
||||
if not self._has_numa_support():
|
||||
|
|
Loading…
Reference in New Issue