Skip to content

Commit b014d67

Browse files
kashyapcjovial
authored andcommitted
libvirt: Add a workaround to skip compareCPU() on destination
Nova's use of libvirt's compareCPU() API served its purpose over the years, but its design limitations break live migration in subtle ways. For example, the compareCPU() API compares against the host physical CPUID. Some of the features from this CPUID aren not exposed by KVM, and then there are some features that KVM emulates that are not in the host CPUID. The latter can cause bogus live migration failures. With QEMU >=2.9 and libvirt >= 4.4.0, libvirt will do the right thing in terms of CPU compatibility checks on the destination host during live migration. Nova satisfies these minimum version requirements by a good margin. So, provide a workaround to skip the CPU comparison check on the destination host before migrating a guest, and let libvirt handle it correctly. This workaround will be removed once Nova replaces the older libvirt APIs with their newer and improved counterparts[1][2]. - - - Note that Nova's libvirt driver calls compareCPU() in another method, _check_cpu_compatibility(); I did not remove its usage yet. As it needs more careful combing of the code, and then: - where possible, remove the usage of compareCPU() altogether, and rely on libvirt doing the right thing under the hood; or - where Nova _must_ do the CPU comparison checks, switch to the better libvirt CPU APIs -- baselineHypervisorCPU() and compareHypervisorCPU() -- that are described here[1]. This is work in progress[2]. [1] https://opendev.org/openstack/nova-specs/commit/70811da221035044e27 [2] https://review.opendev.org/q/topic:bp%252Fcpu-selection-with-hypervisor-consideration Change-Id: I444991584118a969e9ea04d352821b07ec0ba88d Closes-Bug: #1913716 Signed-off-by: Kashyap Chamarthy <[email protected]> Signed-off-by: Balazs Gibizer <[email protected]> (cherry picked from commit 267a406)
1 parent c0ade88 commit b014d67

File tree

4 files changed

+61
-9
lines changed

4 files changed

+61
-9
lines changed

nova/conf/workarounds.py

+8
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,14 @@
398398
Related options:
399399
400400
* :oslo.config:option:`DEFAULT.vif_plugging_timeout`
401+
"""),
402+
cfg.BoolOpt('skip_cpu_compare_on_dest',
403+
default=False,
404+
help="""
405+
With the libvirt driver, during live migration, skip comparing guest CPU
406+
with the destination host. When using QEMU >= 2.9 and libvirt >=
407+
4.4.0, libvirt will do the correct thing with respect to checking CPU
408+
compatibility on the destination host during live migration.
401409
"""),
402410
]
403411

nova/tests/unit/virt/libvirt/test_driver.py

+19
Original file line numberDiff line numberDiff line change
@@ -10951,6 +10951,25 @@ def test_check_can_live_migrate_guest_cpu_none_model(
1095110951
'_create_shared_storage_test_file',
1095210952
return_value='fake')
1095310953
@mock.patch.object(libvirt_driver.LibvirtDriver, '_compare_cpu')
10954+
def test_check_can_live_migrate_guest_cpu_none_model_skip_compare(
10955+
self, mock_cpu, mock_test_file):
10956+
self.flags(group='workarounds', skip_cpu_compare_on_dest=True)
10957+
instance_ref = objects.Instance(**self.test_instance)
10958+
instance_ref.vcpu_model = test_vcpu_model.fake_vcpumodel
10959+
instance_ref.vcpu_model.model = None
10960+
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
10961+
compute_info = {'cpu_info': 'asdf', 'disk_available_least': 1}
10962+
drvr.check_can_live_migrate_destination(
10963+
self.context, instance_ref, compute_info, compute_info)
10964+
mock_cpu.assert_not_called()
10965+
10966+
@mock.patch(
10967+
'nova.network.neutron.API.has_port_binding_extension',
10968+
new=mock.Mock(return_value=False))
10969+
@mock.patch.object(libvirt_driver.LibvirtDriver,
10970+
'_create_shared_storage_test_file',
10971+
return_value='fake')
10972+
@mock.patch.object(libvirt_driver.LibvirtDriver, '_compare_cpu')
1095410973
def test_check_can_live_migrate_dest_numa_lm(
1095510974
self, mock_cpu, mock_test_file):
1095610975
instance_ref = objects.Instance(**self.test_instance)

nova/virt/libvirt/driver.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -8601,15 +8601,16 @@ def check_can_live_migrate_destination(self, context, instance,
86018601
disk_available_mb = (
86028602
(disk_available_gb * units.Ki) - CONF.reserved_host_disk_mb)
86038603

8604-
# Compare CPU
8605-
try:
8606-
if not instance.vcpu_model or not instance.vcpu_model.model:
8607-
source_cpu_info = src_compute_info['cpu_info']
8608-
self._compare_cpu(None, source_cpu_info, instance)
8609-
else:
8610-
self._compare_cpu(instance.vcpu_model, None, instance)
8611-
except exception.InvalidCPUInfo as e:
8612-
raise exception.MigrationPreCheckError(reason=e)
8604+
if not CONF.workarounds.skip_cpu_compare_on_dest:
8605+
# Compare CPU
8606+
try:
8607+
if not instance.vcpu_model or not instance.vcpu_model.model:
8608+
source_cpu_info = src_compute_info['cpu_info']
8609+
self._compare_cpu(None, source_cpu_info, instance)
8610+
else:
8611+
self._compare_cpu(instance.vcpu_model, None, instance)
8612+
except exception.InvalidCPUInfo as e:
8613+
raise exception.MigrationPreCheckError(reason=e)
86138614

86148615
# Create file on storage, to be checked on source host
86158616
filename = self._create_shared_storage_test_file(instance)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
issues:
3+
- |
4+
Nova's use of libvirt's compareCPU() API served its purpose over the
5+
years, but its design limitations break live migration in subtle
6+
ways. For example, the compareCPU() API compares against the host
7+
physical CPUID. Some of the features from this CPUID aren not
8+
exposed by KVM, and then there are some features that KVM emulates
9+
that are not in the host CPUID. The latter can cause bogus live
10+
migration failures.
11+
12+
With QEMU >=2.9 and libvirt >= 4.4.0, libvirt will do the right
13+
thing in terms of CPU compatibility checks on the destination host
14+
during live migration. Nova satisfies these minimum version
15+
requirements by a good margin. So, this workaround provides a way to
16+
skip the CPU comparison check on the destination host before
17+
migrating a guest, and let libvirt handle it correctly.
18+
19+
This workaround will be deprecated and removed once Nova replaces
20+
the older libvirt APIs with their newer counterparts. The work is
21+
being tracked via this `blueprint
22+
cpu-selection-with-hypervisor-consideration`_.
23+
24+
.. _blueprint cpu-selection-with-hypervisor-consideration: https://blueprints.launchpad.net/nova/+spec/cpu-selection-with-hypervisor-consideration

0 commit comments

Comments
 (0)