From 68eea0eb814eb20f2889ba3446c9df1b855599ab Mon Sep 17 00:00:00 2001 From: junxiang Mu <1948535941@qq.com> Date: Wed, 29 May 2024 04:15:20 -0400 Subject: [PATCH] src/tools/rbd: add group info command to output group id Fixes: https://tracker.ceph.com/issues/66010 Signed-off-by: junxiang Mu <1948535941@qq.com> --- src/include/rbd/librbd.h | 2 ++ src/include/rbd/librbd.hpp | 2 ++ src/librbd/api/Group.cc | 18 ++++++++++ src/librbd/api/Group.h | 2 ++ src/librbd/librbd.cc | 30 ++++++++++++++++ src/pybind/rbd/c_rbd.pxd | 2 ++ src/pybind/rbd/mock_rbd.pxi | 3 ++ src/pybind/rbd/rbd.pyx | 23 +++++++++++++ src/test/cli/rbd/help.t | 19 +++++++++++ src/test/librbd/test_Groups.cc | 36 ++++++++++++++++++++ src/test/pybind/test_rbd.py | 5 +++ src/tools/rbd/action/Group.cc | 62 ++++++++++++++++++++++++++++++++++ 12 files changed, 204 insertions(+) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 4a7e108e73f..e94a72a719b 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -1377,6 +1377,8 @@ CEPH_RBD_API int rbd_aio_mirror_image_create_snapshot(rbd_image_t image, CEPH_RBD_API int rbd_group_create(rados_ioctx_t p, const char *name); CEPH_RBD_API int rbd_group_remove(rados_ioctx_t p, const char *name); CEPH_RBD_API int rbd_group_list(rados_ioctx_t p, char *names, size_t *size); +CEPH_RBD_API int rbd_group_get_id(rados_ioctx_t p, const char *group_name, + char *group_id, size_t *size); CEPH_RBD_API int rbd_group_rename(rados_ioctx_t p, const char *src_name, const char *dest_name); CEPH_RBD_API int rbd_group_info_cleanup(rbd_group_info_t *group_info, diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 6d97d1087ad..9224c850c55 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -410,6 +410,8 @@ public: int group_create(IoCtx& io_ctx, const char *group_name); int group_remove(IoCtx& io_ctx, const char *group_name); int group_list(IoCtx& io_ctx, std::vector *names); + int group_get_id(IoCtx& io_ctx, const char *group_name, + std::string *group_id); int group_rename(IoCtx& io_ctx, const char *src_group_name, const char *dest_group_name); diff --git a/src/librbd/api/Group.cc b/src/librbd/api/Group.cc index 06d38fe8500..afa5b0aff03 100644 --- a/src/librbd/api/Group.cc +++ b/src/librbd/api/Group.cc @@ -648,6 +648,24 @@ int Group::list(IoCtx& io_ctx, vector *names) return 0; } +template +int Group::get_id(IoCtx& io_ctx, const char *group_name, + std::string *group_id) +{ + CephContext *cct = (CephContext *)io_ctx.cct(); + ldout(cct, 20) << "io_ctx=" << &io_ctx << dendl; + + int r = cls_client::dir_get_id(&io_ctx, RBD_GROUP_DIRECTORY, group_name, + group_id); + if (r < 0) { + lderr(cct) << "error reading group id object: " + << cpp_strerror(r) << dendl; + return r; + } + + return 0; +} + template int Group::image_add(librados::IoCtx& group_ioctx, const char *group_name, librados::IoCtx& image_ioctx, const char *image_name) diff --git a/src/librbd/api/Group.h b/src/librbd/api/Group.h index 9d3abcc59e8..98833eb506f 100644 --- a/src/librbd/api/Group.h +++ b/src/librbd/api/Group.h @@ -21,6 +21,8 @@ struct Group { static int create(librados::IoCtx& io_ctx, const char *group_name); static int remove(librados::IoCtx& io_ctx, const char *group_name); static int list(librados::IoCtx& io_ctx, std::vector *names); + static int get_id(librados::IoCtx& io_ctx, const char *group_name, + std::string *group_id); static int rename(librados::IoCtx& io_ctx, const char *src_group_name, const char *dest_group_name); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 8749a04d2d5..2fccdf5abb4 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1292,6 +1292,11 @@ namespace librbd { return r; } + int RBD::group_get_id(IoCtx& io_ctx, const char *group_name, std::string *group_id) + { + return librbd::api::Group<>::get_id(io_ctx, group_name, group_id); + } + int RBD::group_rename(IoCtx& io_ctx, const char *src_name, const char *dest_name) { @@ -6923,6 +6928,31 @@ extern "C" int rbd_group_rename(rados_ioctx_t p, const char *src_name, return r; } +extern "C" int rbd_group_get_id(rados_ioctx_t p, + const char *group_name, + char *group_id, + size_t *size) +{ + librados::IoCtx io_ctx; + librados::IoCtx::from_rados_ioctx_t(p, io_ctx); + + std::string cpp_id; + int r = librbd::api::Group<>::get_id(io_ctx, group_name, &cpp_id); + if (r < 0) { + return r; + } + + auto total_len = cpp_id.size() + 1; + if (*size < total_len) { + *size = total_len; + return -ERANGE; + } + *size = total_len; + + strcpy(group_id, cpp_id.c_str()); + return 0; +} + extern "C" int rbd_group_image_add(rados_ioctx_t group_p, const char *group_name, rados_ioctx_t image_p, diff --git a/src/pybind/rbd/c_rbd.pxd b/src/pybind/rbd/c_rbd.pxd index c451baac58e..e7d1958bf31 100644 --- a/src/pybind/rbd/c_rbd.pxd +++ b/src/pybind/rbd/c_rbd.pxd @@ -662,6 +662,8 @@ cdef extern from "rbd/librbd.h" nogil: int rbd_group_create(rados_ioctx_t p, const char *name) int rbd_group_remove(rados_ioctx_t p, const char *name) int rbd_group_list(rados_ioctx_t p, char *names, size_t *size) + int rbd_group_get_id(rados_ioctx_t p, const char *group_name, + char *group_id, size_t *size) int rbd_group_rename(rados_ioctx_t p, const char *src, const char *dest) void rbd_group_info_cleanup(rbd_group_info_t *group_info, size_t group_info_size) diff --git a/src/pybind/rbd/mock_rbd.pxi b/src/pybind/rbd/mock_rbd.pxi index 15f2c78e3b1..dc0d499664e 100644 --- a/src/pybind/rbd/mock_rbd.pxi +++ b/src/pybind/rbd/mock_rbd.pxi @@ -841,6 +841,9 @@ cdef nogil: pass int rbd_group_list(rados_ioctx_t p, char *names, size_t *size): pass + int rbd_group_get_id(rados_ioctx_t p, const char *group_name, + char *group_id, size_t *size): + pass int rbd_group_rename(rados_ioctx_t p, const char *src, const char *dest): pass void rbd_group_info_cleanup(rbd_group_info_t *group_info, diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index df176a410a9..7d33e1ed62b 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -2642,6 +2642,29 @@ cdef class Group(object): def __exit__(self, type_, value, traceback): return False + + def id(self): + """ + Get group's id. + + :returns: str - group id + """ + cdef: + size_t size = 32 + char *id = NULL + try: + while True: + id = realloc_chk(id, size) + with nogil: + ret = rbd_group_get_id(self._ioctx, self._name, id, &size) + if ret >= 0: + break + elif ret != -errno.ERANGE: + raise make_ex(ret, 'error getting id for group %s' % self._name, + group_errno_to_exception) + return decode_cstr(id) + finally: + free(id) def add_image(self, image_ioctx, image_name): """ diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index 866bd8f11c8..69060b0af12 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -48,6 +48,7 @@ group image add Add an image to a group. group image list (... ls) List images in a group. group image remove (... rm) Remove an image from a group. + group info Show information about a group. group list (group ls) List rbd groups. group remove (group rm) Delete a group. group rename Rename a group within pool. @@ -972,6 +973,24 @@ -p [ --pool ] arg pool name unless overridden --image-id arg image id + rbd help group info + usage: rbd group info [--pool ] [--namespace ] + [--group ] [--format ] [--pretty-format] + + + Show information about a group. + + Positional arguments + group specification + (example: [/[/]]) + + Optional arguments + -p [ --pool ] arg pool name + --namespace arg namespace name + --group arg group name + --format arg output format (plain, json, or xml) [default: plain] + --pretty-format pretty formatting (json and xml) + rbd help group list usage: rbd group list [--pool ] [--namespace ] [--format ] [--pretty-format] diff --git a/src/test/librbd/test_Groups.cc b/src/test/librbd/test_Groups.cc index 88b19146f16..5172dac3167 100644 --- a/src/test/librbd/test_Groups.cc +++ b/src/test/librbd/test_Groups.cc @@ -70,6 +70,42 @@ TEST_F(TestGroup, group_createPP) ASSERT_EQ(0U, groups.size()); } +TEST_F(TestGroup, group_get_id) +{ + rados_ioctx_t ioctx; + rados_ioctx_create(_cluster, _pool_name.c_str(), &ioctx); + BOOST_SCOPE_EXIT(ioctx) { + rados_ioctx_destroy(ioctx); + } BOOST_SCOPE_EXIT_END; + + ASSERT_EQ(0, rbd_group_create(ioctx, "group_get_id")); + + size_t size = 0; + ASSERT_EQ(-ERANGE, rbd_group_get_id(ioctx, "group_get_id", NULL, &size)); + ASSERT_GT(size, 0); + + char group_id[32]; + ASSERT_EQ(0, rbd_group_get_id(ioctx, "group_get_id", group_id, &size)); + ASSERT_EQ(strlen(group_id) + 1, size); + + ASSERT_EQ(0, rbd_group_remove(ioctx, "group_get_id")); +} + +TEST_F(TestGroup, group_get_idPP) +{ + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx)); + + librbd::RBD rbd; + ASSERT_EQ(0, rbd.group_create(ioctx, "group_get_idPP")); + + std::string group_id; + ASSERT_EQ(0, rbd.group_get_id(ioctx, "group_get_idPP", &group_id)); + ASSERT_FALSE(group_id.empty()); + + ASSERT_EQ(0, rbd.group_remove(ioctx, "group_get_idPP")); +} + TEST_F(TestGroup, add_image) { REQUIRE_FORMAT_V2(); diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index 0040d1e67e5..94e2bc1c747 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -2769,6 +2769,11 @@ class TestGroups(object): eq([], list(self.group.list_images())) RBD().trash_restore(ioctx, image_id, image_name) + def test_group_get_id(self): + id = self.group.id() + assert isinstance(id, str) + assert len(id) > 0 + def test_group_image_many_images(self): eq([], list(self.group.list_images())) self.group.add_image(ioctx, image_name) diff --git a/src/tools/rbd/action/Group.cc b/src/tools/rbd/action/Group.cc index 5c2232a6fc6..e8cc66ca679 100644 --- a/src/tools/rbd/action/Group.cc +++ b/src/tools/rbd/action/Group.cc @@ -261,6 +261,58 @@ int execute_rename(const po::variables_map &vm, return 0; } +int execute_info(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + size_t arg_index = 0; + + std::string pool_name; + std::string namespace_name; + std::string group_name; + + int r = utils::get_pool_generic_snapshot_names( + vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, at::POOL_NAME, &pool_name, + &namespace_name, GROUP_NAME, "group", &group_name, nullptr, true, + utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL); + if (r < 0) { + return r; + } + + at::Format::Formatter formatter; + r = utils::get_formatter(vm, &formatter); + if (r < 0) { + return r; + } + Formatter *f = formatter.get(); + + librados::Rados rados; + librados::IoCtx io_ctx; + + r = utils::init(pool_name, namespace_name, &rados, &io_ctx); + if (r < 0) { + return r; + } + + librbd::RBD rbd; + std::string group_id; + r = rbd.group_get_id(io_ctx, group_name.c_str(), &group_id); + if (r < 0) { + return r; + } + + if (f) { + f->open_object_section("group"); + f->dump_string("group_name", group_name); + f->dump_string("group_id", group_id); + f->close_section(); + f->flush(std::cout); + } else { + std::cout << "rbd group '" << group_name << "':\n" + << "\t" << "id: " << group_id << std::endl; + } + + return 0; +} + int execute_add(const po::variables_map &vm, const std::vector &ceph_global_init_args) { size_t arg_index = 0; @@ -771,6 +823,13 @@ void get_rename_arguments(po::options_description *positional, false); } +void get_info_arguments(po::options_description *positional, + po::options_description *options) { + add_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE, + false); + at::add_format_options(options); +} + void get_add_arguments(po::options_description *positional, po::options_description *options) { positional->add_options() @@ -877,6 +936,9 @@ Shell::Action action_list( Shell::Action action_rename( {"group", "rename"}, {}, "Rename a group within pool.", "", &get_rename_arguments, &execute_rename); +Shell::Action action_info( + {"group", "info"}, {}, "Show information about a group.", + "", &get_info_arguments, &execute_info); Shell::Action action_add( {"group", "image", "add"}, {}, "Add an image to a group.", "", &get_add_arguments, &execute_add); -- 2.39.5