summaryrefslogtreecommitdiff
path: root/nova/compute
diff options
context:
space:
mode:
authorLee Yarwood <lyarwood@redhat.com>2020-12-24 11:50:43 +0000
committerLee Yarwood <lyarwood@redhat.com>2021-02-04 14:05:31 +0000
commit1252588d4e48da1d3a753639a8a4d937acf3e037 (patch)
tree4cd077e440bdd249874f9acf3ca4eebe3eab14fa /nova/compute
parentee3a8f02253f1f652785c07ea0be6464ab4bcc11 (diff)
downloadnova-1252588d4e48da1d3a753639a8a4d937acf3e037.tar.gz
api: Reject volume attach requests when an active bdm exists
When attaching volumes to instances Nova has previously relied on checks carried out by c-api to ensure that a single non-multiattach volume is not attached to multiple instances at once. While this works well in most cases it does not handle PEBKAC issues when admins reset the state of a volume to available, allowing users to request that Nova attach the volume to another instance. This change aims to address this by including a simple check in the attach flow for non-multiattach volumes ensuring that there are no existing active block device mapping records for the volume already present within Nova. Closes-Bug: #1908075 Change-Id: I2881d77d52bcbde9f3ac6a6ddfb4a22a9bd45c8a
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/api.py33
1 files changed, 32 insertions, 1 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 077a848f43..77785bdbc4 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -4622,6 +4622,28 @@ class API(base.Base):
except exception.VolumeBDMNotFound:
pass
+ def _check_volume_already_attached(
+ self, context: nova_context.RequestContext, volume_id: str
+ ):
+ """Avoid allowing a non-multiattach volumes being attached twice
+
+ Unlike the above _check_volume_already_attached_to_instance check we
+ also need to ensure that non-multiattached volumes are not attached to
+ multiple instances. This check is also carried out later by c-api
+ itself but it can however be circumvented by admins resetting the state
+ of an attached volume to available. As a result we also need to perform
+ a check within Nova before creating a new BDM for the attachment.
+ """
+ try:
+ bdm = objects.BlockDeviceMapping.get_by_volume(
+ context, volume_id)
+ msg = _("volume %(volume_id)s is already attached to instance "
+ "%(instance_uuid)s") % {'volume_id': volume_id,
+ 'instance_uuid': bdm.instance_uuid}
+ raise exception.InvalidVolume(reason=msg)
+ except exception.VolumeBDMNotFound:
+ pass
+
def _check_attach_and_reserve_volume(self, context, volume, instance,
bdm, supports_multiattach=False,
validate_az=True):
@@ -4761,8 +4783,17 @@ class API(base.Base):
self._check_volume_already_attached_to_instance(context,
instance,
volume_id)
-
volume = self.volume_api.get(context, volume_id)
+
+ # NOTE(lyarwood): Ensure that non multiattach volumes don't already
+ # have active block device mappings present in Nova.
+ # TODO(lyarwood): Merge this into the
+ # _check_volume_already_attached_to_instance check once
+ # BlockDeviceMappingList provides a list of active bdms per volume so
+ # we can preform a single lookup for both checks.
+ if not volume.get('multiattach', False):
+ self._check_volume_already_attached(context, volume_id)
+
is_shelved_offloaded = instance.vm_state == vm_states.SHELVED_OFFLOADED
if is_shelved_offloaded:
if tag: