libvirt: Add version check when pinning guest CPUs
Ensure versions of libvirt with broken CPU pinning support are not used for said feature. This requires the addition of a new Exception, specific version check functionality and unit tests for same. Change-Id: I03b462c4985517ff8a4d94f0e1acae4fabdc5d39 Closes-Bug: #1438226
This commit is contained in:
parent
bf70df295b
commit
c380987aa8
|
@ -1845,6 +1845,11 @@ class MemoryPageSizeNotSupported(Invalid):
|
|||
msg_fmt = _("Page size %(pagesize)s is not supported by the host.")
|
||||
|
||||
|
||||
class CPUPinningNotSupported(Invalid):
|
||||
msg_fmt = _("CPU pinning is not supported by the host: "
|
||||
"%(reason)s")
|
||||
|
||||
|
||||
class CPUPinningInvalid(Invalid):
|
||||
msg_fmt = _("Cannot pin/unpin cpus %(requested)s from the following "
|
||||
"pinned set %(pinned)s")
|
||||
|
|
|
@ -304,6 +304,50 @@ class HostTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(self.connect_calls, 1)
|
||||
self.assertEqual(self.register_calls, 1)
|
||||
|
||||
@mock.patch.object(fakelibvirt.virConnect, "getLibVersion")
|
||||
@mock.patch.object(fakelibvirt.virConnect, "getVersion")
|
||||
@mock.patch.object(fakelibvirt.virConnect, "getType")
|
||||
def test_has_min_version(self, fake_hv_type, fake_hv_ver, fake_lv_ver):
|
||||
fake_lv_ver.return_value = 1002003
|
||||
fake_hv_ver.return_value = 4005006
|
||||
fake_hv_type.return_value = 'xyz'
|
||||
|
||||
lv_ver = (1, 2, 3)
|
||||
hv_ver = (4, 5, 6)
|
||||
hv_type = 'xyz'
|
||||
self.assertTrue(self.host.has_min_version(lv_ver, hv_ver, hv_type))
|
||||
|
||||
self.assertFalse(self.host.has_min_version(lv_ver, hv_ver, 'abc'))
|
||||
self.assertFalse(self.host.has_min_version(lv_ver, (4, 5, 7), hv_type))
|
||||
self.assertFalse(self.host.has_min_version((1, 3, 3), hv_ver, hv_type))
|
||||
|
||||
self.assertTrue(self.host.has_min_version(lv_ver, hv_ver, None))
|
||||
self.assertTrue(self.host.has_min_version(lv_ver, None, hv_type))
|
||||
self.assertTrue(self.host.has_min_version(None, hv_ver, hv_type))
|
||||
|
||||
@mock.patch.object(fakelibvirt.virConnect, "getLibVersion")
|
||||
@mock.patch.object(fakelibvirt.virConnect, "getVersion")
|
||||
@mock.patch.object(fakelibvirt.virConnect, "getType")
|
||||
def test_has_version(self, fake_hv_type, fake_hv_ver, fake_lv_ver):
|
||||
fake_lv_ver.return_value = 1002003
|
||||
fake_hv_ver.return_value = 4005006
|
||||
fake_hv_type.return_value = 'xyz'
|
||||
|
||||
lv_ver = (1, 2, 3)
|
||||
hv_ver = (4, 5, 6)
|
||||
hv_type = 'xyz'
|
||||
self.assertTrue(self.host.has_version(lv_ver, hv_ver, hv_type))
|
||||
|
||||
for lv_ver_ in [(1, 2, 2), (1, 2, 4)]:
|
||||
self.assertFalse(self.host.has_version(lv_ver_, hv_ver, hv_type))
|
||||
for hv_ver_ in [(4, 4, 6), (4, 6, 6)]:
|
||||
self.assertFalse(self.host.has_version(lv_ver, hv_ver_, hv_type))
|
||||
self.assertFalse(self.host.has_version(lv_ver, hv_ver, 'abc'))
|
||||
|
||||
self.assertTrue(self.host.has_min_version(lv_ver, hv_ver, None))
|
||||
self.assertTrue(self.host.has_min_version(lv_ver, None, hv_type))
|
||||
self.assertTrue(self.host.has_min_version(None, hv_ver, hv_type))
|
||||
|
||||
@mock.patch.object(fakelibvirt.virConnect, "lookupByID")
|
||||
def test_get_domain_by_id(self, fake_lookup):
|
||||
dom = fakelibvirt.virDomain(self.host.get_connection(),
|
||||
|
|
|
@ -363,6 +363,8 @@ MIN_LIBVIRT_NUMA_VERSION = (1, 2, 7)
|
|||
# cannot make guaranteed decisions, as the huge page size
|
||||
# used by the guest may not match what was requested
|
||||
MIN_LIBVIRT_HUGEPAGE_VERSION = (1, 2, 8)
|
||||
# missing libvirt cpu pinning support
|
||||
BAD_LIBVIRT_CPU_POLICY_VERSIONS = [(1, 2, 9, 2), (1, 2, 10)]
|
||||
# fsFreeze/fsThaw requirement
|
||||
MIN_LIBVIRT_FSFREEZE_VERSION = (1, 2, 5)
|
||||
|
||||
|
@ -519,7 +521,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
self._set_host_enabled(enabled, reason)
|
||||
|
||||
def _version_to_string(self, version):
|
||||
return "%i.%i.%i" % version
|
||||
return '.'.join([str(x) for x in version])
|
||||
|
||||
def init_host(self, host):
|
||||
self._host.initialize()
|
||||
|
@ -3396,6 +3398,14 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
guest_cpu_numa.cells.append(guest_cell)
|
||||
return guest_cpu_numa
|
||||
|
||||
def _has_cpu_policy_support(self):
|
||||
for ver in BAD_LIBVIRT_CPU_POLICY_VERSIONS:
|
||||
if self._host.has_version(ver):
|
||||
ver_ = self._version_to_string(version)
|
||||
raise exception.CPUPinningNotSupported(reason=_(
|
||||
'Invalid libvirt version %(version)s') % {'version': ver_})
|
||||
return True
|
||||
|
||||
def _get_guest_numa_config(self, instance_numa_topology, flavor, pci_devs,
|
||||
allowed_cpus=None):
|
||||
"""Returns the config objects for the guest NUMA specs.
|
||||
|
@ -3499,7 +3509,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
# If there is pinning information in the cell
|
||||
# we pin to individual CPUs, otherwise we float
|
||||
# over the whole host NUMA node
|
||||
if object_numa_cell.cpu_pinning:
|
||||
|
||||
if (object_numa_cell.cpu_pinning and
|
||||
self._has_cpu_policy_support()):
|
||||
pcpu = object_numa_cell.cpu_pinning[cpu]
|
||||
pin_cpuset.cpuset = set([pcpu])
|
||||
else:
|
||||
|
|
|
@ -27,6 +27,7 @@ the raw libvirt API. These APIs are then used by all
|
|||
the other libvirt related classes
|
||||
"""
|
||||
|
||||
import operator
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
|
@ -546,18 +547,19 @@ class Host(object):
|
|||
libvirt.virEventRegisterDefaultImpl()
|
||||
self._init_events()
|
||||
|
||||
def has_min_version(self, lv_ver=None, hv_ver=None, hv_type=None):
|
||||
def _version_check(self, lv_ver=None, hv_ver=None, hv_type=None,
|
||||
op=operator.lt):
|
||||
conn = self.get_connection()
|
||||
try:
|
||||
if lv_ver is not None:
|
||||
libvirt_version = conn.getLibVersion()
|
||||
|
||||
if libvirt_version < utils.convert_version_to_int(lv_ver):
|
||||
if op(libvirt_version, utils.convert_version_to_int(lv_ver)):
|
||||
return False
|
||||
|
||||
if hv_ver is not None:
|
||||
hypervisor_version = conn.getVersion()
|
||||
if hypervisor_version < utils.convert_version_to_int(hv_ver):
|
||||
if op(hypervisor_version,
|
||||
utils.convert_version_to_int(hv_ver)):
|
||||
return False
|
||||
|
||||
if hv_type is not None:
|
||||
|
@ -569,6 +571,14 @@ class Host(object):
|
|||
except Exception:
|
||||
return False
|
||||
|
||||
def has_min_version(self, lv_ver=None, hv_ver=None, hv_type=None):
|
||||
return self._version_check(
|
||||
lv_ver=lv_ver, hv_ver=hv_ver, hv_type=hv_type, op=operator.lt)
|
||||
|
||||
def has_version(self, lv_ver=None, hv_ver=None, hv_type=None):
|
||||
return self._version_check(
|
||||
lv_ver=lv_ver, hv_ver=hv_ver, hv_type=hv_type, op=operator.ne)
|
||||
|
||||
def get_domain(self, instance):
|
||||
"""Retrieve libvirt domain object for an instance.
|
||||
|
||||
|
|
Loading…
Reference in New Issue