py3: use binary mode for opening image files

If binary mode is not used when running with python3 glance image
uploads fail as files are opened with encoding='UTF-8' by default.

It results in the following confusing error message:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfb in position 3:
invalid start byte

(Pdb) e
UnicodeDecodeError('utf-8', b'QFI\xfb\x00\x00\

0xfb is a QCOW magic string and is invalid from UTF-8 standard
perspective. From the QCOW2 spec:

Byte  0 -  3:   magic
                QCOW magic string ("QFI\xfb")

Tracing have shown that the error comes from python-glanceclient when a
file handle passed to it is attempted to be used for sending image
chunks.

Change-Id: I6bb31fe1d3f79a8fd4707a5576204dee69a3f307
Depends-On: I4991acccefd4754e209feafd5e24d03c76c283f8
Closes-Bug: #1819274
This commit is contained in:
Dmitrii Shcherbakov 2019-03-09 02:51:18 +03:00
parent 8222a4e611
commit 4822b45230
4 changed files with 4 additions and 4 deletions

View File

@ -52,7 +52,7 @@ class GlanceV1Service(service.Service, glance_common.GlanceMixin):
try:
if os.path.isfile(image_location):
kwargs["data"] = open(image_location)
kwargs["data"] = open(image_location, "rb")
else:
kwargs["copy_from"] = image_location

View File

@ -44,7 +44,7 @@ class GlanceV2Service(service.Service, glance_common.GlanceMixin):
response = None
try:
if os.path.isfile(image_location):
image_data = open(image_location)
image_data = open(image_location, "rb")
else:
response = requests.get(image_location, stream=True)
image_data = response.raw

View File

@ -70,7 +70,7 @@ class GlanceV1ServiceTestCase(test.TestCase):
if location.startswith("/"):
call_args["data"] = mock_open.return_value
mock_open.assert_called_once_with(location)
mock_open.assert_called_once_with(location, "rb")
mock_open.return_value.close.assert_called_once_with()
else:
call_args["copy_from"] = location

View File

@ -51,7 +51,7 @@ class GlanceV2ServiceTestCase(test.TestCase):
self.service.upload_data(image_id, image_location=location)
if location.startswith("/"):
mock_open.assert_called_once_with(location)
mock_open.assert_called_once_with(location, "rb")
mock_open.return_value.close.assert_called_once_with()
self.gc.images.upload.assert_called_once_with(
image_id, mock_open.return_value)