summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/compute/api.py7
-rw-r--r--nova/tests/compute/test_compute.py53
2 files changed, 59 insertions, 1 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 3f3078d5b..ac52b805d 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -780,11 +780,16 @@ class API(base.Base):
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.
+ # Additionally, check that the volume can be attached to this
+ # instance.
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)
+ volume = self.volume_api.get(context, volume_id)
+ self.volume_api.check_attach(context,
+ volume,
+ instance=instance)
except Exception:
raise exception.InvalidBDMVolume(id=volume_id)
elif snapshot_id is not None:
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 277e804ac..bd253b8ee 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -541,6 +541,59 @@ class ComputeVolumeTestCase(BaseTestCase):
self.assertEqual(1, volume_usage['tot_writes'])
self.assertEqual(20, volume_usage['tot_write_bytes'])
+ def test_validate_bdm(self):
+ # Test if volume is checked for availability before being attached
+ # at boot time
+
+ def fake_bdms(context, instance_uuid):
+ block_device_mapping = [{
+ 'id': 1,
+ 'no_device': None,
+ 'virtual_name': None,
+ 'snapshot_id': None,
+ 'volume_id': self.volume_id,
+ 'device_name': 'vda',
+ 'delete_on_termination': False,
+ }]
+ return block_device_mapping
+ self.stubs.Set(self.compute.db,
+ 'block_device_mapping_get_all_by_instance',
+ fake_bdms)
+
+ # Check that the volume status is 'available' and reject if not
+ def fake_volume_get_1(self, context, volume_id):
+ return {'id': volume_id,
+ 'status': 'creating',
+ 'attach_status': 'detached'}
+ self.stubs.Set(cinder.API, 'get', fake_volume_get_1)
+
+ self.assertRaises(exception.InvalidBDMVolume,
+ self.compute_api._validate_bdm,
+ self.context,
+ instance=self.instance)
+
+ # Check that the volume attach_status is 'detached' and reject if not
+ def fake_volume_get_2(self, context, volume_id):
+ return {'id': volume_id,
+ 'status': 'available',
+ 'attach_status': 'attached'}
+ self.stubs.Set(cinder.API, 'get', fake_volume_get_2)
+
+ self.assertRaises(exception.InvalidBDMVolume,
+ self.compute_api._validate_bdm,
+ self.context,
+ instance=self.instance)
+
+ # Check that the volume status is 'available' and attach_status is
+ # 'detached' and accept the request if so
+ def fake_volume_get_3(self, context, volume_id):
+ return {'id': volume_id,
+ 'status': 'available',
+ 'attach_status': 'detached'}
+ self.stubs.Set(cinder.API, 'get', fake_volume_get_3)
+
+ self.compute_api._validate_bdm(self.context, instance=self.instance)
+
class ComputeTestCase(BaseTestCase):
def test_wrap_instance_fault(self):