diff --git a/nova/image/glance.py b/nova/image/glance.py index 00eb04121f09..adcd7d33440a 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -294,6 +294,12 @@ class GlanceImageServiceV2(object): except Exception: _reraise_translated_image_exception(image_id) + if image_chunks.wrapped is None: + # None is a valid return value, but there's nothing we can do with + # a image with no associated data + raise exception.ImageUnacceptable(image_id=image_id, + reason='Image has no associated data') + # Retrieve properties for verification of Glance image signature verifier = None if CONF.glance.verify_glance_signatures: diff --git a/nova/tests/unit/image/test_glance.py b/nova/tests/unit/image/test_glance.py index 6c3dd015ff93..aaa17e51c4c8 100644 --- a/nova/tests/unit/image/test_glance.py +++ b/nova/tests/unit/image/test_glance.py @@ -637,6 +637,19 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): self.assertRaises(FakeDiskException, service.download, ctx, mock.sentinel.image_id, data=Exceptionator()) + @mock.patch.object(six.moves.builtins, 'open') + @mock.patch('nova.image.glance.GlanceImageServiceV2.show') + def test_download_no_returned_image_data_v2( + self, show_mock, open_mock): + """Verify images with no data are handled correctly.""" + client = mock.MagicMock() + client.call.return_value = fake_glance_response(None) + ctx = mock.sentinel.ctx + service = glance.GlanceImageServiceV2(client) + + with testtools.ExpectedException(exception.ImageUnacceptable): + service.download(ctx, mock.sentinel.image_id) + @mock.patch('nova.image.glance.GlanceImageServiceV2._get_transfer_module') @mock.patch('nova.image.glance.GlanceImageServiceV2.show') def test_download_direct_file_uri_v2(self, show_mock, get_tran_mock):