#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
#include "tools/rbd_mirror/image_replayer/OpenImageRequest.h"
#include "tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
#include "tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h"
#include "tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h"
#include "test/journal/mock/MockJournaler.h"
MOCK_METHOD0(send, void());
};
+template<>
+struct PrepareLocalImageRequest<librbd::MockTestImageCtx> {
+ static PrepareLocalImageRequest* s_instance;
+ std::string *local_image_id = nullptr;
+ std::string *local_image_name = nullptr;
+ std::string *tag_owner = nullptr;
+ Context *on_finish = nullptr;
+
+ static PrepareLocalImageRequest* create(librados::IoCtx &,
+ const std::string &global_image_id,
+ std::string *local_image_id,
+ std::string *local_image_name,
+ std::string *tag_owner,
+ ContextWQ *work_queue,
+ Context *on_finish) {
+ ceph_assert(s_instance != nullptr);
+ s_instance->local_image_id = local_image_id;
+ s_instance->local_image_name = local_image_name;
+ s_instance->tag_owner = tag_owner;
+ s_instance->on_finish = on_finish;
+ return s_instance;
+ }
+
+ PrepareLocalImageRequest() {
+ s_instance = this;
+ }
+
+ MOCK_METHOD0(send, void());
+};
+
+template<>
+struct PrepareRemoteImageRequest<librbd::MockTestImageCtx> {
+ static PrepareRemoteImageRequest* s_instance;
+ std::string *remote_mirror_uuid = nullptr;
+ std::string *remote_image_id = nullptr;
+ ::journal::MockJournaler **remote_journaler = nullptr;
+ cls::journal::ClientState *client_state;
+ librbd::journal::MirrorPeerClientMeta *client_meta = nullptr;
+ Context *on_finish = nullptr;
+
+ static PrepareRemoteImageRequest* create(Threads<librbd::MockTestImageCtx> *threads,
+ librados::IoCtx &,
+ const std::string &global_image_id,
+ const std::string &local_mirror_uuid,
+ const std::string &local_image_id,
+ const ::journal::Settings &settings,
+ ::journal::CacheManagerHandler *cache_manager_handler,
+ std::string *remote_mirror_uuid,
+ std::string *remote_image_id,
+ ::journal::MockJournaler **remote_journaler,
+ cls::journal::ClientState *client_state,
+ librbd::journal::MirrorPeerClientMeta *client_meta,
+ Context *on_finish) {
+ ceph_assert(s_instance != nullptr);
+ s_instance->remote_mirror_uuid = remote_mirror_uuid;
+ s_instance->remote_image_id = remote_image_id;
+ s_instance->remote_journaler = remote_journaler;
+ s_instance->client_state = client_state;
+ s_instance->client_meta = client_meta;
+ s_instance->on_finish = on_finish;
+ return s_instance;
+ }
+
+ PrepareRemoteImageRequest() {
+ s_instance = this;
+ }
+
+ MOCK_METHOD0(send, void());
+};
+
CloseImageRequest<librbd::MockTestImageCtx>*
CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
OpenImageRequest<librbd::MockTestImageCtx>*
OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
OpenLocalImageRequest<librbd::MockTestImageCtx>*
OpenLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+PrepareLocalImageRequest<librbd::MockTestImageCtx>*
+ PrepareLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+PrepareRemoteImageRequest<librbd::MockTestImageCtx>*
+ PrepareRemoteImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
namespace journal {
typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest;
typedef OpenLocalImageRequest<librbd::MockTestImageCtx> MockOpenLocalImageRequest;
+ typedef PrepareLocalImageRequest<librbd::MockTestImageCtx> MockPrepareLocalImageRequest;
+ typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
typedef journal::CreateLocalImageRequest<librbd::MockTestImageCtx> MockCreateLocalImageRequest;
typedef journal::PrepareReplayRequest<librbd::MockTestImageCtx> MockPrepareReplayRequest;
typedef librbd::mirror::GetInfoRequest<librbd::MockTestImageCtx> MockGetMirrorInfoRequest;
ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
}
+ void expect_send(MockPrepareLocalImageRequest &mock_request,
+ const std::string &local_image_id,
+ const std::string &local_image_name,
+ const std::string &tag_owner,
+ int r) {
+ EXPECT_CALL(mock_request, send())
+ .WillOnce(Invoke([&mock_request, local_image_id, local_image_name,
+ tag_owner, r]() {
+ if (r == 0) {
+ *mock_request.local_image_id = local_image_id;
+ *mock_request.local_image_name = local_image_name;
+ *mock_request.tag_owner = tag_owner;
+ }
+ mock_request.on_finish->complete(r);
+ }));
+ }
+
+ void expect_send(MockPrepareRemoteImageRequest& mock_request,
+ ::journal::MockJournaler& mock_remote_journaler,
+ const std::string& mirror_uuid, const std::string& image_id,
+ cls::journal::ClientState client_state,
+ const librbd::journal::MirrorPeerClientMeta& mirror_peer_client_meta,
+ int r) {
+ EXPECT_CALL(mock_request, send())
+ .WillOnce(Invoke([&mock_request, &mock_remote_journaler, image_id,
+ mirror_uuid, client_state, mirror_peer_client_meta,
+ r]() {
+ if (r >= 0) {
+ *mock_request.remote_journaler = &mock_remote_journaler;
+ *mock_request.client_state = client_state;
+ *mock_request.client_meta = mirror_peer_client_meta;
+ }
+
+ *mock_request.remote_mirror_uuid = mirror_uuid;
+ *mock_request.remote_image_id = image_id;
+ mock_request.on_finish->complete(r);
+ }));
+ }
+
void expect_open_image(MockOpenImageRequest &mock_open_image_request,
librados::IoCtx &io_ctx, const std::string &image_id,
librbd::MockTestImageCtx &mock_image_ctx, int r) {
- EXPECT_CALL(mock_open_image_request, construct(IsSameIoCtx(&io_ctx), image_id));
+ EXPECT_CALL(mock_open_image_request,
+ construct(IsSameIoCtx(&io_ctx), image_id));
EXPECT_CALL(mock_open_image_request, send())
.WillOnce(Invoke([this, &mock_open_image_request, &mock_image_ctx, r]() {
*mock_open_image_request.image_ctx = &mock_image_ctx;
MockBootstrapRequest *create_request(MockThreads* mock_threads,
MockInstanceWatcher *mock_instance_watcher,
- ::journal::MockJournaler &mock_journaler,
- const std::string &local_image_id,
const std::string &remote_image_id,
const std::string &global_image_id,
const std::string &local_mirror_uuid,
- const std::string &remote_mirror_uuid,
- cls::journal::ClientState *client_state,
- librbd::journal::MirrorPeerClientMeta *mirror_peer_client_meta,
Context *on_finish) {
- return new MockBootstrapRequest(mock_threads, m_local_io_ctx,
+ return new MockBootstrapRequest(mock_threads,
+ m_local_io_ctx,
m_remote_io_ctx,
mock_instance_watcher,
- &m_local_test_image_ctx,
- local_image_id,
remote_image_id,
global_image_id,
local_mirror_uuid,
- remote_mirror_uuid,
- &mock_journaler,
- client_state, mirror_peer_client_meta,
- on_finish, &m_do_resync);
+ nullptr, nullptr,
+ &m_local_test_image_ctx,
+ &m_local_image_id,
+ &m_remote_mirror_uuid,
+ &m_mock_remote_journaler,
+ &m_do_resync, on_finish);
}
librbd::ImageCtx *m_remote_image_ctx;
librbd::ImageCtx *m_local_image_ctx = nullptr;
+
librbd::MockTestImageCtx *m_local_test_image_ctx = nullptr;
+ std::string m_local_image_id;
+ std::string m_remote_mirror_uuid;
+ ::journal::MockJournaler *m_mock_remote_journaler = nullptr;
bool m_do_resync = false;
};
TEST_F(TestMockImageReplayerBootstrapRequest, Success) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageError) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageDNE) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImagePrimary) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, CreateLocalImageError) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, "", "", "", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler, "",
- mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayError) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayResyncRequested) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_TRUE(m_do_resync);
TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplaySyncing) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayDisconnected) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state =
- cls::journal::CLIENT_STATE_DISCONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncError) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncCanceled) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->cancel();
request->send();
ASSERT_EQ(-ECANCELED, ctx.wait());
TEST_F(TestMockImageReplayerBootstrapRequest, CloseLocalImageError) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, CloseRemoteImageError) {
InSequence seq;
+ // prepare local image
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
+ m_local_image_ctx->name, "remote mirror uuid", 0);
+
+ // prepare remote image
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ ::journal::MockJournaler mock_remote_journaler;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_ctx->id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
+ "remote mirror uuid", m_remote_image_ctx->id, client_state,
+ mirror_peer_client_meta, 0);
+
// open the remote image
librbd::MockJournal mock_journal;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
C_SaferCond ctx;
MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, mock_remote_journaler,
- mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
- "local mirror uuid", "remote mirror uuid", &client_state,
- &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_remote_image_ctx.id,
+ "global image id", "local mirror uuid", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
#include "tools/rbd_mirror/image_replayer/Replayer.h"
#include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
#include "tools/rbd_mirror/image_replayer/Utils.h"
typedef ::journal::MockJournalerProxy Journaler;
};
-struct MirrorPeerClientMeta;
-
} // namespace journal
} // namespace librbd
namespace image_replayer {
-template<>
-struct PrepareLocalImageRequest<librbd::MockTestImageCtx> {
- static PrepareLocalImageRequest* s_instance;
- std::string *local_image_id = nullptr;
- std::string *local_image_name = nullptr;
- std::string *tag_owner = nullptr;
- Context *on_finish = nullptr;
-
- static PrepareLocalImageRequest* create(librados::IoCtx &,
- const std::string &global_image_id,
- std::string *local_image_id,
- std::string *local_image_name,
- std::string *tag_owner,
- MockContextWQ *work_queue,
- Context *on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->local_image_id = local_image_id;
- s_instance->local_image_name = local_image_name;
- s_instance->tag_owner = tag_owner;
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- PrepareLocalImageRequest() {
- s_instance = this;
- }
-
- MOCK_METHOD0(send, void());
-};
-
-template<>
-struct PrepareRemoteImageRequest<librbd::MockTestImageCtx> {
- static PrepareRemoteImageRequest* s_instance;
- std::string *remote_mirror_uuid = nullptr;
- std::string *remote_image_id = nullptr;
- cls::journal::ClientState *client_state;
- ::journal::MockJournalerProxy **remote_journaler = nullptr;
- librbd::journal::MirrorPeerClientMeta *client_meta = nullptr;
- Context *on_finish = nullptr;
-
- static PrepareRemoteImageRequest* create(Threads<librbd::MockTestImageCtx> *threads,
- librados::IoCtx &,
- const std::string &global_image_id,
- const std::string &local_mirror_uuid,
- const std::string &local_image_id,
- const ::journal::Settings &settings,
- ::journal::CacheManagerHandler *cache_manager_handler,
- std::string *remote_mirror_uuid,
- std::string *remote_image_id,
- ::journal::MockJournalerProxy **remote_journaler,
- cls::journal::ClientState *client_state,
- librbd::journal::MirrorPeerClientMeta *client_meta,
- Context *on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->remote_mirror_uuid = remote_mirror_uuid;
- s_instance->remote_image_id = remote_image_id;
- s_instance->remote_journaler = remote_journaler;
- s_instance->client_state = client_state;
- s_instance->client_meta = client_meta;
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- PrepareRemoteImageRequest() {
- s_instance = this;
- }
-
- MOCK_METHOD0(send, void());
-};
-
template<>
struct BootstrapRequest<librbd::MockTestImageCtx> {
static BootstrapRequest* s_instance;
librbd::MockTestImageCtx **image_ctx = nullptr;
- Context *on_finish = nullptr;
+ std::string* local_image_id = nullptr;
bool *do_resync = nullptr;
+ Context *on_finish = nullptr;
static BootstrapRequest* create(
Threads<librbd::MockTestImageCtx>* threads,
- librados::IoCtx &local_io_ctx, librados::IoCtx &remote_io_ctx,
+ librados::IoCtx &local_io_ctx,
+ librados::IoCtx &remote_io_ctx,
rbd::mirror::InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
- librbd::MockTestImageCtx **local_image_ctx,
- const std::string &local_image_name, const std::string &remote_image_id,
+ const std::string &remote_image_id,
const std::string &global_image_id,
const std::string &local_mirror_uuid,
- const std::string &remote_mirror_uuid,
- ::journal::MockJournalerProxy *journaler,
- cls::journal::ClientState *client_state,
- librbd::journal::MirrorPeerClientMeta *client_meta,
- Context *on_finish, bool *do_resync,
- rbd::mirror::ProgressContext *progress_ctx = nullptr) {
+ ::journal::CacheManagerHandler *cache_manager_handler,
+ rbd::mirror::ProgressContext *progress_ctx,
+ librbd::MockTestImageCtx **local_image_ctx,
+ std::string* local_image_id,
+ std::string* remote_mirror_uuid,
+ ::journal::MockJournalerProxy** remote_journaler,
+ bool *do_resync, Context *on_finish) {
ceph_assert(s_instance != nullptr);
s_instance->image_ctx = local_image_ctx;
- s_instance->on_finish = on_finish;
+ s_instance->local_image_id = local_image_id;
s_instance->do_resync = do_resync;
+ s_instance->on_finish = on_finish;
return s_instance;
}
void get() {
}
+ std::string get_local_image_name() const {
+ return "local image name";
+ }
+
inline bool is_syncing() const {
return false;
}
BootstrapRequest<librbd::MockTestImageCtx>* BootstrapRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
CloseImageRequest<librbd::MockTestImageCtx>* CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-PrepareLocalImageRequest<librbd::MockTestImageCtx>* PrepareLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-PrepareRemoteImageRequest<librbd::MockTestImageCtx>* PrepareRemoteImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
namespace journal {
typedef MirrorStatusUpdater<librbd::MockTestImageCtx> MockMirrorStatusUpdater;
typedef image_replayer::BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
typedef image_replayer::CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
- typedef image_replayer::PrepareLocalImageRequest<librbd::MockTestImageCtx> MockPrepareLocalImageRequest;
- typedef image_replayer::PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
typedef image_replayer::journal::Replayer<librbd::MockTestImageCtx> MockJournalReplayer;
typedef ImageReplayer<librbd::MockTestImageCtx> MockImageReplayer;
typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
return bl;
}
- void expect_send(MockPrepareLocalImageRequest &mock_request,
- const std::string &local_image_id,
- const std::string &local_image_name,
- const std::string &tag_owner,
- int r) {
- EXPECT_CALL(mock_request, send())
- .WillOnce(Invoke([&mock_request, local_image_id, local_image_name, tag_owner, r]() {
- if (r == 0) {
- *mock_request.local_image_id = local_image_id;
- *mock_request.local_image_name = local_image_name;
- *mock_request.tag_owner = tag_owner;
- }
- mock_request.on_finish->complete(r);
- }));
- }
-
- void expect_send(MockPrepareRemoteImageRequest& mock_request,
- const std::string& mirror_uuid, const std::string& image_id,
- int r) {
- EXPECT_CALL(mock_request, send())
- .WillOnce(Invoke([&mock_request, image_id, mirror_uuid, r]() {
- if (r >= 0) {
- *mock_request.remote_journaler = new ::journal::MockJournalerProxy();
- }
-
- *mock_request.remote_mirror_uuid = mirror_uuid;
- *mock_request.remote_image_id = image_id;
- mock_request.on_finish->complete(r);
- }));
- }
-
void expect_send(MockBootstrapRequest &mock_bootstrap_request,
librbd::MockTestImageCtx &mock_local_image_ctx,
bool do_resync, int r) {
if (r == 0) {
*mock_bootstrap_request.image_ctx = &mock_local_image_ctx;
*mock_bootstrap_request.do_resync = do_resync;
+ } else if (r == -ENOLINK) {
+ *mock_bootstrap_request.local_image_id = mock_local_image_ctx.id;
}
mock_bootstrap_request.on_finish->complete(r);
}));
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
MockJournalReplayer mock_journal_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
expect_init(mock_journal_replayer, 0);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- "remote image id", 0);
- EXPECT_CALL(mock_remote_journaler, construct());
- expect_mirror_image_status_exists(false);
-
- create_image_replayer(mock_threads);
- C_SaferCond start_ctx;
- m_image_replayer->start(&start_ctx);
- ASSERT_EQ(0, start_ctx.wait());
-}
-
-TEST_F(TestMockImageReplayer, LocalImageDNE) {
- create_local_image();
- librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
- journal::MockJournaler mock_remote_journaler;
- MockThreads mock_threads(m_threads);
- expect_work_queue_repeatedly(mock_threads);
- expect_add_event_after_repeatedly(mock_threads);
-
- MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
-
- expect_set_mirror_image_status_repeatedly();
-
- InSequence seq;
- expect_send(mock_prepare_local_image_request, "", "", "", -ENOENT);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -EREMOTEIO);
+ expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -ENOMSG);
expect_mirror_image_status_exists(false);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
- ASSERT_EQ(-EREMOTEIO, start_ctx.wait());
+ ASSERT_EQ(0, start_ctx.wait());
}
-TEST_F(TestMockImageReplayer, PrepareLocalImageError) {
+TEST_F(TestMockImageReplayer, BootstrapRemoteDeleted) {
create_local_image();
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
expect_work_queue_repeatedly(mock_threads);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- EXPECT_CALL(m_local_status_updater, set_mirror_image_status(_, _, _))
- .WillRepeatedly(Invoke([](auto, auto, auto){}));
+ expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", -EINVAL);
- EXPECT_CALL(m_local_status_updater, exists(_))
- .WillOnce(Return(false));
-
- create_image_replayer(mock_threads);
-
- C_SaferCond start_ctx;
- m_image_replayer->start(&start_ctx);
- ASSERT_EQ(-EINVAL, start_ctx.wait());
-}
-TEST_F(TestMockImageReplayer, GetRemoteImageIdDNE) {
- create_local_image();
- librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
- MockThreads mock_threads(m_threads);
- expect_work_queue_repeatedly(mock_threads);
- expect_add_event_after_repeatedly(mock_threads);
-
- MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
-
- expect_set_mirror_image_status_repeatedly();
+ MockBootstrapRequest mock_bootstrap_request;
+ expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -ENOLINK);
- InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- "", -ENOENT);
expect_trash_move(mock_image_deleter, "global image id", false, 0);
expect_mirror_image_status_exists(false);
ASSERT_EQ(0, start_ctx.wait());
}
-TEST_F(TestMockImageReplayer, GetRemoteImageIdNonLinkedDNE) {
+TEST_F(TestMockImageReplayer, BootstrapResyncRequested) {
create_local_image();
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
expect_work_queue_repeatedly(mock_threads);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "some other mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- "", -ENOENT);
- expect_mirror_image_status_exists(false);
-
- create_image_replayer(mock_threads);
- C_SaferCond start_ctx;
- m_image_replayer->start(&start_ctx);
- ASSERT_EQ(-ENOENT, start_ctx.wait());
-}
-
-TEST_F(TestMockImageReplayer, GetRemoteImageIdError) {
- create_local_image();
- librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
- MockThreads mock_threads(m_threads);
- expect_work_queue_repeatedly(mock_threads);
- expect_add_event_after_repeatedly(mock_threads);
-
- MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ MockBootstrapRequest mock_bootstrap_request;
+ expect_send(mock_bootstrap_request, mock_local_image_ctx, true, 0);
- expect_set_mirror_image_status_repeatedly();
+ MockCloseImageRequest mock_close_image_request;
+ expect_send(mock_close_image_request, 0);
- InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, -EINVAL);
+ expect_trash_move(mock_image_deleter, "global image id", true, 0);
expect_mirror_image_status_exists(false);
create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
- ASSERT_EQ(-EINVAL, start_ctx.wait());
+ ASSERT_EQ(0, start_ctx.wait());
}
TEST_F(TestMockImageReplayer, BootstrapError) {
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -EINVAL);
expect_mirror_image_status_exists(false);
ASSERT_EQ(-EINVAL, start_ctx.wait());
}
-TEST_F(TestMockImageReplayer, StopBeforeBootstrap) {
+TEST_F(TestMockImageReplayer, BootstrapCancel) {
create_local_image();
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct())
- .WillOnce(Invoke([this]() {
- m_image_replayer->stop(nullptr, true);
- }));
-
- expect_mirror_image_status_exists(false);
create_image_replayer(mock_threads);
+ MockBootstrapRequest mock_bootstrap_request;
+ EXPECT_CALL(mock_bootstrap_request, send())
+ .WillOnce(Invoke([this, &mock_bootstrap_request]() {
+ m_image_replayer->stop();
+ mock_bootstrap_request.on_finish->complete(-ECANCELED);
+ }));
+ EXPECT_CALL(mock_bootstrap_request, cancel());
+
+ expect_mirror_image_status_exists(false);
+
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
ASSERT_EQ(-ECANCELED, start_ctx.wait());
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
MockJournalReplayer mock_journal_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
expect_init(mock_journal_replayer, 0);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
MockJournalReplayer mock_journal_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
expect_init(mock_journal_replayer, -EINVAL);
EXPECT_CALL(mock_journal_replayer, get_error_description())
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
MockJournalReplayer mock_journal_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
expect_init(mock_journal_replayer, 0);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
MockJournalReplayer mock_journal_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
expect_init(mock_journal_replayer, 0);
expect_add_event_after_repeatedly(mock_threads);
MockImageDeleter mock_image_deleter;
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
MockBootstrapRequest mock_bootstrap_request;
MockJournalReplayer mock_journal_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- mock_local_image_ctx.name, "remote mirror uuid", 0);
- expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
- m_remote_image_ctx->id, 0);
- EXPECT_CALL(mock_remote_journaler, construct());
expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
expect_init(mock_journal_replayer, 0);
#include "common/WorkQueue.h"
#include "global/global_context.h"
#include "journal/Journaler.h"
-#include "journal/Settings.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
#include "Threads.h"
#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
#include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
#include "tools/rbd_mirror/image_replayer/Utils.h"
#include "tools/rbd_mirror/image_replayer/journal/Replayer.h"
return;
}
- prepare_local_image();
+ bootstrap();
}
template <typename I>
-void ImageReplayer<I>::prepare_local_image() {
+void ImageReplayer<I>::bootstrap() {
dout(10) << dendl;
- m_local_image_id = "";
- Context *ctx = create_context_callback<
- ImageReplayer, &ImageReplayer<I>::handle_prepare_local_image>(this);
- auto req = image_replayer::PrepareLocalImageRequest<I>::create(
- m_local_io_ctx, m_global_image_id, &m_local_image_id, &m_local_image_name,
- &m_local_image_tag_owner, m_threads->work_queue, ctx);
- req->send();
-}
-
-template <typename I>
-void ImageReplayer<I>::handle_prepare_local_image(int r) {
- dout(10) << "r=" << r << dendl;
-
- if (r == -ENOENT) {
- dout(10) << "local image does not exist" << dendl;
- } else if (r < 0) {
- on_start_fail(r, "error preparing local image for replay");
- return;
- } else {
- // have the correct local image name now
- reregister_admin_socket_hook();
- }
-
- prepare_remote_image();
-}
-
-template <typename I>
-void ImageReplayer<I>::prepare_remote_image() {
- dout(10) << dendl;
+ std::unique_lock locker{m_lock};
if (m_peers.empty()) {
- // technically nothing to bootstrap, but it handles the status update
- bootstrap();
+ locker.unlock();
+
+ dout(5) << "no peer clusters" << dendl;
+ on_start_fail(-ENOENT, "no peer clusters");
return;
}
ceph_assert(!m_peers.empty());
m_remote_image = {*m_peers.begin()};
- auto cct = static_cast<CephContext *>(m_local_io_ctx.cct());
- journal::Settings journal_settings;
- journal_settings.commit_interval = cct->_conf.get_val<double>(
- "rbd_mirror_journal_commit_age");
-
- ceph_assert(m_remote_journaler == nullptr);
-
- Context *ctx = create_context_callback<
- ImageReplayer, &ImageReplayer<I>::handle_prepare_remote_image>(this);
- auto req = image_replayer::PrepareRemoteImageRequest<I>::create(
- m_threads, m_remote_image.io_ctx, m_global_image_id, m_local_mirror_uuid,
- m_local_image_id, journal_settings, m_cache_manager_handler,
- &m_remote_image.mirror_uuid, &m_remote_image.image_id, &m_remote_journaler,
- &m_client_state, &m_client_meta, ctx);
- req->send();
-}
-
-template <typename I>
-void ImageReplayer<I>::handle_prepare_remote_image(int r) {
- dout(10) << "r=" << r << dendl;
-
- ceph_assert(r < 0 ? m_remote_journaler == nullptr :
- m_remote_journaler != nullptr);
- if (r < 0 && !m_local_image_id.empty() &&
- m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
- // local image is primary -- fall-through
- } else if (r == -ENOENT) {
- dout(10) << "remote image does not exist" << dendl;
-
- // TODO need to support multiple remote images
- if (m_remote_image.image_id.empty() && !m_local_image_id.empty() &&
- m_local_image_tag_owner == m_remote_image.mirror_uuid) {
- // local image exists and is non-primary and linked to the missing
- // remote image
-
- m_delete_requested = true;
- on_start_fail(0, "remote image no longer exists");
- } else {
- on_start_fail(-ENOENT, "remote image does not exist");
- }
- return;
- } else if (r < 0) {
- on_start_fail(r, "error retrieving remote image id");
+ if (on_start_interrupted(m_lock)) {
return;
}
- bootstrap();
-}
-
-template <typename I>
-void ImageReplayer<I>::bootstrap() {
- dout(10) << dendl;
-
- if (!m_local_image_id.empty() &&
- m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
- dout(5) << "local image is primary" << dendl;
- on_start_fail(0, "local image is primary");
- return;
- } else if (m_peers.empty()) {
- dout(5) << "no peer clusters" << dendl;
- on_start_fail(-ENOENT, "no peer clusters");
- return;
- }
-
- image_replayer::BootstrapRequest<I> *request = nullptr;
- {
- std::lock_guard locker{m_lock};
- if (on_start_interrupted(m_lock)) {
- return;
- }
-
- auto ctx = create_context_callback<
+ m_local_image_id = "";
+ auto ctx = create_context_callback<
ImageReplayer, &ImageReplayer<I>::handle_bootstrap>(this);
- request = image_replayer::BootstrapRequest<I>::create(
+ auto request = image_replayer::BootstrapRequest<I>::create(
m_threads, m_local_io_ctx, m_remote_image.io_ctx, m_instance_watcher,
- &m_local_image_ctx, m_local_image_id, m_remote_image.image_id,
- m_global_image_id, m_local_mirror_uuid, m_remote_image.mirror_uuid,
- m_remote_journaler, &m_client_state, &m_client_meta, ctx,
- &m_resync_requested, &m_progress_cxt);
- request->get();
- m_bootstrap_request = request;
- }
+ m_remote_image.image_id, m_global_image_id, m_local_mirror_uuid,
+ m_cache_manager_handler, &m_progress_cxt, &m_local_image_ctx,
+ &m_local_image_id, &m_remote_image.mirror_uuid, &m_remote_journaler,
+ &m_resync_requested, ctx);
- update_mirror_image_status(false, boost::none);
+ request->get();
+ m_bootstrap_request = request;
+ locker.unlock();
+ update_mirror_image_status(false, boost::none);
request->send();
}
if (on_start_interrupted()) {
return;
+ } else if (r == -ENOMSG) {
+ dout(5) << "local image is primary" << dendl;
+ on_start_fail(0, "local image is primary");
+ return;
} else if (r == -EREMOTEIO) {
- m_local_image_tag_owner = "";
dout(5) << "remote image is non-primary" << dendl;
on_start_fail(-EREMOTEIO, "remote image is non-primary");
return;
} else if (r == -EEXIST) {
- m_local_image_tag_owner = "";
on_start_fail(r, "split-brain detected");
return;
+ } else if (r == -ENOLINK) {
+ m_delete_requested = true;
+ on_start_fail(0, "remote image no longer exists");
+ return;
} else if (r < 0) {
on_start_fail(r, "error bootstrapping replay");
return;
template <typename I>
void ImageReplayer<I>::reregister_admin_socket_hook() {
- {
- std::lock_guard locker{m_lock};
+ std::unique_lock locker{m_lock};
+ if (m_state == STATE_STARTING && m_bootstrap_request != nullptr) {
+ m_local_image_name = m_bootstrap_request->get_local_image_name();
+ }
- auto image_spec = image_replayer::util::compute_image_spec(
- m_local_io_ctx, m_local_image_name);
- if (m_asok_hook != nullptr && m_image_spec == image_spec) {
- return;
- }
- m_image_spec = image_spec;
+ auto image_spec = image_replayer::util::compute_image_spec(
+ m_local_io_ctx, m_local_image_name);
+ if (m_asok_hook != nullptr && m_image_spec == image_spec) {
+ return;
}
+
+ m_image_spec = image_spec;
+ locker.unlock();
+
unregister_admin_socket_hook();
register_admin_socket_hook();
}
* <starting> *
* | *
* v (error) *
- * PREPARE_LOCAL_IMAGE * * * * * * * * * * * * * * * * * *
- * | *
- * v (error) *
- * PREPARE_REMOTE_IMAGE * * * * * * * * * * * * * * * * * *
- * | *
- * v (error) *
* BOOTSTRAP_IMAGE * * * * * * * * * * * * * * * * * * * *
* | *
* v (error) *
}
void update_progress(const std::string &description,
- bool flush = true) override;
+ bool flush = true) override;
+
private:
ImageReplayer<ImageCtxT> *replayer;
};
bool m_resync_requested = false;
ImageCtxT *m_local_image_ctx = nullptr;
- std::string m_local_image_tag_owner;
decltype(ImageCtxT::journal) m_local_journal = nullptr;
Journaler* m_remote_journaler = nullptr;
image_replayer::BootstrapRequest<ImageCtxT> *m_bootstrap_request = nullptr;
- cls::journal::ClientState m_client_state =
- cls::journal::CLIENT_STATE_DISCONNECTED;
- librbd::journal::MirrorPeerClientMeta m_client_meta;
-
AsyncOpTracker m_in_flight_op_tracker;
static std::string to_string(const State state);
void shut_down(int r);
void handle_shut_down(int r);
- void prepare_local_image();
- void handle_prepare_local_image(int r);
-
- void prepare_remote_image();
- void handle_prepare_remote_image(int r);
-
void bootstrap();
void handle_bootstrap(int r);
#include "common/WorkQueue.h"
#include "cls/rbd/cls_rbd_client.h"
#include "journal/Journaler.h"
+#include "journal/Settings.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
#include "librbd/internal.h"
#include "tools/rbd_mirror/ProgressContext.h"
#include "tools/rbd_mirror/ImageSync.h"
#include "tools/rbd_mirror/Threads.h"
+#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
#include "tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h"
#include "tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h"
template <typename I>
BootstrapRequest<I>::BootstrapRequest(
- Threads<I>* threads,
- librados::IoCtx &local_io_ctx,
- librados::IoCtx &remote_io_ctx,
- InstanceWatcher<I> *instance_watcher,
- I **local_image_ctx,
- const std::string &local_image_id,
- const std::string &remote_image_id,
- const std::string &global_image_id,
- const std::string &local_mirror_uuid,
- const std::string &remote_mirror_uuid,
- Journaler *remote_journaler,
- cls::journal::ClientState *client_state,
- MirrorPeerClientMeta *client_meta,
- Context *on_finish,
- bool *do_resync,
- rbd::mirror::ProgressContext *progress_ctx)
+ Threads<I>* threads,
+ librados::IoCtx& local_io_ctx,
+ librados::IoCtx& remote_io_ctx,
+ InstanceWatcher<I>* instance_watcher,
+ const std::string& remote_image_id,
+ const std::string& global_image_id,
+ const std::string& local_mirror_uuid,
+ ::journal::CacheManagerHandler* cache_manager_handler,
+ ProgressContext* progress_ctx,
+ I** local_image_ctx,
+ std::string* local_image_id,
+ std::string* remote_mirror_uuid,
+ Journaler** remote_journaler,
+ bool* do_resync,
+ Context* on_finish)
: BaseRequest("rbd::mirror::image_replayer::BootstrapRequest",
reinterpret_cast<CephContext*>(local_io_ctx.cct()), on_finish),
- m_threads(threads), m_local_io_ctx(local_io_ctx),
- m_remote_io_ctx(remote_io_ctx), m_instance_watcher(instance_watcher),
- m_local_image_ctx(local_image_ctx), m_local_image_id(local_image_id),
- m_remote_image_id(remote_image_id), m_global_image_id(global_image_id),
+ m_threads(threads),
+ m_local_io_ctx(local_io_ctx),
+ m_remote_io_ctx(remote_io_ctx),
+ m_instance_watcher(instance_watcher),
+ m_remote_image_id(remote_image_id),
+ m_global_image_id(global_image_id),
m_local_mirror_uuid(local_mirror_uuid),
+ m_cache_manager_handler(cache_manager_handler),
+ m_progress_ctx(progress_ctx),
+ m_local_image_ctx(local_image_ctx),
+ m_local_image_id(local_image_id),
m_remote_mirror_uuid(remote_mirror_uuid),
m_remote_journaler(remote_journaler),
- m_client_state(client_state), m_client_meta(client_meta),
- m_progress_ctx(progress_ctx), m_do_resync(do_resync),
+ m_do_resync(do_resync),
m_lock(ceph::make_mutex(unique_lock_name("BootstrapRequest::m_lock",
this))) {
dout(10) << dendl;
void BootstrapRequest<I>::send() {
*m_do_resync = false;
- open_remote_image();
+ prepare_local_image();
}
template <typename I>
}
}
+template <typename I>
+std::string BootstrapRequest<I>::get_local_image_name() const {
+ std::unique_lock locker{m_lock};
+ return m_local_image_name;
+}
+
+template <typename I>
+void BootstrapRequest<I>::prepare_local_image() {
+ dout(10) << dendl;
+ update_progress("PREPARE_LOCAL_IMAGE");
+
+ *m_local_image_id = "";
+ m_local_image_name = m_global_image_id;
+ auto ctx = create_context_callback<
+ BootstrapRequest, &BootstrapRequest<I>::handle_prepare_local_image>(this);
+ auto req = image_replayer::PrepareLocalImageRequest<I>::create(
+ m_local_io_ctx, m_global_image_id, m_local_image_id,
+ &m_prepare_local_image_name, &m_local_image_tag_owner,
+ m_threads->work_queue, ctx);
+ req->send();
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_prepare_local_image(int r) {
+ dout(10) << "r=" << r << dendl;
+
+ if (r == -ENOENT) {
+ dout(10) << "local image does not exist" << dendl;
+ } else if (r < 0) {
+ derr << "error preparing local image for replay" << cpp_strerror(r)
+ << dendl;
+ finish(r);
+ return;
+ }
+
+ // image replayer will detect the name change (if any) at next
+ // status update
+ {
+ std::unique_lock locker{m_lock};
+ m_local_image_name = m_prepare_local_image_name;
+ }
+
+ prepare_remote_image();
+}
+
+template <typename I>
+void BootstrapRequest<I>::prepare_remote_image() {
+ dout(10) << dendl;
+ update_progress("PREPARE_REMOTE_IMAGE");
+
+ auto cct = static_cast<CephContext *>(m_local_io_ctx.cct());
+ ::journal::Settings journal_settings;
+ journal_settings.commit_interval = cct->_conf.get_val<double>(
+ "rbd_mirror_journal_commit_age");
+
+ ceph_assert(*m_remote_journaler == nullptr);
+
+ Context *ctx = create_context_callback<
+ BootstrapRequest, &BootstrapRequest<I>::handle_prepare_remote_image>(this);
+ auto req = image_replayer::PrepareRemoteImageRequest<I>::create(
+ m_threads, m_remote_io_ctx, m_global_image_id, m_local_mirror_uuid,
+ *m_local_image_id, journal_settings, m_cache_manager_handler,
+ m_remote_mirror_uuid, &m_remote_image_id, m_remote_journaler,
+ &m_client_state, &m_client_meta, ctx);
+ req->send();
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_prepare_remote_image(int r) {
+ dout(10) << "r=" << r << dendl;
+
+ ceph_assert(r < 0 ? *m_remote_journaler == nullptr :
+ *m_remote_journaler != nullptr);
+ if (r < 0 && !m_local_image_id->empty() &&
+ m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
+ // local image is primary -- fall-through
+ } else if (r == -ENOENT) {
+ dout(10) << "remote image does not exist" << dendl;
+
+ // TODO need to support multiple remote images
+ if (m_remote_image_id.empty() && !m_local_image_id->empty() &&
+ m_local_image_tag_owner == *m_remote_mirror_uuid) {
+ // local image exists and is non-primary and linked to the missing
+ // remote image
+ finish(-ENOLINK);
+ } else {
+ dout(10) << "remote image does not exist" << dendl;
+ finish(-ENOENT);
+ }
+ return;
+ } else if (r < 0) {
+ derr << "error retrieving remote image id" << cpp_strerror(r) << dendl;
+ finish(r);
+ return;
+ }
+
+ if (!m_local_image_id->empty() &&
+ m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
+ dout(5) << "local image is primary" << dendl;
+ finish(-ENOMSG);
+ return;
+ }
+
+ open_remote_image();
+}
+
template <typename I>
void BootstrapRequest<I>::open_remote_image() {
dout(15) << "remote_image_id=" << m_remote_image_id << dendl;
}
if (m_promotion_state != librbd::mirror::PROMOTION_STATE_PRIMARY &&
- m_local_image_id.empty()) {
+ m_local_image_id->empty()) {
// no local image and remote isn't primary -- don't sync it
dout(5) << "remote image is not primary -- not syncing"
<< dendl;
return;
}
- if (!m_client_meta->image_id.empty()) {
+ if (!m_client_meta.image_id.empty()) {
// have an image id -- use that to open the image since a deletion (resync)
// will leave the old image id registered in the peer
- m_local_image_id = m_client_meta->image_id;
+ *m_local_image_id = m_client_meta.image_id;
}
- if (m_local_image_id.empty()) {
+ if (m_local_image_id->empty()) {
create_local_image();
return;
}
template <typename I>
void BootstrapRequest<I>::open_local_image() {
- dout(15) << "local_image_id=" << m_local_image_id << dendl;
+ dout(15) << "local_image_id=" << *m_local_image_id << dendl;
update_progress("OPEN_LOCAL_IMAGE");
BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_local_image>(
this);
OpenLocalImageRequest<I> *request = OpenLocalImageRequest<I>::create(
- m_local_io_ctx, m_local_image_ctx, m_local_image_id, m_threads->work_queue,
+ m_local_io_ctx, m_local_image_ctx, *m_local_image_id, m_threads->work_queue,
ctx);
request->send();
}
BootstrapRequest<I>,
&BootstrapRequest<I>::handle_prepare_replay>(this);
auto request = journal::PrepareReplayRequest<I>::create(
- *m_local_image_ctx, m_remote_journaler, m_promotion_state,
- m_local_mirror_uuid, m_remote_mirror_uuid, m_client_meta,
+ *m_local_image_ctx, *m_remote_journaler, m_promotion_state,
+ m_local_mirror_uuid, *m_remote_mirror_uuid, &m_client_meta,
m_progress_ctx, m_do_resync, &m_syncing, ctx);
request->send();
}
dout(10) << "local image resync requested" << dendl;
close_remote_image();
return;
- } else if (*m_client_state == cls::journal::CLIENT_STATE_DISCONNECTED) {
+ } else if (m_client_state == cls::journal::CLIENT_STATE_DISCONNECTED) {
dout(10) << "client flagged disconnected -- skipping bootstrap" << dendl;
// The caller is expected to detect disconnect initializing remote journal.
m_ret_val = 0;
BootstrapRequest<I>,
&BootstrapRequest<I>::handle_create_local_image>(this);
auto request = journal::CreateLocalImageRequest<I>::create(
- m_threads, m_local_io_ctx, m_remote_image_ctx, m_remote_journaler,
- m_global_image_id, m_remote_mirror_uuid, m_client_meta, m_progress_ctx,
- &m_local_image_id, ctx);
+ m_threads, m_local_io_ctx, m_remote_image_ctx, *m_remote_journaler,
+ m_global_image_id, *m_remote_mirror_uuid, &m_client_meta, m_progress_ctx,
+ m_local_image_id, ctx);
request->send();
}
return;
}
- *m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
open_local_image();
}
BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(this);
m_image_sync = ImageSync<I>::create(
*m_local_image_ctx, m_remote_image_ctx, m_threads->timer,
- &m_threads->timer_lock, m_local_mirror_uuid, m_remote_journaler,
- m_client_meta, m_threads->work_queue, m_instance_watcher, ctx,
+ &m_threads->timer_lock, m_local_mirror_uuid, *m_remote_journaler,
+ &m_client_meta, m_threads->work_queue, m_instance_watcher, ctx,
m_progress_ctx);
m_image_sync->get();
locker.unlock();
class Context;
class ContextWQ;
class SafeTimer;
+
+namespace journal { class CacheManagerHandler; }
namespace librbd { class ImageCtx; }
namespace rbd {
typedef rbd::mirror::ProgressContext ProgressContext;
static BootstrapRequest* create(
- Threads<ImageCtxT>* threads,
- librados::IoCtx &local_io_ctx,
- librados::IoCtx &remote_io_ctx,
- InstanceWatcher<ImageCtxT> *instance_watcher,
- ImageCtxT **local_image_ctx,
- const std::string &local_image_id,
- const std::string &remote_image_id,
- const std::string &global_image_id,
- const std::string &local_mirror_uuid,
- const std::string &remote_mirror_uuid,
- Journaler *remote_journaler,
- cls::journal::ClientState *client_state,
- MirrorPeerClientMeta *client_meta,
- Context *on_finish,
- bool *do_resync,
- ProgressContext *progress_ctx = nullptr) {
- return new BootstrapRequest(threads, local_io_ctx, remote_io_ctx,
- instance_watcher, local_image_ctx,
- local_image_id, remote_image_id,
- global_image_id, local_mirror_uuid,
- remote_mirror_uuid, remote_journaler,
- client_state, client_meta, on_finish,
- do_resync, progress_ctx);
+ Threads<ImageCtxT>* threads,
+ librados::IoCtx& local_io_ctx,
+ librados::IoCtx& remote_io_ctx,
+ InstanceWatcher<ImageCtxT>* instance_watcher,
+ const std::string& remote_image_id,
+ const std::string& global_image_id,
+ const std::string& local_mirror_uuid,
+ ::journal::CacheManagerHandler* cache_manager_handler,
+ ProgressContext* progress_ctx,
+ ImageCtxT** local_image_ctx,
+ std::string* local_image_id,
+ std::string* remote_mirror_uuid,
+ Journaler** remote_journaler,
+ bool* do_resync,
+ Context* on_finish) {
+ return new BootstrapRequest(
+ threads, local_io_ctx, remote_io_ctx, instance_watcher, remote_image_id,
+ global_image_id, local_mirror_uuid, cache_manager_handler, progress_ctx,
+ local_image_ctx, local_image_id, remote_mirror_uuid, remote_journaler,
+ do_resync, on_finish);
}
- BootstrapRequest(Threads<ImageCtxT>* threads,
- librados::IoCtx &local_io_ctx,
- librados::IoCtx &remote_io_ctx,
- InstanceWatcher<ImageCtxT> *instance_watcher,
- ImageCtxT **local_image_ctx,
- const std::string &local_image_id,
- const std::string &remote_image_id,
- const std::string &global_image_id,
- const std::string &local_mirror_uuid,
- const std::string &remote_mirror_uuid,
- Journaler *remote_journaler,
- cls::journal::ClientState *client_state,
- MirrorPeerClientMeta *client_meta, Context *on_finish,
- bool *do_resync, ProgressContext *progress_ctx = nullptr);
+ BootstrapRequest(
+ Threads<ImageCtxT>* threads,
+ librados::IoCtx& local_io_ctx,
+ librados::IoCtx& remote_io_ctx,
+ InstanceWatcher<ImageCtxT>* instance_watcher,
+ const std::string& remote_image_id,
+ const std::string& global_image_id,
+ const std::string& local_mirror_uuid,
+ ::journal::CacheManagerHandler* cache_manager_handler,
+ ProgressContext* progress_ctx,
+ ImageCtxT** local_image_ctx,
+ std::string* local_image_id,
+ std::string* remote_mirror_uuid,
+ Journaler** remote_journaler,
+ bool* do_resync,
+ Context* on_finish);
~BootstrapRequest() override;
bool is_syncing() const;
void send() override;
void cancel() override;
+ std::string get_local_image_name() const;
+
private:
/**
* @verbatim
*
* <start>
* |
- * v
- * OPEN_REMOTE_IMAGE * * * * * * * * * * * * * * * * * * * (error)
+ * v (error)
+ * PREPARE_LOCAL_IMAGE * * * * * * * * * * * * * * * * * *
+ * | *
+ * v (error) *
+ * PREPARE_REMOTE_IMAGE * * * * * * * * * * * * * * * * * *
+ * | *
+ * v (error) *
+ * OPEN_REMOTE_IMAGE * * * * * * * * * * * * * * * * * * *
* | *
* v *
* GET_REMOTE_MIRROR_INFO * * * * * * * * * * * * * * * *
librados::IoCtx &m_local_io_ctx;
librados::IoCtx &m_remote_io_ctx;
InstanceWatcher<ImageCtxT> *m_instance_watcher;
- ImageCtxT **m_local_image_ctx;
- std::string m_local_image_id;
std::string m_remote_image_id;
std::string m_global_image_id;
std::string m_local_mirror_uuid;
- std::string m_remote_mirror_uuid;
- Journaler *m_remote_journaler;
- cls::journal::ClientState *m_client_state;
- MirrorPeerClientMeta *m_client_meta;
+ ::journal::CacheManagerHandler *m_cache_manager_handler;
ProgressContext *m_progress_ctx;
+ ImageCtxT **m_local_image_ctx;
+ std::string* m_local_image_id;
+ std::string* m_remote_mirror_uuid;
+ Journaler** m_remote_journaler;
bool *m_do_resync;
mutable ceph::mutex m_lock;
librbd::mirror::PROMOTION_STATE_NON_PRIMARY;
int m_ret_val = 0;
+ std::string m_local_image_name;
+ std::string m_local_image_tag_owner;
+ std::string m_prepare_local_image_name;
+
+ cls::journal::ClientState m_client_state =
+ cls::journal::CLIENT_STATE_DISCONNECTED;
+ librbd::journal::MirrorPeerClientMeta m_client_meta;
+
bool m_syncing = false;
ImageSync<ImageCtxT> *m_image_sync = nullptr;
+ void prepare_local_image();
+ void handle_prepare_local_image(int r);
+
+ void prepare_remote_image();
+ void handle_prepare_remote_image(int r);
+
void open_remote_image();
void handle_open_remote_image(int r);
template <typename I>
void PrepareLocalImageRequest<I>::send() {
- dout(20) << dendl;
+ dout(10) << dendl;
get_local_image_id();
}
template <typename I>
void PrepareLocalImageRequest<I>::get_local_image_id() {
- dout(20) << dendl;
+ dout(10) << dendl;
Context *ctx = create_context_callback<
PrepareLocalImageRequest<I>,
template <typename I>
void PrepareLocalImageRequest<I>::handle_get_local_image_id(int r) {
- dout(20) << "r=" << r << ", "
+ dout(10) << "r=" << r << ", "
<< "local_image_id=" << *m_local_image_id << dendl;
if (r < 0) {
template <typename I>
void PrepareLocalImageRequest<I>::get_local_image_name() {
- dout(20) << dendl;
+ dout(10) << dendl;
librados::ObjectReadOperation op;
librbd::cls_client::dir_get_name_start(&op, *m_local_image_id);
template <typename I>
void PrepareLocalImageRequest<I>::handle_get_local_image_name(int r) {
- dout(20) << "r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r == 0) {
auto it = m_out_bl.cbegin();
template <typename I>
void PrepareLocalImageRequest<I>::get_mirror_state() {
- dout(20) << dendl;
+ dout(10) << dendl;
librados::ObjectReadOperation op;
librbd::cls_client::mirror_image_get_start(&op, *m_local_image_id);
template <typename I>
void PrepareLocalImageRequest<I>::handle_get_mirror_state(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << ": r=" << r << dendl;
cls::rbd::MirrorImage mirror_image;
if (r == 0) {
typename std::remove_pointer<decltype(std::declval<I>().journal)>
::type>::type;
- dout(20) << dendl;
+ dout(10) << dendl;
Context *ctx = create_context_callback<
PrepareLocalImageRequest<I>,
template <typename I>
void PrepareLocalImageRequest<I>::handle_get_tag_owner(int r) {
- dout(20) << "r=" << r << ", "
+ dout(10) << "r=" << r << ", "
<< "tag_owner=" << *m_tag_owner << dendl;
if (r < 0) {
template <typename I>
void PrepareLocalImageRequest<I>::finish(int r) {
- dout(20) << "r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
m_on_finish->complete(r);
delete this;
template <typename I>
void PrepareRemoteImageRequest<I>::get_remote_mirror_uuid() {
- dout(20) << dendl;
+ dout(10) << dendl;
librados::ObjectReadOperation op;
librbd::cls_client::mirror_uuid_get_start(&op);
}
}
- dout(20) << "r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
if (r == -ENOENT) {
dout(5) << "remote mirror uuid missing" << dendl;
template <typename I>
void PrepareRemoteImageRequest<I>::get_remote_image_id() {
- dout(20) << dendl;
+ dout(10) << dendl;
Context *ctx = create_context_callback<
PrepareRemoteImageRequest<I>,
template <typename I>
void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
- dout(20) << "r=" << r << ", "
+ dout(10) << "r=" << r << ", "
<< "remote_image_id=" << *m_remote_image_id << dendl;
if (r < 0) {
template <typename I>
void PrepareRemoteImageRequest<I>::get_client() {
- dout(20) << dendl;
+ dout(10) << dendl;
ceph_assert(*m_remote_journaler == nullptr);
*m_remote_journaler = new Journaler(m_threads->work_queue, m_threads->timer,
template <typename I>
void PrepareRemoteImageRequest<I>::handle_get_client(int r) {
- dout(20) << "r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r == -ENOENT) {
dout(10) << "client not registered" << dendl;
template <typename I>
void PrepareRemoteImageRequest<I>::register_client() {
- dout(20) << dendl;
+ dout(10) << dendl;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
m_local_image_id};
template <typename I>
void PrepareRemoteImageRequest<I>::handle_register_client(int r) {
- dout(20) << "r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
derr << "failed to register with remote journal: " << cpp_strerror(r)
template <typename I>
void PrepareRemoteImageRequest<I>::finish(int r) {
- dout(20) << "r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
delete *m_remote_journaler;