Get rid of the oslo.serialization dependency

It was used to smoothen out the difference in handling bytes in
Python 2 and 3. Now that we only support Python 3, it can be
replaced.

A side effect of this change is that we no longer accept bytes
in JSON. JSON does not support bytes, but this problem has been
hidden due to oslo.serialization until now. The configdrive
handling has been updated to account for that.

Change-Id: I230b55db55bce08d46f5023ad7a3f6501c96d100
This commit is contained in:
Dmitry Tantsur 2020-04-28 12:54:56 +02:00
parent a44a77e6d3
commit 0242f8219a
7 changed files with 32 additions and 11 deletions

View File

@ -16,6 +16,7 @@
from distutils.version import StrictVersion from distutils.version import StrictVersion
import functools import functools
from http import client as http_client from http import client as http_client
import json
import logging import logging
import re import re
import textwrap import textwrap
@ -24,7 +25,6 @@ from urllib import parse as urlparse
from keystoneauth1 import adapter from keystoneauth1 import adapter
from keystoneauth1 import exceptions as kexc from keystoneauth1 import exceptions as kexc
from oslo_serialization import jsonutils
from ironicclient.common import filecache from ironicclient.common import filecache
from ironicclient.common.i18n import _ from ironicclient.common.i18n import _
@ -67,7 +67,7 @@ def _trim_endpoint_api_version(url):
def _extract_error_json(body): def _extract_error_json(body):
"""Return error_message from the HTTP response body.""" """Return error_message from the HTTP response body."""
try: try:
body_json = jsonutils.loads(body) body_json = json.loads(body)
except ValueError: except ValueError:
return {} return {}
@ -75,7 +75,7 @@ def _extract_error_json(body):
return {} return {}
try: try:
error_json = jsonutils.loads(body_json['error_message']) error_json = json.loads(body_json['error_message'])
except ValueError: except ValueError:
return body_json return body_json
@ -393,7 +393,7 @@ class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter):
kwargs['headers'].setdefault('Accept', 'application/json') kwargs['headers'].setdefault('Accept', 'application/json')
if 'body' in kwargs: if 'body' in kwargs:
kwargs['data'] = jsonutils.dump_as_bytes(kwargs.pop('body')) kwargs['json'] = kwargs.pop('body')
resp = self._http_request(url, method, **kwargs) resp = self._http_request(url, method, **kwargs)
body = resp.content body = resp.content

View File

@ -16,6 +16,7 @@
from __future__ import print_function from __future__ import print_function
import argparse import argparse
import base64
import contextlib import contextlib
import gzip import gzip
import json import json
@ -26,7 +27,6 @@ import sys
import tempfile import tempfile
import time import time
from oslo_serialization import base64
from oslo_utils import strutils from oslo_utils import strutils
from ironicclient.common.i18n import _ from ironicclient.common.i18n import _
@ -296,7 +296,7 @@ def make_configdrive(path):
shutil.copyfileobj(tmpfile, gz_file) shutil.copyfileobj(tmpfile, gz_file)
tmpzipfile.seek(0) tmpzipfile.seek(0)
return base64.encode_as_bytes(tmpzipfile.read()) return base64.b64encode(tmpzipfile.read())
def check_empty_arg(arg, arg_descriptor): def check_empty_arg(arg, arg_descriptor):

View File

@ -14,11 +14,11 @@
# under the License. # under the License.
from http import client as http_client from http import client as http_client
import json
import time import time
from unittest import mock from unittest import mock
from keystoneauth1 import exceptions as kexc from keystoneauth1 import exceptions as kexc
from oslo_serialization import jsonutils
from ironicclient.common import filecache from ironicclient.common import filecache
from ironicclient.common import http from ironicclient.common import http
@ -40,9 +40,9 @@ def _get_error_body(faultstring=None, debuginfo=None, description=None):
'faultstring': faultstring, 'faultstring': faultstring,
'debuginfo': debuginfo 'debuginfo': debuginfo
} }
raw_error_body = jsonutils.dump_as_bytes(error_body) raw_error_body = json.dumps(error_body)
body = {'error_message': raw_error_body} body = {'error_message': raw_error_body}
return jsonutils.dumps(body) return json.dumps(body)
def _session_client(**kwargs): def _session_client(**kwargs):

View File

@ -1498,6 +1498,15 @@ class NodeManagerTest(testtools.TestCase):
] ]
self.assertEqual(expect, self.api.calls) self.assertEqual(expect, self.api.calls)
def test_node_set_provision_state_with_configdrive_invalid_bytes(self):
invalid_utf8 = b"\xc3\x28"
target_state = 'active'
self.assertRaisesRegex(ValueError,
'Config drive',
self.mgr.set_provision_state,
NODE1['uuid'], target_state,
configdrive=invalid_utf8)
def test_node_set_provision_state_with_configdrive_as_dict(self): def test_node_set_provision_state_with_configdrive_as_dict(self):
target_state = 'active' target_state = 'active'
self.mgr.set_provision_state(NODE1['uuid'], target_state, self.mgr.set_provision_state(NODE1['uuid'], target_state,
@ -1518,7 +1527,8 @@ class NodeManagerTest(testtools.TestCase):
self.mgr.set_provision_state(NODE1['uuid'], target_state, self.mgr.set_provision_state(NODE1['uuid'], target_state,
configdrive=f.name) configdrive=f.name)
body = {'target': target_state, 'configdrive': file_content} body = {'target': target_state,
'configdrive': file_content.decode('utf-8')}
expect = [ expect = [
('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body), ('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body),
] ]

View File

@ -557,6 +557,12 @@ class NodeManager(base.CreateManager):
if os.path.isdir(configdrive): if os.path.isdir(configdrive):
configdrive = utils.make_configdrive(configdrive) configdrive = utils.make_configdrive(configdrive)
if isinstance(configdrive, bytes):
try:
configdrive = configdrive.decode('utf-8')
except UnicodeError:
raise ValueError('Config drive must be a dictionary or '
'a base64 encoded string')
body['configdrive'] = configdrive body['configdrive'] = configdrive
elif cleansteps: elif cleansteps:
body['clean_steps'] = cleansteps body['clean_steps'] = cleansteps

View File

@ -0,0 +1,6 @@
---
upgrade:
- |
The Python API used to accepts byte arrays and other non-serializable in
JSON data types in a few places where strings are required. This is no
longer supported, an attempt to do it will result in an exception.

View File

@ -9,7 +9,6 @@ jsonschema>=2.6.0 # MIT
keystoneauth1>=3.4.0 # Apache-2.0 keystoneauth1>=3.4.0 # Apache-2.0
openstacksdk>=0.18.0 # Apache-2.0 openstacksdk>=0.18.0 # Apache-2.0
osc-lib>=1.10.0 # Apache-2.0 osc-lib>=1.10.0 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
PyYAML>=3.12 # MIT PyYAML>=3.12 # MIT
requests>=2.14.2 # Apache-2.0 requests>=2.14.2 # Apache-2.0