Fix linuxrbd to work with Python 3

All string args used with librbd must be None or utf-8 otherwise
librbd will break. This patch uses convert_str instead of
oslo_utils.encodeutils.

Change-Id: I77aad9f8ddd1b7175ee1521a43d16511059a9ad0
Closes-Bug: #1612290
This commit is contained in:
Ivan Kolodyazhny 2016-08-11 18:17:19 +03:00
parent f38c6c87be
commit 91ac58fe77
4 changed files with 35 additions and 19 deletions

View File

@ -14,10 +14,10 @@
import io import io
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import encodeutils
from os_brick import exception from os_brick import exception
from os_brick.i18n import _, _LE, _LW from os_brick.i18n import _, _LE, _LW
from os_brick import utils
try: try:
import rados import rados
@ -40,7 +40,7 @@ class RBDClient(object):
for attr in ['rbd_user', 'rbd_pool']: for attr in ['rbd_user', 'rbd_pool']:
val = getattr(self, attr) val = getattr(self, attr)
if val is not None: if val is not None:
setattr(self, attr, encodeutils.safe_encode(val)) setattr(self, attr, utils.convert_str(val))
# allow these to be overridden for testing # allow these to be overridden for testing
self.rados = kwargs.get('rados', rados) self.rados = kwargs.get('rados', rados)
@ -98,11 +98,11 @@ class RBDVolume(object):
def __init__(self, client, name, snapshot=None, read_only=False): def __init__(self, client, name, snapshot=None, read_only=False):
if snapshot is not None: if snapshot is not None:
snapshot = encodeutils.safe_encode(snapshot) snapshot = utils.convert_str(snapshot)
try: try:
self.image = client.rbd.Image(client.ioctx, self.image = client.rbd.Image(client.ioctx,
encodeutils.safe_encode(name), utils.convert_str(name),
snapshot=snapshot, snapshot=snapshot,
read_only=read_only) read_only=read_only)
except client.rbd.Error: except client.rbd.Error:
@ -129,9 +129,9 @@ class RBDImageMetadata(object):
"""RBD image metadata to be used with RBDVolumeIOWrapper.""" """RBD image metadata to be used with RBDVolumeIOWrapper."""
def __init__(self, image, pool, user, conf): def __init__(self, image, pool, user, conf):
self.image = image self.image = image
self.pool = encodeutils.safe_encode(pool or '') self.pool = utils.convert_str(pool or '')
self.user = encodeutils.safe_encode(user or '') self.user = utils.convert_str(user or '')
self.conf = encodeutils.safe_encode(conf or '') self.conf = utils.convert_str(conf or '')
class RBDVolumeIOWrapper(io.RawIOBase): class RBDVolumeIOWrapper(io.RawIOBase):

View File

@ -13,12 +13,11 @@
# under the License. # under the License.
import mock import mock
from oslo_utils import encodeutils
from os_brick.initiator.connectors import rbd from os_brick.initiator.connectors import rbd
from os_brick.initiator import linuxrbd from os_brick.initiator import linuxrbd
from os_brick.privileged import rootwrap as priv_rootwrap from os_brick.privileged import rootwrap as priv_rootwrap
from os_brick.tests.initiator import test_connector from os_brick.tests.initiator import test_connector
from os_brick import utils
class RBDConnectorTestCase(test_connector.ConnectorTestCase): class RBDConnectorTestCase(test_connector.ConnectorTestCase):
@ -65,18 +64,18 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
# Ensure rados is instantiated correctly # Ensure rados is instantiated correctly
mock_rados.Rados.assert_called_once_with( mock_rados.Rados.assert_called_once_with(
clustername='ceph', clustername='ceph',
rados_id=encodeutils.safe_encode(self.user), rados_id=utils.convert_str(self.user),
conffile='/etc/ceph/ceph.conf') conffile='/etc/ceph/ceph.conf')
# Ensure correct calls to connect to cluster # Ensure correct calls to connect to cluster
self.assertEqual(1, mock_rados.Rados.return_value.connect.call_count) self.assertEqual(1, mock_rados.Rados.return_value.connect.call_count)
mock_rados.Rados.return_value.open_ioctx.assert_called_once_with( mock_rados.Rados.return_value.open_ioctx.assert_called_once_with(
encodeutils.safe_encode(self.pool)) utils.convert_str(self.pool))
# Ensure rbd image is instantiated correctly # Ensure rbd image is instantiated correctly
mock_rbd.Image.assert_called_once_with( mock_rbd.Image.assert_called_once_with(
mock_rados.Rados.return_value.open_ioctx.return_value, mock_rados.Rados.return_value.open_ioctx.return_value,
encodeutils.safe_encode(self.volume), read_only=False, utils.convert_str(self.volume), read_only=False,
snapshot=None) snapshot=None)
# Ensure expected object is returned correctly # Ensure expected object is returned correctly

View File

@ -14,7 +14,7 @@ import mock
from os_brick.initiator import linuxrbd from os_brick.initiator import linuxrbd
from os_brick.tests import base from os_brick.tests import base
from oslo_utils import encodeutils from os_brick import utils
class RBDClientTestCase(base.TestCase): class RBDClientTestCase(base.TestCase):
@ -29,22 +29,20 @@ class RBDClientTestCase(base.TestCase):
# Verify object attributes are assigned as expected # Verify object attributes are assigned as expected
self.assertEqual('/etc/ceph/ceph.conf', client.rbd_conf) self.assertEqual('/etc/ceph/ceph.conf', client.rbd_conf)
self.assertEqual(encodeutils.safe_encode('test_user'), self.assertEqual(utils.convert_str('test_user'), client.rbd_user)
client.rbd_user) self.assertEqual(utils.convert_str('test_pool'), client.rbd_pool)
self.assertEqual(encodeutils.safe_encode('test_pool'),
client.rbd_pool)
# Assert connect is called with correct paramaters # Assert connect is called with correct paramaters
mock_rados.Rados.assert_called_once_with( mock_rados.Rados.assert_called_once_with(
clustername='ceph', clustername='ceph',
rados_id=encodeutils.safe_encode('test_user'), rados_id=utils.convert_str('test_user'),
conffile='/etc/ceph/ceph.conf') conffile='/etc/ceph/ceph.conf')
# Ensure correct calls to connect to cluster # Ensure correct calls to connect to cluster
self.assertEqual( self.assertEqual(
1, mock_rados.Rados.return_value.connect.call_count) 1, mock_rados.Rados.return_value.connect.call_count)
mock_rados.Rados.return_value.open_ioctx.assert_called_once_with( mock_rados.Rados.return_value.open_ioctx.assert_called_once_with(
encodeutils.safe_encode('test_pool')) utils.convert_str('test_pool'))
self.assertEqual(1, mock_rados.Rados.return_value.shutdown.call_count) self.assertEqual(1, mock_rados.Rados.return_value.shutdown.call_count)

View File

@ -18,6 +18,7 @@ import logging as py_logging
import time import time
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import encodeutils
import retrying import retrying
import six import six
@ -156,3 +157,21 @@ def trace(f):
'result': result}) 'result': result})
return result return result
return trace_logging_wrapper return trace_logging_wrapper
def convert_str(text):
"""Convert to native string.
Convert bytes and Unicode strings to native strings:
* convert to bytes on Python 2:
encode Unicode using encodeutils.safe_encode()
* convert to Unicode on Python 3: decode bytes from UTF-8
"""
if six.PY2:
return encodeutils.to_utf8(text)
else:
if isinstance(text, bytes):
return text.decode('utf-8')
else:
return text