summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Riedemann <mriedem.os@gmail.com>2017-06-15 11:46:44 -0400
committerMatt Riedemann <mriedem.os@gmail.com>2017-08-11 15:05:53 -0400
commit89b6da0c2832e739e6e0d30a0e205165005dc41c (patch)
tree21610c01b5776348a3563159ee055c9e470c6f91
parentae45c4a72a6cb72aaf4baa2ac9c0749d4a7b33d0 (diff)
downloadnova-89b6da0c2832e739e6e0d30a0e205165005dc41c.tar.gz
Provide original fault message when BFV fails
When booting from volume and Nova is creating the volume, it can fail (timeout, invalid AZ in Cinder, etc) and the generic Exception handling in _prep_block_device will log the original exception trace but then raise a generic InvalidBDM exception, which is handled higher up and converted to a BuildAbortException, which is recorded as an instance fault, but the original error message is lost from the fault. It would be better to include the original exception message that triggered the failure so that goes into the fault for debug. For example, this is a difference of getting an error like this: BuildAbortException: Build of instance 9484f5a7-3198-47ff-b728-178515a26277 aborted: Block Device Mapping is Invalid. To something more useful like this: BuildAbortException: Build of instance 9484f5a7-3198-47ff-b728-178515a26277 aborted: Volume da947c97-66c6-4b7e-9ae6-54eb8128bb75 did not finish being created even after we waited 3 seconds or 2 attempts. And its status is error. Change-Id: I20a5e8e5e10dd505c1b24c208f919c6550e9d1a4 Closes-Bug: #1693315 (cherry picked from commit 20c4715a49a44c642882618f102cd0fc9342978d) (cherry picked from commit 0d5fd4356af38ca0487979ad614d294a2002911d)
-rw-r--r--nova/compute/manager.py8
-rwxr-xr-xnova/tests/unit/compute/test_compute_mgr.py22
2 files changed, 28 insertions, 2 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index b7edfa9859..cd79e81f89 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1594,10 +1594,14 @@ class ComputeManager(manager.Manager):
LOG.warning(msg, instance=instance)
raise exception.VolumeLimitExceeded()
- except Exception:
+ except Exception as ex:
LOG.exception(_LE('Instance failed block device setup'),
instance=instance)
- raise exception.InvalidBDM()
+ # InvalidBDM will eventually result in a BuildAbortException when
+ # booting from volume, and will be recorded as an instance fault.
+ # Maintain the original exception message which most likely has
+ # useful details which the standard InvalidBDM error message lacks.
+ raise exception.InvalidBDM(six.text_type(ex))
def _update_instance_after_spawn(self, context, instance):
instance.power_state = self._get_power_state(context, instance)
diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py
index 7e00e5fcad..822cb667bc 100755
--- a/nova/tests/unit/compute/test_compute_mgr.py
+++ b/nova/tests/unit/compute/test_compute_mgr.py
@@ -4136,6 +4136,28 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
mock_prep.assert_called_once_with(self.context, self.instance,
self.block_device_mapping)
+ @mock.patch('nova.virt.block_device.attach_block_devices',
+ side_effect=exception.VolumeNotCreated('oops!'))
+ def test_prep_block_device_maintain_original_error_message(self,
+ mock_attach):
+ """Tests that when attach_block_devices raises an Exception, the
+ re-raised InvalidBDM has the original error message which contains
+ the actual details of the failure.
+ """
+ bdms = objects.BlockDeviceMappingList(
+ objects=[fake_block_device.fake_bdm_object(
+ self.context,
+ dict(source_type='image',
+ destination_type='volume',
+ boot_index=0,
+ image_id=uuids.image_id,
+ device_name='/dev/vda',
+ volume_size=1))])
+ ex = self.assertRaises(exception.InvalidBDM,
+ self.compute._prep_block_device,
+ self.context, self.instance, bdms)
+ self.assertEqual('oops!', six.text_type(ex))
+
def test_failed_bdm_prep_from_delete_raises_unexpected(self):
with test.nested(
mock.patch.object(self.compute,