mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
Merge pull request #2552 from ceph/wip-8188
librados: Add rados_pool_get_tiers call Reviewed-by: Sage Weil <sage@redhat.com>
This commit is contained in:
commit
c79b53c238
@ -709,6 +709,19 @@ int rados_pool_create_with_crush_rule(rados_t cluster, const char *pool_name,
|
|||||||
int rados_pool_create_with_all(rados_t cluster, const char *pool_name, uint64_t auid,
|
int rados_pool_create_with_all(rados_t cluster, const char *pool_name, uint64_t auid,
|
||||||
uint8_t crush_rule_num);
|
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
|
* Delete a pool and all data inside it
|
||||||
*
|
*
|
||||||
|
@ -909,6 +909,7 @@ namespace librados
|
|||||||
int pool_create_async(const char *name, PoolAsyncCompletion *c);
|
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, PoolAsyncCompletion *c);
|
||||||
int pool_create_async(const char *name, uint64_t auid, uint8_t crush_rule, 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(const char *name);
|
||||||
int pool_delete_async(const char *name, PoolAsyncCompletion *c);
|
int pool_delete_async(const char *name, PoolAsyncCompletion *c);
|
||||||
int64_t pool_lookup(const char *name);
|
int64_t pool_lookup(const char *name);
|
||||||
|
@ -569,6 +569,31 @@ int librados::RadosClient::pool_create_async(string& name, PoolAsyncCompletionIm
|
|||||||
return r;
|
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 librados::RadosClient::pool_delete(const char *name)
|
||||||
{
|
{
|
||||||
int r = wait_for_osdmap();
|
int r = wait_for_osdmap();
|
||||||
|
@ -102,6 +102,7 @@ public:
|
|||||||
int pool_create(string& name, unsigned long long auid=0, __u8 crush_rule=0);
|
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,
|
int pool_create_async(string& name, PoolAsyncCompletionImpl *c, unsigned long long auid=0,
|
||||||
__u8 crush_rule=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(const char *name);
|
||||||
|
|
||||||
int pool_delete_async(const char *name, PoolAsyncCompletionImpl *c);
|
int pool_delete_async(const char *name, PoolAsyncCompletionImpl *c);
|
||||||
|
@ -1647,6 +1647,14 @@ int librados::Rados::pool_create_async(const char *name, uint64_t auid, __u8 cru
|
|||||||
return client->pool_create_async(str, c->pc, auid, crush_rule);
|
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)
|
int librados::Rados::pool_delete(const char *name)
|
||||||
{
|
{
|
||||||
return client->pool_delete(name);
|
return client->pool_delete(name);
|
||||||
@ -2611,6 +2619,15 @@ extern "C" int rados_pool_create_with_all(rados_t cluster, const char *name,
|
|||||||
return retval;
|
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)
|
extern "C" int rados_pool_delete(rados_t cluster, const char *pool_name)
|
||||||
{
|
{
|
||||||
tracepoint(librados, rados_pool_delete_enter, cluster, pool_name);
|
tracepoint(librados, rados_pool_delete_enter, cluster, pool_name);
|
||||||
|
@ -5,7 +5,7 @@ Copyright 2011, Hannu Valtonen <hannu.valtonen@ormod.com>
|
|||||||
"""
|
"""
|
||||||
from ctypes import CDLL, c_char_p, c_size_t, c_void_p, c_char, c_int, c_long, \
|
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, \
|
c_ulong, create_string_buffer, byref, Structure, c_uint64, c_ubyte, \
|
||||||
pointer, CFUNCTYPE
|
pointer, CFUNCTYPE, c_int64
|
||||||
from ctypes.util import find_library
|
from ctypes.util import find_library
|
||||||
import ctypes
|
import ctypes
|
||||||
import errno
|
import errno
|
||||||
@ -470,6 +470,56 @@ Rados object in state %s." % (self.state))
|
|||||||
else:
|
else:
|
||||||
raise make_ex(ret, "error looking up pool '%s'" % pool_name)
|
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):
|
def create_pool(self, pool_name, auid=None, crush_rule=None):
|
||||||
"""
|
"""
|
||||||
Create a pool:
|
Create a pool:
|
||||||
@ -513,6 +563,22 @@ Rados object in state %s." % (self.state))
|
|||||||
if ret < 0:
|
if ret < 0:
|
||||||
raise make_ex(ret, "error creating pool '%s'" % pool_name)
|
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):
|
def delete_pool(self, pool_name):
|
||||||
"""
|
"""
|
||||||
Delete a pool and all data inside it.
|
Delete a pool and all data inside it.
|
||||||
@ -685,6 +751,10 @@ Rados object in state %s." % (self.state))
|
|||||||
|
|
||||||
return (ret, my_outbuf, my_outs)
|
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):
|
class ObjectIterator(object):
|
||||||
"""rados.Ioctx Object iterator"""
|
"""rados.Ioctx Object iterator"""
|
||||||
def __init__(self, ioctx):
|
def __init__(self, ioctx):
|
||||||
|
@ -104,3 +104,51 @@ TEST(LibRadosPools, PoolCreateWithCrushRule) {
|
|||||||
rados_ioctx_destroy(ioctx);
|
rados_ioctx_destroy(ioctx);
|
||||||
ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
|
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));
|
||||||
|
}
|
||||||
|
@ -88,6 +88,36 @@ class TestRados(object):
|
|||||||
eq(set(['a' * 500]), self.list_non_default_pools())
|
eq(set(['a' * 500]), self.list_non_default_pools())
|
||||||
self.rados.delete_pool('a' * 500)
|
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):
|
def test_get_fsid(self):
|
||||||
fsid = self.rados.get_fsid()
|
fsid = self.rados.get_fsid()
|
||||||
eq(len(fsid), 36)
|
eq(len(fsid), 36)
|
||||||
|
@ -980,6 +980,26 @@ TRACEPOINT_EVENT(librados, rados_pool_create_with_all_exit,
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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,
|
TRACEPOINT_EVENT(librados, rados_pool_delete_enter,
|
||||||
TP_ARGS(
|
TP_ARGS(
|
||||||
rados_t, cluster,
|
rados_t, cluster,
|
||||||
|
Loading…
Reference in New Issue
Block a user