TEST_F(TestImageDeleter, Delete_NonPrimary_Image) {
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
TEST_F(TestImageDeleter, Fail_Delete_Primary_Image) {
promote_image();
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
}
-TEST_F(TestImageDeleter, Fail_Delete_Diff_GlobalId) {
- // This test case represents a case that should never happen, unless
- // there is bug in the implementation
-
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- "diff global id");
-
- C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, "diff global id",
- &ctx);
- EXPECT_EQ(-EINVAL, ctx.wait());
-
- ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
- ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
-}
-
TEST_F(TestImageDeleter, Delete_Image_With_Child) {
create_snapshot();
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
create_snapshot("snap1");
create_snapshot("snap2");
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChild) {
create_snapshot("snap1", true);
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
create_snapshot("snap1", true);
create_snapshot("snap2", true);
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
TEST_F(TestImageDeleter, Delete_Image_With_Clone) {
std::string clone_id = create_clone();
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
ASSERT_EQ(1u, m_deleter->get_delete_queue_items().size());
ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, clone_id,
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id,
GLOBAL_CLONE_IMAGE_ID);
C_SaferCond ctx2;
EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
mirror_image));
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
mirror_image));
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
TEST_F(TestImageDeleter, Delete_NonExistent_Image_Without_MirroringState) {
remove_image();
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
false);
EXPECT_EQ(0, ictx->state->open(false));
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
m_deleter->set_failed_timer_interval(2);
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
false);
EXPECT_EQ(0, ictx->state->open(false));
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
- m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- GLOBAL_IMAGE_ID);
+ m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
start();
- std::string image_id = m_replayer->get_local_image_id();
-
generate_test_data();
open_remote_image(&ictx);
m_replayer->start(&cond);
ASSERT_EQ(0, cond.wait());
- ASSERT_NE(image_id, m_replayer->get_local_image_id());
ASSERT_TRUE(m_replayer->is_replaying());
wait_for_replay_complete();
start();
- std::string image_id = m_replayer->get_local_image_id();
-
generate_test_data();
librbd::ImageCtx *ictx;
m_replayer->start(&cond3);
ASSERT_EQ(0, cond3.wait());
- ASSERT_NE(image_id, m_replayer->get_local_image_id());
ASSERT_TRUE(m_replayer->is_replaying());
wait_for_replay_complete();
bootstrap();
- std::string image_id = m_replayer->get_local_image_id();
-
librbd::ImageCtx *ictx;
open_local_image(&ictx);
librbd::Journal<>::request_resync(ictx);
m_watch_ctx = new C_WatchCtx(this, oid);
ASSERT_EQ(0, m_remote_ioctx.watch2(oid, &m_watch_handle, m_watch_ctx));
- ASSERT_NE(image_id, m_replayer->get_local_image_id());
-
ASSERT_TRUE(m_replayer->is_replaying());
open_remote_image(&ictx);
void ImageDeleter::schedule_image_delete(RadosRef local_rados,
int64_t local_pool_id,
- const std::string& local_image_id,
const std::string& global_image_id) {
dout(20) << "enter" << dendl;
auto del_info = find_delete_info(local_pool_id, global_image_id);
if (del_info != nullptr) {
- dout(20) << "image " << local_image_id << " (" << global_image_id << ") "
+ dout(20) << "image " << global_image_id << " "
<< "was already scheduled for deletion" << dendl;
return;
}
- m_delete_queue.push_front(unique_ptr<DeleteInfo>(
- new DeleteInfo(local_rados, local_pool_id, local_image_id,
- global_image_id)));
+ m_delete_queue.push_front(
+ unique_ptr<DeleteInfo>(new DeleteInfo(local_rados, local_pool_id,
+ global_image_id)));
m_delete_queue_cond.Signal();
}
r = m_active_delete->local_rados->ioctx_create2(
m_active_delete->local_pool_id, ioctx);
if (r < 0) {
- derr << "error accessing local pool: " << cpp_strerror(r) << dendl;
+ derr << "error accessing local pool " << m_active_delete->local_pool_id
+ << ": " << cpp_strerror(r) << dendl;
enqueue_failed_delete(r);
return true;
}
dout(20) << "connected to local pool: " << ioctx.get_pool_name() << dendl;
+ auto &global_image_id = m_active_delete->global_image_id;
+ std::string local_image_id;
+ r = librbd::cls_client::mirror_image_get_image_id(
+ &ioctx, global_image_id, &local_image_id);
+ if (r == -ENOENT) {
+ dout(10) << "image " << global_image_id << " is not mirrored" << dendl;
+ complete_active_delete(r);
+ return true;
+ } else if (r < 0) {
+ derr << "error retrieving local id for image " << global_image_id
+ << ": " << cpp_strerror(r) << dendl;
+ enqueue_failed_delete(r);
+ return true;
+ }
+
bool is_primary = false;
- r = Journal<>::is_tag_owner(ioctx, m_active_delete->local_image_id,
- &is_primary, m_work_queue);
+ r = Journal<>::is_tag_owner(ioctx, local_image_id, &is_primary,
+ m_work_queue);
if (r < 0 && r != -ENOENT) {
- derr << "error retrieving image primary info: " << cpp_strerror(r)
- << dendl;
+ derr << "error retrieving image primary info for image " << global_image_id
+ << ": " << cpp_strerror(r) << dendl;
enqueue_failed_delete(r);
return true;
}
if (is_primary) {
- dout(10) << "local image is the primary image, aborting deletion..."
- << dendl;
+ dout(10) << "image " << global_image_id << " is local primary" << dendl;
complete_active_delete(-EISPRM);
return true;
}
dout(20) << "local image is not the primary" << dendl;
bool has_snapshots;
- r = image_has_snapshots_and_children(&ioctx, m_active_delete->local_image_id,
- &has_snapshots);
+ r = image_has_snapshots_and_children(&ioctx, local_image_id, &has_snapshots);
if (r < 0) {
enqueue_failed_delete(r);
return true;
}
- mirror_image.global_image_id = m_active_delete->global_image_id;
+ mirror_image.global_image_id = global_image_id;
mirror_image.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
- r = cls_client::mirror_image_set(&ioctx, m_active_delete->local_image_id,
- mirror_image);
+ r = cls_client::mirror_image_set(&ioctx, local_image_id, mirror_image);
if (r == -ENOENT) {
dout(10) << "local image is not mirrored, aborting deletion..." << dendl;
complete_active_delete(r);
return true;
} else if (r == -EEXIST || r == -EINVAL) {
- derr << "cannot disable mirroring for image id "
- << m_active_delete->local_image_id
- << ": global_image_id has changed/reused, aborting deletion: "
+ derr << "cannot disable mirroring for image " << global_image_id
+ << ": global_image_id has changed/reused: "
<< cpp_strerror(r) << dendl;
complete_active_delete(r);
return true;
} else if (r < 0) {
- derr << "cannot disable mirroring for image id "
- << m_active_delete->local_image_id << ": " << cpp_strerror(r) << dendl;
+ derr << "cannot disable mirroring for image " << global_image_id
+ << ": " << cpp_strerror(r) << dendl;
enqueue_failed_delete(r);
return true;
}
if (has_snapshots) {
dout(20) << "local image has snapshots" << dendl;
- ImageCtx *imgctx = new ImageCtx("", m_active_delete->local_image_id,
- nullptr, ioctx, false);
+ ImageCtx *imgctx = new ImageCtx("", local_image_id, nullptr, ioctx, false);
r = imgctx->state->open(false);
if (r < 0) {
- derr << "error opening image id " << m_active_delete->local_image_id
- << ": " << cpp_strerror(r) << dendl;
+ derr << "error opening image " << global_image_id << " ("
+ << local_image_id << "): " << cpp_strerror(r) << dendl;
enqueue_failed_delete(r);
return true;
}
dout(20) << "snapshot " << imgctx->name << "@" << snap.name
<< " is protected, issuing unprotect command" << dendl;
- r = imgctx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(),
- snap.name.c_str());
+ r = imgctx->operations->snap_unprotect(
+ cls::rbd::UserSnapshotNamespace(), snap.name.c_str());
if (r == -EBUSY) {
// there are still clones of snapshots of this image, therefore send
// the delete request to the end of the queue
- dout(10) << "local image id " << m_active_delete->local_image_id << " has "
+ dout(10) << "local image id " << local_image_id << " has "
<< "snapshots with cloned children, postponing deletion..."
<< dendl;
imgctx->state->close();
}
librbd::NoOpProgressContext ctx;
- r = librbd::remove(ioctx, "", m_active_delete->local_image_id, ctx, true);
+ r = librbd::remove(ioctx, "", local_image_id, ctx, true);
if (r < 0 && r != -ENOENT) {
- derr << "error removing image " << m_active_delete->local_image_id << " "
- << "(" << m_active_delete->global_image_id << ") from local pool: "
+ derr << "error removing image " << global_image_id << " "
+ << "(" << local_image_id << ") from local pool: "
<< cpp_strerror(r) << dendl;
enqueue_failed_delete(r);
return true;
<< dendl;
}
- r = cls_client::mirror_image_remove(&ioctx, m_active_delete->local_image_id);
+ r = cls_client::mirror_image_remove(&ioctx, local_image_id);
if (r < 0 && r != -ENOENT) {
derr << "error removing image from mirroring directory: "
<< cpp_strerror(r) << dendl;
}
dout(10) << "Successfully deleted image "
- << m_active_delete->local_image_id << " "
- << "(" << m_active_delete->global_image_id << ")" << dendl;
+ << global_image_id << " " << "(" << local_image_id << ")" << dendl;
complete_active_delete(0);
return true;
void ImageDeleter::DeleteInfo::to_string(stringstream& ss) {
ss << "[" << "local_pool_id=" << local_pool_id << ", ";
- ss << "local_image_id=" << local_image_id << ", ";
ss << "global_image_id=" << global_image_id << "]";
}
if (f) {
f->open_object_section("delete_info");
f->dump_int("local_pool_id", local_pool_id);
- f->dump_string("local_image_id", local_image_id);
f->dump_string("global_image_id", global_image_id);
if (print_failure_info) {
f->dump_string("error_code", cpp_strerror(error_code));
Mutex::Locker l(m_delete_lock);
for (const auto& del_info : m_delete_queue) {
- items.push_back(del_info->local_image_id);
+ items.push_back(del_info->global_image_id);
}
return items;
Mutex::Locker l(m_delete_lock);
for (const auto& del_info : m_failed_queue) {
- items.push_back(make_pair(del_info->local_image_id,
+ items.push_back(make_pair(del_info->global_image_id,
del_info->error_code));
}
void schedule_image_delete(RadosRef local_rados,
int64_t local_pool_id,
- const std::string& local_image_id,
const std::string& global_image_id);
void wait_for_scheduled_deletion(int64_t local_pool_id,
const std::string &global_image_id,
struct DeleteInfo {
RadosRef local_rados;
int64_t local_pool_id;
- std::string local_image_id;
std::string global_image_id;
- int error_code;
- int retries;
- bool notify_on_failed_retry;
- Context *on_delete;
+ int error_code = 0;
+ int retries = 0;
+ bool notify_on_failed_retry = true;
+ Context *on_delete = nullptr;
DeleteInfo(RadosRef local_rados, int64_t local_pool_id,
- const std::string& local_image_id,
const std::string& global_image_id) :
local_rados(local_rados), local_pool_id(local_pool_id),
- local_image_id(local_image_id), global_image_id(global_image_id),
- error_code(0), retries(0), notify_on_failed_retry(true),
- on_delete(nullptr) {
+ global_image_id(global_image_id) {
}
bool match(int64_t local_pool_id, const std::string &global_image_id) {
if (m_stopping_for_resync) {
m_image_deleter->schedule_image_delete(m_local,
m_local_pool_id,
- m_local_image_id,
m_global_image_id);
m_stopping_for_resync = false;
}
inline const std::string& get_global_image_id() const {
return m_global_image_id;
}
- inline std::string get_local_image_id() {
- Mutex::Locker locker(m_lock);
- return m_local_image_id;
- }
void start(Context *on_finish = nullptr, bool manual = false);
void stop(Context *on_finish = nullptr, bool manual = false,
on_finish = new FunctionContext(
[this, image_replayer, on_finish] (int r) {
auto global_image_id = image_replayer->get_global_image_id();
- auto local_image_id = image_replayer->get_local_image_id();
- if (local_image_id.empty()) {
- dout(20) << global_image_id << ": unknown local_image_id"
- << " (image does not exist or primary), skipping delete"
- << dendl;
- } else {
- m_image_deleter->schedule_image_delete(
- m_local_rados, m_local_pool_id, local_image_id, global_image_id);
- }
+ m_image_deleter->schedule_image_delete(
+ m_local_rados, m_local_pool_id, global_image_id);
on_finish->complete(0);
});
}
dout(20) << "scheduling the deletion of init image: "
<< image_id.global_id << " (" << image_id.id << ")" << dendl;
m_image_deleter->schedule_image_delete(m_local_rados, m_local_pool_id,
- image_id.id, image_id.global_id);
+ image_id.global_id);
}
m_init_image_ids.clear();
}