class ProgressContext;
+template <>
+struct Threads<librbd::MockTestImageCtx> {
+ Mutex &timer_lock;
+ SafeTimer *timer;
+ ContextWQ *work_queue;
+
+ Threads(Threads<librbd::ImageCtx> *threads)
+ : timer_lock(threads->timer_lock), timer(threads->timer),
+ work_queue(threads->work_queue) {
+ }
+};
+
template<>
struct ImageSync<librbd::MockTestImageCtx> {
static ImageSync* s_instance;
static CreateImageRequest* s_instance;
Context *on_finish = nullptr;
- static CreateImageRequest* create(librados::IoCtx &local_io_ctx,
- ContextWQ *work_queue,
+ static CreateImageRequest* create(Threads<librbd::MockTestImageCtx>* threads,
+ librados::IoCtx &local_io_ctx,
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
class TestMockImageReplayerBootstrapRequest : public TestMockFixture {
public:
+ typedef Threads<librbd::MockTestImageCtx> MockThreads;
typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
return bl;
}
- MockBootstrapRequest *create_request(MockInstanceWatcher *mock_instance_watcher,
+ 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,
cls::journal::ClientState *client_state,
librbd::journal::MirrorPeerClientMeta *mirror_peer_client_meta,
Context *on_finish) {
- return new MockBootstrapRequest(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,
- m_threads->work_queue,
- m_threads->timer,
- &m_threads->timer_lock,
local_mirror_uuid,
remote_mirror_uuid,
&mock_journaler,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_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_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);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
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_instance_watcher, mock_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_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);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
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_instance_watcher, mock_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_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);
request->send();
ASSERT_EQ(0, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
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_instance_watcher, mock_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_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);
request->send();
ASSERT_EQ(0, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
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_instance_watcher, mock_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_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);
request->send();
ASSERT_EQ(0, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
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_instance_watcher, mock_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_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);
request->send();
ASSERT_EQ(-EEXIST, ctx.wait());
ASSERT_EQ(NULL, m_local_test_image_ctx);
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
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_instance_watcher, mock_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_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);
m_do_resync = false;
request->send();
ASSERT_EQ(0, ctx.wait());
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
mirror_peer_client_meta.image_id = "";
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, "",
+ &mock_threads, &mock_instance_watcher, mock_journaler, "",
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
mirror_peer_client_meta.image_id = "missing image id";
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, "missing image id",
+ &mock_threads, &mock_instance_watcher, mock_journaler, "missing image id",
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
#include "include/rbd/librbd.hpp"
#include "librbd/ImageState.h"
#include "librbd/Operations.h"
+#include "test/journal/mock/MockJournaler.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librados_test_stub/MockTestMemRadosClient.h"
#include "test/librbd/mock/MockImageCtx.h"
CloneRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
} // namespace image
+
+namespace journal {
+
+template <>
+struct TypeTraits<MockTestImageCtx> {
+ typedef ::journal::MockJournalerProxy Journaler;
+};
+
+} // namespace journal
} // namespace librbd
namespace rbd {
namespace mirror {
+
+template <>
+struct Threads<librbd::MockTestImageCtx> {
+ Mutex &timer_lock;
+ SafeTimer *timer;
+ ContextWQ *work_queue;
+
+ Threads(Threads<librbd::ImageCtx> *threads)
+ : timer_lock(threads->timer_lock), timer(threads->timer),
+ work_queue(threads->work_queue) {
+ }
+};
+
namespace image_replayer {
template<>
class TestMockImageReplayerCreateImageRequest : public TestMockFixture {
public:
+ typedef Threads<librbd::MockTestImageCtx> MockThreads;
typedef librbd::image::CreateRequest<librbd::MockTestImageCtx> MockCreateRequest;
typedef librbd::image::CloneRequest<librbd::MockTestImageCtx> MockCloneRequest;
typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
}));
}
- MockCreateImageRequest *create_request(const std::string &global_image_id,
+ void expect_mirror_uuid_get(librados::IoCtx &io_ctx,
+ const std::string &mirror_uuid, int r) {
+ bufferlist bl;
+ encode(mirror_uuid, bl);
+
+ EXPECT_CALL(get_mock_io_ctx(io_ctx),
+ exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_uuid_get"), _, _, _))
+ .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
+ *out_bl = bl;
+ })),
+ Return(r)));
+ }
+
+ void expect_journaler_get_client(journal::MockJournaler& mock_journaler,
+ const std::string& client_id,
+ librbd::journal::MirrorPeerState state,
+ int r) {
+ EXPECT_CALL(mock_journaler, construct());
+
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+ mirror_peer_client_meta.state = state;
+
+ librbd::journal::ClientData client_data{mirror_peer_client_meta};
+
+ cls::journal::Client client;
+ encode(client_data, client.data);
+
+ EXPECT_CALL(mock_journaler, get_client(StrEq(client_id), _, _))
+ .WillOnce(DoAll(WithArg<1>(Invoke([client](cls::journal::Client *out_client) {
+ *out_client = client;
+ })),
+ WithArg<2>(Invoke([this, r](Context *on_finish) {
+ m_threads->work_queue->queue(on_finish, r);
+ }))));
+ }
+
+ MockCreateImageRequest *create_request(MockThreads* mock_threads,
+ const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
const std::string &local_image_id,
librbd::MockTestImageCtx &mock_remote_image_ctx,
Context *on_finish) {
- return new MockCreateImageRequest(m_local_io_ctx, m_threads->work_queue,
+ return new MockCreateImageRequest(mock_threads, m_local_io_ctx,
global_image_id, remote_mirror_uuid,
local_image_name, local_image_id,
&mock_remote_image_ctx, on_finish);
expect_create_image(mock_create_request, m_local_io_ctx, 0);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_image_ctx, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
expect_create_image(mock_create_request, m_local_io_ctx, -EINVAL);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_image_ctx, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
MockCloneRequest mock_clone_request;
MockOpenImageRequest mock_open_image_request;
MockCloseImageRequest mock_close_image_request;
+ journal::MockJournaler mock_remote_journaler;
InSequence seq;
expect_ioctx_create(m_remote_io_ctx);
expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_clone_image_ctx,
&ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneParentMirrorUuidGetError) {
+ std::string clone_image_name = get_temp_image_name();
+ ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
+
+ librbd::ImageCtx *remote_clone_image_ctx;
+ ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
+ &remote_clone_image_ctx));
+
+ librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
+
+ InSequence seq;
+ expect_ioctx_create(m_remote_io_ctx);
+ expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", -EPERM);
+
+ C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
+ mock_remote_clone_image_ctx,
+ &ctx);
+ request->send();
+ ASSERT_EQ(-EPERM, ctx.wait());
+}
+
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetRemoteParentClientStateError) {
+ std::string clone_image_name = get_temp_image_name();
+ ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
+
+ librbd::ImageCtx *remote_clone_image_ctx;
+ ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
+ &remote_clone_image_ctx));
+
+ librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
+ journal::MockJournaler mock_remote_journaler;
+
+ InSequence seq;
+ expect_ioctx_create(m_remote_io_ctx);
+ expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, -EPERM);
+
+ C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
+ mock_remote_clone_image_ctx,
+ &ctx);
+ request->send();
+ ASSERT_EQ(-EPERM, ctx.wait());
+}
+
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetRemoteParentClientStateSyncing) {
+ std::string clone_image_name = get_temp_image_name();
+ ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
+
+ librbd::ImageCtx *remote_clone_image_ctx;
+ ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
+ &remote_clone_image_ctx));
+
+ librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
+ journal::MockJournaler mock_remote_journaler;
+
+ InSequence seq;
+ expect_ioctx_create(m_remote_io_ctx);
+ expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_SYNCING, 0);
+
+ C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
+ mock_remote_clone_image_ctx,
+ &ctx);
+ request->send();
+ ASSERT_EQ(-ENOENT, ctx.wait());
+}
+
TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) {
std::string clone_image_name = get_temp_image_name();
ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
&remote_clone_image_ctx));
librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
- MockCloneRequest mock_clone_request;
+ journal::MockJournaler mock_remote_journaler;
InSequence seq;
expect_ioctx_create(m_remote_io_ctx);
expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", -ENOENT);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_clone_image_ctx,
&ctx);
request->send();
&remote_clone_image_ctx));
librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
- MockCloneRequest mock_clone_request;
+ journal::MockJournaler mock_remote_journaler;
InSequence seq;
expect_ioctx_create(m_remote_io_ctx);
expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", -ENOENT);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_clone_image_ctx,
&ctx);
request->send();
librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
- MockCloneRequest mock_clone_request;
MockOpenImageRequest mock_open_image_request;
+ journal::MockJournaler mock_remote_journaler;
InSequence seq;
expect_ioctx_create(m_remote_io_ctx);
expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
expect_open_image(mock_open_image_request, m_remote_io_ctx,
- m_remote_image_ctx->id, mock_remote_parent_image_ctx, -ENOENT);
+ m_remote_image_ctx->id, mock_remote_parent_image_ctx,
+ -ENOENT);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_clone_image_ctx,
&ctx);
request->send();
MockCloneRequest mock_clone_request;
MockOpenImageRequest mock_open_image_request;
MockCloseImageRequest mock_close_image_request;
+ journal::MockJournaler mock_remote_journaler;
InSequence seq;
expect_ioctx_create(m_remote_io_ctx);
expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_clone_image_ctx,
&ctx);
request->send();
MockCloneRequest mock_clone_request;
MockOpenImageRequest mock_open_image_request;
MockCloseImageRequest mock_close_image_request;
+ journal::MockJournaler mock_remote_journaler;
InSequence seq;
expect_ioctx_create(m_remote_io_ctx);
expect_ioctx_create(m_local_io_ctx);
+ expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+ expect_journaler_get_client(
+ mock_remote_journaler, "local parent uuid",
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
expect_open_image(mock_open_image_request, m_remote_io_ctx,
m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
expect_clone_image(mock_clone_request, 0);
- expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, -EINVAL);
+ expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx,
+ -EINVAL);
C_SaferCond ctx;
- MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name", "101241a7c4c9",
+ MockThreads mock_threads(m_threads);
+ MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+ "remote uuid", "image name",
+ "101241a7c4c9",
mock_remote_clone_image_ctx,
&ctx);
request->send();
bool *do_resync = nullptr;
static BootstrapRequest* create(
+ Threads<librbd::MockTestImageCtx>* threads,
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 &global_image_id, MockContextWQ *work_queue,
- MockSafeTimer *timer, Mutex *timer_lock,
+ const std::string &global_image_id,
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid,
::journal::MockJournalerProxy *journaler,
image_replayer/PrepareLocalImageRequest.cc
image_replayer/PrepareRemoteImageRequest.cc
image_replayer/ReplayStatusFormatter.cc
+ image_replayer/Utils.cc
image_sync/SyncPointCreateRequest.cc
image_sync/SyncPointPruneRequest.cc
pool_watcher/RefreshImagesRequest.cc
ImageReplayer, &ImageReplayer<I>::handle_bootstrap>(this);
BootstrapRequest<I> *request = BootstrapRequest<I>::create(
- *m_local_ioctx, m_remote_image.io_ctx, m_instance_watcher,
+ m_threads, *m_local_ioctx, 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_threads->work_queue, m_threads->timer,
- &m_threads->timer_lock, m_local_mirror_uuid, m_remote_image.mirror_uuid,
+ 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);
#include "librbd/journal/Types.h"
#include "tools/rbd_mirror/ProgressContext.h"
#include "tools/rbd_mirror/ImageSync.h"
+#include "tools/rbd_mirror/Threads.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
template <typename I>
BootstrapRequest<I>::BootstrapRequest(
+ Threads<I>* threads,
librados::IoCtx &local_io_ctx,
librados::IoCtx &remote_io_ctx,
InstanceWatcher<I> *instance_watcher,
const std::string &local_image_id,
const std::string &remote_image_id,
const std::string &global_image_id,
- ContextWQ *work_queue, SafeTimer *timer,
- Mutex *timer_lock,
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid,
Journaler *journaler,
rbd::mirror::ProgressContext *progress_ctx)
: BaseRequest("rbd::mirror::image_replayer::BootstrapRequest",
reinterpret_cast<CephContext*>(local_io_ctx.cct()), on_finish),
- 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_work_queue(work_queue),
- m_timer(timer), m_timer_lock(timer_lock),
+ 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_local_mirror_uuid(local_mirror_uuid),
m_remote_mirror_uuid(remote_mirror_uuid), m_journaler(journaler),
m_client_state(client_state), m_client_meta(client_meta),
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_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_create_local_image>(
this);
CreateImageRequest<I> *request = CreateImageRequest<I>::create(
- m_local_io_ctx, m_work_queue, m_global_image_id, m_remote_mirror_uuid,
+ m_threads, m_local_io_ctx, m_global_image_id, m_remote_mirror_uuid,
image_name, m_local_image_id, m_remote_image_ctx, ctx);
request->send();
}
Context *ctx = create_context_callback<
BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(this);
m_image_sync = ImageSync<I>::create(
- *m_local_image_ctx, m_remote_image_ctx, m_timer, m_timer_lock,
- m_local_mirror_uuid, m_journaler, m_client_meta, m_work_queue,
- m_instance_watcher, ctx, m_progress_ctx);
+ *m_local_image_ctx, m_remote_image_ctx, m_threads->timer,
+ &m_threads->timer_lock, m_local_mirror_uuid, m_journaler,
+ m_client_meta, m_threads->work_queue, m_instance_watcher, ctx,
+ m_progress_ctx);
m_image_sync->get();
template <typename> class ImageSync;
template <typename> class InstanceWatcher;
+template <typename> struct Threads;
namespace image_replayer {
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,
const std::string &local_image_id,
const std::string &remote_image_id,
const std::string &global_image_id,
- ContextWQ *work_queue, SafeTimer *timer,
- Mutex *timer_lock,
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid,
Journaler *journaler,
Context *on_finish,
bool *do_resync,
ProgressContext *progress_ctx = nullptr) {
- return new BootstrapRequest(local_io_ctx, remote_io_ctx,
+ return new BootstrapRequest(threads, local_io_ctx, remote_io_ctx,
instance_watcher, local_image_ctx,
local_image_id, remote_image_id,
- global_image_id, work_queue, timer, timer_lock,
- local_mirror_uuid, remote_mirror_uuid,
- journaler, client_state, client_meta, on_finish,
- do_resync, progress_ctx);
+ global_image_id, local_mirror_uuid,
+ remote_mirror_uuid, journaler, client_state,
+ client_meta, on_finish, do_resync,
+ progress_ctx);
}
- BootstrapRequest(librados::IoCtx &local_io_ctx,
+ 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, ContextWQ *work_queue,
- SafeTimer *timer, Mutex *timer_lock,
+ const std::string &global_image_id,
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid, Journaler *journaler,
cls::journal::ClientState *client_state,
*/
typedef std::list<cls::journal::Tag> Tags;
+ Threads<ImageCtxT>* m_threads;
librados::IoCtx &m_local_io_ctx;
librados::IoCtx &m_remote_io_ctx;
InstanceWatcher<ImageCtxT> *m_instance_watcher;
std::string m_local_image_id;
std::string m_remote_image_id;
std::string m_global_image_id;
- ContextWQ *m_work_queue;
- SafeTimer *m_timer;
- Mutex *m_timer_lock;
std::string m_local_mirror_uuid;
std::string m_remote_mirror_uuid;
Journaler *m_journaler;
#include "common/errno.h"
#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 "librbd/Utils.h"
#include "librbd/image/CreateRequest.h"
#include "librbd/image/CloneRequest.h"
+#include "librbd/journal/Types.h"
+#include "tools/rbd_mirror/Threads.h"
+#include "tools/rbd_mirror/image_replayer/Utils.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
#undef dout_prefix
#define dout_prefix *_dout << "rbd::mirror::image_replayer::CreateImageRequest: " \
- << this << " " << __func__
+ << this << " " << __func__ << ": "
+using librbd::util::create_async_context_callback;
using librbd::util::create_context_callback;
using librbd::util::create_rados_callback;
namespace image_replayer {
template <typename I>
-CreateImageRequest<I>::CreateImageRequest(librados::IoCtx &local_io_ctx,
- ContextWQ *work_queue,
+CreateImageRequest<I>::CreateImageRequest(Threads<I>* threads,
+ librados::IoCtx &local_io_ctx,
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
const std::string &local_image_id,
I *remote_image_ctx,
Context *on_finish)
- : m_local_io_ctx(local_io_ctx), m_work_queue(work_queue),
+ : m_threads(threads), m_local_io_ctx(local_io_ctx),
m_global_image_id(global_image_id),
m_remote_mirror_uuid(remote_mirror_uuid),
m_local_image_name(local_image_name), m_local_image_id(local_image_id),
if (m_remote_parent_spec.pool_id == -1) {
create_image();
} else {
- get_parent_global_image_id();
+ get_local_parent_mirror_uuid();
}
}
template <typename I>
void CreateImageRequest<I>::create_image() {
- dout(20) << dendl;
+ dout(10) << dendl;
using klass = CreateImageRequest<I>;
- Context *ctx = create_context_callback<klass, &klass::handle_create_image>(this);
+ Context *ctx = create_context_callback<
+ klass, &klass::handle_create_image>(this);
RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
librbd::ImageOptions image_options;
populate_image_options(&image_options);
- librbd::image::CreateRequest<I> *req = librbd::image::CreateRequest<I>::create(
+ auto req = librbd::image::CreateRequest<I>::create(
m_local_io_ctx, m_local_image_name, m_local_image_id,
m_remote_image_ctx->size, image_options, m_global_image_id,
m_remote_mirror_uuid, false, m_remote_image_ctx->op_work_queue, ctx);
template <typename I>
void CreateImageRequest<I>::handle_create_image(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
- derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
+ derr << "failed to create local image: " << cpp_strerror(r) << dendl;
finish(r);
return;
}
finish(0);
}
+template <typename I>
+void CreateImageRequest<I>::get_local_parent_mirror_uuid() {
+ dout(10) << dendl;
+
+ librados::ObjectReadOperation op;
+ librbd::cls_client::mirror_uuid_get_start(&op);
+
+ librados::AioCompletion *aio_comp = create_rados_callback<
+ CreateImageRequest<I>,
+ &CreateImageRequest<I>::handle_get_local_parent_mirror_uuid>(this);
+ m_out_bl.clear();
+ int r = m_local_parent_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op,
+ &m_out_bl);
+ ceph_assert(r == 0);
+ aio_comp->release();
+}
+
+template <typename I>
+void CreateImageRequest<I>::handle_get_local_parent_mirror_uuid(int r) {
+ if (r >= 0) {
+ auto it = m_out_bl.cbegin();
+ r = librbd::cls_client::mirror_uuid_get_finish(
+ &it, &m_local_parent_mirror_uuid);
+ if (r >= 0 && m_local_parent_mirror_uuid.empty()) {
+ r = -ENOENT;
+ }
+ }
+
+ dout(10) << "r=" << r << dendl;
+ if (r < 0) {
+ if (r == -ENOENT) {
+ dout(5) << "local parent mirror uuid missing" << dendl;
+ } else {
+ derr << "failed to retrieve local parent mirror uuid: " << cpp_strerror(r)
+ << dendl;
+ }
+ finish(r);
+ return;
+ }
+
+ dout(15) << "local_parent_mirror_uuid=" << m_local_parent_mirror_uuid
+ << dendl;
+ get_remote_parent_client_state();
+}
+
+template <typename I>
+void CreateImageRequest<I>::get_remote_parent_client_state() {
+ dout(10) << dendl;
+
+ m_remote_journaler = new Journaler(m_threads->work_queue, m_threads->timer,
+ &m_threads->timer_lock,
+ m_remote_parent_io_ctx,
+ m_remote_parent_spec.image_id,
+ m_local_parent_mirror_uuid, {});
+
+ Context *ctx = create_async_context_callback(
+ m_threads->work_queue, create_context_callback<
+ CreateImageRequest<I>,
+ &CreateImageRequest<I>::handle_get_remote_parent_client_state>(this));
+ m_remote_journaler->get_client(m_local_parent_mirror_uuid, &m_client, ctx);
+}
+
+template <typename I>
+void CreateImageRequest<I>::handle_get_remote_parent_client_state(int r) {
+ dout(10) << "r=" << r << dendl;
+
+ delete m_remote_journaler;
+ m_remote_journaler = nullptr;
+
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+ if (r == -ENOENT) {
+ dout(15) << "client not registered to parent image" << dendl;
+ finish(r);
+ return;
+ } else if (r < 0) {
+ derr << "failed to retrieve parent client: " << cpp_strerror(r) << dendl;
+ finish(r);
+ return;
+ } else if (!util::decode_client_meta(m_client, &mirror_peer_client_meta)) {
+ // require operator intervention since the data is corrupt
+ derr << "failed to decode parent client: " << cpp_strerror(r) << dendl;
+ finish(-EBADMSG);
+ return;
+ } else if (mirror_peer_client_meta.state !=
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING) {
+ // avoid possible race w/ incomplete parent image since the parent snapshot
+ // might be deleted if the sync restarts
+ dout(15) << "parent image still syncing" << dendl;
+ finish(-ENOENT);
+ return;
+ }
+
+ get_parent_global_image_id();
+}
+
+
template <typename I>
void CreateImageRequest<I>::get_parent_global_image_id() {
- dout(20) << dendl;
+ dout(10) << dendl;
librados::ObjectReadOperation op;
- librbd::cls_client::mirror_image_get_start(&op, m_remote_parent_spec.image_id);
+ librbd::cls_client::mirror_image_get_start(&op,
+ m_remote_parent_spec.image_id);
librados::AioCompletion *aio_comp = create_rados_callback<
CreateImageRequest<I>,
template <typename I>
void CreateImageRequest<I>::handle_get_parent_global_image_id(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r == 0) {
cls::rbd::MirrorImage mirror_image;
auto iter = m_out_bl.cbegin();
r = librbd::cls_client::mirror_image_get_finish(&iter, &mirror_image);
if (r == 0) {
m_parent_global_image_id = mirror_image.global_image_id;
- dout(20) << ": parent_global_image_id=" << m_parent_global_image_id
+ dout(15) << "parent_global_image_id=" << m_parent_global_image_id
<< dendl;
}
}
if (r == -ENOENT) {
- dout(10) << ": parent image " << m_remote_parent_spec.image_id << " not mirrored"
- << dendl;
+ dout(10) << "parent image " << m_remote_parent_spec.image_id
+ << " not mirrored" << dendl;
finish(r);
return;
} else if (r < 0) {
- derr << ": failed to retrieve global image id for parent image "
+ derr << "failed to retrieve global image id for parent image "
<< m_remote_parent_spec.image_id << ": " << cpp_strerror(r) << dendl;
finish(r);
return;
template <typename I>
void CreateImageRequest<I>::get_local_parent_image_id() {
- dout(20) << dendl;
+ dout(10) << dendl;
librados::ObjectReadOperation op;
librbd::cls_client::mirror_image_get_image_id_start(
template <typename I>
void CreateImageRequest<I>::handle_get_local_parent_image_id(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r == 0) {
auto iter = m_out_bl.cbegin();
}
if (r == -ENOENT) {
- dout(10) << ": parent image " << m_parent_global_image_id << " not "
+ dout(10) << "parent image " << m_parent_global_image_id << " not "
<< "registered locally" << dendl;
finish(r);
return;
} else if (r < 0) {
- derr << ": failed to retrieve local image id for parent image "
+ derr << "failed to retrieve local image id for parent image "
<< m_parent_global_image_id << ": " << cpp_strerror(r) << dendl;
finish(r);
return;
template <typename I>
void CreateImageRequest<I>::open_remote_parent_image() {
- dout(20) << dendl;
+ dout(10) << dendl;
Context *ctx = create_context_callback<
CreateImageRequest<I>,
template <typename I>
void CreateImageRequest<I>::handle_open_remote_parent_image(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
- derr << ": failed to open remote parent image " << m_parent_pool_name << "/"
+ derr << "failed to open remote parent image " << m_parent_pool_name << "/"
<< m_remote_parent_spec.image_id << dendl;
finish(r);
return;
template <typename I>
void CreateImageRequest<I>::clone_image() {
- dout(20) << dendl;
+ dout(10) << dendl;
std::string snap_name;
cls::rbd::SnapshotNamespace snap_namespace;
template <typename I>
void CreateImageRequest<I>::handle_clone_image(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
- derr << ": failed to clone image " << m_parent_pool_name << "/"
+ derr << "failed to clone image " << m_parent_pool_name << "/"
<< m_remote_parent_spec.image_id << " to "
<< m_local_image_name << dendl;
m_ret_val = r;
template <typename I>
void CreateImageRequest<I>::close_remote_parent_image() {
- dout(20) << dendl;
+ dout(10) << dendl;
Context *ctx = create_context_callback<
CreateImageRequest<I>,
&CreateImageRequest<I>::handle_close_remote_parent_image>(this);
template <typename I>
void CreateImageRequest<I>::handle_close_remote_parent_image(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
if (r < 0) {
- derr << ": error encountered closing remote parent image: "
+ derr << "error encountered closing remote parent image: "
<< cpp_strerror(r) << dendl;
}
template <typename I>
void CreateImageRequest<I>::error(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
- m_work_queue->queue(create_context_callback<
+ m_threads->work_queue->queue(create_context_callback<
CreateImageRequest<I>, &CreateImageRequest<I>::finish>(this), r);
}
template <typename I>
void CreateImageRequest<I>::finish(int r) {
- dout(20) << ": r=" << r << dendl;
+ dout(10) << "r=" << r << dendl;
m_on_finish->complete(r);
delete this;
}
}
if (m_remote_parent_spec != parent_spec) {
- derr << ": remote image parent spec mismatch" << dendl;
+ derr << "remote image parent spec mismatch" << dendl;
return -EINVAL;
}
}
int r = remote_rados.ioctx_create2(m_remote_parent_spec.pool_id,
m_remote_parent_io_ctx);
if (r < 0) {
- derr << ": failed to open remote parent pool " << m_remote_parent_spec.pool_id
+ derr << "failed to open remote parent pool " << m_remote_parent_spec.pool_id
<< ": " << cpp_strerror(r) << dendl;
return r;
}
r = local_rados.ioctx_create(m_parent_pool_name.c_str(),
m_local_parent_io_ctx);
if (r < 0) {
- derr << ": failed to open local parent pool " << m_parent_pool_name << ": "
+ derr << "failed to open local parent pool " << m_parent_pool_name << ": "
<< cpp_strerror(r) << dendl;
return r;
}
#include "include/int_types.h"
#include "include/types.h"
#include "include/rados/librados.hpp"
+#include "cls/journal/cls_journal_types.h"
#include "librbd/Types.h"
+#include "librbd/journal/TypeTraits.h"
#include <string>
class Context;
class ContextWQ;
+namespace journal { class Journaler; }
namespace librbd { class ImageCtx; }
namespace librbd { class ImageOptions; }
namespace rbd {
namespace mirror {
+
+template <typename> struct Threads;
+
namespace image_replayer {
template <typename ImageCtxT = librbd::ImageCtx>
class CreateImageRequest {
public:
- static CreateImageRequest *create(librados::IoCtx &local_io_ctx,
- ContextWQ *work_queue,
+ static CreateImageRequest *create(Threads<ImageCtxT> *threads,
+ librados::IoCtx &local_io_ctx,
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
const std::string &local_image_id,
ImageCtxT *remote_image_ctx,
Context *on_finish) {
- return new CreateImageRequest(local_io_ctx, work_queue, global_image_id,
+ return new CreateImageRequest(threads, local_io_ctx, global_image_id,
remote_mirror_uuid, local_image_name,
local_image_id, remote_image_ctx, on_finish);
}
- CreateImageRequest(librados::IoCtx &local_io_ctx, ContextWQ *work_queue,
+ CreateImageRequest(Threads<ImageCtxT> *threads, librados::IoCtx &local_io_ctx,
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
* |\------------> CREATE_IMAGE ---------------------\ * (error)
* | | *
* | (clone) | *
- * \-------------> GET_PARENT_GLOBAL_IMAGE_ID * * * | * * * *
+ * \-------------> GET_LOCAL_PARENT_MIRROR_UUID * * | * * * *
+ * | | * *
+ * v | *
+ * GET_REMOTE_PARENT_CLIENT_STATE * | * * * *
+ * | | * *
+ * v | *
+ * GET_PARENT_GLOBAL_IMAGE_ID * * * | * * * *
* | | * *
* v | *
* GET_LOCAL_PARENT_IMAGE_ID * * * * | * * * *
* @endverbatim
*/
+ typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
+ typedef typename TypeTraits::Journaler Journaler;
+
+ Threads<ImageCtxT> *m_threads;
librados::IoCtx &m_local_io_ctx;
- ContextWQ *m_work_queue;
std::string m_global_image_id;
std::string m_remote_mirror_uuid;
std::string m_local_image_name;
Context *m_on_finish;
librados::IoCtx m_remote_parent_io_ctx;
+ std::string m_local_parent_mirror_uuid;
+ Journaler *m_remote_journaler = nullptr;
ImageCtxT *m_remote_parent_image_ctx = nullptr;
librbd::ParentSpec m_remote_parent_spec;
bufferlist m_out_bl;
std::string m_parent_global_image_id;
std::string m_parent_pool_name;
+ cls::journal::Client m_client;
int m_ret_val = 0;
void create_image();
void handle_create_image(int r);
+ void get_local_parent_mirror_uuid();
+ void handle_get_local_parent_mirror_uuid(int r);
+
+ void get_remote_parent_client_state();
+ void handle_get_remote_parent_client_state(int r);
+
void get_parent_global_image_id();
void handle_get_parent_global_image_id(int r);
#include "librbd/journal/Types.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
+#include "tools/rbd_mirror/image_replayer/Utils.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
} else if (r < 0) {
derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
finish(r);
- } else if (!decode_client_meta()) {
+ } else if (!util::decode_client_meta(m_client, m_client_meta)) {
// require operator intervention since the data is corrupt
finish(-EBADMSG);
} else {
finish(0);
}
-template <typename I>
-bool PrepareRemoteImageRequest<I>::decode_client_meta() {
- dout(20) << dendl;
-
- librbd::journal::ClientData client_data;
- auto it = m_client.data.cbegin();
- try {
- decode(client_data, it);
- } catch (const buffer::error &err) {
- derr << "failed to decode client meta data: " << err.what() << dendl;
- return false;
- }
-
- librbd::journal::MirrorPeerClientMeta *client_meta =
- boost::get<librbd::journal::MirrorPeerClientMeta>(&client_data.client_meta);
- if (client_meta == nullptr) {
- derr << "unknown peer registration" << dendl;
- return false;
- }
-
- *m_client_meta = *client_meta;
- dout(20) << "client found: client_meta=" << *m_client_meta << dendl;
- return true;
-}
-
template <typename I>
void PrepareRemoteImageRequest<I>::finish(int r) {
dout(20) << "r=" << r << dendl;
void handle_register_client(int r);
void finish(int r);
-
- bool decode_client_meta();
};
} // namespace image_replayer
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "tools/rbd_mirror/image_replayer/Utils.h"
+#include "common/debug.h"
+#include "common/errno.h"
+#include "cls/journal/cls_journal_types.h"
+#include "librbd/journal/Types.h"
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rbd_mirror
+#undef dout_prefix
+#define dout_prefix *_dout << "rbd::mirror::image_replayer::util::" \
+ << __func__ << ": "
+
+namespace rbd {
+namespace mirror {
+namespace image_replayer {
+namespace util {
+
+bool decode_client_meta(const cls::journal::Client& client,
+ librbd::journal::MirrorPeerClientMeta* client_meta) {
+ dout(15) << dendl;
+
+ librbd::journal::ClientData client_data;
+ auto it = client.data.cbegin();
+ try {
+ decode(client_data, it);
+ } catch (const buffer::error &err) {
+ derr << "failed to decode client meta data: " << err.what() << dendl;
+ return false;
+ }
+
+ auto local_client_meta = boost::get<librbd::journal::MirrorPeerClientMeta>(
+ &client_data.client_meta);
+ if (local_client_meta == nullptr) {
+ derr << "unknown peer registration" << dendl;
+ return false;
+ }
+
+ *client_meta = *local_client_meta;
+ dout(15) << "client found: client_meta=" << *client_meta << dendl;
+ return true;
+}
+
+} // namespace util
+} // namespace image_replayer
+} // namespace mirror
+} // namespace rbd
+
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef RBD_MIRROR_IMAGE_REPLAYER_UTILS_H
+#define RBD_MIRROR_IMAGE_REPLAYER_UTILS_H
+
+namespace cls { namespace journal { struct Client; } }
+namespace librbd { namespace journal { struct MirrorPeerClientMeta; } }
+
+namespace rbd {
+namespace mirror {
+namespace image_replayer {
+namespace util {
+
+bool decode_client_meta(const cls::journal::Client& client,
+ librbd::journal::MirrorPeerClientMeta* client_meta);
+
+} // namespace util
+} // namespace image_replayer
+} // namespace mirror
+} // namespace rbd
+
+#endif // RBD_MIRROR_IMAGE_REPLAYER_UTILS_H