From 24fffd9d8b77e9b71e8013fc22c172f76bb4e84c Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 24 Jan 2013 10:07:33 +0000 Subject: validate specified volumes to boot from at the API layer This causes the create to fail fast instead of putting the instance into error later in the process. Related to bug: 1069904 Change-Id: I5f7c8d20d3ebf33ce1ce64bf0a8418bd2b5a6411 --- nova/compute/api.py | 27 ++++++++++++++++++++++----- nova/exception.py | 14 ++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index 06ce2e07e..4961827fd 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -558,6 +558,11 @@ class API(base.Base): security_group, block_device_mapping) instances.append(instance) instance_uuids.append(instance['uuid']) + self._validate_bdm(context, instance) + # send a state update notification for the initial create to + # show it going from non-existent to BUILDING + notifications.send_update_with_states(context, instance, None, + vm_states.BUILDING, None, None, service="api") # In the case of any exceptions, attempt DB cleanup and rollback the # quota reservations. @@ -704,6 +709,23 @@ class API(base.Base): self.db.block_device_mapping_update_or_create(elevated_context, values) + def _validate_bdm(self, context, instance): + for bdm in self.db.block_device_mapping_get_all_by_instance( + context, instance['uuid']): + # NOTE(vish): For now, just make sure the volumes are accessible. + snapshot_id = bdm.get('snapshot_id') + volume_id = bdm.get('volume_id') + if volume_id is not None: + try: + self.volume_api.get(context, volume_id) + except Exception: + raise exception.InvalidBDMVolume(id=volume_id) + elif snapshot_id is not None: + try: + self.volume_api.get_snapshot(context, snapshot_id) + except Exception: + raise exception.InvalidBDMSnapshot(id=snapshot_id) + def _populate_instance_for_bdm(self, context, instance, instance_type, image, block_device_mapping): """Populate instance block device mapping information.""" @@ -818,11 +840,6 @@ class API(base.Base): self._populate_instance_for_bdm(context, instance, instance_type, image, block_device_mapping) - # send a state update notification for the initial create to - # show it going from non-existent to BUILDING - notifications.send_update_with_states(context, instance, None, - vm_states.BUILDING, None, None, service="api") - return instance def _check_create_policies(self, context, availability_zone, diff --git a/nova/exception.py b/nova/exception.py index bb7749dd7..6915c14bb 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -226,6 +226,20 @@ class Invalid(NovaException): code = 400 +class InvalidBDM(Invalid): + message = _("Block Device Mapping is Invalid.") + + +class InvalidBDMSnapshot(InvalidBDM): + message = _("Block Device Mapping is Invalid: " + "failed to get snapshot %(id)s.") + + +class InvalidBDMVolume(InvalidBDM): + message = _("Block Device Mapping is Invalid: " + "failed to get volume %(id)s.") + + class VolumeUnattached(Invalid): message = _("Volume %(volume_id)s is not attached to anything") -- cgit