summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Coles <dcoles@gaikai.com>2015-10-15 23:58:53 +0200
committerDavid Coles <dcoles@gaikai.com>2015-10-20 00:06:52 +0200
commitab6b92398071a5e364514afe2bdb57a634c04ceb (patch)
treef310a591abdd2c0902b031503f5da06e988c7ffd /src
parentMerge pull request #5335 from zhouyuan/radosgw_admin_secret_key_alias (diff)
downloadceph-ab6b92398071a5e364514afe2bdb57a634c04ceb.tar.xz
ceph-ab6b92398071a5e364514afe2bdb57a634c04ceb.zip
pybind: Add Python 3 support for rados and rbd modules
Python 3 explicitly distinguishes between strings (which can contain any Unicode character) and 8-bit byte strings. This means that we must explicitly encode and decode strings that use C-style char* string APIs. Functions that take a true-strings now have their values encoded to UTF-8 before being passed to the C API, while functions that accept binary data only accept the bytes type. To help with this the `cstr` helper function has been introduced as a way of easily a string into a C-string compatible form. There is also a number of general Python 3 compatibility fixes: - dict.iteritems() is replaced with just dict.items() - xrange() is replaced with just range - Iterators now use the __next__ magic method - zip() and map() now return iterators, rather than lists - print() is now a function - contextlib.nexted() is replaced with multiple manager with-statement (from Python 2.7) This also required updating of the unit-tests for these modules, mostly due to explicitly distinguishing between strings and byte strings. Signed-off-by: David Coles <dcoles@gaikai.com>
Diffstat (limited to 'src')
-rw-r--r--src/pybind/rados.py195
-rw-r--r--src/pybind/rbd.py95
-rw-r--r--src/test/pybind/test_rados.py181
-rw-r--r--src/test/pybind/test_rbd.py181
4 files changed, 340 insertions, 312 deletions
diff --git a/src/pybind/rados.py b/src/pybind/rados.py
index 804a1692020..30be4f93789 100644
--- a/src/pybind/rados.py
+++ b/src/pybind/rados.py
@@ -12,6 +12,7 @@ import errno
import threading
import time
+from collections import Iterator
from datetime import datetime
from functools import wraps
from itertools import chain
@@ -261,6 +262,19 @@ def requires(*types):
return wrapper
+def cstr(val, encoding="utf-8"):
+ """
+ Create a C-style string from a Python string
+
+ :param str val: Python string
+ :rtype: c_char_p
+ """
+ if val is None:
+ return c_char_p(None)
+
+ return c_char_p(val.encode(encoding))
+
+
class Rados(object):
"""librados python wrapper"""
def require_state(self, *args):
@@ -297,15 +311,15 @@ Rados object in state %s." % self.state)
if clustername is None:
clustername = 'ceph'
ret = run_in_thread(self.librados.rados_create2,
- (byref(self.cluster), c_char_p(clustername),
- c_char_p(name), c_uint64(flags)))
+ (byref(self.cluster), cstr(clustername),
+ cstr(name), c_uint64(flags)))
if ret != 0:
raise Error("rados_initialize failed with error code: %d" % ret)
self.state = "configuring"
# order is important: conf_defaults, then conffile, then conf
if conf_defaults:
- for key, value in conf_defaults.iteritems():
+ for key, value in conf_defaults.items():
self.conf_set(key, value)
if conffile is not None:
# read the default conf file when '' is given
@@ -313,7 +327,7 @@ Rados object in state %s." % self.state)
conffile = None
self.conf_read_file(conffile)
if conf:
- for key, value in conf.iteritems():
+ for key, value in conf.items():
self.conf_set(key, value)
def shutdown(self):
@@ -358,7 +372,7 @@ Rados object in state %s." % self.state)
"""
self.require_state("configuring", "connected")
ret = run_in_thread(self.librados.rados_conf_read_file,
- (self.cluster, c_char_p(path)))
+ (self.cluster, cstr(path)))
if (ret != 0):
raise make_ex(ret, "error calling conf_read_file")
@@ -372,7 +386,7 @@ Rados object in state %s." % self.state)
return
# create instances of arrays of c_char_p's, both len(args) long
# cretargs will always be a subset of cargs (perhaps identical)
- cargs = (c_char_p * len(args))(*args)
+ cargs = (c_char_p * len(args))(*map(cstr, args))
cretargs = (c_char_p * len(args))()
ret = run_in_thread(self.librados.rados_conf_parse_argv_remainder,
(self.cluster, len(args), cargs, cretargs))
@@ -395,7 +409,7 @@ Rados object in state %s." % self.state)
if not var:
return
ret = run_in_thread(self.librados.rados_conf_parse_env,
- (self.cluster, c_char_p(var)))
+ (self.cluster, cstr(var)))
if (ret != 0):
raise make_ex(ret, "error calling conf_parse_env")
@@ -415,10 +429,10 @@ Rados object in state %s." % self.state)
while True:
ret_buf = create_string_buffer(length)
ret = run_in_thread(self.librados.rados_conf_get,
- (self.cluster, c_char_p(option), ret_buf,
- c_size_t(length)))
+ (self.cluster, cstr(option), ret_buf,
+ c_size_t(length)))
if (ret == 0):
- return ret_buf.value
+ return ret_buf.value.decode("utf-8")
elif (ret == -errno.ENAMETOOLONG):
length = length * 2
elif (ret == -errno.ENOENT):
@@ -440,7 +454,7 @@ Rados object in state %s." % self.state)
"""
self.require_state("configuring", "connected")
ret = run_in_thread(self.librados.rados_conf_set,
- (self.cluster, c_char_p(option), c_char_p(val)))
+ (self.cluster, cstr(option), cstr(val)))
if (ret != 0):
raise make_ex(ret, "error calling conf_set")
@@ -463,7 +477,7 @@ Rados object in state %s." % self.state)
outstrlen = c_long()
ret = run_in_thread(self.librados.rados_ping_monitor,
- (self.cluster, c_char_p(mon_id),
+ (self.cluster, cstr(mon_id),
outstrp, byref(outstrlen)))
my_outstr = outstrp.contents[:(outstrlen.value)]
@@ -528,7 +542,7 @@ Rados object in state %s." % self.state)
"""
self.require_state("connected")
ret = run_in_thread(self.librados.rados_pool_lookup,
- (self.cluster, c_char_p(pool_name)))
+ (self.cluster, cstr(pool_name)))
if (ret >= 0):
return True
elif (ret == -errno.ENOENT):
@@ -549,7 +563,7 @@ Rados object in state %s." % self.state)
"""
self.require_state("connected")
ret = run_in_thread(self.librados.rados_pool_lookup,
- (self.cluster, c_char_p(pool_name)))
+ (self.cluster, cstr(pool_name)))
if (ret >= 0):
return int(ret)
elif (ret == -errno.ENOENT):
@@ -606,20 +620,20 @@ Rados object in state %s." % self.state)
if auid is None:
if crush_rule is None:
ret = run_in_thread(self.librados.rados_pool_create,
- (self.cluster, c_char_p(pool_name)))
+ (self.cluster, cstr(pool_name)))
else:
ret = run_in_thread(self.librados.
rados_pool_create_with_crush_rule,
- (self.cluster, c_char_p(pool_name),
+ (self.cluster, cstr(pool_name),
c_ubyte(crush_rule)))
elif crush_rule is None:
ret = run_in_thread(self.librados.rados_pool_create_with_auid,
- (self.cluster, c_char_p(pool_name),
+ (self.cluster, cstr(pool_name),
c_uint64(auid)))
else:
ret = run_in_thread(self.librados.rados_pool_create_with_all,
- (self.cluster, c_char_p(pool_name),
+ (self.cluster, cstr(pool_name),
c_uint64(auid), c_ubyte(crush_rule)))
if ret < 0:
raise make_ex(ret, "error creating pool '%s'" % pool_name)
@@ -654,7 +668,7 @@ Rados object in state %s." % self.state)
"""
self.require_state("connected")
ret = run_in_thread(self.librados.rados_pool_delete,
- (self.cluster, c_char_p(pool_name)))
+ (self.cluster, cstr(pool_name)))
if ret < 0:
raise make_ex(ret, "error deleting pool '%s'" % pool_name)
@@ -674,7 +688,8 @@ Rados object in state %s." % self.state)
size = c_size_t(ret)
else:
break
- return filter(lambda name: name != '', c_names.raw.split('\0'))
+
+ return [name for name in c_names.raw.decode("utf-8").split('\0') if len(name) > 0]
def get_fsid(self):
"""
@@ -709,7 +724,7 @@ Rados object in state %s." % self.state)
self.require_state("connected")
ioctx = c_void_p()
ret = run_in_thread(self.librados.rados_ioctx_create,
- (self.cluster, c_char_p(ioctx_name), byref(ioctx)))
+ (self.cluster, cstr(ioctx_name), byref(ioctx)))
if ret < 0:
raise make_ex(ret, "error opening pool '%s'" % ioctx_name)
return Ioctx(ioctx_name, self.librados, ioctx)
@@ -724,11 +739,11 @@ Rados object in state %s." % self.state)
outbuflen = c_long()
outsp = pointer(pointer(c_char()))
outslen = c_long()
- cmdarr = (c_char_p * len(cmd))(*cmd)
+ cmdarr = (c_char_p * len(cmd))(*map(cstr, cmd))
if target:
ret = run_in_thread(self.librados.rados_mon_command_target,
- (self.cluster, c_char_p(target), cmdarr,
+ (self.cluster, cstr(target), cmdarr,
len(cmd), c_char_p(inbuf), len(inbuf),
outbufp, byref(outbuflen), outsp,
byref(outslen)), timeout)
@@ -761,7 +776,7 @@ Rados object in state %s." % self.state)
outbuflen = c_long()
outsp = pointer(pointer(c_char()))
outslen = c_long()
- cmdarr = (c_char_p * len(cmd))(*cmd)
+ cmdarr = (c_char_p * len(cmd))(*map(cstr, cmd))
ret = run_in_thread(self.librados.rados_osd_command,
(self.cluster, osdid, cmdarr, len(cmd),
c_char_p(inbuf), len(inbuf),
@@ -790,9 +805,9 @@ Rados object in state %s." % self.state)
outbuflen = c_long()
outsp = pointer(pointer(c_char()))
outslen = c_long()
- cmdarr = (c_char_p * len(cmd))(*cmd)
+ cmdarr = (c_char_p * len(cmd))(*map(cstr, cmd))
ret = run_in_thread(self.librados.rados_pg_command,
- (self.cluster, c_char_p(pgid), cmdarr, len(cmd),
+ (self.cluster, cstr(pgid), cmdarr, len(cmd),
c_char_p(inbuf), len(inbuf),
outbufp, byref(outbuflen), outsp, byref(outslen)),
timeout)
@@ -826,13 +841,13 @@ Rados object in state %s." % self.state)
"""
self.require_state("connected")
ret = run_in_thread(self.librados.rados_blacklist_add,
- (self.cluster, c_char_p(client_address),
+ (self.cluster, cstr(client_address),
c_uint32(expire_seconds)))
if ret < 0:
raise make_ex(ret, "error blacklisting client '%s'" % client_address)
-class OmapIterator(object):
+class OmapIterator(Iterator):
"""Omap iterator"""
def __init__(self, ioctx, ctx):
self.ioctx = ioctx
@@ -842,6 +857,9 @@ class OmapIterator(object):
return self
def next(self):
+ return self.__next__()
+
+ def __next__(self):
"""
Get the next key-value pair in the object
:returns: next rados.OmapItem
@@ -855,7 +873,7 @@ class OmapIterator(object):
raise make_ex(ret, "error iterating over the omap")
if key_.value is None:
raise StopIteration()
- key = ctypes.string_at(key_)
+ key = key_.value.decode("utf-8")
val = None
if val_.value is not None:
val = ctypes.string_at(val_, len_)
@@ -865,7 +883,7 @@ class OmapIterator(object):
run_in_thread(self.ioctx.librados.rados_omap_get_end, (self.ctx,))
-class ObjectIterator(object):
+class ObjectIterator(Iterator):
"""rados.Ioctx Object iterator"""
def __init__(self, ioctx):
self.ioctx = ioctx
@@ -880,26 +898,33 @@ class ObjectIterator(object):
return self
def next(self):
+ return self.__next__()
+
+ def __next__(self):
"""
Get the next object name and locator in the pool
:raises: StopIteration
:returns: next rados.Ioctx Object
"""
- key = c_char_p()
- locator = c_char_p()
- nspace = c_char_p()
+ key_ = c_char_p()
+ locator_ = c_char_p()
+ nspace_ = c_char_p()
ret = run_in_thread(self.ioctx.librados.rados_nobjects_list_next,
- (self.ctx, byref(key), byref(locator), byref(nspace)))
+ (self.ctx, byref(key_), byref(locator_), byref(nspace_)))
if ret < 0:
raise StopIteration()
- return Object(self.ioctx, key.value, locator.value, nspace.value)
+
+ key = None if key_.value is None else key_.value.decode("utf-8")
+ locator = None if locator_.value is None else locator_.value.decode("utf-8")
+ nspace = None if nspace_.value is None else nspace_.value.decode("utf-8")
+ return Object(self.ioctx, key, locator, nspace)
def __del__(self):
run_in_thread(self.ioctx.librados.rados_nobjects_list_close, (self.ctx,))
-class XattrIterator(object):
+class XattrIterator(Iterator):
"""Extended attribute iterator"""
def __init__(self, ioctx, it, oid):
self.ioctx = ioctx
@@ -910,6 +935,9 @@ class XattrIterator(object):
return self
def next(self):
+ return self.__next__()
+
+ def __next__(self):
"""
Get the next xattr on the object
@@ -926,7 +954,7 @@ class XattrIterator(object):
in '%s'" % self.oid)
if name_.value is None:
raise StopIteration()
- name = ctypes.string_at(name_)
+ name = ctypes.string_at(name_).decode("utf-8")
val = ctypes.string_at(val_, len_)
return (name, val)
@@ -934,7 +962,7 @@ in '%s'" % self.oid)
run_in_thread(self.ioctx.librados.rados_getxattrs_end, (self.it,))
-class SnapIterator(object):
+class SnapIterator(Iterator):
"""Snapshot iterator"""
def __init__(self, ioctx):
self.ioctx = ioctx
@@ -958,6 +986,9 @@ ioctx '%s'" % self.ioctx.name)
return self
def next(self):
+ return self.__next__()
+
+ def __next__(self):
"""
Get the next Snapshot
@@ -979,7 +1010,7 @@ ioctx '%s'" % self.ioctx.name)
elif (ret != -errno.ERANGE):
raise make_ex(ret, "rados_snap_get_name error")
name_len = name_len * 2
- snap = Snap(self.ioctx, name.value, snap_id)
+ snap = Snap(self.ioctx, name.value.decode("utf-8"), snap_id)
self.cur_snap = self.cur_snap + 1
return snap
@@ -1244,7 +1275,7 @@ class Ioctx(object):
"""
completion = self.__get_completion(oncomplete, onsafe)
ret = run_in_thread(self.librados.rados_aio_write,
- (self.io, c_char_p(object_name),
+ (self.io, cstr(object_name),
completion.rados_comp, c_char_p(to_write),
c_size_t(len(to_write)), c_uint64(offset)))
if ret < 0:
@@ -1276,7 +1307,7 @@ class Ioctx(object):
"""
completion = self.__get_completion(oncomplete, onsafe)
ret = run_in_thread(self.librados.rados_aio_write_full,
- (self.io, c_char_p(object_name),
+ (self.io, cstr(object_name),
completion.rados_comp, c_char_p(to_write),
c_size_t(len(to_write))))
if ret < 0:
@@ -1307,7 +1338,7 @@ class Ioctx(object):
"""
completion = self.__get_completion(oncomplete, onsafe)
ret = run_in_thread(self.librados.rados_aio_append,
- (self.io, c_char_p(object_name),
+ (self.io, cstr(object_name),
completion.rados_comp, c_char_p(to_append),
c_size_t(len(to_append))))
if ret < 0:
@@ -1354,7 +1385,7 @@ class Ioctx(object):
completion = self.__get_completion(oncomplete_, None)
ret = run_in_thread(self.librados.rados_aio_read,
- (self.io, c_char_p(object_name),
+ (self.io, cstr(object_name),
completion.rados_comp, buf, c_size_t(length),
c_uint64(offset)))
if ret < 0:
@@ -1379,7 +1410,7 @@ class Ioctx(object):
"""
completion = self.__get_completion(oncomplete, onsafe)
ret = run_in_thread(self.librados.rados_aio_remove,
- (self.io, c_char_p(object_name),
+ (self.io, cstr(object_name),
completion.rados_comp))
if ret < 0:
raise make_ex(ret, "error removing %s" % object_name)
@@ -1428,7 +1459,7 @@ class Ioctx(object):
"""
self.require_ioctx_open()
run_in_thread(self.librados.rados_ioctx_locator_set_key,
- (self.io, c_char_p(loc_key)))
+ (self.io, cstr(loc_key)))
self.locator_key = loc_key
def get_locator_key(self):
@@ -1459,7 +1490,7 @@ class Ioctx(object):
if nspace is None:
nspace = ""
run_in_thread(self.librados.rados_ioctx_set_namespace,
- (self.io, c_char_p(nspace)))
+ (self.io, cstr(nspace)))
self.nspace = nspace
def get_namespace(self):
@@ -1485,7 +1516,7 @@ class Ioctx(object):
self.state = "closed"
- @requires(('key', str), ('data', str))
+ @requires(('key', str), ('data', bytes))
def write(self, key, data, offset=0):
"""
Write data to an object synchronously
@@ -1493,7 +1524,7 @@ class Ioctx(object):
:param key: name of the object
:type key: str
:param data: data to write
- :type data: str
+ :type data: bytes
:param offset: byte offset in the object to begin writing at
:type offset: int
@@ -1504,7 +1535,7 @@ class Ioctx(object):
self.require_ioctx_open()
length = len(data)
ret = run_in_thread(self.librados.rados_write,
- (self.io, c_char_p(key), c_char_p(data),
+ (self.io, cstr(key), c_char_p(data),
c_size_t(length), c_uint64(offset)))
if ret == 0:
return ret
@@ -1515,7 +1546,7 @@ class Ioctx(object):
raise LogicError("Ioctx.write(%s): rados_write \
returned %d, but should return zero on success." % (self.name, ret))
- @requires(('key', str), ('data', str))
+ @requires(('key', str), ('data', bytes))
def write_full(self, key, data):
"""
Write an entire object synchronously.
@@ -1526,7 +1557,7 @@ returned %d, but should return zero on success." % (self.name, ret))
:param key: name of the object
:type key: str
:param data: data to write
- :type data: str
+ :type data: bytes
:raises: :class:`TypeError`
:raises: :class:`Error`
@@ -1535,7 +1566,7 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
length = len(data)
ret = run_in_thread(self.librados.rados_write_full,
- (self.io, c_char_p(key), c_char_p(data),
+ (self.io, cstr(key), c_char_p(data),
c_size_t(length)))
if ret == 0:
return ret
@@ -1546,7 +1577,7 @@ returned %d, but should return zero on success." % (self.name, ret))
raise LogicError("Ioctx.write_full(%s): rados_write_full \
returned %d, but should return zero on success." % (self.name, ret))
- @requires(('key', str), ('data', str))
+ @requires(('key', str), ('data', bytes))
def append(self, key, data):
"""
Append data to an object synchronously
@@ -1554,7 +1585,7 @@ returned %d, but should return zero on success." % (self.name, ret))
:param key: name of the object
:type key: str
:param data: data to write
- :type data: str
+ :type data: bytes
:raises: :class:`TypeError`
:raises: :class:`LogicError`
@@ -1563,7 +1594,7 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
length = len(data)
ret = run_in_thread(self.librados.rados_append,
- (self.io, c_char_p(key), c_char_p(data),
+ (self.io, cstr(key), c_char_p(data),
c_size_t(length)))
if ret == 0:
return ret
@@ -1593,7 +1624,7 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
ret_buf = create_string_buffer(length)
ret = run_in_thread(self.librados.rados_read,
- (self.io, c_char_p(key), ret_buf, c_size_t(length),
+ (self.io, cstr(key), ret_buf, c_size_t(length),
c_uint64(offset)))
if ret < 0:
raise make_ex(ret, "Ioctx.read(%s): failed to read %s" % (self.name, key))
@@ -1665,7 +1696,7 @@ returned %d, but should return zero on success." % (self.name, ret))
"""
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_remove,
- (self.io, c_char_p(key)))
+ (self.io, cstr(key)))
if ret < 0:
raise make_ex(ret, "Failed to remove '%s'" % key)
return True
@@ -1690,7 +1721,7 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_trunc,
- (self.io, c_char_p(key), c_uint64(size)))
+ (self.io, cstr(key), c_uint64(size)))
if ret < 0:
raise make_ex(ret, "Ioctx.trunc(%s): failed to truncate %s" % (self.name, key))
return ret
@@ -1712,7 +1743,7 @@ returned %d, but should return zero on success." % (self.name, ret))
pmtime = c_uint64()
ret = run_in_thread(self.librados.rados_stat,
- (self.io, c_char_p(key), pointer(psize),
+ (self.io, cstr(key), pointer(psize),
pointer(pmtime)))
if ret < 0:
raise make_ex(ret, "Failed to stat %r" % key)
@@ -1737,7 +1768,7 @@ returned %d, but should return zero on success." % (self.name, ret))
while ret_length < 4096 * 1024 * 1024:
ret_buf = create_string_buffer(ret_length)
ret = run_in_thread(self.librados.rados_getxattr,
- (self.io, c_char_p(key), c_char_p(xattr_name),
+ (self.io, cstr(key), cstr(xattr_name),
ret_buf, c_size_t(ret_length)))
if (ret == -errno.ERANGE):
ret_length *= 2
@@ -1753,7 +1784,7 @@ returned %d, but should return zero on success." % (self.name, ret))
Start iterating over xattrs on an object.
:param oid: the name of the object to get xattrs from
- :type key: str
+ :type oid: str
:raises: :class:`TypeError`
:raises: :class:`Error`
@@ -1762,12 +1793,12 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
it = c_void_p(0)
ret = run_in_thread(self.librados.rados_getxattrs,
- (self.io, oid, byref(it)))
+ (self.io, cstr(oid), byref(it)))
if ret != 0:
raise make_ex(ret, "Failed to get rados xattrs for object %r" % oid)
return XattrIterator(self, it, oid)
- @requires(('key', str), ('xattr_name', str), ('xattr_value', str))
+ @requires(('key', str), ('xattr_name', str), ('xattr_value', bytes))
def set_xattr(self, key, xattr_name, xattr_value):
"""
Set an extended attribute on an object.
@@ -1777,7 +1808,7 @@ returned %d, but should return zero on success." % (self.name, ret))
:param xattr_name: which extended attribute to set
:type xattr_name: str
:param xattr_value: the value of the extended attribute
- :type xattr_value: str
+ :type xattr_value: bytes
:raises: :class:`TypeError`
:raises: :class:`Error`
@@ -1785,7 +1816,7 @@ returned %d, but should return zero on success." % (self.name, ret))
"""
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_setxattr,
- (self.io, c_char_p(key), c_char_p(xattr_name),
+ (self.io, cstr(key), cstr(xattr_name),
c_char_p(xattr_value), c_size_t(len(xattr_value))))
if ret < 0:
raise make_ex(ret, "Failed to set xattr %r" % xattr_name)
@@ -1807,7 +1838,7 @@ returned %d, but should return zero on success." % (self.name, ret))
"""
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_rmxattr,
- (self.io, c_char_p(key), c_char_p(xattr_name)))
+ (self.io, cstr(key), cstr(xattr_name)))
if ret < 0:
raise make_ex(ret, "Failed to delete key %r xattr %r" %
(key, xattr_name))
@@ -1844,7 +1875,7 @@ returned %d, but should return zero on success." % (self.name, ret))
"""
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_ioctx_snap_create,
- (self.io, c_char_p(snap_name)))
+ (self.io, cstr(snap_name)))
if (ret != 0):
raise make_ex(ret, "Failed to create snap %s" % snap_name)
@@ -1861,7 +1892,7 @@ returned %d, but should return zero on success." % (self.name, ret))
"""
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_ioctx_snap_remove,
- (self.io, c_char_p(snap_name)))
+ (self.io, cstr(snap_name)))
if (ret != 0):
raise make_ex(ret, "Failed to remove snap %s" % snap_name)
@@ -1880,7 +1911,7 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
snap_id = c_uint64()
ret = run_in_thread(self.librados.rados_ioctx_snap_lookup,
- (self.io, c_char_p(snap_name), byref(snap_id)))
+ (self.io, cstr(snap_name), byref(snap_id)))
if (ret != 0):
raise make_ex(ret, "Failed to lookup snap %s" % snap_name)
return Snap(self, snap_name, snap_id)
@@ -1945,7 +1976,7 @@ returned %d, but should return zero on success." % (self.name, ret))
key_num = len(keys)
key_array_type = c_char_p*key_num
key_array = key_array_type()
- key_array[:] = keys
+ key_array[:] = [cstr(key) for key in keys]
value_array_type = c_char_p*key_num
value_array = value_array_type()
@@ -1974,7 +2005,7 @@ returned %d, but should return zero on success." % (self.name, ret))
:type flags: int
"""
run_in_thread(self.librados.rados_write_op_operate,
- (c_void_p(write_op), self.io, c_char_p(oid),
+ (c_void_p(write_op), self.io, cstr(oid),
c_long(mtime), c_int(flags),))
@requires(('read_op', int), ('oid', str), ('flag', opt(int)))
@@ -1989,7 +2020,7 @@ returned %d, but should return zero on success." % (self.name, ret))
:type flag: int
"""
run_in_thread(self.librados.rados_read_op_operate,
- (c_void_p(read_op), self.io, c_char_p(oid), c_int(flag),))
+ (c_void_p(read_op), self.io, cstr(oid), c_int(flag),))
@requires(('read_op', int), ('start_after', str), ('filter_prefix', str), ('max_return', int))
def get_omap_vals(self, read_op, start_after, filter_prefix, max_return):
@@ -2008,8 +2039,8 @@ returned %d, but should return zero on success." % (self.name, ret))
prval = c_int()
iter_addr = c_void_p()
run_in_thread(self.librados.rados_read_op_omap_get_vals,
- (c_void_p(read_op), c_char_p(start_after),
- c_char_p(filter_prefix), c_int(max_return),
+ (c_void_p(read_op), cstr(start_after),
+ cstr(filter_prefix), c_int(max_return),
byref(iter_addr), pointer(prval)))
return OmapIterator(self, iter_addr), prval.value
@@ -2028,7 +2059,7 @@ returned %d, but should return zero on success." % (self.name, ret))
prval = c_int()
iter_addr = c_void_p()
run_in_thread(self.librados.rados_read_op_omap_get_keys,
- (c_void_p(read_op), c_char_p(start_after),
+ (c_void_p(read_op), cstr(start_after),
c_int(max_return), byref(iter_addr), pointer(prval)))
return OmapIterator(self, iter_addr), prval.value
@@ -2047,7 +2078,7 @@ returned %d, but should return zero on success." % (self.name, ret))
key_num = len(keys)
key_array_type = c_char_p*key_num
key_array = key_array_type()
- key_array[:] = keys
+ key_array[:] = [cstr(key) for key in keys]
run_in_thread(self.librados.rados_read_op_omap_get_vals_by_keys,
(c_void_p(read_op), byref(key_array), c_int(key_num),
byref(iter_addr), pointer(prval)))
@@ -2065,7 +2096,7 @@ returned %d, but should return zero on success." % (self.name, ret))
key_num = len(keys)
key_array_type = c_char_p*key_num
key_array = key_array_type()
- key_array[:] = keys
+ key_array[:] = [cstr(key) for key in keys]
run_in_thread(self.librados.rados_write_op_omap_rm_keys,
(c_void_p(write_op), byref(key_array), c_int(key_num)))
@@ -2105,8 +2136,8 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_lock_exclusive,
- (self.io, c_char_p(key), c_char_p(name), c_char_p(cookie),
- c_char_p(desc),
+ (self.io, cstr(key), cstr(name), cstr(cookie),
+ cstr(desc),
timeval(duration, None) if duration is None else None,
c_uint8(flags)))
if ret < 0:
@@ -2140,8 +2171,8 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_lock_shared,
- (self.io, c_char_p(key), c_char_p(name), c_char_p(cookie),
- c_char_p(tag), c_char_p(desc),
+ (self.io, cstr(key), cstr(name), cstr(cookie),
+ cstr(tag), cstr(desc),
timeval(duration, None) if duration is None else None,
c_uint8(flags)))
if ret < 0:
@@ -2166,7 +2197,7 @@ returned %d, but should return zero on success." % (self.name, ret))
self.require_ioctx_open()
ret = run_in_thread(self.librados.rados_unlock,
- (self.io, c_char_p(key), c_char_p(name), c_char_p(cookie)))
+ (self.io, cstr(key), cstr(name), cstr(cookie)))
if ret < 0:
raise make_ex(ret, "Ioctx.rados_lock_exclusive(%s): failed to set lock %s on %s" % (self.name, name, key))
diff --git a/src/pybind/rbd.py b/src/pybind/rbd.py
index b570a00ebd6..b04e8453f25 100644
--- a/src/pybind/rbd.py
+++ b/src/pybind/rbd.py
@@ -15,6 +15,7 @@ to interact correctly with librbd. If unicode is passed to these
methods, a :class:`TypeError` will be raised.
"""
# Copyright 2011 Josh Durgin
+from collections import Iterable
from ctypes import CDLL, c_char, c_char_p, c_size_t, c_void_p, c_int, \
create_string_buffer, byref, Structure, c_uint64, c_int64, c_uint8, \
CFUNCTYPE
@@ -194,6 +195,19 @@ def load_librbd():
raise EnvironmentError("Unable to load librbd: %s" % e)
+def cstr(val, encoding="utf-8"):
+ """
+ Create a C-style string from a Python string
+
+ :param str val: Python string
+ :rtype: c_char_p
+ """
+ if val is None:
+ return c_char_p(None)
+
+ return c_char_p(val.encode(encoding))
+
+
class RBD(object):
"""
This class wraps librbd CRUD functions.
@@ -250,7 +264,7 @@ class RBD(object):
if features != 0 or stripe_unit != 0 or stripe_count != 0:
raise InvalidArgument('format 1 images do not support feature'
' masks or non-default striping')
- ret = self.librbd.rbd_create(ioctx.io, c_char_p(name),
+ ret = self.librbd.rbd_create(ioctx.io, cstr(name),
c_uint64(size),
byref(c_int(order)))
else:
@@ -262,14 +276,14 @@ class RBD(object):
raise FunctionNotSupported('installed version of librbd does'
' not support stripe unit or count')
if has_create3:
- ret = self.librbd.rbd_create3(ioctx.io, c_char_p(name),
+ ret = self.librbd.rbd_create3(ioctx.io, cstr(name),
c_uint64(size),
c_uint64(features),
byref(c_int(order)),
c_uint64(stripe_unit),
c_uint64(stripe_count))
else:
- ret = self.librbd.rbd_create2(ioctx.io, c_char_p(name),
+ ret = self.librbd.rbd_create2(ioctx.io, cstr(name),
c_uint64(size),
c_uint64(features),
byref(c_int(order)))
@@ -308,9 +322,9 @@ class RBD(object):
if not isinstance(c_name, str):
raise TypeError('child name must be a string')
- ret = self.librbd.rbd_clone(p_ioctx.io, c_char_p(p_name),
- c_char_p(p_snapname),
- c_ioctx.io, c_char_p(c_name),
+ ret = self.librbd.rbd_clone(p_ioctx.io, cstr(p_name),
+ cstr(p_snapname),
+ c_ioctx.io, cstr(c_name),
c_uint64(features),
byref(c_int(order)))
if ret < 0:
@@ -332,7 +346,8 @@ class RBD(object):
break
elif ret != -errno.ERANGE:
raise make_ex(ret, 'error listing images')
- return filter(lambda name: name != '', c_names.raw.split('\0'))
+
+ return [name for name in c_names.raw.decode("utf-8").split('\0') if len(name) > 0]
def remove(self, ioctx, name):
"""
@@ -353,7 +368,7 @@ class RBD(object):
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_remove(ioctx.io, c_char_p(name))
+ ret = self.librbd.rbd_remove(ioctx.io, cstr(name))
if ret != 0:
raise make_ex(ret, 'error removing image')
@@ -371,7 +386,7 @@ class RBD(object):
"""
if not isinstance(src, str) or not isinstance(dest, str):
raise TypeError('src and dest must be strings')
- ret = self.librbd.rbd_rename(ioctx.io, c_char_p(src), c_char_p(dest))
+ ret = self.librbd.rbd_rename(ioctx.io, cstr(src), cstr(dest))
if ret != 0:
raise make_ex(ret, 'error renaming image')
@@ -420,12 +435,12 @@ class Image(object):
if not hasattr(self.librbd, 'rbd_open_read_only'):
raise FunctionNotSupported('installed version of librbd does '
'not support open in read-only mode')
- ret = self.librbd.rbd_open_read_only(ioctx.io, c_char_p(name),
+ ret = self.librbd.rbd_open_read_only(ioctx.io, cstr(name),
byref(self.image),
- c_char_p(snapshot))
+ cstr(snapshot))
else:
- ret = self.librbd.rbd_open(ioctx.io, c_char_p(name),
- byref(self.image), c_char_p(snapshot))
+ ret = self.librbd.rbd_open(ioctx.io, cstr(name),
+ byref(self.image), cstr(snapshot))
if ret != 0:
raise make_ex(ret, 'error opening image %s at snapshot %s' % (name, snapshot))
self.closed = False
@@ -644,7 +659,7 @@ class Image(object):
"""
if not isinstance(dest_name, str):
raise TypeError('dest_name must be a string')
- ret = self.librbd.rbd_copy(self.image, dest_ioctx.io, c_char_p(dest_name))
+ ret = self.librbd.rbd_copy(self.image, dest_ioctx.io, cstr(dest_name))
if ret < 0:
raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
@@ -666,7 +681,7 @@ class Image(object):
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_snap_create(self.image, c_char_p(name))
+ ret = self.librbd.rbd_snap_create(self.image, cstr(name))
if ret != 0:
raise make_ex(ret, 'error creating snapshot %s from %s' % (name, self.name))
@@ -680,7 +695,7 @@ class Image(object):
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_snap_remove(self.image, c_char_p(name))
+ ret = self.librbd.rbd_snap_remove(self.image, cstr(name))
if ret != 0:
raise make_ex(ret, 'error removing snapshot %s from %s' % (name, self.name))
@@ -696,7 +711,7 @@ class Image(object):
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_snap_rollback(self.image, c_char_p(name))
+ ret = self.librbd.rbd_snap_rollback(self.image, cstr(name))
if ret != 0:
raise make_ex(ret, 'error rolling back image %s to snapshot %s' % (self.name, name))
@@ -711,7 +726,7 @@ class Image(object):
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_snap_protect(self.image, c_char_p(name))
+ ret = self.librbd.rbd_snap_protect(self.image, cstr(name))
if ret != 0:
raise make_ex(ret, 'error protecting snapshot %s@%s' % (self.name, name))
@@ -726,7 +741,7 @@ class Image(object):
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_snap_unprotect(self.image, c_char_p(name))
+ ret = self.librbd.rbd_snap_unprotect(self.image, cstr(name))
if ret != 0:
raise make_ex(ret, 'error unprotecting snapshot %s@%s' % (self.name, name))
@@ -742,7 +757,7 @@ class Image(object):
if not isinstance(name, str):
raise TypeError('name must be a string')
is_protected = c_int()
- ret = self.librbd.rbd_snap_is_protected(self.image, c_char_p(name),
+ ret = self.librbd.rbd_snap_is_protected(self.image, cstr(name),
byref(is_protected))
if ret != 0:
raise make_ex(ret, 'error checking if snapshot %s@%s is protected' % (self.name, name))
@@ -759,7 +774,7 @@ class Image(object):
"""
if name is not None and not isinstance(name, str):
raise TypeError('name must be a string')
- ret = self.librbd.rbd_snap_set(self.image, c_char_p(name))
+ ret = self.librbd.rbd_snap_set(self.image, cstr(name))
if ret != 0:
raise make_ex(ret, 'error setting image %s to snapshot %s' % (self.name, name))
@@ -838,7 +853,7 @@ class Image(object):
cb_holder = DiffIterateCB(iterate_cb)
cb = RBD_DIFF_CB(cb_holder.callback)
ret = self.librbd.rbd_diff_iterate2(self.image,
- c_char_p(from_snapshot),
+ cstr(from_snapshot),
c_uint64(offset),
c_uint64(length),
c_uint8(include_parent),
@@ -855,7 +870,7 @@ class Image(object):
part of the write would fall outside the image.
:param data: the data to be written
- :type data: str
+ :type data: bytes
:param offset: where to start writing data
:type offset: int
:param fadvise_flags: fadvise flags for this write
@@ -864,8 +879,8 @@ class Image(object):
:raises: :class:`IncompleteWriteError`, :class:`LogicError`,
:class:`InvalidArgument`, :class:`IOError`
"""
- if not isinstance(data, str):
- raise TypeError('data must be a string')
+ if not isinstance(data, bytes):
+ raise TypeError('data must be a byte string')
length = len(data)
if fadvise_flags == 0:
@@ -967,7 +982,7 @@ written." % (self.name, ret, length))
return []
pools = c_pools.raw[:pools_size.value - 1].split('\0')
images = c_images.raw[:images_size.value - 1].split('\0')
- return zip(pools, images)
+ return list(zip(pools, images))
def list_lockers(self):
"""
@@ -1010,13 +1025,13 @@ written." % (self.name, ret, length))
raise make_ex(ret, 'error listing images')
if ret == 0:
return []
- clients = c_clients.raw[:clients_size.value - 1].split('\0')
- cookies = c_cookies.raw[:cookies_size.value - 1].split('\0')
- addrs = c_addrs.raw[:addrs_size.value - 1].split('\0')
+ clients = [client.decode("utf-8") for client in c_clients.raw[:clients_size.value - 1].split(b'\0')]
+ cookies = [cookie.decode("utf-8") for cookie in c_cookies.raw[:cookies_size.value - 1].split(b'\0')]
+ addrs = [addr.decode("utf-8") for addr in c_addrs.raw[:addrs_size.value - 1].split(b'\0')]
return {
- 'tag' : c_tag.value,
+ 'tag' : c_tag.value.decode("utf-8"),
'exclusive' : exclusive.value == 1,
- 'lockers' : zip(clients, cookies, addrs),
+ 'lockers' : list(zip(clients, cookies, addrs)),
}
def lock_exclusive(self, cookie):
@@ -1028,7 +1043,7 @@ written." % (self.name, ret, length))
"""
if not isinstance(cookie, str):
raise TypeError('cookie must be a string')
- ret = self.librbd.rbd_lock_exclusive(self.image, c_char_p(cookie))
+ ret = self.librbd.rbd_lock_exclusive(self.image, cstr(cookie))
if ret < 0:
raise make_ex(ret, 'error acquiring exclusive lock on image')
@@ -1044,8 +1059,8 @@ written." % (self.name, ret, length))
raise TypeError('cookie must be a string')
if not isinstance(tag, str):
raise TypeError('tag must be a string')
- ret = self.librbd.rbd_lock_shared(self.image, c_char_p(cookie),
- c_char_p(tag))
+ ret = self.librbd.rbd_lock_shared(self.image, cstr(cookie),
+ cstr(tag))
if ret < 0:
raise make_ex(ret, 'error acquiring shared lock on image')
@@ -1055,7 +1070,7 @@ written." % (self.name, ret, length))
"""
if not isinstance(cookie, str):
raise TypeError('cookie must be a string')
- ret = self.librbd.rbd_unlock(self.image, c_char_p(cookie))
+ ret = self.librbd.rbd_unlock(self.image, cstr(cookie))
if ret < 0:
raise make_ex(ret, 'error unlocking image')
@@ -1067,8 +1082,8 @@ written." % (self.name, ret, length))
raise TypeError('client must be a string')
if not isinstance(cookie, str):
raise TypeError('cookie must be a string')
- ret = self.librbd.rbd_break_lock(self.image, c_char_p(client),
- c_char_p(cookie))
+ ret = self.librbd.rbd_break_lock(self.image, cstr(client),
+ cstr(cookie))
if ret < 0:
raise make_ex(ret, 'error unlocking image')
@@ -1082,7 +1097,7 @@ class DiffIterateCB(object):
return 0
-class SnapIterator(object):
+class SnapIterator(Iterable):
"""
Iterator over snapshot info for an image.
@@ -1110,11 +1125,11 @@ class SnapIterator(object):
raise make_ex(ret, 'error listing snapshots for image %s' % (image.name,))
def __iter__(self):
- for i in xrange(self.num_snaps):
+ for i in range(self.num_snaps):
yield {
'id' : self.snaps[i].id,
'size' : self.snaps[i].size,
- 'name' : self.snaps[i].name,
+ 'name' : self.snaps[i].name.decode("utf-8"),
}
def __del__(self):
diff --git a/src/test/pybind/test_rados.py b/src/test/pybind/test_rados.py
index d05c25bd864..11457a7bc3b 100644
--- a/src/test/pybind/test_rados.py
+++ b/src/test/pybind/test_rados.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
from nose.tools import eq_ as eq, ok_ as ok, assert_raises
from rados import (Rados, Error, RadosStateError, Object, ObjectExists,
ObjectNotFound, ObjectBusy, requires, opt,
@@ -13,16 +14,6 @@ def test_rados_init_error():
assert_raises(Error, Rados, conffile='', name='invalid')
assert_raises(Error, Rados, conffile='', name='bad.invalid')
-def test_rados_init_type_error():
- assert_raises(TypeError, Rados, rados_id=u'admin')
- assert_raises(TypeError, Rados, rados_id=u'')
- assert_raises(TypeError, Rados, name=u'client.admin')
- assert_raises(TypeError, Rados, name=u'')
- assert_raises(TypeError, Rados, conffile=u'blah')
- assert_raises(TypeError, Rados, conffile=u'')
- assert_raises(TypeError, Rados, clusternaem=u'blah')
- assert_raises(TypeError, Rados, clustername=u'')
-
def test_rados_init():
with Rados(conffile='', rados_id='admin'):
pass
@@ -91,9 +82,9 @@ class TestRadosStateError(object):
assert_raises(RadosStateError, rados.list_pools)
assert_raises(RadosStateError, rados.get_fsid)
assert_raises(RadosStateError, rados.open_ioctx, 'foo')
- assert_raises(RadosStateError, rados.mon_command, '', '')
- assert_raises(RadosStateError, rados.osd_command, 0, '', '')
- assert_raises(RadosStateError, rados.pg_command, '', '', '')
+ assert_raises(RadosStateError, rados.mon_command, '', b'')
+ assert_raises(RadosStateError, rados.osd_command, 0, '', b'')
+ assert_raises(RadosStateError, rados.pg_command, '', '', b'')
assert_raises(RadosStateError, rados.wait_for_latest_osdmap)
assert_raises(RadosStateError, rados.blacklist_add, '127.0.0.1/123', 0)
@@ -179,12 +170,12 @@ class TestRados(object):
tier_pool_id = self.rados.pool_lookup('foo-cache')
cmd = {"prefix":"osd tier add", "pool":"foo", "tierpool":"foo-cache", "force_nonempty":""}
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30)
eq(ret, 0)
try:
cmd = {"prefix":"osd tier cache-mode", "pool":"foo-cache", "tierpool":"foo-cache", "mode":"readonly"}
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30)
eq(ret, 0)
eq(self.rados.wait_for_latest_osdmap(), 0)
@@ -193,7 +184,7 @@ class TestRados(object):
eq(pool_id, self.rados.get_pool_base_tier(tier_pool_id))
finally:
cmd = {"prefix":"osd tier remove", "pool":"foo", "tierpool":"foo-cache"}
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30)
eq(ret, 0)
finally:
self.rados.delete_pool('foo-cache')
@@ -218,7 +209,7 @@ class TestIoctx(object):
def tearDown(self):
cmd = {"prefix":"osd unset", "key":"noup"}
- self.rados.mon_command(json.dumps(cmd), '')
+ self.rados.mon_command(json.dumps(cmd), b'')
self.ioctx.close()
self.rados.delete_pool('test_pool')
self.rados.shutdown()
@@ -228,29 +219,29 @@ class TestIoctx(object):
self.ioctx.change_auid(ADMIN_AUID)
def test_write(self):
- self.ioctx.write('abc', 'abc')
- eq(self.ioctx.read('abc'), 'abc')
+ self.ioctx.write('abc', b'abc')
+ eq(self.ioctx.read('abc'), b'abc')
def test_write_full(self):
- self.ioctx.write('abc', 'abc')
- eq(self.ioctx.read('abc'), 'abc')
- self.ioctx.write_full('abc', 'd')
- eq(self.ioctx.read('abc'), 'd')
+ self.ioctx.write('abc', b'abc')
+ eq(self.ioctx.read('abc'), b'abc')
+ self.ioctx.write_full('abc', b'd')
+ eq(self.ioctx.read('abc'), b'd')
def test_append(self):
- self.ioctx.write('abc', 'a')
- self.ioctx.append('abc', 'b')
- self.ioctx.append('abc', 'c')
- eq(self.ioctx.read('abc'), 'abc')
+ self.ioctx.write('abc', b'a')
+ self.ioctx.append('abc', b'b')
+ self.ioctx.append('abc', b'c')
+ eq(self.ioctx.read('abc'), b'abc')
def test_write_zeros(self):
- self.ioctx.write('abc', 'a\0b\0c')
- eq(self.ioctx.read('abc'), 'a\0b\0c')
+ self.ioctx.write('abc', b'a\0b\0c')
+ eq(self.ioctx.read('abc'), b'a\0b\0c')
def test_trunc(self):
- self.ioctx.write('abc', 'abc')
+ self.ioctx.write('abc', b'abc')
self.ioctx.trunc('abc', 2)
- eq(self.ioctx.read('abc'), 'ab')
+ eq(self.ioctx.read('abc'), b'ab')
size = self.ioctx.stat('abc')[0]
eq(size, 2)
@@ -258,24 +249,24 @@ class TestIoctx(object):
eq(list(self.ioctx.list_objects()), [])
def test_list_objects(self):
- self.ioctx.write('a', '')
- self.ioctx.write('b', 'foo')
- self.ioctx.write_full('c', 'bar')
- self.ioctx.append('d', 'jazz')
+ self.ioctx.write('a', b'')
+ self.ioctx.write('b', b'foo')
+ self.ioctx.write_full('c', b'bar')
+ self.ioctx.append('d', b'jazz')
object_names = [obj.key for obj in self.ioctx.list_objects()]
eq(sorted(object_names), ['a', 'b', 'c', 'd'])
def test_list_ns_objects(self):
- self.ioctx.write('a', '')
- self.ioctx.write('b', 'foo')
- self.ioctx.write_full('c', 'bar')
- self.ioctx.append('d', 'jazz')
+ self.ioctx.write('a', b'')
+ self.ioctx.write('b', b'foo')
+ self.ioctx.write_full('c', b'bar')
+ self.ioctx.append('d', b'jazz')
self.ioctx.set_namespace("ns1")
- self.ioctx.write('ns1-a', '')
- self.ioctx.write('ns1-b', 'foo')
- self.ioctx.write_full('ns1-c', 'bar')
- self.ioctx.append('ns1-d', 'jazz')
- self.ioctx.append('d', 'jazz')
+ self.ioctx.write('ns1-a', b'')
+ self.ioctx.write('ns1-b', b'foo')
+ self.ioctx.write_full('ns1-c', b'bar')
+ self.ioctx.append('ns1-d', b'jazz')
+ self.ioctx.append('d', b'jazz')
self.ioctx.set_namespace(LIBRADOS_ALL_NSPACES)
object_names = [(obj.nspace, obj.key) for obj in self.ioctx.list_objects()]
eq(sorted(object_names), [('', 'a'), ('','b'), ('','c'), ('','d'),\
@@ -283,9 +274,9 @@ class TestIoctx(object):
('ns1', 'ns1-c'), ('ns1', 'ns1-d')])
def test_xattrs(self):
- xattrs = dict(a='1', b='2', c='3', d='a\0b', e='\0')
- self.ioctx.write('abc', '')
- for key, value in xattrs.iteritems():
+ xattrs = dict(a=b'1', b=b'2', c=b'3', d=b'a\0b', e=b'\0')
+ self.ioctx.write('abc', b'')
+ for key, value in xattrs.items():
self.ioctx.set_xattr('abc', key, value)
eq(self.ioctx.get_xattr('abc', key), value)
stored_xattrs = {}
@@ -294,10 +285,10 @@ class TestIoctx(object):
eq(stored_xattrs, xattrs)
def test_obj_xattrs(self):
- xattrs = dict(a='1', b='2', c='3', d='a\0b', e='\0')
- self.ioctx.write('abc', '')
+ xattrs = dict(a=b'1', b=b'2', c=b'3', d=b'a\0b', e=b'\0')
+ self.ioctx.write('abc', b'')
obj = list(self.ioctx.list_objects())[0]
- for key, value in xattrs.iteritems():
+ for key, value in xattrs.items():
obj.set_xattr(key, value)
eq(obj.get_xattr(key), value)
stored_xattrs = {}
@@ -339,7 +330,7 @@ class TestIoctx(object):
def test_set_omap(self):
keys = ("1", "2", "3", "4")
- values = ("aaa", "bbb", "ccc", "\x04\x04\x04\x04")
+ values = (b"aaa", b"bbb", b"ccc", b"\x04\x04\x04\x04")
with WriteOpCtx(self.ioctx) as write_op:
self.ioctx.set_omap(write_op, keys, values)
self.ioctx.operate_write_op(write_op, "hw")
@@ -347,22 +338,22 @@ class TestIoctx(object):
iter, ret = self.ioctx.get_omap_vals(read_op, "", "", 4)
self.ioctx.operate_read_op(read_op, "hw")
iter.next()
- eq(list(iter), [("2", "bbb"), ("3", "ccc"), ("4", "\x04\x04\x04\x04")])
+ eq(list(iter), [("2", b"bbb"), ("3", b"ccc"), ("4", b"\x04\x04\x04\x04")])
def test_get_omap_vals_by_keys(self):
keys = ("1", "2", "3", "4")
- values = ("aaa", "bbb", "ccc", "\x04\x04\x04\x04")
+ values = (b"aaa", b"bbb", b"ccc", b"\x04\x04\x04\x04")
with WriteOpCtx(self.ioctx) as write_op:
self.ioctx.set_omap(write_op, keys, values)
self.ioctx.operate_write_op(write_op, "hw")
with ReadOpCtx(self.ioctx) as read_op:
iter, ret = self.ioctx.get_omap_vals_by_keys(read_op,("3","4",))
self.ioctx.operate_read_op(read_op, "hw")
- eq(list(iter), [("3", "ccc"), ("4", "\x04\x04\x04\x04")])
+ eq(list(iter), [("3", b"ccc"), ("4", b"\x04\x04\x04\x04")])
def test_get_omap_keys(self):
keys = ("1", "2", "3")
- values = ("aaa", "bbb", "ccc")
+ values = (b"aaa", b"bbb", b"ccc")
with WriteOpCtx(self.ioctx) as write_op:
self.ioctx.set_omap(write_op, keys, values)
self.ioctx.operate_write_op(write_op, "hw")
@@ -373,7 +364,7 @@ class TestIoctx(object):
def test_clear_omap(self):
keys = ("1", "2", "3")
- values = ("aaa", "bbb", "ccc")
+ values = (b"aaa", b"bbb", b"ccc")
with WriteOpCtx(self.ioctx) as write_op:
self.ioctx.set_omap(write_op, keys, values)
self.ioctx.operate_write_op(write_op, "hw")
@@ -387,17 +378,17 @@ class TestIoctx(object):
def test_locator(self):
self.ioctx.set_locator_key("bar")
- self.ioctx.write('foo', 'contents1')
+ self.ioctx.write('foo', b'contents1')
objects = [i for i in self.ioctx.list_objects()]
eq(len(objects), 1)
eq(self.ioctx.get_locator_key(), "bar")
self.ioctx.set_locator_key("")
objects[0].seek(0)
- objects[0].write("contents2")
+ objects[0].write(b"contents2")
eq(self.ioctx.get_locator_key(), "")
self.ioctx.set_locator_key("bar")
contents = self.ioctx.read("foo")
- eq(contents, "contents2")
+ eq(contents, b"contents2")
eq(self.ioctx.get_locator_key(), "bar")
objects[0].remove()
objects = [i for i in self.ioctx.list_objects()]
@@ -412,7 +403,7 @@ class TestIoctx(object):
count[0] += 1
lock.notify()
return 0
- comp = self.ioctx.aio_write("foo", "bar", 0, cb, cb)
+ comp = self.ioctx.aio_write("foo", b"bar", 0, cb, cb)
comp.wait_for_complete()
comp.wait_for_safe()
with lock:
@@ -420,7 +411,7 @@ class TestIoctx(object):
lock.wait()
eq(comp.get_return_value(), 0)
contents = self.ioctx.read("foo")
- eq(contents, "bar")
+ eq(contents, b"bar")
[i.remove() for i in self.ioctx.list_objects()]
def test_aio_append(self):
@@ -431,11 +422,11 @@ class TestIoctx(object):
count[0] += 1
lock.notify()
return 0
- comp = self.ioctx.aio_write("foo", "bar", 0, cb, cb)
- comp2 = self.ioctx.aio_append("foo", "baz", cb, cb)
+ comp = self.ioctx.aio_write("foo", b"bar", 0, cb, cb)
+ comp2 = self.ioctx.aio_append("foo", b"baz", cb, cb)
comp.wait_for_complete()
contents = self.ioctx.read("foo")
- eq(contents, "barbaz")
+ eq(contents, b"barbaz")
with lock:
while count[0] < 4:
lock.wait()
@@ -451,8 +442,8 @@ class TestIoctx(object):
count[0] += 1
lock.notify()
return 0
- self.ioctx.aio_write("foo", "barbaz", 0, cb, cb)
- comp = self.ioctx.aio_write_full("foo", "bar", cb, cb)
+ self.ioctx.aio_write("foo", b"barbaz", 0, cb, cb)
+ comp = self.ioctx.aio_write_full("foo", b"bar", cb, cb)
comp.wait_for_complete()
comp.wait_for_safe()
with lock:
@@ -460,7 +451,7 @@ class TestIoctx(object):
lock.wait()
eq(comp.get_return_value(), 0)
contents = self.ioctx.read("foo")
- eq(contents, "bar")
+ eq(contents, b"bar")
[i.remove() for i in self.ioctx.list_objects()]
def _take_down_acting_set(self, pool, objectname):
@@ -472,14 +463,14 @@ class TestIoctx(object):
"object":objectname,
"format":"json",
}
- r, jsonout, _ = self.rados.mon_command(json.dumps(cmd), '')
- objmap = json.loads(jsonout)
+ r, jsonout, _ = self.rados.mon_command(json.dumps(cmd), b'')
+ objmap = json.loads(jsonout.decode("utf-8"))
acting_set = objmap['acting']
cmd = {"prefix":"osd set", "key":"noup"}
- r, _, _ = self.rados.mon_command(json.dumps(cmd), '')
+ r, _, _ = self.rados.mon_command(json.dumps(cmd), b'')
eq(r, 0)
cmd = {"prefix":"osd down", "ids":[str(i) for i in acting_set]}
- r, _, _ = self.rados.mon_command(json.dumps(cmd), '')
+ r, _, _ = self.rados.mon_command(json.dumps(cmd), b'')
eq(r, 0)
# wait for OSDs to acknowledge the down
@@ -487,7 +478,7 @@ class TestIoctx(object):
def _let_osds_back_up(self):
cmd = {"prefix":"osd unset", "key":"noup"}
- r, _, _ = self.rados.mon_command(json.dumps(cmd), '')
+ r, _, _ = self.rados.mon_command(json.dumps(cmd), b'')
eq(r, 0)
def test_aio_read(self):
@@ -498,7 +489,7 @@ class TestIoctx(object):
with lock:
retval[0] = buf
lock.notify()
- payload = "bar\000frob"
+ payload = b"bar\000frob"
self.ioctx.write("foo", payload)
# test1: use wait_for_complete() and wait for cb by
@@ -570,7 +561,7 @@ class TestObject(object):
self.rados.create_pool('test_pool')
assert self.rados.pool_exists('test_pool')
self.ioctx = self.rados.open_ioctx('test_pool')
- self.ioctx.write('foo', 'bar')
+ self.ioctx.write('foo', b'bar')
self.object = Object(self.ioctx, 'foo')
def tearDown(self):
@@ -579,21 +570,21 @@ class TestObject(object):
self.rados.shutdown()
def test_read(self):
- eq(self.object.read(3), 'bar')
- eq(self.object.read(100), '')
+ eq(self.object.read(3), b'bar')
+ eq(self.object.read(100), b'')
def test_seek(self):
- self.object.write('blah')
+ self.object.write(b'blah')
self.object.seek(0)
- eq(self.object.read(4), 'blah')
+ eq(self.object.read(4), b'blah')
self.object.seek(1)
- eq(self.object.read(3), 'lah')
+ eq(self.object.read(3), b'lah')
def test_write(self):
- self.object.write('barbaz')
+ self.object.write(b'barbaz')
self.object.seek(0)
- eq(self.object.read(3), 'bar')
- eq(self.object.read(3), 'baz')
+ eq(self.object.read(3), b'bar')
+ eq(self.object.read(3), b'baz')
class TestCommand(object):
@@ -608,53 +599,53 @@ class TestCommand(object):
# check for success and some plain output with epoch in it
cmd = {"prefix":"mon dump"}
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30)
eq(ret, 0)
assert len(buf) > 0
- assert('epoch' in buf)
+ assert(b'epoch' in buf)
# JSON, and grab current epoch
cmd['format'] = 'json'
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30)
eq(ret, 0)
assert len(buf) > 0
- d = json.loads(buf)
+ d = json.loads(buf.decode("utf-8"))
assert('epoch' in d)
epoch = d['epoch']
# assume epoch + 1000 does not exist; test for ENOENT
cmd['epoch'] = epoch + 1000
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30)
eq(ret, -errno.ENOENT)
eq(len(buf), 0)
del cmd['epoch']
# send to specific target by name
target = d['mons'][0]['name']
- print target
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30,
+ print(target)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30,
target=target)
eq(ret, 0)
assert len(buf) > 0
- d = json.loads(buf)
+ d = json.loads(buf.decode("utf-8"))
assert('epoch' in d)
# and by rank
target = d['mons'][0]['rank']
- print target
- ret, buf, errs = self.rados.mon_command(json.dumps(cmd), '', timeout=30,
+ print(target)
+ ret, buf, errs = self.rados.mon_command(json.dumps(cmd), b'', timeout=30,
target=target)
eq(ret, 0)
assert len(buf) > 0
- d = json.loads(buf)
+ d = json.loads(buf.decode("utf-8"))
assert('epoch' in d)
def test_osd_bench(self):
cmd = dict(prefix='bench', size=4096, count=8192)
- ret, buf, err = self.rados.osd_command(0, json.dumps(cmd), '',
+ ret, buf, err = self.rados.osd_command(0, json.dumps(cmd), b'',
timeout=30)
eq(ret, 0)
assert len(err) > 0
- out = json.loads(err)
+ out = json.loads(err.decode("utf-8"))
eq(out['blocksize'], cmd['size'])
eq(out['bytes_written'], cmd['count'])
diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py
index a98b5dcea9f..1498524ee9b 100644
--- a/src/test/pybind/test_rbd.py
+++ b/src/test/pybind/test_rbd.py
@@ -1,10 +1,9 @@
# vim: expandtab smarttab shiftwidth=4 softtabstop=4
import functools
import socket
-import struct
import os
+import time
-from contextlib import nested
from nose import with_setup, SkipTest
from nose.tools import eq_ as eq, assert_raises
from rados import (Rados,
@@ -17,7 +16,6 @@ from rbd import (RBD, Image, ImageNotFound, InvalidArgument, ImageExists,
RBD_FEATURE_LAYERING, RBD_FEATURE_STRIPINGV2,
RBD_FEATURE_EXCLUSIVE_LOCK)
-
rados = None
ioctx = None
features = None
@@ -166,7 +164,7 @@ def check_default_params(format, order=None, features=None, stripe_count=None,
else:
assert_raises(exception, RBD().create, ioctx, image_name, IMG_SIZE)
finally:
- for k, v in orig_vals.iteritems():
+ for k, v in orig_vals.items():
rados.conf_set(k, v)
def test_create_defaults():
@@ -240,13 +238,13 @@ def test_open_read_only():
eq(data, read)
def test_open_dne():
- for i in xrange(100):
+ for i in range(100):
image_name = get_temp_image_name()
assert_raises(ImageNotFound, Image, ioctx, image_name + 'dne')
assert_raises(ImageNotFound, Image, ioctx, image_name, 'snap')
def test_open_readonly_dne():
- for i in xrange(100):
+ for i in range(100):
image_name = get_temp_image_name()
assert_raises(ImageNotFound, Image, ioctx, image_name + 'dne',
read_only=True)
@@ -301,10 +299,10 @@ class TestImage(object):
eq(features | RBD_FEATURE_EXCLUSIVE_LOCK, self.image.features())
def test_invalidate_cache(self):
- self.image.write('abc', 0)
- eq('abc', self.image.read(0, 3))
+ self.image.write(b'abc', 0)
+ eq(b'abc', self.image.read(0, 3))
self.image.invalidate_cache()
- eq('abc', self.image.read(0, 3))
+ eq(b'abc', self.image.read(0, 3))
def test_stat(self):
info = self.image.stat()
@@ -325,13 +323,13 @@ class TestImage(object):
def test_read(self):
data = self.image.read(0, 20)
- eq(data, '\0' * 20)
+ eq(data, b'\0' * 20)
def test_read_with_fadvise_flags(self):
data = self.image.read(0, 20, LIBRADOS_OP_FLAG_FADVISE_DONTNEED)
- eq(data, '\0' * 20)
+ eq(data, b'\0' * 20)
data = self.image.read(0, 20, LIBRADOS_OP_FLAG_FADVISE_RANDOM)
- eq(data, '\0' * 20)
+ eq(data, b'\0' * 20)
def test_large_write(self):
data = rand_data(IMG_SIZE)
@@ -339,7 +337,7 @@ class TestImage(object):
def test_large_read(self):
data = self.image.read(0, IMG_SIZE)
- eq(data, '\0' * IMG_SIZE)
+ eq(data, b'\0' * IMG_SIZE)
def test_write_read(self):
data = rand_data(256)
@@ -374,24 +372,24 @@ class TestImage(object):
self.image.remove_snap('snap2')
def test_resize_down(self):
- new_size = IMG_SIZE / 2
+ new_size = IMG_SIZE // 2
data = rand_data(256)
- self.image.write(data, IMG_SIZE / 2);
+ self.image.write(data, IMG_SIZE // 2);
self.image.resize(new_size)
self.image.resize(IMG_SIZE)
- read = self.image.read(IMG_SIZE / 2, 256)
- eq('\0' * 256, read)
+ read = self.image.read(IMG_SIZE // 2, 256)
+ eq(b'\0' * 256, read)
def test_resize_bytes(self):
- new_size = IMG_SIZE / 2 - 5
+ new_size = IMG_SIZE // 2 - 5
data = rand_data(256)
- self.image.write(data, IMG_SIZE / 2 - 10);
+ self.image.write(data, IMG_SIZE // 2 - 10);
self.image.resize(new_size)
self.image.resize(IMG_SIZE)
- read = self.image.read(IMG_SIZE / 2 - 10, 5)
+ read = self.image.read(IMG_SIZE // 2 - 10, 5)
eq(data[:5], read)
- read = self.image.read(IMG_SIZE / 2 - 5, 251)
- eq('\0' * 251, read)
+ read = self.image.read(IMG_SIZE // 2 - 5, 251)
+ eq(b'\0' * 251, read)
def test_copy(self):
global ioctx
@@ -410,7 +408,7 @@ class TestImage(object):
global ioctx
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
@@ -418,22 +416,22 @@ class TestImage(object):
at_snapshot = Image(ioctx, image_name, 'snap1')
snap_data = at_snapshot.read(0, 256)
at_snapshot.close()
- eq(snap_data, '\0' * 256)
+ eq(snap_data, b'\0' * 256)
self.image.remove_snap('snap1')
def test_list_snaps(self):
eq([], list(self.image.list_snaps()))
self.image.create_snap('snap1')
- eq(['snap1'], map(lambda snap: snap['name'], self.image.list_snaps()))
+ eq(['snap1'], [snap['name'] for snap in self.image.list_snaps()])
self.image.create_snap('snap2')
- eq(['snap1', 'snap2'], map(lambda snap: snap['name'], self.image.list_snaps()))
+ eq(['snap1', 'snap2'], [snap['name'] for snap in self.image.list_snaps()])
self.image.remove_snap('snap1')
self.image.remove_snap('snap2')
def test_remove_snap(self):
eq([], list(self.image.list_snaps()))
self.image.create_snap('snap1')
- eq(['snap1'], map(lambda snap: snap['name'], self.image.list_snaps()))
+ eq(['snap1'], [snap['name'] for snap in self.image.list_snaps()])
self.image.remove_snap('snap1')
eq([], list(self.image.list_snaps()))
@@ -469,35 +467,35 @@ class TestImage(object):
eq(read, data)
def test_rollback_to_snap(self):
- self.image.write('\0' * 256, 0)
+ self.image.write(b'\0' * 256, 0)
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
eq(read, data)
self.image.rollback_to_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
self.image.remove_snap('snap1')
def test_rollback_to_snap_sparse(self):
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
eq(read, data)
self.image.rollback_to_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
self.image.remove_snap('snap1')
def test_rollback_with_resize(self):
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
self.image.create_snap('snap1')
@@ -521,31 +519,31 @@ class TestImage(object):
self.image.remove_snap('snap2')
def test_set_snap(self):
- self.image.write('\0' * 256, 0)
+ self.image.write(b'\0' * 256, 0)
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
eq(read, data)
self.image.set_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
self.image.remove_snap('snap1')
def test_set_no_snap(self):
- self.image.write('\0' * 256, 0)
+ self.image.write(b'\0' * 256, 0)
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
eq(read, data)
self.image.set_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
self.image.set_snap(None)
read = self.image.read(0, 256)
eq(read, data)
@@ -554,19 +552,19 @@ class TestImage(object):
def test_set_snap_sparse(self):
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
eq(read, data)
self.image.set_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
self.image.remove_snap('snap1')
def test_many_snaps(self):
num_snaps = 200
- for i in xrange(num_snaps):
+ for i in range(num_snaps):
self.image.create_snap(str(i))
snaps = sorted(self.image.list_snaps(),
key=lambda snap: int(snap['name']))
@@ -574,14 +572,14 @@ class TestImage(object):
for i, snap in enumerate(snaps):
eq(snap['size'], IMG_SIZE)
eq(snap['name'], str(i))
- for i in xrange(num_snaps):
+ for i in range(num_snaps):
self.image.remove_snap(str(i))
def test_set_snap_deleted(self):
- self.image.write('\0' * 256, 0)
+ self.image.write(b'\0' * 256, 0)
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
@@ -594,10 +592,10 @@ class TestImage(object):
eq(read, data)
def test_set_snap_recreated(self):
- self.image.write('\0' * 256, 0)
+ self.image.write(b'\0' * 256, 0)
self.image.create_snap('snap1')
read = self.image.read(0, 256)
- eq(read, '\0' * 256)
+ eq(read, b'\0' * 256)
data = rand_data(256)
self.image.write(data, 0)
read = self.image.read(0, 256)
@@ -633,14 +631,14 @@ class TestImage(object):
eq([], self.image.list_lockers())
num_shared = 10
- for i in xrange(num_shared):
+ for i in range(num_shared):
self.image.lock_shared(str(i), 'tag')
lockers = self.image.list_lockers()
eq('tag', lockers['tag'])
assert not lockers['exclusive']
eq(num_shared, len(lockers['lockers']))
cookies = sorted(map(lambda x: x[1], lockers['lockers']))
- for i in xrange(num_shared):
+ for i in range(num_shared):
eq(str(i), cookies[i])
self.image.unlock(str(i))
eq([], self.image.list_lockers())
@@ -680,7 +678,7 @@ class TestClone(object):
create_image()
self.image = Image(ioctx, image_name)
data = rand_data(256)
- self.image.write(data, IMG_SIZE / 2)
+ self.image.write(data, IMG_SIZE // 2)
self.image.create_snap('snap1')
global features
self.image.protect_snap('snap1')
@@ -758,52 +756,52 @@ class TestClone(object):
eq(clone_info['size'], self.clone.overlap())
def test_resize_stat(self):
- self.clone.resize(IMG_SIZE / 2)
+ self.clone.resize(IMG_SIZE // 2)
image_info = self.image.stat()
clone_info = self.clone.stat()
- eq(clone_info['size'], IMG_SIZE / 2)
+ eq(clone_info['size'], IMG_SIZE // 2)
eq(image_info['size'], IMG_SIZE)
- eq(self.clone.overlap(), IMG_SIZE / 2)
+ eq(self.clone.overlap(), IMG_SIZE // 2)
self.clone.resize(IMG_SIZE * 2)
image_info = self.image.stat()
clone_info = self.clone.stat()
eq(clone_info['size'], IMG_SIZE * 2)
eq(image_info['size'], IMG_SIZE)
- eq(self.clone.overlap(), IMG_SIZE / 2)
+ eq(self.clone.overlap(), IMG_SIZE // 2)
def test_resize_io(self):
- parent_data = self.image.read(IMG_SIZE / 2, 256)
+ parent_data = self.image.read(IMG_SIZE // 2, 256)
self.image.resize(0)
- self.clone.resize(IMG_SIZE / 2 + 128)
- child_data = self.clone.read(IMG_SIZE / 2, 128)
+ self.clone.resize(IMG_SIZE // 2 + 128)
+ child_data = self.clone.read(IMG_SIZE // 2, 128)
eq(child_data, parent_data[:128])
self.clone.resize(IMG_SIZE)
- child_data = self.clone.read(IMG_SIZE / 2, 256)
- eq(child_data, parent_data[:128] + ('\0' * 128))
- self.clone.resize(IMG_SIZE / 2 + 1)
- child_data = self.clone.read(IMG_SIZE / 2, 1)
+ child_data = self.clone.read(IMG_SIZE // 2, 256)
+ eq(child_data, parent_data[:128] + (b'\0' * 128))
+ self.clone.resize(IMG_SIZE // 2 + 1)
+ child_data = self.clone.read(IMG_SIZE // 2, 1)
eq(child_data, parent_data[0])
self.clone.resize(0)
self.clone.resize(IMG_SIZE)
- child_data = self.clone.read(IMG_SIZE / 2, 256)
- eq(child_data, '\0' * 256)
+ child_data = self.clone.read(IMG_SIZE // 2, 256)
+ eq(child_data, b'\0' * 256)
def test_read(self):
- parent_data = self.image.read(IMG_SIZE / 2, 256)
- child_data = self.clone.read(IMG_SIZE / 2, 256)
+ parent_data = self.image.read(IMG_SIZE // 2, 256)
+ child_data = self.clone.read(IMG_SIZE // 2, 256)
eq(child_data, parent_data)
def test_write(self):
- parent_data = self.image.read(IMG_SIZE / 2, 256)
+ parent_data = self.image.read(IMG_SIZE // 2, 256)
new_data = rand_data(256)
- self.clone.write(new_data, IMG_SIZE / 2 + 256)
- child_data = self.clone.read(IMG_SIZE / 2 + 256, 256)
+ self.clone.write(new_data, IMG_SIZE // 2 + 256)
+ child_data = self.clone.read(IMG_SIZE // 2 + 256, 256)
eq(child_data, new_data)
- child_data = self.clone.read(IMG_SIZE / 2, 256)
+ child_data = self.clone.read(IMG_SIZE // 2, 256)
eq(child_data, parent_data)
- parent_data = self.image.read(IMG_SIZE / 2 + 256, 256)
- eq(parent_data, '\0' * 256)
+ parent_data = self.image.read(IMG_SIZE // 2 + 256, 256)
+ eq(parent_data, b'\0' * 256)
def check_children(self, expected):
actual = self.image.list_children()
@@ -823,13 +821,13 @@ class TestClone(object):
clone_name = get_temp_image_name() + '_'
expected_children = []
- for i in xrange(10):
+ for i in range(10):
self.rbd.clone(ioctx, image_name, 'snap1', ioctx,
clone_name + str(i), features)
expected_children.append((pool_name, clone_name + str(i)))
self.check_children(expected_children)
- for i in xrange(10):
+ for i in range(10):
self.rbd.remove(ioctx, clone_name + str(i))
expected_children.pop(0)
self.check_children(expected_children)
@@ -899,15 +897,15 @@ class TestClone(object):
with Image(ioctx, clone_name2) as clone:
with Image(ioctx, clone_name2) as clone2:
# cache object non-existence
- data = clone.read(IMG_SIZE / 2, 256)
- clone2_data = clone2.read(IMG_SIZE / 2, 256)
+ data = clone.read(IMG_SIZE // 2, 256)
+ clone2_data = clone2.read(IMG_SIZE // 2, 256)
eq(data, clone2_data)
clone.flatten()
assert_raises(ImageNotFound, clone.parent_info)
assert_raises(ImageNotFound, clone2.parent_info)
- after_flatten = clone.read(IMG_SIZE / 2, 256)
+ after_flatten = clone.read(IMG_SIZE // 2, 256)
eq(data, after_flatten)
- after_flatten = clone2.read(IMG_SIZE / 2, 256)
+ after_flatten = clone2.read(IMG_SIZE // 2, 256)
eq(data, after_flatten)
self.rbd.remove(ioctx, clone_name2)
@@ -962,8 +960,7 @@ class TestExclusiveLock(object):
rados2.shutdown()
def test_ownership(self):
- with nested(Image(ioctx, image_name), Image(ioctx2, image_name)) as (
- image1, image2):
+ with Image(ioctx, image_name) as image1, Image(ioctx2, image_name) as image2:
image1.write('0'*256, 0)
eq(image1.is_exclusive_lock_owner(), True)
eq(image2.is_exclusive_lock_owner(), False)
@@ -974,7 +971,7 @@ class TestExclusiveLock(object):
eq(image.is_exclusive_lock_owner(), True)
try:
with Image(ioctx, image_name) as image:
- image.write('0'*256, 0)
+ image.write(b'0'*256, 0)
eq(image.is_exclusive_lock_owner(), True)
image.set_snap('snap')
eq(image.is_exclusive_lock_owner(), False)
@@ -994,14 +991,13 @@ class TestExclusiveLock(object):
image.protect_snap('snap')
try:
RBD().clone(ioctx, image_name, 'snap', ioctx, 'clone', features)
- with nested(Image(ioctx, 'clone'), Image(ioctx2, 'clone')) as (
- image1, image2):
+ with Image(ioctx, 'clone') as image1, Image(ioctx2, 'clone') as image2:
data = rand_data(256)
image1.write(data, 0)
image2.flatten()
assert_raises(ImageNotFound, image1.parent_info)
parent = True
- for x in xrange(30):
+ for x in range(30):
try:
image2.parent_info()
except ImageNotFound:
@@ -1015,27 +1011,24 @@ class TestExclusiveLock(object):
image.remove_snap('snap')
def test_follower_resize(self):
- with nested(Image(ioctx, image_name), Image(ioctx2, image_name)) as (
- image1, image2):
- image1.write('0'*256, 0)
+ with Image(ioctx, image_name) as image1, Image(ioctx2, image_name) as image2:
+ image1.write(b'0'*256, 0)
for new_size in [IMG_SIZE * 2, IMG_SIZE / 2]:
image2.resize(new_size);
eq(new_size, image1.size())
- for x in xrange(30):
+ for x in range(30):
if new_size == image2.size():
break
time.sleep(1)
eq(new_size, image2.size())
def test_follower_snap_create(self):
- with nested(Image(ioctx, image_name), Image(ioctx2, image_name)) as (
- image1, image2):
+ with Image(ioctx, image_name) as image1, Image(ioctx2, image_name) as image2:
image2.create_snap('snap1')
image1.remove_snap('snap1')
def test_follower_snap_rollback(self):
- with nested(Image(ioctx, image_name), Image(ioctx2, image_name)) as (
- image1, image2):
+ with Image(ioctx, image_name) as image1, Image(ioctx2, image_name) as image2:
image1.create_snap('snap')
try:
assert_raises(ReadOnlyImage, image2.rollback_to_snap, 'snap')
@@ -1044,8 +1037,7 @@ class TestExclusiveLock(object):
image1.remove_snap('snap')
def test_follower_discard(self):
- with nested(Image(ioctx, image_name), Image(ioctx2, image_name)) as (
- image1, image2):
+ with Image(ioctx, image_name) as image1, Image(ioctx2, image_name) as image2:
data = rand_data(256)
image1.write(data, 0)
image2.discard(0, 256)
@@ -1055,8 +1047,7 @@ class TestExclusiveLock(object):
eq(256*'\0', read)
def test_follower_write(self):
- with nested(Image(ioctx, image_name), Image(ioctx2, image_name)) as (
- image1, image2):
+ with Image(ioctx, image_name) as image1, Image(ioctx2, image_name) as image2:
data = rand_data(256)
image1.write(data, 0)
image2.write(data, IMG_SIZE / 2)