Commit 1d8a7812 authored by Andrea Spadaccini's avatar Andrea Spadaccini
Browse files

Fix interaction between CPU pinning and KVM migration



CPU pinning requires the KVM hypervisor to start in the paused state, in
order to retrieve information, and immediately unpauses it.

This does not play well with live migration, as the unpausing was done
before the migration started and so the receiving kvm process left the
migrated instance in the stopped status.

This patch fixes this behavior, by not launching the KVM process in
stopped state while on the receiving side of a migration.

Also, the stopping is now done outside _ExecuteCpuAffinity.
Signed-off-by: default avatarAndrea Spadaccini <spadaccio@google.com>
Reviewed-by: default avatarTsachy Shacham <tsachy@google.com>
parent 1c7c4578
......@@ -839,33 +839,21 @@ class KVMHypervisor(hv_base.BaseHypervisor):
return result
def _ExecuteCpuAffinity(self, instance_name, cpu_mask, startup_paused):
"""Complete CPU pinning and resume instance execution if needed.
def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
"""Complete CPU pinning.
@type instance_name: string
@param instance_name: name of instance
@type cpu_mask: string
@param cpu_mask: CPU pinning mask as entered by user
@type startup_paused: bool
@param startup_paused: was instance requested to pause before startup
"""
try:
# Get KVM process ID, to be used if need to pin entire VM
_, pid, _ = self._InstancePidAlive(instance_name)
# Get vCPU thread IDs, to be used if need to pin vCPUs separately
thread_dict = self._GetVcpuThreadIds(instance_name)
# Run CPU pinning, based on configured mask
self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
finally:
# To control CPU pinning, the VM was started frozen, so we need
# to resume its execution, but only if freezing was not
# explicitly requested.
# Note: this is done even when an exception occurred so the VM
# is not unintentionally frozen.
if not startup_paused:
self._CallMonitorCommand(instance_name, self._CONT_CMD)
# Get KVM process ID, to be used if need to pin entire VM
_, pid, _ = self._InstancePidAlive(instance_name)
# Get vCPU thread IDs, to be used if need to pin vCPUs separately
thread_dict = self._GetVcpuThreadIds(instance_name)
# Run CPU pinning, based on configured mask
self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
def ListInstances(self):
"""Get the list of running instances.
......@@ -1388,10 +1376,10 @@ class KVMHypervisor(hv_base.BaseHypervisor):
continue
self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
# Before running the KVM command, capture wether the instance is
# supposed to start paused. This is used later when changing CPU
# affinity in order to know whether to resume instance execution.
startup_paused = _KVM_START_PAUSED_FLAG in kvm_cmd
# CPU affinity requires kvm to start paused, so we set this flag if the
# instance is not already paused and if we are not going to accept a
# migrating instance. In the latter case, pausing is not needed.
start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
# Note: CPU pinning is using up_hvp since changes take effect
# during instance startup anyway, and to avoid problems when soft
......@@ -1399,7 +1387,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
cpu_pinning = False
if up_hvp.get(constants.HV_CPU_MASK, None):
cpu_pinning = True
if not startup_paused:
if start_kvm_paused:
kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
if security_model == constants.HT_SM_POOL:
......@@ -1455,8 +1443,16 @@ class KVMHypervisor(hv_base.BaseHypervisor):
# If requested, set CPU affinity and resume instance execution
if cpu_pinning:
self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK],
startup_paused)
try:
self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
finally:
if start_kvm_paused:
# To control CPU pinning, the VM was started frozen, so we need
# to resume its execution, but only if freezing was not
# explicitly requested.
# Note: this is done even when an exception occurred so the VM
# is not unintentionally frozen.
self._CallMonitorCommand(instance.name, self._CONT_CMD)
def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment