summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2013-01-24 10:07:33 +0000
committerPádraig Brady <pbrady@redhat.com>2013-01-29 14:53:12 +0000
commit24fffd9d8b77e9b71e8013fc22c172f76bb4e84c (patch)
treeb6c8968294beaac0ab470f6d9e99923e5231d911
parent3ddd1aeda69b1d8d0bc689fea8d4c2c530d55fc0 (diff)
downloadnova-24fffd9d8b77e9b71e8013fc22c172f76bb4e84c.tar.gz
nova-24fffd9d8b77e9b71e8013fc22c172f76bb4e84c.tar.xz
nova-24fffd9d8b77e9b71e8013fc22c172f76bb4e84c.zip
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
-rw-r--r--nova/compute/api.py27
-rw-r--r--nova/exception.py14
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")