Make rbd driver string encoding checks consistent

All string checks should use strutils.safe_encode()

Closes-Bug: 1333446
Change-Id: I56c9ccbcedd34c83793620561da17c47cb5f551c
This commit is contained in:
Edward Hope-Morley 2014-06-23 17:51:44 +01:00
parent 0f4d8d4c1b
commit 20001f2470
2 changed files with 34 additions and 42 deletions

View File

@ -122,15 +122,6 @@ CEPH_MON_DUMP = """dumped monmap epoch 1
"""
class TestUtil(test.TestCase):
def test_ascii_str(self):
self.assertIsNone(driver.ascii_str(None))
self.assertEqual('foo', driver.ascii_str('foo'))
self.assertEqual('foo', driver.ascii_str(u'foo'))
self.assertRaises(UnicodeEncodeError,
driver.ascii_str, 'foo' + unichr(300))
class RBDTestCase(test.TestCase):
def setUp(self):

View File

@ -79,24 +79,13 @@ CONF = cfg.CONF
CONF.register_opts(rbd_opts)
def ascii_str(string):
"""Convert a string to ascii, or return None if the input is None.
This is useful when a parameter is None by default, or a string. LibRBD
only accepts ascii, hence the need for conversion.
"""
if string is None:
return string
return str(string)
class RBDImageMetadata(object):
"""RBD image metadata to be used with RBDImageIOWrapper."""
def __init__(self, image, pool, user, conf):
self.image = image
self.pool = str(pool)
self.user = str(user)
self.conf = str(conf)
self.pool = strutils.safe_encode(pool)
self.user = strutils.safe_encode(user)
self.conf = strutils.safe_encode(conf)
class RBDImageIOWrapper(io.RawIOBase):
@ -209,9 +198,12 @@ class RBDVolumeProxy(object):
def __init__(self, driver, name, pool=None, snapshot=None,
read_only=False):
client, ioctx = driver._connect_to_rados(pool)
if snapshot is not None:
snapshot = strutils.safe_encode(snapshot)
try:
self.volume = driver.rbd.Image(ioctx, str(name),
snapshot=ascii_str(snapshot),
self.volume = driver.rbd.Image(ioctx, strutils.safe_encode(name),
snapshot=snapshot,
read_only=read_only)
except driver.rbd.Error:
LOG.exception(_("error opening rbd image %s"), name)
@ -260,6 +252,13 @@ class RBDDriver(driver.VolumeDriver):
self.rados = kwargs.get('rados', rados)
self.rbd = kwargs.get('rbd', rbd)
# All string args used with librbd must be None or utf-8 otherwise
# librbd will break.
for attr in ['rbd_user', 'rbd_ceph_conf', 'rbd_pool']:
val = getattr(self.configuration, attr)
if val is not None:
setattr(self.configuration, attr, strutils.safe_encode(val))
def check_for_setup_error(self):
"""Returns an error if prerequisites aren't met."""
if rados is None:
@ -282,13 +281,16 @@ class RBDDriver(driver.VolumeDriver):
return args
def _connect_to_rados(self, pool=None):
ascii_user = ascii_str(self.configuration.rbd_user)
ascii_conf = ascii_str(self.configuration.rbd_ceph_conf)
client = self.rados.Rados(rados_id=ascii_user, conffile=ascii_conf)
client = self.rados.Rados(rados_id=self.configuration.rbd_user,
conffile=self.configuration.rbd_ceph_conf)
if pool is not None:
pool = strutils.safe_encode(pool)
else:
pool = self.configuration.rbd_pool
try:
client.connect()
pool_to_open = str(pool or self.configuration.rbd_pool)
ioctx = client.open_ioctx(pool_to_open)
ioctx = client.open_ioctx(pool)
return client, ioctx
except self.rados.Error:
# shutdown cannot raise an exception
@ -397,8 +399,8 @@ class RBDDriver(driver.VolumeDriver):
and that clone has rbd_max_clone_depth clones behind it, the source
volume will be flattened.
"""
src_name = str(src_vref['name'])
dest_name = str(volume['name'])
src_name = strutils.safe_encode(src_vref['name'])
dest_name = strutils.safe_encode(volume['name'])
flatten_parent = False
# Do full copy if requested
@ -484,7 +486,7 @@ class RBDDriver(driver.VolumeDriver):
with RADOSClient(self) as client:
self.rbd.RBD().create(client.ioctx,
str(volume['name']),
strutils.safe_encode(volume['name']),
size,
order,
old_format=old_format,
@ -503,10 +505,10 @@ class RBDDriver(driver.VolumeDriver):
with RADOSClient(self, src_pool) as src_client:
with RADOSClient(self) as dest_client:
self.rbd.RBD().clone(src_client.ioctx,
str(src_image),
str(src_snap),
strutils.safe_encode(src_image),
strutils.safe_encode(src_snap),
dest_client.ioctx,
str(volume['name']),
strutils.safe_encode(volume['name']),
features=self.rbd.RBD_FEATURE_LAYERING)
def _resize(self, volume, **kwargs):
@ -659,7 +661,7 @@ class RBDDriver(driver.VolumeDriver):
def create_snapshot(self, snapshot):
"""Creates an rbd snapshot."""
with RBDVolumeProxy(self, snapshot['volume_name']) as volume:
snap = str(snapshot['name'])
snap = strutils.safe_encode(snapshot['name'])
volume.create_snap(snap)
if self._supports_layering():
volume.protect_snap(snap)
@ -819,9 +821,9 @@ class RBDDriver(driver.VolumeDriver):
def backup_volume(self, context, backup, backup_service):
"""Create a new backup from an existing volume."""
volume = self.db.volume_get(context, backup['volume_id'])
pool = self.configuration.rbd_pool
with RBDVolumeProxy(self, volume['name'], pool) as rbd_image:
with RBDVolumeProxy(self, volume['name'],
self.configuration.rbd_pool) as rbd_image:
rbd_meta = RBDImageMetadata(rbd_image, self.configuration.rbd_pool,
self.configuration.rbd_user,
self.configuration.rbd_ceph_conf)
@ -832,9 +834,8 @@ class RBDDriver(driver.VolumeDriver):
def restore_backup(self, context, backup, volume, backup_service):
"""Restore an existing backup to a new or existing volume."""
pool = self.configuration.rbd_pool
with RBDVolumeProxy(self, volume['name'], pool) as rbd_image:
with RBDVolumeProxy(self, volume['name'],
self.configuration.rbd_pool) as rbd_image:
rbd_meta = RBDImageMetadata(rbd_image, self.configuration.rbd_pool,
self.configuration.rbd_user,
self.configuration.rbd_ceph_conf)