Skip to content

Commit ed1b598

Browse files
committed
Check that Glance returns image data before processing it
Now if Glance v2 cannot find image data it returns an empty response with 204 status code, instead of raising an error. Glance client handles this situation and wraps the response with a RequestIdProxy object, whose 'wrapped' attribute is None. But when openstack client tries to parse this object using glanceclient's save_image util function, it fails with "NoneType object is not iterable" message, for the object doesn't contain any data. This patch adds additional check to prevent such behaviour and raises SystemExit exception if no data was returned from the server. Glance v1 is not affected, because it raises an error if can't find an image data. Change-Id: I016a60462ba586f9fa7585c2cfafffd7be38de7b Closes-Bug: #1741223
1 parent b13a323 commit ed1b598

3 files changed

Lines changed: 64 additions & 0 deletions

File tree

openstackclient/image/v2/image.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import argparse
1919
import logging
20+
import sys
2021

2122
from glanceclient.common import utils as gc_utils
2223
from osc_lib.cli import parseractions
@@ -649,6 +650,12 @@ def take_action(self, parsed_args):
649650
)
650651
data = image_client.images.data(image.id)
651652

653+
if data.wrapped is None:
654+
msg = _('Image %s has no data.') % image.id
655+
LOG.error(msg)
656+
sys.stdout.write(msg + '\n')
657+
raise SystemExit
658+
652659
gc_utils.save_image(data, parsed_args.file)
653660

654661

openstackclient/tests/unit/image/v2/test_image.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import copy
1717

18+
from glanceclient.common import utils as glanceclient_utils
1819
from glanceclient.v2 import schemas
1920
import mock
2021
from osc_lib import exceptions
@@ -1505,3 +1506,53 @@ def test_image_unset_mixed_option(self):
15051506
self.image.id, 'test'
15061507
)
15071508
self.assertIsNone(result)
1509+
1510+
1511+
class TestImageSave(TestImage):
1512+
1513+
image = image_fakes.FakeImage.create_one_image({})
1514+
1515+
def setUp(self):
1516+
super(TestImageSave, self).setUp()
1517+
1518+
# Generate a request id
1519+
self.resp = mock.MagicMock()
1520+
self.resp.headers['x-openstack-request-id'] = 'req_id'
1521+
1522+
# Get the command object to test
1523+
self.cmd = image.SaveImage(self.app, None)
1524+
1525+
def test_save_data(self):
1526+
req_id_proxy = glanceclient_utils.RequestIdProxy(
1527+
['some_data', self.resp]
1528+
)
1529+
self.images_mock.data.return_value = req_id_proxy
1530+
1531+
arglist = ['--file', '/path/to/file', self.image.id]
1532+
1533+
verifylist = [
1534+
('file', '/path/to/file'),
1535+
('image', self.image.id)
1536+
]
1537+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1538+
1539+
with mock.patch('glanceclient.common.utils.save_image') as mocked_save:
1540+
self.cmd.take_action(parsed_args)
1541+
mocked_save.assert_called_once_with(req_id_proxy, '/path/to/file')
1542+
1543+
def test_save_no_data(self):
1544+
req_id_proxy = glanceclient_utils.RequestIdProxy(
1545+
[None, self.resp]
1546+
)
1547+
self.images_mock.data.return_value = req_id_proxy
1548+
1549+
arglist = ['--file', '/path/to/file', self.image.id]
1550+
1551+
verifylist = [
1552+
('file', '/path/to/file'),
1553+
('image', self.image.id)
1554+
]
1555+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1556+
1557+
# Raise SystemExit if no data was provided.
1558+
self.assertRaises(SystemExit, self.cmd.take_action, parsed_args)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fixes:
3+
- |
4+
'NoneType' object is not iterable when Glance cannot find image data in its
5+
backend.
6+
[Bug `1741223 <https://bugs.launchpad.net/ironic/+bug/1741223>`_]

0 commit comments

Comments
 (0)