mirror of
https://github.com/ceph/ceph
synced 2025-03-25 03:37:38 +00:00
Merge pull request #18136 from dillaman/wip-21561
rbd-mirror: primary image should register in remote, non-primary image's journal Reviewed-by: Mykola Golub <to.my.trociny@gmail.com>
This commit is contained in:
commit
069c8dc2f4
src
test
journal/mock
rbd_mirror
tools/rbd_mirror
@ -138,6 +138,10 @@ struct MockJournaler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MockJournalerProxy {
|
struct MockJournalerProxy {
|
||||||
|
MockJournalerProxy() {
|
||||||
|
MockJournaler::get_instance().construct();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename IoCtxT>
|
template <typename IoCtxT>
|
||||||
MockJournalerProxy(IoCtxT &header_ioctx, const std::string &,
|
MockJournalerProxy(IoCtxT &header_ioctx, const std::string &,
|
||||||
const std::string &, const Settings&) {
|
const std::string &, const Settings&) {
|
||||||
|
@ -448,6 +448,8 @@ public:
|
|||||||
const std::string &global_image_id,
|
const std::string &global_image_id,
|
||||||
const std::string &local_mirror_uuid,
|
const std::string &local_mirror_uuid,
|
||||||
const std::string &remote_mirror_uuid,
|
const std::string &remote_mirror_uuid,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
|
librbd::journal::MirrorPeerClientMeta *mirror_peer_client_meta,
|
||||||
Context *on_finish) {
|
Context *on_finish) {
|
||||||
return new MockBootstrapRequest(m_local_io_ctx,
|
return new MockBootstrapRequest(m_local_io_ctx,
|
||||||
m_remote_io_ctx,
|
m_remote_io_ctx,
|
||||||
@ -462,14 +464,13 @@ public:
|
|||||||
local_mirror_uuid,
|
local_mirror_uuid,
|
||||||
remote_mirror_uuid,
|
remote_mirror_uuid,
|
||||||
&mock_journaler,
|
&mock_journaler,
|
||||||
&m_mirror_peer_client_meta,
|
client_state, mirror_peer_client_meta,
|
||||||
on_finish, &m_do_resync);
|
on_finish, &m_do_resync);
|
||||||
}
|
}
|
||||||
|
|
||||||
librbd::ImageCtx *m_remote_image_ctx;
|
librbd::ImageCtx *m_remote_image_ctx;
|
||||||
librbd::ImageCtx *m_local_image_ctx = nullptr;
|
librbd::ImageCtx *m_local_image_ctx = nullptr;
|
||||||
librbd::MockTestImageCtx *m_local_test_image_ctx = nullptr;
|
librbd::MockTestImageCtx *m_local_test_image_ctx = nullptr;
|
||||||
librbd::journal::MirrorPeerClientMeta m_mirror_peer_client_meta;
|
|
||||||
bool m_do_resync;
|
bool m_do_resync;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -495,22 +496,14 @@ TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteSyncingState) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
mock_local_image_ctx.id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, false, 0);
|
expect_is_primary(mock_is_primary_request, false, 0);
|
||||||
|
|
||||||
// switch the state to replaying
|
// switch the state to replaying
|
||||||
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
||||||
|
mock_local_image_ctx.id};
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
client_data.client_meta = mirror_peer_client_meta;
|
||||||
expect_journaler_update_client(mock_journaler, client_data, 0);
|
expect_journaler_update_client(mock_journaler, client_data, 0);
|
||||||
@ -520,10 +513,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteSyncingState) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(-EREMOTEIO, ctx.wait());
|
ASSERT_EQ(-EREMOTEIO, ctx.wait());
|
||||||
}
|
}
|
||||||
@ -550,22 +545,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
mock_local_image_ctx.id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
|
|
||||||
// open the local image
|
// open the local image
|
||||||
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
MockOpenLocalImageRequest mock_open_local_image_request;
|
MockOpenLocalImageRequest mock_open_local_image_request;
|
||||||
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
||||||
@ -596,10 +581,14 @@ TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
}
|
}
|
||||||
@ -626,22 +615,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
mock_local_image_ctx.id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
|
|
||||||
// open the local image
|
// open the local image
|
||||||
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
MockOpenLocalImageRequest mock_open_local_image_request;
|
MockOpenLocalImageRequest mock_open_local_image_request;
|
||||||
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
||||||
@ -682,10 +661,14 @@ TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
}
|
}
|
||||||
@ -712,22 +695,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
mock_local_image_ctx.id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
|
|
||||||
// open the local image
|
// open the local image
|
||||||
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
MockOpenLocalImageRequest mock_open_local_image_request;
|
MockOpenLocalImageRequest mock_open_local_image_request;
|
||||||
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
||||||
@ -756,10 +729,14 @@ TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
}
|
}
|
||||||
@ -786,22 +763,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
mock_local_image_ctx.id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
|
|
||||||
// open the local image
|
// open the local image
|
||||||
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
MockOpenLocalImageRequest mock_open_local_image_request;
|
MockOpenLocalImageRequest mock_open_local_image_request;
|
||||||
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
||||||
@ -829,10 +796,14 @@ TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(-EEXIST, ctx.wait());
|
ASSERT_EQ(-EEXIST, ctx.wait());
|
||||||
ASSERT_EQ(NULL, m_local_test_image_ctx);
|
ASSERT_EQ(NULL, m_local_test_image_ctx);
|
||||||
@ -860,22 +831,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
mock_local_image_ctx.id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
|
|
||||||
// open the local image
|
// open the local image
|
||||||
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
MockOpenLocalImageRequest mock_open_local_image_request;
|
MockOpenLocalImageRequest mock_open_local_image_request;
|
||||||
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
|
||||||
@ -890,10 +851,14 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
&mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
m_do_resync = false;
|
m_do_resync = false;
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
@ -922,17 +887,6 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
client = {};
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, -ENOENT);
|
|
||||||
|
|
||||||
// register missing client in remote journal
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
expect_journaler_register_client(mock_journaler, client_data, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
@ -942,7 +896,8 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
|
|||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
|
|
||||||
librbd::util::s_image_id = mock_local_image_ctx.id;
|
librbd::util::s_image_id = mock_local_image_ctx.id;
|
||||||
mirror_peer_client_meta = {mock_local_image_ctx.id};
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
|
||||||
|
mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
client_data.client_meta = mirror_peer_client_meta;
|
||||||
client.data.clear();
|
client.data.clear();
|
||||||
@ -968,10 +923,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, "",
|
&mock_instance_watcher, mock_journaler, "",
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
}
|
}
|
||||||
@ -998,16 +956,6 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
|
|||||||
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
expect_open_image(mock_open_image_request, m_remote_io_ctx,
|
||||||
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
|
||||||
|
|
||||||
// lookup local peer in remote journal
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
"missing image id"};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
|
||||||
client.data.clear();
|
|
||||||
::encode(client_data, client.data);
|
|
||||||
expect_journaler_get_client(mock_journaler, "local mirror uuid",
|
|
||||||
client, 0);
|
|
||||||
|
|
||||||
// test if remote image is primary
|
// test if remote image is primary
|
||||||
MockIsPrimaryRequest mock_is_primary_request;
|
MockIsPrimaryRequest mock_is_primary_request;
|
||||||
expect_is_primary(mock_is_primary_request, true, 0);
|
expect_is_primary(mock_is_primary_request, true, 0);
|
||||||
@ -1019,7 +967,8 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
|
|||||||
|
|
||||||
// re-register the client
|
// re-register the client
|
||||||
expect_journaler_unregister_client(mock_journaler, 0);
|
expect_journaler_unregister_client(mock_journaler, 0);
|
||||||
mirror_peer_client_meta = {};
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
|
||||||
|
mirror_peer_client_meta.image_id = "";
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
client_data.client_meta = mirror_peer_client_meta;
|
||||||
expect_journaler_register_client(mock_journaler, client_data, 0);
|
expect_journaler_register_client(mock_journaler, client_data, 0);
|
||||||
@ -1032,7 +981,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
|
|||||||
mock_local_image_ctx.journal = &mock_journal;
|
mock_local_image_ctx.journal = &mock_journal;
|
||||||
|
|
||||||
librbd::util::s_image_id = mock_local_image_ctx.id;
|
librbd::util::s_image_id = mock_local_image_ctx.id;
|
||||||
mirror_peer_client_meta = {mock_local_image_ctx.id};
|
mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
|
||||||
client_data.client_meta = mirror_peer_client_meta;
|
client_data.client_meta = mirror_peer_client_meta;
|
||||||
client.data.clear();
|
client.data.clear();
|
||||||
@ -1057,10 +1006,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
|
|||||||
|
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
MockInstanceWatcher mock_instance_watcher;
|
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(
|
MockBootstrapRequest *request = create_request(
|
||||||
&mock_instance_watcher, mock_journaler, "",
|
&mock_instance_watcher, mock_journaler, "missing image id",
|
||||||
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
|
||||||
"remote mirror uuid", &ctx);
|
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
|
||||||
request->send();
|
request->send();
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
#include "test/rbd_mirror/test_mock_fixture.h"
|
#include "test/rbd_mirror/test_mock_fixture.h"
|
||||||
#include "cls/rbd/cls_rbd_types.h"
|
#include "cls/rbd/cls_rbd_types.h"
|
||||||
#include "librbd/journal/TypeTraits.h"
|
#include "librbd/journal/TypeTraits.h"
|
||||||
|
#include "tools/rbd_mirror/Threads.h"
|
||||||
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
|
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
|
||||||
#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
|
#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
|
||||||
|
#include "test/journal/mock/MockJournaler.h"
|
||||||
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
|
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
|
||||||
#include "test/librbd/mock/MockImageCtx.h"
|
#include "test/librbd/mock/MockImageCtx.h"
|
||||||
|
|
||||||
@ -20,10 +22,32 @@ struct MockTestImageCtx : public librbd::MockImageCtx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace journal {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct TypeTraits<MockTestImageCtx> {
|
||||||
|
typedef ::journal::MockJournalerProxy Journaler;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace journal
|
||||||
} // namespace librbd
|
} // namespace librbd
|
||||||
|
|
||||||
namespace rbd {
|
namespace rbd {
|
||||||
namespace mirror {
|
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 {
|
namespace image_replayer {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -72,6 +96,7 @@ using ::testing::WithArg;
|
|||||||
|
|
||||||
class TestMockImageReplayerPrepareRemoteImageRequest : public TestMockFixture {
|
class TestMockImageReplayerPrepareRemoteImageRequest : public TestMockFixture {
|
||||||
public:
|
public:
|
||||||
|
typedef Threads<librbd::MockTestImageCtx> MockThreads;
|
||||||
typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
|
typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
|
||||||
typedef GetMirrorImageIdRequest<librbd::MockTestImageCtx> MockGetMirrorImageIdRequest;
|
typedef GetMirrorImageIdRequest<librbd::MockTestImageCtx> MockGetMirrorImageIdRequest;
|
||||||
|
|
||||||
@ -96,49 +121,160 @@ public:
|
|||||||
})),
|
})),
|
||||||
Return(r)));
|
Return(r)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expect_journaler_get_client(::journal::MockJournaler &mock_journaler,
|
||||||
|
const std::string &client_id,
|
||||||
|
cls::journal::Client &client, int r) {
|
||||||
|
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);
|
||||||
|
}))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void expect_journaler_register_client(::journal::MockJournaler &mock_journaler,
|
||||||
|
const librbd::journal::ClientData &client_data,
|
||||||
|
int r) {
|
||||||
|
bufferlist bl;
|
||||||
|
::encode(client_data, bl);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _))
|
||||||
|
.WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
|
||||||
|
m_threads->work_queue->queue(on_finish, r);
|
||||||
|
})));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) {
|
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) {
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
|
MockThreads mock_threads(m_threads);
|
||||||
|
|
||||||
InSequence seq;
|
InSequence seq;
|
||||||
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
||||||
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
||||||
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
|
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
|
||||||
"remote image id", 0);
|
"remote image id", 0);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_remote_journaler, construct());
|
||||||
|
|
||||||
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
|
||||||
|
mirror_peer_client_meta.image_id = "local image id";
|
||||||
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
|
||||||
|
librbd::journal::ClientData client_data{mirror_peer_client_meta};
|
||||||
|
cls::journal::Client client;
|
||||||
|
client.state = cls::journal::CLIENT_STATE_DISCONNECTED;
|
||||||
|
::encode(client_data, client.data);
|
||||||
|
expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
|
||||||
|
client, 0);
|
||||||
|
|
||||||
std::string remote_mirror_uuid;
|
std::string remote_mirror_uuid;
|
||||||
std::string remote_image_id;
|
std::string remote_image_id;
|
||||||
|
journal::MockJournalerProxy *remote_journaler = nullptr;
|
||||||
|
cls::journal::ClientState client_state;
|
||||||
|
librbd::journal::MirrorPeerClientMeta client_meta;
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
auto req = MockPrepareRemoteImageRequest::create(m_remote_io_ctx,
|
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
|
||||||
|
m_remote_io_ctx,
|
||||||
"global image id",
|
"global image id",
|
||||||
|
"local mirror uuid",
|
||||||
|
"local image id",
|
||||||
&remote_mirror_uuid,
|
&remote_mirror_uuid,
|
||||||
&remote_image_id,
|
&remote_image_id,
|
||||||
|
&remote_journaler,
|
||||||
|
&client_state, &client_meta,
|
||||||
&ctx);
|
&ctx);
|
||||||
req->send();
|
req->send();
|
||||||
|
|
||||||
ASSERT_EQ(0, ctx.wait());
|
ASSERT_EQ(0, ctx.wait());
|
||||||
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
||||||
ASSERT_EQ(std::string("remote image id"), remote_image_id);
|
ASSERT_EQ(std::string("remote image id"), remote_image_id);
|
||||||
|
ASSERT_TRUE(remote_journaler != nullptr);
|
||||||
|
ASSERT_EQ(cls::journal::CLIENT_STATE_DISCONNECTED, client_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) {
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
|
MockThreads mock_threads(m_threads);
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
||||||
|
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
||||||
|
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
|
||||||
|
"remote image id", 0);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_remote_journaler, construct());
|
||||||
|
|
||||||
|
cls::journal::Client client;
|
||||||
|
expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
|
||||||
|
client, -ENOENT);
|
||||||
|
|
||||||
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
|
||||||
|
mirror_peer_client_meta.image_id = "local image id";
|
||||||
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
|
librbd::journal::ClientData client_data{mirror_peer_client_meta};
|
||||||
|
expect_journaler_register_client(mock_remote_journaler, client_data, 0);
|
||||||
|
|
||||||
|
std::string remote_mirror_uuid;
|
||||||
|
std::string remote_image_id;
|
||||||
|
journal::MockJournalerProxy *remote_journaler = nullptr;
|
||||||
|
cls::journal::ClientState client_state;
|
||||||
|
librbd::journal::MirrorPeerClientMeta client_meta;
|
||||||
|
C_SaferCond ctx;
|
||||||
|
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
|
||||||
|
m_remote_io_ctx,
|
||||||
|
"global image id",
|
||||||
|
"local mirror uuid",
|
||||||
|
"local image id",
|
||||||
|
&remote_mirror_uuid,
|
||||||
|
&remote_image_id,
|
||||||
|
&remote_journaler,
|
||||||
|
&client_state, &client_meta,
|
||||||
|
&ctx);
|
||||||
|
req->send();
|
||||||
|
|
||||||
|
ASSERT_EQ(0, ctx.wait());
|
||||||
|
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
||||||
|
ASSERT_EQ(std::string("remote image id"), remote_image_id);
|
||||||
|
ASSERT_TRUE(remote_journaler != nullptr);
|
||||||
|
ASSERT_EQ(cls::journal::CLIENT_STATE_CONNECTED, client_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorUuidError) {
|
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorUuidError) {
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
|
MockThreads mock_threads(m_threads);
|
||||||
|
|
||||||
InSequence seq;
|
InSequence seq;
|
||||||
expect_mirror_uuid_get(m_remote_io_ctx, "", -EINVAL);
|
expect_mirror_uuid_get(m_remote_io_ctx, "", -EINVAL);
|
||||||
|
|
||||||
std::string remote_mirror_uuid;
|
std::string remote_mirror_uuid;
|
||||||
std::string remote_image_id;
|
std::string remote_image_id;
|
||||||
|
journal::MockJournalerProxy *remote_journaler = nullptr;
|
||||||
|
cls::journal::ClientState client_state;
|
||||||
|
librbd::journal::MirrorPeerClientMeta client_meta;
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
auto req = MockPrepareRemoteImageRequest::create(m_remote_io_ctx,
|
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
|
||||||
|
m_remote_io_ctx,
|
||||||
"global image id",
|
"global image id",
|
||||||
|
"local mirror uuid",
|
||||||
|
"",
|
||||||
&remote_mirror_uuid,
|
&remote_mirror_uuid,
|
||||||
&remote_image_id,
|
&remote_image_id,
|
||||||
|
&remote_journaler,
|
||||||
|
&client_state, &client_meta,
|
||||||
&ctx);
|
&ctx);
|
||||||
req->send();
|
req->send();
|
||||||
|
|
||||||
ASSERT_EQ(-EINVAL, ctx.wait());
|
ASSERT_EQ(-EINVAL, ctx.wait());
|
||||||
ASSERT_EQ(std::string(""), remote_mirror_uuid);
|
ASSERT_EQ(std::string(""), remote_mirror_uuid);
|
||||||
|
ASSERT_TRUE(remote_journaler == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
|
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
|
MockThreads mock_threads(m_threads);
|
||||||
|
|
||||||
InSequence seq;
|
InSequence seq;
|
||||||
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
||||||
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
||||||
@ -146,16 +282,111 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
|
|||||||
|
|
||||||
std::string remote_mirror_uuid;
|
std::string remote_mirror_uuid;
|
||||||
std::string remote_image_id;
|
std::string remote_image_id;
|
||||||
|
journal::MockJournalerProxy *remote_journaler = nullptr;
|
||||||
|
cls::journal::ClientState client_state;
|
||||||
|
librbd::journal::MirrorPeerClientMeta client_meta;
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
auto req = MockPrepareRemoteImageRequest::create(m_remote_io_ctx,
|
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
|
||||||
|
m_remote_io_ctx,
|
||||||
"global image id",
|
"global image id",
|
||||||
|
"local mirror uuid",
|
||||||
|
"",
|
||||||
&remote_mirror_uuid,
|
&remote_mirror_uuid,
|
||||||
&remote_image_id,
|
&remote_image_id,
|
||||||
|
&remote_journaler,
|
||||||
|
&client_state, &client_meta,
|
||||||
&ctx);
|
&ctx);
|
||||||
req->send();
|
req->send();
|
||||||
|
|
||||||
ASSERT_EQ(-EINVAL, ctx.wait());
|
ASSERT_EQ(-EINVAL, ctx.wait());
|
||||||
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
||||||
|
ASSERT_TRUE(remote_journaler == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) {
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
|
MockThreads mock_threads(m_threads);
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
||||||
|
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
||||||
|
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
|
||||||
|
"remote image id", 0);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_remote_journaler, construct());
|
||||||
|
|
||||||
|
cls::journal::Client client;
|
||||||
|
expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
|
||||||
|
client, -EINVAL);
|
||||||
|
|
||||||
|
std::string remote_mirror_uuid;
|
||||||
|
std::string remote_image_id;
|
||||||
|
journal::MockJournalerProxy *remote_journaler = nullptr;
|
||||||
|
cls::journal::ClientState client_state;
|
||||||
|
librbd::journal::MirrorPeerClientMeta client_meta;
|
||||||
|
C_SaferCond ctx;
|
||||||
|
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
|
||||||
|
m_remote_io_ctx,
|
||||||
|
"global image id",
|
||||||
|
"local mirror uuid",
|
||||||
|
"local image id",
|
||||||
|
&remote_mirror_uuid,
|
||||||
|
&remote_image_id,
|
||||||
|
&remote_journaler,
|
||||||
|
&client_state, &client_meta,
|
||||||
|
&ctx);
|
||||||
|
req->send();
|
||||||
|
|
||||||
|
ASSERT_EQ(-EINVAL, ctx.wait());
|
||||||
|
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
||||||
|
ASSERT_EQ(std::string("remote image id"), remote_image_id);
|
||||||
|
ASSERT_TRUE(remote_journaler == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) {
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
|
MockThreads mock_threads(m_threads);
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
|
||||||
|
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
|
||||||
|
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
|
||||||
|
"remote image id", 0);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_remote_journaler, construct());
|
||||||
|
|
||||||
|
cls::journal::Client client;
|
||||||
|
expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
|
||||||
|
client, -ENOENT);
|
||||||
|
|
||||||
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
|
||||||
|
mirror_peer_client_meta.image_id = "local image id";
|
||||||
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
|
librbd::journal::ClientData client_data{mirror_peer_client_meta};
|
||||||
|
expect_journaler_register_client(mock_remote_journaler, client_data, -EINVAL);
|
||||||
|
|
||||||
|
std::string remote_mirror_uuid;
|
||||||
|
std::string remote_image_id;
|
||||||
|
journal::MockJournalerProxy *remote_journaler = nullptr;
|
||||||
|
cls::journal::ClientState client_state;
|
||||||
|
librbd::journal::MirrorPeerClientMeta client_meta;
|
||||||
|
C_SaferCond ctx;
|
||||||
|
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
|
||||||
|
m_remote_io_ctx,
|
||||||
|
"global image id",
|
||||||
|
"local mirror uuid",
|
||||||
|
"local image id",
|
||||||
|
&remote_mirror_uuid,
|
||||||
|
&remote_image_id,
|
||||||
|
&remote_journaler,
|
||||||
|
&client_state, &client_meta,
|
||||||
|
&ctx);
|
||||||
|
req->send();
|
||||||
|
|
||||||
|
ASSERT_EQ(-EINVAL, ctx.wait());
|
||||||
|
ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
|
||||||
|
ASSERT_EQ(std::string("remote image id"), remote_image_id);
|
||||||
|
ASSERT_TRUE(remote_journaler == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace image_replayer
|
} // namespace image_replayer
|
||||||
|
@ -141,16 +141,28 @@ struct PrepareRemoteImageRequest<librbd::MockTestImageCtx> {
|
|||||||
static PrepareRemoteImageRequest* s_instance;
|
static PrepareRemoteImageRequest* s_instance;
|
||||||
std::string *remote_mirror_uuid = nullptr;
|
std::string *remote_mirror_uuid = nullptr;
|
||||||
std::string *remote_image_id = 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;
|
Context *on_finish = nullptr;
|
||||||
|
|
||||||
static PrepareRemoteImageRequest* create(librados::IoCtx &,
|
static PrepareRemoteImageRequest* create(Threads<librbd::MockTestImageCtx> *threads,
|
||||||
|
librados::IoCtx &,
|
||||||
const std::string &global_image_id,
|
const std::string &global_image_id,
|
||||||
|
const std::string &local_mirror_uuid,
|
||||||
|
const std::string &local_image_id,
|
||||||
std::string *remote_mirror_uuid,
|
std::string *remote_mirror_uuid,
|
||||||
std::string *remote_image_id,
|
std::string *remote_image_id,
|
||||||
|
::journal::MockJournalerProxy **remote_journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
|
librbd::journal::MirrorPeerClientMeta *client_meta,
|
||||||
Context *on_finish) {
|
Context *on_finish) {
|
||||||
assert(s_instance != nullptr);
|
assert(s_instance != nullptr);
|
||||||
s_instance->remote_mirror_uuid = remote_mirror_uuid;
|
s_instance->remote_mirror_uuid = remote_mirror_uuid;
|
||||||
s_instance->remote_image_id = remote_image_id;
|
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;
|
s_instance->on_finish = on_finish;
|
||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
@ -179,6 +191,7 @@ struct BootstrapRequest<librbd::MockTestImageCtx> {
|
|||||||
const std::string &local_mirror_uuid,
|
const std::string &local_mirror_uuid,
|
||||||
const std::string &remote_mirror_uuid,
|
const std::string &remote_mirror_uuid,
|
||||||
::journal::MockJournalerProxy *journaler,
|
::journal::MockJournalerProxy *journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
librbd::journal::MirrorPeerClientMeta *client_meta,
|
librbd::journal::MirrorPeerClientMeta *client_meta,
|
||||||
Context *on_finish, bool *do_resync,
|
Context *on_finish, bool *do_resync,
|
||||||
rbd::mirror::ProgressContext *progress_ctx = nullptr) {
|
rbd::mirror::ProgressContext *progress_ctx = nullptr) {
|
||||||
@ -422,6 +435,10 @@ public:
|
|||||||
int r) {
|
int r) {
|
||||||
EXPECT_CALL(mock_request, send())
|
EXPECT_CALL(mock_request, send())
|
||||||
.WillOnce(Invoke([&mock_request, image_id, mirror_uuid, r]() {
|
.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_mirror_uuid = mirror_uuid;
|
||||||
*mock_request.remote_image_id = image_id;
|
*mock_request.remote_image_id = image_id;
|
||||||
mock_request.on_finish->complete(r);
|
mock_request.on_finish->complete(r);
|
||||||
@ -650,12 +667,14 @@ TEST_F(TestMockImageReplayer, LocalImagePrimary) {
|
|||||||
create_local_image();
|
create_local_image();
|
||||||
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
|
||||||
|
|
||||||
|
journal::MockJournaler mock_remote_journaler;
|
||||||
MockThreads mock_threads(m_threads);
|
MockThreads mock_threads(m_threads);
|
||||||
expect_work_queue_repeatedly(mock_threads);
|
expect_work_queue_repeatedly(mock_threads);
|
||||||
expect_add_event_after_repeatedly(mock_threads);
|
expect_add_event_after_repeatedly(mock_threads);
|
||||||
|
|
||||||
MockImageDeleter mock_image_deleter;
|
MockImageDeleter mock_image_deleter;
|
||||||
MockPrepareLocalImageRequest mock_prepare_local_image_request;
|
MockPrepareLocalImageRequest mock_prepare_local_image_request;
|
||||||
|
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
|
||||||
MockReplayStatusFormatter mock_replay_status_formatter;
|
MockReplayStatusFormatter mock_replay_status_formatter;
|
||||||
|
|
||||||
expect_get_or_send_update(mock_replay_status_formatter);
|
expect_get_or_send_update(mock_replay_status_formatter);
|
||||||
@ -664,6 +683,11 @@ TEST_F(TestMockImageReplayer, LocalImagePrimary) {
|
|||||||
expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
|
expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
|
||||||
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
|
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
|
||||||
"", 0);
|
"", 0);
|
||||||
|
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
|
||||||
|
"remote image id", 0);
|
||||||
|
EXPECT_CALL(mock_remote_journaler, construct());
|
||||||
|
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
|
||||||
|
expect_shut_down(mock_remote_journaler, 0);
|
||||||
|
|
||||||
create_image_replayer(mock_threads, mock_image_deleter);
|
create_image_replayer(mock_threads, mock_image_deleter);
|
||||||
|
|
||||||
|
@ -440,10 +440,6 @@ void ImageReplayer<I>::handle_prepare_local_image(int r) {
|
|||||||
} else if (r < 0) {
|
} else if (r < 0) {
|
||||||
on_start_fail(r, "error preparing local image for replay");
|
on_start_fail(r, "error preparing local image for replay");
|
||||||
return;
|
return;
|
||||||
} else if (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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// local image doesn't exist or is non-primary
|
// local image doesn't exist or is non-primary
|
||||||
@ -453,6 +449,11 @@ void ImageReplayer<I>::handle_prepare_local_image(int r) {
|
|||||||
template <typename I>
|
template <typename I>
|
||||||
void ImageReplayer<I>::prepare_remote_image() {
|
void ImageReplayer<I>::prepare_remote_image() {
|
||||||
dout(20) << dendl;
|
dout(20) << dendl;
|
||||||
|
if (m_peers.empty()) {
|
||||||
|
// technically nothing to bootstrap, but it handles the status update
|
||||||
|
bootstrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO need to support multiple remote images
|
// TODO need to support multiple remote images
|
||||||
assert(!m_peers.empty());
|
assert(!m_peers.empty());
|
||||||
@ -461,8 +462,9 @@ void ImageReplayer<I>::prepare_remote_image() {
|
|||||||
Context *ctx = create_context_callback<
|
Context *ctx = create_context_callback<
|
||||||
ImageReplayer, &ImageReplayer<I>::handle_prepare_remote_image>(this);
|
ImageReplayer, &ImageReplayer<I>::handle_prepare_remote_image>(this);
|
||||||
auto req = PrepareRemoteImageRequest<I>::create(
|
auto req = PrepareRemoteImageRequest<I>::create(
|
||||||
m_remote_image.io_ctx, m_global_image_id, &m_remote_image.mirror_uuid,
|
m_threads, m_remote_image.io_ctx, m_global_image_id, m_local_mirror_uuid,
|
||||||
&m_remote_image.image_id, ctx);
|
m_local_image_id, &m_remote_image.mirror_uuid, &m_remote_image.image_id,
|
||||||
|
&m_remote_journaler, &m_client_state, &m_client_meta, ctx);
|
||||||
req->send();
|
req->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +472,11 @@ template <typename I>
|
|||||||
void ImageReplayer<I>::handle_prepare_remote_image(int r) {
|
void ImageReplayer<I>::handle_prepare_remote_image(int r) {
|
||||||
dout(20) << "r=" << r << dendl;
|
dout(20) << "r=" << r << dendl;
|
||||||
|
|
||||||
if (r == -ENOENT) {
|
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(20) << "remote image does not exist" << dendl;
|
dout(20) << "remote image does not exist" << dendl;
|
||||||
|
|
||||||
// TODO need to support multiple remote images
|
// TODO need to support multiple remote images
|
||||||
@ -497,19 +503,16 @@ template <typename I>
|
|||||||
void ImageReplayer<I>::bootstrap() {
|
void ImageReplayer<I>::bootstrap() {
|
||||||
dout(20) << dendl;
|
dout(20) << dendl;
|
||||||
|
|
||||||
CephContext *cct = static_cast<CephContext *>(m_local->cct());
|
if (!m_local_image_id.empty() &&
|
||||||
journal::Settings settings;
|
m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
|
||||||
settings.commit_interval = cct->_conf->get_val<double>(
|
dout(5) << "local image is primary" << dendl;
|
||||||
"rbd_mirror_journal_commit_age");
|
on_start_fail(0, "local image is primary");
|
||||||
settings.max_fetch_bytes = cct->_conf->get_val<uint64_t>(
|
return;
|
||||||
"rbd_mirror_journal_max_fetch_bytes");
|
} else if (m_peers.empty()) {
|
||||||
|
dout(5) << "no peer clusters" << dendl;
|
||||||
m_remote_journaler = new Journaler(m_threads->work_queue,
|
on_start_fail(-ENOENT, "no peer clusters");
|
||||||
m_threads->timer,
|
return;
|
||||||
&m_threads->timer_lock,
|
}
|
||||||
m_remote_image.io_ctx,
|
|
||||||
m_remote_image.image_id,
|
|
||||||
m_local_mirror_uuid, settings);
|
|
||||||
|
|
||||||
Context *ctx = create_context_callback<
|
Context *ctx = create_context_callback<
|
||||||
ImageReplayer, &ImageReplayer<I>::handle_bootstrap>(this);
|
ImageReplayer, &ImageReplayer<I>::handle_bootstrap>(this);
|
||||||
@ -519,8 +522,8 @@ void ImageReplayer<I>::bootstrap() {
|
|||||||
&m_local_image_ctx, m_local_image_id, m_remote_image.image_id,
|
&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_global_image_id, m_threads->work_queue, m_threads->timer,
|
||||||
&m_threads->timer_lock, m_local_mirror_uuid, m_remote_image.mirror_uuid,
|
&m_threads->timer_lock, m_local_mirror_uuid, m_remote_image.mirror_uuid,
|
||||||
m_remote_journaler, &m_client_meta, ctx, &m_resync_requested,
|
m_remote_journaler, &m_client_state, &m_client_meta, ctx,
|
||||||
&m_progress_cxt);
|
&m_resync_requested, &m_progress_cxt);
|
||||||
|
|
||||||
{
|
{
|
||||||
Mutex::Locker locker(m_lock);
|
Mutex::Locker locker(m_lock);
|
||||||
|
@ -331,6 +331,8 @@ private:
|
|||||||
bool m_update_status_requested = false;
|
bool m_update_status_requested = false;
|
||||||
Context *m_on_update_status_finish = nullptr;
|
Context *m_on_update_status_finish = nullptr;
|
||||||
|
|
||||||
|
cls::journal::ClientState m_client_state =
|
||||||
|
cls::journal::CLIENT_STATE_DISCONNECTED;
|
||||||
librbd::journal::MirrorPeerClientMeta m_client_meta;
|
librbd::journal::MirrorPeerClientMeta m_client_meta;
|
||||||
|
|
||||||
ReplayEntry m_replay_entry;
|
ReplayEntry m_replay_entry;
|
||||||
|
@ -51,6 +51,7 @@ BootstrapRequest<I>::BootstrapRequest(
|
|||||||
const std::string &local_mirror_uuid,
|
const std::string &local_mirror_uuid,
|
||||||
const std::string &remote_mirror_uuid,
|
const std::string &remote_mirror_uuid,
|
||||||
Journaler *journaler,
|
Journaler *journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
MirrorPeerClientMeta *client_meta,
|
MirrorPeerClientMeta *client_meta,
|
||||||
Context *on_finish,
|
Context *on_finish,
|
||||||
bool *do_resync,
|
bool *do_resync,
|
||||||
@ -64,8 +65,8 @@ BootstrapRequest<I>::BootstrapRequest(
|
|||||||
m_timer(timer), m_timer_lock(timer_lock),
|
m_timer(timer), m_timer_lock(timer_lock),
|
||||||
m_local_mirror_uuid(local_mirror_uuid),
|
m_local_mirror_uuid(local_mirror_uuid),
|
||||||
m_remote_mirror_uuid(remote_mirror_uuid), m_journaler(journaler),
|
m_remote_mirror_uuid(remote_mirror_uuid), m_journaler(journaler),
|
||||||
m_client_meta(client_meta), m_progress_ctx(progress_ctx),
|
m_client_state(client_state), m_client_meta(client_meta),
|
||||||
m_do_resync(do_resync),
|
m_progress_ctx(progress_ctx), m_do_resync(do_resync),
|
||||||
m_lock(unique_lock_name("BootstrapRequest::m_lock", this)) {
|
m_lock(unique_lock_name("BootstrapRequest::m_lock", this)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,77 +173,6 @@ void BootstrapRequest<I>::handle_open_remote_image(int r) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_client();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename I>
|
|
||||||
void BootstrapRequest<I>::get_client() {
|
|
||||||
dout(20) << dendl;
|
|
||||||
|
|
||||||
update_progress("GET_CLIENT");
|
|
||||||
|
|
||||||
Context *ctx = create_context_callback<
|
|
||||||
BootstrapRequest<I>, &BootstrapRequest<I>::handle_get_client>(
|
|
||||||
this);
|
|
||||||
m_journaler->get_client(m_local_mirror_uuid, &m_client, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename I>
|
|
||||||
void BootstrapRequest<I>::handle_get_client(int r) {
|
|
||||||
dout(20) << ": r=" << r << dendl;
|
|
||||||
|
|
||||||
if (r == -ENOENT) {
|
|
||||||
dout(10) << ": client not registered" << dendl;
|
|
||||||
} else if (r < 0) {
|
|
||||||
derr << ": failed to retrieve client: " << cpp_strerror(r) << dendl;
|
|
||||||
m_ret_val = r;
|
|
||||||
close_remote_image();
|
|
||||||
return;
|
|
||||||
} else if (decode_client_meta()) {
|
|
||||||
// skip registration if it already exists
|
|
||||||
is_primary();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_client();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename I>
|
|
||||||
void BootstrapRequest<I>::register_client() {
|
|
||||||
dout(20) << dendl;
|
|
||||||
|
|
||||||
update_progress("REGISTER_CLIENT");
|
|
||||||
|
|
||||||
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
|
||||||
m_local_image_id};
|
|
||||||
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
|
|
||||||
librbd::journal::ClientData client_data{mirror_peer_client_meta};
|
|
||||||
bufferlist client_data_bl;
|
|
||||||
::encode(client_data, client_data_bl);
|
|
||||||
|
|
||||||
Context *ctx = create_context_callback<
|
|
||||||
BootstrapRequest<I>, &BootstrapRequest<I>::handle_register_client>(
|
|
||||||
this);
|
|
||||||
m_journaler->register_client(client_data_bl, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename I>
|
|
||||||
void BootstrapRequest<I>::handle_register_client(int r) {
|
|
||||||
dout(20) << ": r=" << r << dendl;
|
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
derr << ": failed to register with remote journal: " << cpp_strerror(r)
|
|
||||||
<< dendl;
|
|
||||||
m_ret_val = r;
|
|
||||||
close_remote_image();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_client = {};
|
|
||||||
*m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
|
|
||||||
m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
|
||||||
|
|
||||||
is_primary();
|
is_primary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,6 +210,12 @@ void BootstrapRequest<I>::handle_is_primary(int r) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_local_image_id.empty()) {
|
if (m_local_image_id.empty()) {
|
||||||
update_client_image();
|
update_client_image();
|
||||||
return;
|
return;
|
||||||
@ -386,7 +322,7 @@ void BootstrapRequest<I>::handle_open_local_image(int r) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_client.state == cls::journal::CLIENT_STATE_DISCONNECTED) {
|
if (*m_client_state == cls::journal::CLIENT_STATE_DISCONNECTED) {
|
||||||
dout(10) << ": client flagged disconnected -- skipping bootstrap" << dendl;
|
dout(10) << ": client flagged disconnected -- skipping bootstrap" << dendl;
|
||||||
// The caller is expected to detect disconnect initializing remote journal.
|
// The caller is expected to detect disconnect initializing remote journal.
|
||||||
m_ret_val = 0;
|
m_ret_val = 0;
|
||||||
@ -424,6 +360,45 @@ void BootstrapRequest<I>::handle_unregister_client(int r) {
|
|||||||
register_client();
|
register_client();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
void BootstrapRequest<I>::register_client() {
|
||||||
|
dout(20) << dendl;
|
||||||
|
|
||||||
|
update_progress("REGISTER_CLIENT");
|
||||||
|
|
||||||
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
||||||
|
m_local_image_id};
|
||||||
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
|
|
||||||
|
librbd::journal::ClientData client_data{mirror_peer_client_meta};
|
||||||
|
bufferlist client_data_bl;
|
||||||
|
::encode(client_data, client_data_bl);
|
||||||
|
|
||||||
|
Context *ctx = create_context_callback<
|
||||||
|
BootstrapRequest<I>, &BootstrapRequest<I>::handle_register_client>(
|
||||||
|
this);
|
||||||
|
m_journaler->register_client(client_data_bl, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
void BootstrapRequest<I>::handle_register_client(int r) {
|
||||||
|
dout(20) << ": r=" << r << dendl;
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
derr << ": failed to register with remote journal: " << cpp_strerror(r)
|
||||||
|
<< dendl;
|
||||||
|
m_ret_val = r;
|
||||||
|
close_remote_image();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
|
||||||
|
*m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
|
||||||
|
m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
|
|
||||||
|
is_primary();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
void BootstrapRequest<I>::update_client_image() {
|
void BootstrapRequest<I>::update_client_image() {
|
||||||
dout(20) << dendl;
|
dout(20) << dendl;
|
||||||
@ -769,36 +744,6 @@ void BootstrapRequest<I>::handle_close_remote_image(int r) {
|
|||||||
finish(m_ret_val);
|
finish(m_ret_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename I>
|
|
||||||
bool BootstrapRequest<I>::decode_client_meta() {
|
|
||||||
dout(20) << dendl;
|
|
||||||
|
|
||||||
librbd::journal::ClientData client_data;
|
|
||||||
bufferlist::iterator it = m_client.data.begin();
|
|
||||||
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;
|
|
||||||
} else if (!client_meta->image_id.empty()) {
|
|
||||||
// have an image id -- use that to open the image
|
|
||||||
m_local_image_id = client_meta->image_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
*m_client_meta = *client_meta;
|
|
||||||
|
|
||||||
dout(20) << ": client found: image_id=" << m_local_image_id
|
|
||||||
<< ", client_meta=" << *m_client_meta << dendl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
void BootstrapRequest<I>::update_progress(const std::string &description) {
|
void BootstrapRequest<I>::update_progress(const std::string &description) {
|
||||||
dout(20) << ": " << description << dendl;
|
dout(20) << ": " << description << dendl;
|
||||||
|
@ -53,6 +53,7 @@ public:
|
|||||||
const std::string &local_mirror_uuid,
|
const std::string &local_mirror_uuid,
|
||||||
const std::string &remote_mirror_uuid,
|
const std::string &remote_mirror_uuid,
|
||||||
Journaler *journaler,
|
Journaler *journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
MirrorPeerClientMeta *client_meta,
|
MirrorPeerClientMeta *client_meta,
|
||||||
Context *on_finish,
|
Context *on_finish,
|
||||||
bool *do_resync,
|
bool *do_resync,
|
||||||
@ -62,8 +63,8 @@ public:
|
|||||||
local_image_id, remote_image_id,
|
local_image_id, remote_image_id,
|
||||||
global_image_id, work_queue, timer, timer_lock,
|
global_image_id, work_queue, timer, timer_lock,
|
||||||
local_mirror_uuid, remote_mirror_uuid,
|
local_mirror_uuid, remote_mirror_uuid,
|
||||||
journaler, client_meta, on_finish, do_resync,
|
journaler, client_state, client_meta, on_finish,
|
||||||
progress_ctx);
|
do_resync, progress_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
BootstrapRequest(librados::IoCtx &local_io_ctx,
|
BootstrapRequest(librados::IoCtx &local_io_ctx,
|
||||||
@ -76,6 +77,7 @@ public:
|
|||||||
SafeTimer *timer, Mutex *timer_lock,
|
SafeTimer *timer, Mutex *timer_lock,
|
||||||
const std::string &local_mirror_uuid,
|
const std::string &local_mirror_uuid,
|
||||||
const std::string &remote_mirror_uuid, Journaler *journaler,
|
const std::string &remote_mirror_uuid, Journaler *journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
MirrorPeerClientMeta *client_meta, Context *on_finish,
|
MirrorPeerClientMeta *client_meta, Context *on_finish,
|
||||||
bool *do_resync, ProgressContext *progress_ctx = nullptr);
|
bool *do_resync, ProgressContext *progress_ctx = nullptr);
|
||||||
~BootstrapRequest() override;
|
~BootstrapRequest() override;
|
||||||
@ -97,14 +99,8 @@ private:
|
|||||||
* v *
|
* v *
|
||||||
* OPEN_REMOTE_IMAGE * * * * * * * * * * * * * * * * * * *
|
* OPEN_REMOTE_IMAGE * * * * * * * * * * * * * * * * * * *
|
||||||
* | *
|
* | *
|
||||||
* v *
|
* |/--------------------------------------------------*---\
|
||||||
* GET_CLIENT * * * * * * * * * * * * * * * * * * * * * *
|
* v * |
|
||||||
* | * *
|
|
||||||
* |/----------------------------------------------*---*---\
|
|
||||||
* v (skip if not needed) * * |
|
|
||||||
* REGISTER_CLIENT * * * * * * * * * * * * * * * * * * * |
|
|
||||||
* | * * |
|
|
||||||
* v * * |
|
|
||||||
* IS_PRIMARY * * * * * * * * * * * * * * * * * * * * * * |
|
* IS_PRIMARY * * * * * * * * * * * * * * * * * * * * * * |
|
||||||
* | * * |
|
* | * * |
|
||||||
* | (remote image primary, no local image id) * * |
|
* | (remote image primary, no local image id) * * |
|
||||||
@ -120,6 +116,9 @@ private:
|
|||||||
* | | . (image doesn't exist) * * |
|
* | | . (image doesn't exist) * * |
|
||||||
* | | . . > UNREGISTER_CLIENT * * * * * * * |
|
* | | . . > UNREGISTER_CLIENT * * * * * * * |
|
||||||
* | | | * * |
|
* | | | * * |
|
||||||
|
* | | v * * |
|
||||||
|
* | | REGISTER_CLIENT * * * * * * * * |
|
||||||
|
* | | | * * |
|
||||||
* | | \-----------------------*---*---/
|
* | | \-----------------------*---*---/
|
||||||
* | | * *
|
* | | * *
|
||||||
* | v (skip if not needed) * *
|
* | v (skip if not needed) * *
|
||||||
@ -159,6 +158,7 @@ private:
|
|||||||
std::string m_local_mirror_uuid;
|
std::string m_local_mirror_uuid;
|
||||||
std::string m_remote_mirror_uuid;
|
std::string m_remote_mirror_uuid;
|
||||||
Journaler *m_journaler;
|
Journaler *m_journaler;
|
||||||
|
cls::journal::ClientState *m_client_state;
|
||||||
MirrorPeerClientMeta *m_client_meta;
|
MirrorPeerClientMeta *m_client_meta;
|
||||||
ProgressContext *m_progress_ctx;
|
ProgressContext *m_progress_ctx;
|
||||||
bool *m_do_resync;
|
bool *m_do_resync;
|
||||||
@ -179,12 +179,6 @@ private:
|
|||||||
void get_remote_tag_class();
|
void get_remote_tag_class();
|
||||||
void handle_get_remote_tag_class(int r);
|
void handle_get_remote_tag_class(int r);
|
||||||
|
|
||||||
void get_client();
|
|
||||||
void handle_get_client(int r);
|
|
||||||
|
|
||||||
void register_client();
|
|
||||||
void handle_register_client(int r);
|
|
||||||
|
|
||||||
void open_remote_image();
|
void open_remote_image();
|
||||||
void handle_open_remote_image(int r);
|
void handle_open_remote_image(int r);
|
||||||
|
|
||||||
@ -200,6 +194,9 @@ private:
|
|||||||
void unregister_client();
|
void unregister_client();
|
||||||
void handle_unregister_client(int r);
|
void handle_unregister_client(int r);
|
||||||
|
|
||||||
|
void register_client();
|
||||||
|
void handle_register_client(int r);
|
||||||
|
|
||||||
void create_local_image();
|
void create_local_image();
|
||||||
void handle_create_local_image(int r);
|
void handle_create_local_image(int r);
|
||||||
|
|
||||||
@ -218,8 +215,6 @@ private:
|
|||||||
void close_remote_image();
|
void close_remote_image();
|
||||||
void handle_close_remote_image(int r);
|
void handle_close_remote_image(int r);
|
||||||
|
|
||||||
bool decode_client_meta();
|
|
||||||
|
|
||||||
void update_progress(const std::string &description);
|
void update_progress(const std::string &description);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,8 +5,13 @@
|
|||||||
#include "include/rados/librados.hpp"
|
#include "include/rados/librados.hpp"
|
||||||
#include "cls/rbd/cls_rbd_client.h"
|
#include "cls/rbd/cls_rbd_client.h"
|
||||||
#include "common/errno.h"
|
#include "common/errno.h"
|
||||||
|
#include "common/WorkQueue.h"
|
||||||
|
#include "journal/Journaler.h"
|
||||||
|
#include "journal/Settings.h"
|
||||||
#include "librbd/ImageCtx.h"
|
#include "librbd/ImageCtx.h"
|
||||||
#include "librbd/Utils.h"
|
#include "librbd/Utils.h"
|
||||||
|
#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/GetMirrorImageIdRequest.h"
|
||||||
|
|
||||||
#define dout_context g_ceph_context
|
#define dout_context g_ceph_context
|
||||||
@ -20,6 +25,7 @@ namespace rbd {
|
|||||||
namespace mirror {
|
namespace mirror {
|
||||||
namespace image_replayer {
|
namespace image_replayer {
|
||||||
|
|
||||||
|
using librbd::util::create_async_context_callback;
|
||||||
using librbd::util::create_context_callback;
|
using librbd::util::create_context_callback;
|
||||||
using librbd::util::create_rados_callback;
|
using librbd::util::create_rados_callback;
|
||||||
|
|
||||||
@ -38,7 +44,7 @@ void PrepareRemoteImageRequest<I>::get_remote_mirror_uuid() {
|
|||||||
librados::AioCompletion *aio_comp = create_rados_callback<
|
librados::AioCompletion *aio_comp = create_rados_callback<
|
||||||
PrepareRemoteImageRequest<I>,
|
PrepareRemoteImageRequest<I>,
|
||||||
&PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid>(this);
|
&PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid>(this);
|
||||||
int r = m_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
|
int r = m_remote_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
aio_comp->release();
|
aio_comp->release();
|
||||||
}
|
}
|
||||||
@ -75,7 +81,8 @@ void PrepareRemoteImageRequest<I>::get_remote_image_id() {
|
|||||||
Context *ctx = create_context_callback<
|
Context *ctx = create_context_callback<
|
||||||
PrepareRemoteImageRequest<I>,
|
PrepareRemoteImageRequest<I>,
|
||||||
&PrepareRemoteImageRequest<I>::handle_get_remote_image_id>(this);
|
&PrepareRemoteImageRequest<I>::handle_get_remote_image_id>(this);
|
||||||
auto req = GetMirrorImageIdRequest<I>::create(m_io_ctx, m_global_image_id,
|
auto req = GetMirrorImageIdRequest<I>::create(m_remote_io_ctx,
|
||||||
|
m_global_image_id,
|
||||||
m_remote_image_id, ctx);
|
m_remote_image_id, ctx);
|
||||||
req->send();
|
req->send();
|
||||||
}
|
}
|
||||||
@ -90,13 +97,125 @@ void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_client();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
void PrepareRemoteImageRequest<I>::get_client() {
|
||||||
|
dout(20) << dendl;
|
||||||
|
|
||||||
|
journal::Settings settings;
|
||||||
|
settings.commit_interval = g_ceph_context->_conf->get_val<double>(
|
||||||
|
"rbd_mirror_journal_commit_age");
|
||||||
|
settings.max_fetch_bytes = g_ceph_context->_conf->get_val<uint64_t>(
|
||||||
|
"rbd_mirror_journal_max_fetch_bytes");
|
||||||
|
|
||||||
|
assert(*m_remote_journaler == nullptr);
|
||||||
|
*m_remote_journaler = new Journaler(m_threads->work_queue, m_threads->timer,
|
||||||
|
&m_threads->timer_lock, m_remote_io_ctx,
|
||||||
|
*m_remote_image_id, m_local_mirror_uuid,
|
||||||
|
settings);
|
||||||
|
|
||||||
|
Context *ctx = create_async_context_callback(
|
||||||
|
m_threads->work_queue, create_context_callback<
|
||||||
|
PrepareRemoteImageRequest<I>,
|
||||||
|
&PrepareRemoteImageRequest<I>::handle_get_client>(this));
|
||||||
|
(*m_remote_journaler)->get_client(m_local_mirror_uuid, &m_client, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
void PrepareRemoteImageRequest<I>::handle_get_client(int r) {
|
||||||
|
dout(20) << "r=" << r << dendl;
|
||||||
|
|
||||||
|
if (r == -ENOENT) {
|
||||||
|
dout(10) << "client not registered" << dendl;
|
||||||
|
} else if (r < 0) {
|
||||||
|
derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
|
||||||
|
finish(r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_client_state = m_client.state;
|
||||||
|
if (decode_client_meta()) {
|
||||||
|
// skip registration if it already exists
|
||||||
|
finish(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_client();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
void PrepareRemoteImageRequest<I>::register_client() {
|
||||||
|
dout(20) << dendl;
|
||||||
|
|
||||||
|
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
|
||||||
|
m_local_image_id};
|
||||||
|
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
|
|
||||||
|
librbd::journal::ClientData client_data{mirror_peer_client_meta};
|
||||||
|
bufferlist client_data_bl;
|
||||||
|
::encode(client_data, client_data_bl);
|
||||||
|
|
||||||
|
Context *ctx = create_async_context_callback(
|
||||||
|
m_threads->work_queue, create_context_callback<
|
||||||
|
PrepareRemoteImageRequest<I>,
|
||||||
|
&PrepareRemoteImageRequest<I>::handle_register_client>(this));
|
||||||
|
(*m_remote_journaler)->register_client(client_data_bl, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
void PrepareRemoteImageRequest<I>::handle_register_client(int r) {
|
||||||
|
dout(20) << "r=" << r << dendl;
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
derr << "failed to register with remote journal: " << cpp_strerror(r)
|
||||||
|
<< dendl;
|
||||||
|
finish(r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
|
||||||
|
*m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
|
||||||
|
m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
|
||||||
|
|
||||||
finish(0);
|
finish(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
bool PrepareRemoteImageRequest<I>::decode_client_meta() {
|
||||||
|
dout(20) << dendl;
|
||||||
|
|
||||||
|
librbd::journal::ClientData client_data;
|
||||||
|
bufferlist::iterator it = m_client.data.begin();
|
||||||
|
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>
|
template <typename I>
|
||||||
void PrepareRemoteImageRequest<I>::finish(int r) {
|
void PrepareRemoteImageRequest<I>::finish(int r) {
|
||||||
dout(20) << "r=" << r << dendl;
|
dout(20) << "r=" << r << dendl;
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
delete *m_remote_journaler;
|
||||||
|
*m_remote_journaler = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_on_finish->complete(r);
|
m_on_finish->complete(r);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
@ -5,40 +5,68 @@
|
|||||||
#define RBD_MIRROR_IMAGE_REPLAYER_PREPARE_REMOTE_IMAGE_REQUEST_H
|
#define RBD_MIRROR_IMAGE_REPLAYER_PREPARE_REMOTE_IMAGE_REQUEST_H
|
||||||
|
|
||||||
#include "include/buffer.h"
|
#include "include/buffer.h"
|
||||||
|
#include "cls/journal/cls_journal_types.h"
|
||||||
|
#include "librbd/journal/TypeTraits.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
namespace journal { class Journaler; }
|
||||||
namespace librados { struct IoCtx; }
|
namespace librados { struct IoCtx; }
|
||||||
namespace librbd { struct ImageCtx; }
|
namespace librbd { struct ImageCtx; }
|
||||||
|
namespace librbd { namespace journal { struct MirrorPeerClientMeta; } }
|
||||||
|
|
||||||
struct Context;
|
struct Context;
|
||||||
struct ContextWQ;
|
struct ContextWQ;
|
||||||
|
|
||||||
namespace rbd {
|
namespace rbd {
|
||||||
namespace mirror {
|
namespace mirror {
|
||||||
|
|
||||||
|
template <typename> struct Threads;
|
||||||
|
|
||||||
namespace image_replayer {
|
namespace image_replayer {
|
||||||
|
|
||||||
template <typename ImageCtxT = librbd::ImageCtx>
|
template <typename ImageCtxT = librbd::ImageCtx>
|
||||||
class PrepareRemoteImageRequest {
|
class PrepareRemoteImageRequest {
|
||||||
public:
|
public:
|
||||||
static PrepareRemoteImageRequest *create(librados::IoCtx &io_ctx,
|
typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
|
||||||
|
typedef typename TypeTraits::Journaler Journaler;
|
||||||
|
typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
|
||||||
|
|
||||||
|
static PrepareRemoteImageRequest *create(Threads<ImageCtxT> *threads,
|
||||||
|
librados::IoCtx &remote_io_ctx,
|
||||||
const std::string &global_image_id,
|
const std::string &global_image_id,
|
||||||
|
const std::string &local_mirror_uuid,
|
||||||
|
const std::string &local_image_id,
|
||||||
std::string *remote_mirror_uuid,
|
std::string *remote_mirror_uuid,
|
||||||
std::string *remote_image_id,
|
std::string *remote_image_id,
|
||||||
|
Journaler **remote_journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
|
MirrorPeerClientMeta *client_meta,
|
||||||
Context *on_finish) {
|
Context *on_finish) {
|
||||||
return new PrepareRemoteImageRequest(io_ctx, global_image_id,
|
return new PrepareRemoteImageRequest(threads, remote_io_ctx,
|
||||||
remote_mirror_uuid, remote_image_id,
|
global_image_id, local_mirror_uuid,
|
||||||
on_finish);
|
local_image_id, remote_mirror_uuid,
|
||||||
|
remote_image_id, remote_journaler,
|
||||||
|
client_state, client_meta, on_finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrepareRemoteImageRequest(librados::IoCtx &io_ctx,
|
PrepareRemoteImageRequest(Threads<ImageCtxT> *threads,
|
||||||
|
librados::IoCtx &remote_io_ctx,
|
||||||
const std::string &global_image_id,
|
const std::string &global_image_id,
|
||||||
|
const std::string &local_mirror_uuid,
|
||||||
|
const std::string &local_image_id,
|
||||||
std::string *remote_mirror_uuid,
|
std::string *remote_mirror_uuid,
|
||||||
std::string *remote_image_id,
|
std::string *remote_image_id,
|
||||||
|
Journaler **remote_journaler,
|
||||||
|
cls::journal::ClientState *client_state,
|
||||||
|
MirrorPeerClientMeta *client_meta,
|
||||||
Context *on_finish)
|
Context *on_finish)
|
||||||
: m_io_ctx(io_ctx), m_global_image_id(global_image_id),
|
: m_threads(threads), m_remote_io_ctx(remote_io_ctx),
|
||||||
|
m_global_image_id(global_image_id),
|
||||||
|
m_local_mirror_uuid(local_mirror_uuid), m_local_image_id(local_image_id),
|
||||||
m_remote_mirror_uuid(remote_mirror_uuid),
|
m_remote_mirror_uuid(remote_mirror_uuid),
|
||||||
m_remote_image_id(remote_image_id),
|
m_remote_image_id(remote_image_id),
|
||||||
m_on_finish(on_finish) {
|
m_remote_journaler(remote_journaler), m_client_state(client_state),
|
||||||
|
m_client_meta(client_meta), m_on_finish(on_finish) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send();
|
void send();
|
||||||
@ -56,18 +84,31 @@ private:
|
|||||||
* GET_REMOTE_IMAGE_ID
|
* GET_REMOTE_IMAGE_ID
|
||||||
* |
|
* |
|
||||||
* v
|
* v
|
||||||
|
* GET_CLIENT
|
||||||
|
* |
|
||||||
|
* v (skip if not needed)
|
||||||
|
* REGISTER_CLIENT
|
||||||
|
* |
|
||||||
|
* v
|
||||||
* <finish>
|
* <finish>
|
||||||
|
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
librados::IoCtx &m_io_ctx;
|
Threads<ImageCtxT> *m_threads;
|
||||||
|
librados::IoCtx &m_remote_io_ctx;
|
||||||
std::string m_global_image_id;
|
std::string m_global_image_id;
|
||||||
|
std::string m_local_mirror_uuid;
|
||||||
|
std::string m_local_image_id;
|
||||||
std::string *m_remote_mirror_uuid;
|
std::string *m_remote_mirror_uuid;
|
||||||
std::string *m_remote_image_id;
|
std::string *m_remote_image_id;
|
||||||
|
Journaler **m_remote_journaler;
|
||||||
|
cls::journal::ClientState *m_client_state;
|
||||||
|
MirrorPeerClientMeta *m_client_meta;
|
||||||
Context *m_on_finish;
|
Context *m_on_finish;
|
||||||
|
|
||||||
bufferlist m_out_bl;
|
bufferlist m_out_bl;
|
||||||
|
cls::journal::Client m_client;
|
||||||
|
|
||||||
void get_remote_mirror_uuid();
|
void get_remote_mirror_uuid();
|
||||||
void handle_get_remote_mirror_uuid(int r);
|
void handle_get_remote_mirror_uuid(int r);
|
||||||
@ -75,8 +116,15 @@ private:
|
|||||||
void get_remote_image_id();
|
void get_remote_image_id();
|
||||||
void handle_get_remote_image_id(int r);
|
void handle_get_remote_image_id(int r);
|
||||||
|
|
||||||
|
void get_client();
|
||||||
|
void handle_get_client(int r);
|
||||||
|
|
||||||
|
void register_client();
|
||||||
|
void handle_register_client(int r);
|
||||||
|
|
||||||
void finish(int r);
|
void finish(int r);
|
||||||
|
|
||||||
|
bool decode_client_meta();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace image_replayer
|
} // namespace image_replayer
|
||||||
|
Loading…
Reference in New Issue
Block a user