int rados_pool_create_with_all(rados_t cluster, const char *pool_name, uint64_t auid,
uint8_t crush_rule_num);
+/**
+ * Returns the pool that is the base tier for this pool.
+ *
+ * The return value is the ID of the pool that should be used to read from/write to.
+ * If tiering is not set up for the pool, returns \c pool.
+ *
+ * @param cluster the cluster the pool is in
+ * @param pool ID of the pool to query
+ * @param[out] base_tier base tier, or \c pool if tiering is not configured
+ * @returns 0 on success, negative error code on failure
+ */
+int rados_pool_get_base_tier(rados_t cluster, int64_t pool, int64_t* base_tier);
+
/**
* Delete a pool and all data inside it
*
int pool_create_async(const char *name, PoolAsyncCompletion *c);
int pool_create_async(const char *name, uint64_t auid, PoolAsyncCompletion *c);
int pool_create_async(const char *name, uint64_t auid, uint8_t crush_rule, PoolAsyncCompletion *c);
+ int pool_get_base_tier(int64_t pool, int64_t* base_tier);
int pool_delete(const char *name);
int pool_delete_async(const char *name, PoolAsyncCompletion *c);
int64_t pool_lookup(const char *name);
return r;
}
+int librados::RadosClient::pool_get_base_tier(int64_t pool_id, int64_t* base_tier)
+{
+ int r = wait_for_osdmap();
+ if (r < 0) {
+ return r;
+ }
+
+ const OSDMap *osdmap = objecter->get_osdmap_read();
+
+ const pg_pool_t* pool = osdmap->get_pg_pool(pool_id);
+ if (pool) {
+ if (pool->tier_of < 0) {
+ *base_tier = pool_id;
+ } else {
+ *base_tier = pool->tier_of;
+ }
+ r = 0;
+ } else {
+ r = -ENOENT;
+ }
+
+ objecter->put_osdmap_read();
+ return r;
+}
+
int librados::RadosClient::pool_delete(const char *name)
{
int r = wait_for_osdmap();
int pool_create(string& name, unsigned long long auid=0, __u8 crush_rule=0);
int pool_create_async(string& name, PoolAsyncCompletionImpl *c, unsigned long long auid=0,
__u8 crush_rule=0);
+ int pool_get_base_tier(int64_t pool_id, int64_t* base_tier);
int pool_delete(const char *name);
int pool_delete_async(const char *name, PoolAsyncCompletionImpl *c);
return client->pool_create_async(str, c->pc, auid, crush_rule);
}
+int librados::Rados::pool_get_base_tier(int64_t pool_id, int64_t* base_tier)
+{
+ tracepoint(librados, rados_pool_get_base_tier_enter, (rados_t)client, pool_id);
+ int retval = client->pool_get_base_tier(pool_id, base_tier);
+ tracepoint(librados, rados_pool_get_base_tier_exit, retval, *base_tier);
+ return retval;
+}
+
int librados::Rados::pool_delete(const char *name)
{
return client->pool_delete(name);
return retval;
}
+extern "C" int rados_pool_get_base_tier(rados_t cluster, int64_t pool_id, int64_t* base_tier)
+{
+ tracepoint(librados, rados_pool_get_base_tier_enter, cluster, pool_id);
+ librados::RadosClient *client = (librados::RadosClient *)cluster;
+ int retval = client->pool_get_base_tier(pool_id, base_tier);
+ tracepoint(librados, rados_pool_get_base_tier_exit, retval, *base_tier);
+ return retval;
+}
+
extern "C" int rados_pool_delete(rados_t cluster, const char *pool_name)
{
tracepoint(librados, rados_pool_delete_enter, cluster, pool_name);
"""
from ctypes import CDLL, c_char_p, c_size_t, c_void_p, c_char, c_int, c_long, \
c_ulong, create_string_buffer, byref, Structure, c_uint64, c_ubyte, \
- pointer, CFUNCTYPE
+ pointer, CFUNCTYPE, c_int64
from ctypes.util import find_library
import ctypes
import errno
else:
raise make_ex(ret, "error looking up pool '%s'" % pool_name)
+ def pool_lookup(self, pool_name):
+ """
+ Returns a pool's ID based on its name.
+
+ :param pool_name: name of the pool to look up
+ :type pool_name: str
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: int - pool ID, or None if it doesn't exist
+ """
+ self.require_state("connected")
+ if not isinstance(pool_name, str):
+ raise TypeError('pool_name must be a string')
+ ret = run_in_thread(self.librados.rados_pool_lookup,
+ (self.cluster, c_char_p(pool_name)))
+ if (ret >= 0):
+ return int(ret)
+ elif (ret == -errno.ENOENT):
+ return None
+ else:
+ raise make_ex(ret, "error looking up pool '%s'" % pool_name)
+
+ def pool_reverse_lookup(self, pool_id):
+ """
+ Returns a pool's name based on its ID.
+
+ :param pool_id: ID of the pool to look up
+ :type pool_id: int
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: string - pool name, or None if it doesn't exist
+ """
+ self.require_state("connected")
+ if not isinstance(pool_id, int):
+ raise TypeError('pool_id must be an integer')
+ size = c_size_t(512)
+ while True:
+ c_name = create_string_buffer(size.value)
+ ret = run_in_thread(self.librados.rados_pool_reverse_lookup,
+ (self.cluster, c_int64(pool_id), byref(c_name), size))
+ if ret > size.value:
+ size = c_size_t(ret)
+ elif ret == -errno.ENOENT:
+ return None
+ elif ret < 0:
+ raise make_ex(ret, "error reverse looking up pool '%s'" % pool_id)
+ else:
+ return c_name.value
+ break
+
def create_pool(self, pool_name, auid=None, crush_rule=None):
"""
Create a pool:
if ret < 0:
raise make_ex(ret, "error creating pool '%s'" % pool_name)
+ def get_pool_base_tier(self, pool_id):
+ """
+ Get base pool
+
+ :returns: base pool, or pool_id if tiering is not configured for the pool
+ """
+ self.require_state("connected")
+ if not isinstance(pool_id, int):
+ raise TypeError('pool_id must be an int')
+ base_tier = c_int64(0)
+ ret = run_in_thread(self.librados.rados_pool_get_base_tier,
+ (self.cluster, c_int64(pool_id), byref(base_tier)))
+ if ret < 0:
+ raise make_ex(ret, "get_pool_base_tier(%d)" % pool_id)
+ return base_tier.value
+
def delete_pool(self, pool_name):
"""
Delete a pool and all data inside it.
return (ret, my_outbuf, my_outs)
+ def wait_for_latest_osdmap(self):
+ self.require_state("connected")
+ return run_in_thread(self.librados.rados_wait_for_latest_osdmap, (self.cluster,))
+
class ObjectIterator(object):
"""rados.Ioctx Object iterator"""
def __init__(self, ioctx):
rados_ioctx_destroy(ioctx);
ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
}
+
+TEST(LibRadosPools, PoolGetBaseTier) {
+ rados_t cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool(pool_name, &cluster));
+ std::string tier_pool_name = pool_name + "-cache";
+ ASSERT_EQ(0, rados_pool_create(cluster, tier_pool_name.c_str()));
+
+ int64_t pool_id = rados_pool_lookup(cluster, pool_name.c_str());
+ ASSERT_GE(pool_id, 0);
+
+ int64_t tier_pool_id = rados_pool_lookup(cluster, tier_pool_name.c_str());
+ ASSERT_GE(tier_pool_id, 0);
+
+
+ int64_t base_tier = 0;
+ EXPECT_EQ(0, rados_pool_get_base_tier(cluster, pool_id, &base_tier));
+ EXPECT_EQ(pool_id, base_tier);
+
+ std::string cmdstr = "{\"prefix\": \"osd tier add\", \"pool\": \"" +
+ pool_name + "\", \"tierpool\":\"" + tier_pool_name + "\", \"force_nonempty\":\"\"}";
+ char *cmd[1];
+ cmd[0] = (char *)cmdstr.c_str();
+ ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
+
+ cmdstr = "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" +
+ tier_pool_name + "\", \"mode\":\"readonly\"}";
+ cmd[0] = (char *)cmdstr.c_str();
+ ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
+
+ EXPECT_EQ(0, rados_wait_for_latest_osdmap(cluster));
+
+ EXPECT_EQ(0, rados_pool_get_base_tier(cluster, pool_id, &base_tier));
+ EXPECT_EQ(pool_id, base_tier);
+
+ EXPECT_EQ(0, rados_pool_get_base_tier(cluster, tier_pool_id, &base_tier));
+ EXPECT_EQ(pool_id, base_tier);
+
+ int64_t nonexistent_pool_id = (int64_t)((-1ULL) >> 1);
+ EXPECT_EQ(-ENOENT, rados_pool_get_base_tier(cluster, nonexistent_pool_id, &base_tier));
+
+ cmdstr = "{\"prefix\": \"osd tier remove\", \"pool\": \"" +
+ pool_name + "\", \"tierpool\":\"" + tier_pool_name + "\"}";
+ cmd[0] = (char *)cmdstr.c_str();
+ ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0));
+ ASSERT_EQ(0, rados_pool_delete(cluster, tier_pool_name.c_str()));
+ ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
+}
eq(set(['a' * 500]), self.list_non_default_pools())
self.rados.delete_pool('a' * 500)
+ def test_get_pool_base_tier(self):
+ self.rados.create_pool('foo')
+ try:
+ self.rados.create_pool('foo-cache')
+ try:
+ pool_id = self.rados.pool_lookup('foo')
+ 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)
+ 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)
+ eq(ret, 0)
+
+ eq(self.rados.wait_for_latest_osdmap(), 0)
+
+ eq(pool_id, self.rados.get_pool_base_tier(pool_id))
+ 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)
+ eq(ret, 0)
+ finally:
+ self.rados.delete_pool('foo-cache')
+ finally:
+ self.rados.delete_pool('foo')
+
def test_get_fsid(self):
fsid = self.rados.get_fsid()
eq(len(fsid), 36)
)
)
+TRACEPOINT_EVENT(librados, rados_pool_get_base_tier_enter,
+ TP_ARGS(
+ rados_t, cluster,
+ int64_t, pool_id),
+ TP_FIELDS(
+ ctf_integer_hex(rados_t, cluster, cluster)
+ ctf_integer(int64_t, pool_id, pool_id)
+ )
+)
+
+TRACEPOINT_EVENT(librados, rados_pool_get_base_tier_exit,
+ TP_ARGS(
+ int, retval,
+ int64_t, base_tier),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ ctf_integer(int64_t, base_tier, base_tier)
+ )
+)
+
TRACEPOINT_EVENT(librados, rados_pool_delete_enter,
TP_ARGS(
rados_t, cluster,