compute: Lock by instance.uuid lock during swap_volume

The libvirt driver is currently the only virt driver implementing swap
volume within Nova. While libvirt itself does support moving between
multiple volumes attached to the same instance at the same time the
current logic within the libvirt driver makes a call to
virDomainGetXMLDesc that fails if there are active block jobs against
any disk attached to the domain.

This change simply uses an instance.uuid based lock in the compute layer
to serialise requests to swap_volume to avoid this from being possible.

Closes-Bug: #1896621
Change-Id: Ic5ce2580e7638a47f1ffddb4edbb503bf490504c
(cherry picked from commit 6cf449bdd0)
(cherry picked from commit eebf94b654)
This commit is contained in:
Lee Yarwood 2020-09-28 12:18:29 +01:00 committed by melanie witt
parent 845c383b93
commit f7ba1aab5f
1 changed files with 26 additions and 2 deletions

View File

@ -7321,9 +7321,33 @@ class ComputeManager(manager.Manager):
@wrap_instance_fault
def swap_volume(self, context, old_volume_id, new_volume_id, instance,
new_attachment_id):
"""Swap volume for an instance."""
context = context.elevated()
"""Replace the old volume with the new volume within the active server
:param context: User request context
:param old_volume_id: Original volume id
:param new_volume_id: New volume id being swapped to
:param instance: Instance with original_volume_id attached
:param new_attachment_id: ID of the new attachment for new_volume_id
"""
@utils.synchronized(instance.uuid)
def _do_locked_swap_volume(context, old_volume_id, new_volume_id,
instance, new_attachment_id):
self._do_swap_volume(context, old_volume_id, new_volume_id,
instance, new_attachment_id)
_do_locked_swap_volume(context, old_volume_id, new_volume_id, instance,
new_attachment_id)
def _do_swap_volume(self, context, old_volume_id, new_volume_id,
instance, new_attachment_id):
"""Replace the old volume with the new volume within the active server
:param context: User request context
:param old_volume_id: Original volume id
:param new_volume_id: New volume id being swapped to
:param instance: Instance with original_volume_id attached
:param new_attachment_id: ID of the new attachment for new_volume_id
"""
context = context.elevated()
compute_utils.notify_about_volume_swap(
context, instance, self.host,
fields.NotificationPhase.START,