libvirt: Deprecate support for monitoring Intel CMT `perf` events

Upstream Linux kernel has deleted[*] the `perf` framework integration
with Intel CMT (Cache Monitoring Technology; or "CQM" in Linux kernel
parlance), because the feature was broken by design -- an
incompatibility between Linux's `perf` infrastructure and Intel CMT
hardware support.  It was removed in upstream kernel version v4.14; but
bear in mind that downstream Linux distributions with lower kernel
versions than 4.14 have backported the said change.

Nova supports monitoring of the above mentioned Intel CMT events
(namely: 'cmt', 'mbm_local', and 'mbm_total') via the configuration
attribute `[libvirt]/enabled_perf_events`. Given that the underlying
Linux kernel infrastructure for Intel CMT is removed, we should remove
support for it in Nova too.  Otherwise enabling them in Nova, and
updating to a Linux kernel 4.14 (or above) will result in instances
failing to boot.

To that end, deprecate support for the three Intel CMT events in "Rocky"
release, with the intention to remove support for it in the upcoming
"Stein" release.  Note that we cannot deprecate / remove
`enabled_perf_events` config attribute altogether -- since there are
other[+] `perf` events besides Intel CMT.  Whether anyone is using those
other events with Nova is a good question to which we don't have an
equally good answer for, if at all.

[*] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c39a0e2
[+] https://libvirt.org/formatdomain.html#elementsPerf

Closes-Bug: #1751073
Change-Id: I7e77f87650d966d605807c7be184e670259a81c1
Signed-off-by: Kashyap Chamarthy <kchamart@redhat.com>
This commit is contained in:
Kashyap Chamarthy 2018-05-08 10:52:17 +02:00 committed by Matt Riedemann
parent 8ede37e8b1
commit fc4794acc6
4 changed files with 90 additions and 43 deletions

View File

@ -696,17 +696,29 @@ Possible cache modes:
cfg.ListOpt('enabled_perf_events',
default=[],
help= """
This is a performance event list which could be used as monitor. These events
will be passed to libvirt domain xml while creating a new instances.
Then event statistics data can be collected from libvirt. The minimum
libvirt version is 2.0.0. For more information about `Performance monitoring
events`, refer https://libvirt.org/formatdomain.html#elementsPerf .
This will allow you to specify a list of events to monitor low-level
performance of guests, and collect related statsitics via the libvirt
driver, which in turn uses the Linux kernel's `perf` infrastructure.
With this config attribute set, Nova will generate libvirt guest XML to
monitor the specified events. For more information, refer to the
"Performance monitoring events" section here:
https://libvirt.org/formatdomain.html#elementsPerf. And here:
https://libvirt.org/html/libvirt-libvirt-domain.html -- look for
``VIR_PERF_PARAM_*``
Possible values:
* A string list. For example: ``enabled_perf_events = cmt, mbml, mbmt``
The supported events list can be found in
https://libvirt.org/html/libvirt-libvirt-domain.html ,
which you may need to search key words ``VIR_PERF_PARAM_*``
For example, to monitor the count of CPU cycles (total/elapsed) and the
count of cache misses, enable them as follows::
[libvirt]
enabled_perf_events = cpu_clock, cache_misses
Possible values: A string list. The list of supported events can be
found here: https://libvirt.org/formatdomain.html#elementsPerf.
Note that support for Intel CMT events (`cmt`, `mbmbt`, `mbml`) is
deprecated, and will be removed in the "Stein" release. That's because
the upstream Linux kernel (from 4.14 onwards) has deleted support for
Intel CMT, because it is broken by design.
"""),
cfg.IntOpt('num_pcie_ports',
default=0,

View File

@ -6567,34 +6567,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(events, cfg.perf_events)
@mock.patch.object(fakelibvirt, 'VIR_PERF_PARAM_CMT', True,
create=True)
@mock.patch.object(fakelibvirt, 'VIR_PERF_PARAM_MBMT', True,
create=True)
@mock.patch.object(fakelibvirt, 'VIR_PERF_PARAM_MBML', True,
create=True)
@mock.patch.object(host.Host, 'has_min_version', return_value=True)
def test_get_guest_with_perf_supported(self,
mock_min_version):
self.flags(enabled_perf_events=['cmt', 'mbml', 'mbmt'],
group='libvirt')
caps = vconfig.LibvirtConfigCaps()
caps.host = vconfig.LibvirtConfigCapsHost()
caps.host.cpu = vconfig.LibvirtConfigCPU()
caps.host.cpu.arch = fields.Architecture.X86_64
caps.host.topology = fakelibvirt.NUMATopology()
features = []
for f in ('cmt', 'mbm_local', 'mbm_total'):
feature = vconfig.LibvirtConfigGuestCPUFeature()
feature.name = f
feature.policy = fields.CPUFeaturePolicy.REQUIRE
features.append(feature)
caps.host.cpu.features = set(features)
self._test_get_guest_with_perf(caps, ['cmt', 'mbml', 'mbmt'])
@mock.patch.object(host.Host, 'has_min_version')
def test_get_guest_with_perf_libvirt_unsupported(self, mock_min_version):
@ -6627,6 +6599,46 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self._test_get_guest_with_perf(caps, [])
@mock.patch.object(fakelibvirt, 'VIR_PERF_PARAM_CMT', True,
create=True)
@mock.patch.object(fakelibvirt, 'VIR_PERF_PARAM_MBMT', True,
create=True)
@mock.patch.object(fakelibvirt, 'VIR_PERF_PARAM_MBML', True,
create=True)
@mock.patch.object(libvirt_driver.LOG, 'warning')
@mock.patch.object(host.Host, 'has_min_version', return_value=True)
def test_intel_cmt_perf_deprecation_warning(self,
mock_min_version,
mock_warn):
perf_events = ['cmt', 'mbml', 'mbmt']
self.flags(enabled_perf_events=['cmt', 'mbml', 'mbmt'],
group='libvirt')
caps = vconfig.LibvirtConfigCaps()
caps.host = vconfig.LibvirtConfigCapsHost()
caps.host.cpu = vconfig.LibvirtConfigCPU()
caps.host.cpu.arch = fields.Architecture.X86_64
caps.host.topology = fakelibvirt.NUMATopology()
features = []
for f in ('cmt', 'mbm_local', 'mbm_total'):
feature = vconfig.LibvirtConfigGuestCPUFeature()
feature.name = f
feature.policy = fields.CPUFeaturePolicy.REQUIRE
features.append(feature)
caps.host.cpu.features = set(features)
self._test_get_guest_with_perf(caps, ['cmt', 'mbml', 'mbmt'])
warning_count = 0
call_args_list = mock_warn.call_args_list
for call in call_args_list:
# Call can be unpackaged as a tuple of args and kwargs
# so we want to check the first arg in the args list
if (len(call) == 2 and len(call[0]) == 2 and
call[0][1] in perf_events and
'Monitoring Intel CMT' in call[0][0]):
warning_count += 1
self.assertEqual(3, warning_count)
def test_xml_and_uri_no_ramdisk_no_kernel(self):
instance_data = dict(self.test_instance)
self._check_xml_and_uri(instance_data,

View File

@ -4740,11 +4740,17 @@ class LibvirtDriver(driver.ComputeDriver):
LOG.warning("Libvirt doesn't support event type %s.", event)
return False
if (event in PERF_EVENTS_CPU_FLAG_MAPPING
and PERF_EVENTS_CPU_FLAG_MAPPING[event] not in cpu_features):
LOG.warning("Host does not support event type %s.", event)
return False
if event in PERF_EVENTS_CPU_FLAG_MAPPING:
LOG.warning('Monitoring Intel CMT `perf` event(s) %s is '
'deprecated and will be removed in the "Stein" '
'release. It was broken by design in the '
'Linux kernel, so support for Intel CMT was '
'removed from Linux 4.14 onwards. Therefore '
'it is recommended to not enable them.',
event)
if PERF_EVENTS_CPU_FLAG_MAPPING[event] not in cpu_features:
LOG.warning("Host does not support event type %s.", event)
return False
return True
def _configure_guest_by_virt_type(self, guest, virt_type, caps, instance,

View File

@ -0,0 +1,17 @@
---
deprecations:
- |
Support to monitor performance events for Intel CMT (Cache
Monitoring Technology, or "CQM" in Linux kernel parlance) -- namely
``cmt``, ``mbm_local`` and ``mbm_total`` -- via the config attribute
``[libvirt]/enabled_perf_events`` is now *deprecated* from Nova, and
will be *removed* in the "Stein" release. Otherwise, if you have
enabled those events, and upgraded to Linux kernel 4.14 (or suitable
downstream version), it will result in instances failing to boot.
That is because the Linux kernel has deleted the `perf` framework
integration with Intel CMT, as the feature was broken by design --
an incompatibility between Linux's `perf` infrastructure and Intel
CMT. It was removed in upstream Linux version v4.14; but bear in
mind that downstream Linux distributions with lower kernel versions
than 4.14 have backported the said change.