From 1a6d03dfc35fd415d31f331bb5accced1b37b59f Mon Sep 17 00:00:00 2001 From: Walter Boring IV Date: Wed, 27 Sep 2023 16:42:01 -0400 Subject: [PATCH] SAP: Add affinity UUID validation This patch adds some basic UUID volume validation for the cinder create volume API request when passing in scheduler hints for volume affinity or anti-affinity. The API now ensures that the UUIDs are valid cinder volumes. The UUID must be a valid cinder volume UUID for the create call to work. --- cinder/volume/api.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cinder/volume/api.py b/cinder/volume/api.py index 27e7735cc21..2fc8aa18354 100644 --- a/cinder/volume/api.py +++ b/cinder/volume/api.py @@ -26,6 +26,7 @@ from oslo_utils import excutils from oslo_utils import strutils from oslo_utils import timeutils +from oslo_utils import uuidutils from oslo_utils import versionutils from cinder import action_track @@ -204,6 +205,36 @@ def _is_encrypted(self, volume_type): return False return specs.get('encryption', {}) is not {} + def _validate_scheduler_hints(self, scheduler_hints): + if scheduler_hints: + validate_volume_uuids = [] + if 'same_host' in scheduler_hints: + if isinstance(scheduler_hints['same_host'], list): + validate_volume_uuids.extend(scheduler_hints['same_host']) + else: + validate_volume_uuids.append(scheduler_hints['same_host']) + elif 'different_host' in scheduler_hints: + if isinstance(scheduler_hints['different_host'], list): + validate_volume_uuids.extend( + scheduler_hints['different_host']) + else: + validate_volume_uuids.append( + scheduler_hints['different_host']) + + for hint_volume_id in validate_volume_uuids: + if not uuidutils.is_uuid_like(hint_volume_id): + msg = _("Invalid UUID(s) '%s' provided in scheduler " + "hints.") % hint_volume_id + raise exception.InvalidInput(reason=msg) + + # Now validate that the uuids are valid volumes that exist in + # cinder DB. + for hint_volume_id in validate_volume_uuids: + # All we have to do here is try and fetch the UUID as volume. + # If the UUID doesn't exist in the DB, Cinder will throw + # a VolumeNotFound exception. + objects.Volume.get_by_id(context, hint_volume_id) + @action_track.track_decorator(action_track.ACTION_VOLUME_CREATE) def create(self, context, size, name, description, snapshot=None, image_id=None, volume_type=None, metadata=None, @@ -298,6 +329,10 @@ def create(self, context, size, name, description, snapshot=None, if CONF.storage_availability_zone: availability_zones.add(CONF.storage_availability_zone) + # Validate the scheduler_hints same_host and different_hosts as + # valid volume UUIDs. + self._validate_scheduler_hints(scheduler_hints) + # Force the scheduler hints into the volume metadata if not metadata: metadata = {}