summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tantsur <divius.inside@gmail.com>2018-01-04 16:47:20 +0100
committerDmitry Tantsur <divius.inside@gmail.com>2018-02-07 13:45:55 +0100
commit70039cbe607195f66872d8640976c13284f75b79 (patch)
tree9e72b2273f7f316fc35ef711109210a0fbe19881
parentbf8cb05aa4fcdb3b8c115fda6139d464fc94c014 (diff)
downloadironic-70039cbe607195f66872d8640976c13284f75b79.tar.gz
Handle case when a glance image contains no data
In my experience, it happens when Swift storage backing Glance was purged, but it can probably also happen if an image never had data at all. This patch raises a correct exception instead of TypeError. Switch relevant unit tests to Glance V2, as V1 is long deprecated. Change-Id: I75e5ae7f46ce3a1506ed6108ff05df3083fd5084 Closes-Bug: #1741223
-rw-r--r--ironic/common/glance_service/base_image_service.py8
-rw-r--r--ironic/tests/unit/common/test_glance_service.py15
-rw-r--r--ironic/tests/unit/stubs.py12
-rw-r--r--releasenotes/notes/image-no-data-c281f638d3dedfb2.yaml6
4 files changed, 38 insertions, 3 deletions
diff --git a/ironic/common/glance_service/base_image_service.py b/ironic/common/glance_service/base_image_service.py
index 1768b2a11..85aae5734 100644
--- a/ironic/common/glance_service/base_image_service.py
+++ b/ironic/common/glance_service/base_image_service.py
@@ -217,6 +217,14 @@ class BaseImageService(object):
return
image_chunks = self.call(method, image_id)
+ # NOTE(dtantsur): when using Glance V2, image_chunks is a wrapper
+ # around real data, so we have to check the wrapped data for None.
+ # Glance V1 returns HTTP 404 in this case, so no need to fix it.
+ # TODO(dtantsur): remove the hasattr check when we no longer support
+ # Glance V1.
+ if hasattr(image_chunks, 'wrapped') and image_chunks.wrapped is None:
+ raise exception.ImageDownloadFailed(
+ image_href=image_href, reason=_('image contains no data.'))
if data is None:
return image_chunks
diff --git a/ironic/tests/unit/common/test_glance_service.py b/ironic/tests/unit/common/test_glance_service.py
index 7e135fb40..71c9846fc 100644
--- a/ironic/tests/unit/common/test_glance_service.py
+++ b/ironic/tests/unit/common/test_glance_service.py
@@ -92,11 +92,11 @@ class TestGlanceImageService(base.TestCase):
def setUp(self):
super(TestGlanceImageService, self).setUp()
- client = stubs.StubGlanceClient()
+ self.client = stubs.StubGlanceClient()
self.context = context.RequestContext(auth_token=True)
self.context.user_id = 'fake'
self.context.project_id = 'fake'
- self.service = service.GlanceImageService(client, 1, self.context)
+ self.service = service.GlanceImageService(self.client, 2, self.context)
self.config(glance_api_servers=['http://localhost'], group='glance')
self.config(auth_strategy='keystone', group='glance')
@@ -203,6 +203,17 @@ class TestGlanceImageService(base.TestCase):
stub_service.download(image_id, writer)
self.assertTrue(mock_sleep.called)
+ def test_download_no_data(self):
+ self.client.fake_wrapped = None
+ image_id = uuidutils.generate_uuid()
+
+ image = self._make_datetime_fixture()
+ with mock.patch.object(self.client, 'get', return_value=image,
+ autospec=True):
+ self.assertRaisesRegex(exception.ImageDownloadFailed,
+ 'image contains no data',
+ self.service.download, image_id)
+
@mock.patch('sendfile.sendfile', autospec=True)
@mock.patch('os.path.getsize', autospec=True)
@mock.patch('%s.open' % __name__, new=mock.mock_open(), create=True)
diff --git a/ironic/tests/unit/stubs.py b/ironic/tests/unit/stubs.py
index d639ad95d..ba66e15f2 100644
--- a/ironic/tests/unit/stubs.py
+++ b/ironic/tests/unit/stubs.py
@@ -18,8 +18,18 @@ from glanceclient import exc as glance_exc
NOW_GLANCE_FORMAT = "2010-10-11T10:30:22"
+class _GlanceWrapper(object):
+ def __init__(self, wrapped):
+ self.wrapped = wrapped
+
+ def __iter__(self):
+ return iter(())
+
+
class StubGlanceClient(object):
+ fake_wrapped = object()
+
def __init__(self, images=None):
self._images = []
_images = images or []
@@ -38,7 +48,7 @@ class StubGlanceClient(object):
def data(self, image_id):
self.get(image_id)
- return []
+ return _GlanceWrapper(self.fake_wrapped)
class FakeImage(object):
diff --git a/releasenotes/notes/image-no-data-c281f638d3dedfb2.yaml b/releasenotes/notes/image-no-data-c281f638d3dedfb2.yaml
new file mode 100644
index 000000000..66e1165b1
--- /dev/null
+++ b/releasenotes/notes/image-no-data-c281f638d3dedfb2.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fails deployment with the correct error message in a node's ``last_error``
+ field if an image from the Image service doesn't contain any data.
+ See `bug 1741223 <https://bugs.launchpad.net/bugs/1741223>`_ for details.