From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/test/rbd_mirror/test_PoolWatcher.cc | 254 ++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 src/test/rbd_mirror/test_PoolWatcher.cc (limited to 'src/test/rbd_mirror/test_PoolWatcher.cc') diff --git a/src/test/rbd_mirror/test_PoolWatcher.cc b/src/test/rbd_mirror/test_PoolWatcher.cc new file mode 100644 index 000000000..c29ed65af --- /dev/null +++ b/src/test/rbd_mirror/test_PoolWatcher.cc @@ -0,0 +1,254 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "include/rados/librados.hpp" +#include "include/rbd/librbd.hpp" +#include "include/stringify.h" +#include "test/rbd_mirror/test_fixture.h" +#include "cls/rbd/cls_rbd_types.h" +#include "cls/rbd/cls_rbd_client.h" +#include "include/rbd_types.h" +#include "librbd/internal.h" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Operations.h" +#include "librbd/Utils.h" +#include "librbd/api/Mirror.h" +#include "common/Cond.h" +#include "common/errno.h" +#include "common/ceph_mutex.h" +#include "tools/rbd_mirror/PoolWatcher.h" +#include "tools/rbd_mirror/Threads.h" +#include "tools/rbd_mirror/Types.h" +#include "tools/rbd_mirror/pool_watcher/Types.h" +#include "test/librados/test_cxx.h" +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include + +using rbd::mirror::ImageId; +using rbd::mirror::ImageIds; +using rbd::mirror::PoolWatcher; +using rbd::mirror::PeerSpec; +using rbd::mirror::RadosRef; +using std::map; +using std::set; +using std::string; + +void register_test_pool_watcher() { +} + +class TestPoolWatcher : public ::rbd::mirror::TestFixture { +public: + + TestPoolWatcher() + : m_pool_watcher_listener(this), + m_image_number(0), m_snap_number(0) + { + m_cluster = std::make_shared(); + EXPECT_EQ("", connect_cluster_pp(*m_cluster)); + } + + void TearDown() override { + if (m_pool_watcher) { + C_SaferCond ctx; + m_pool_watcher->shut_down(&ctx); + EXPECT_EQ(0, ctx.wait()); + } + + m_cluster->wait_for_latest_osdmap(); + for (auto& pool : m_pools) { + EXPECT_EQ(0, m_cluster->pool_delete(pool.c_str())); + } + + TestFixture::TearDown(); + } + + struct PoolWatcherListener : public rbd::mirror::pool_watcher::Listener { + TestPoolWatcher *test; + ceph::condition_variable cond; + ImageIds image_ids; + + explicit PoolWatcherListener(TestPoolWatcher *test) : test(test) { + } + + void handle_update(const std::string &mirror_uuid, + ImageIds &&added_image_ids, + ImageIds &&removed_image_ids) override { + std::lock_guard locker{test->m_lock}; + for (auto &image_id : removed_image_ids) { + image_ids.erase(image_id); + } + image_ids.insert(added_image_ids.begin(), added_image_ids.end()); + cond.notify_all(); + } + }; + + void create_pool(bool enable_mirroring, const PeerSpec &peer, string *name=nullptr) { + string pool_name = get_temp_pool_name("test-rbd-mirror-"); + ASSERT_EQ(0, m_cluster->pool_create(pool_name.c_str())); + + int64_t pool_id = m_cluster->pool_lookup(pool_name.c_str()); + ASSERT_GE(pool_id, 0); + m_pools.insert(pool_name); + + librados::IoCtx ioctx; + ASSERT_EQ(0, m_cluster->ioctx_create2(pool_id, ioctx)); + ioctx.application_enable("rbd", true); + + m_pool_watcher.reset(new PoolWatcher<>(m_threads, ioctx, "mirror uuid", + m_pool_watcher_listener)); + + if (enable_mirroring) { + ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(ioctx, + RBD_MIRROR_MODE_POOL)); + std::string uuid; + ASSERT_EQ(0, librbd::api::Mirror<>::peer_site_add( + ioctx, &uuid, RBD_MIRROR_PEER_DIRECTION_RX_TX, peer.cluster_name, + peer.client_name)); + } + if (name != nullptr) { + *name = pool_name; + } + + m_pool_watcher->init(); + } + + string get_image_id(librados::IoCtx *ioctx, const string &image_name) { + string obj = librbd::util::id_obj_name(image_name); + string id; + EXPECT_EQ(0, librbd::cls_client::get_id(ioctx, obj, &id)); + return id; + } + + void create_image(const string &pool_name, bool mirrored=true, + string *image_name=nullptr) { + uint64_t features = librbd::util::get_rbd_default_features(g_ceph_context); + string name = "image" + stringify(++m_image_number); + if (mirrored) { + features |= RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING; + } + + librados::IoCtx ioctx; + ASSERT_EQ(0, m_cluster->ioctx_create(pool_name.c_str(), ioctx)); + int order = 0; + ASSERT_EQ(0, librbd::create(ioctx, name.c_str(), 1 << 22, false, + features, &order, 0, 0)); + if (mirrored) { + librbd::Image image; + librbd::RBD rbd; + rbd.open(ioctx, image, name.c_str()); + image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL); + + librbd::mirror_image_info_t mirror_image_info; + ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info, + sizeof(mirror_image_info))); + image.close(); + + m_mirrored_images.insert(ImageId( + mirror_image_info.global_id, get_image_id(&ioctx, name))); + } + if (image_name != nullptr) + *image_name = name; + } + + void clone_image(const string &parent_pool_name, + const string &parent_image_name, + const string &clone_pool_name, + bool mirrored=true, + string *image_name=nullptr) { + librados::IoCtx pioctx, cioctx; + ASSERT_EQ(0, m_cluster->ioctx_create(parent_pool_name.c_str(), pioctx)); + ASSERT_EQ(0, m_cluster->ioctx_create(clone_pool_name.c_str(), cioctx)); + + string snap_name = "snap" + stringify(++m_snap_number); + { + librbd::ImageCtx *ictx = new librbd::ImageCtx(parent_image_name.c_str(), + "", "", pioctx, false); + ictx->state->open(0); + librbd::NoOpProgressContext prog_ctx; + EXPECT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(), + snap_name, 0, prog_ctx)); + EXPECT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), + snap_name)); + ictx->state->close(); + } + + uint64_t features = librbd::util::get_rbd_default_features(g_ceph_context); + string name = "clone" + stringify(++m_image_number); + if (mirrored) { + features |= RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING; + } + int order = 0; + librbd::clone(pioctx, parent_image_name.c_str(), snap_name.c_str(), + cioctx, name.c_str(), features, &order, 0, 0); + if (mirrored) { + librbd::Image image; + librbd::RBD rbd; + rbd.open(cioctx, image, name.c_str()); + image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL); + + librbd::mirror_image_info_t mirror_image_info; + ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info, + sizeof(mirror_image_info))); + image.close(); + + m_mirrored_images.insert(ImageId( + mirror_image_info.global_id, get_image_id(&cioctx, name))); + } + if (image_name != nullptr) + *image_name = name; + } + + void check_images() { + std::unique_lock l{m_lock}; + while (m_mirrored_images != m_pool_watcher_listener.image_ids) { + if (m_pool_watcher_listener.cond.wait_for(l, 10s) == std::cv_status::timeout) { + break; + } + } + + ASSERT_EQ(m_mirrored_images, m_pool_watcher_listener.image_ids); + } + + ceph::mutex m_lock = ceph::make_mutex("TestPoolWatcherLock"); + RadosRef m_cluster; + PoolWatcherListener m_pool_watcher_listener; + unique_ptr > m_pool_watcher; + + set m_pools; + ImageIds m_mirrored_images; + + uint64_t m_image_number; + uint64_t m_snap_number; +}; + +TEST_F(TestPoolWatcher, EmptyPool) { + string uuid1 = "00000000-0000-0000-0000-000000000001"; + PeerSpec site1(uuid1, "site1", "mirror1"); + create_pool(true, site1); + check_images(); +} + +TEST_F(TestPoolWatcher, ReplicatedPools) { + string uuid1 = "00000000-0000-0000-0000-000000000001"; + PeerSpec site1(uuid1, "site1", "mirror1"); + string first_pool, local_pool, last_pool; + create_pool(true, site1, &first_pool); + check_images(); + create_image(first_pool); + check_images(); + string parent_image, parent_image2; + create_image(first_pool, true, &parent_image); + check_images(); + clone_image(first_pool, parent_image, first_pool); + check_images(); + clone_image(first_pool, parent_image, first_pool, true, &parent_image2); + check_images(); + create_image(first_pool, false); + check_images(); +} -- cgit v1.2.3