diff options
author | Lee Yarwood <lyarwood@redhat.com> | 2020-12-24 11:50:43 +0000 |
---|---|---|
committer | Lee Yarwood <lyarwood@redhat.com> | 2021-02-04 14:05:31 +0000 |
commit | 1252588d4e48da1d3a753639a8a4d937acf3e037 (patch) | |
tree | 4cd077e440bdd249874f9acf3ca4eebe3eab14fa /nova/compute | |
parent | ee3a8f02253f1f652785c07ea0be6464ab4bcc11 (diff) | |
download | nova-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.py | 33 |
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: |