1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/Context.h"
5 #include "test/rbd_mirror/test_fixture.h"
6 #include "tools/rbd_mirror/image_map/Types.h"
7 #include "tools/rbd_mirror/image_map/SimplePolicy.h"
8 #include "include/stringify.h"
9 #include "common/Thread.h"
11 void register_test_image_policy() {
18 class TestImageMapPolicy
: public TestFixture
{
20 void SetUp() override
{
23 EXPECT_EQ(0, _rados
->conf_set("rbd_mirror_image_policy_migration_throttle",
26 CephContext
*cct
= reinterpret_cast<CephContext
*>(m_local_io_ctx
.cct());
27 std::string policy_type
= cct
->_conf
.get_val
<string
>("rbd_mirror_image_policy_type");
29 if (policy_type
== "none" || policy_type
== "simple") {
30 m_policy
= image_map::SimplePolicy::create(m_local_io_ctx
);
38 void TearDown() override
{
39 TestFixture::TearDown();
43 void map_image(const std::string
&global_image_id
) {
44 ASSERT_TRUE(m_policy
->add_image(global_image_id
));
46 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
47 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
49 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
50 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
53 void unmap_image(const std::string
&global_image_id
) {
54 ASSERT_TRUE(m_policy
->remove_image(global_image_id
));
56 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
57 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
59 ASSERT_EQ(ACTION_TYPE_MAP_REMOVE
, m_policy
->start_action(global_image_id
));
60 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
63 void shuffle_image(const std::string
&global_image_id
) {
64 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
65 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
67 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
68 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
70 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
71 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
77 TEST_F(TestImageMapPolicy
, NegativeLookup
) {
78 const std::string global_image_id
= "global id 1";
80 LookupInfo info
= m_policy
->lookup(global_image_id
);
81 ASSERT_TRUE(info
.instance_id
== UNMAPPED_INSTANCE_ID
);
84 TEST_F(TestImageMapPolicy
, Init
) {
85 const std::string global_image_id
= "global id 1";
87 m_policy
->init({{global_image_id
, {"9876", {}, {}}}});
89 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
90 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
93 TEST_F(TestImageMapPolicy
, MapImage
) {
94 const std::string global_image_id
= "global id 1";
96 map_image(global_image_id
);
98 LookupInfo info
= m_policy
->lookup(global_image_id
);
99 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
102 TEST_F(TestImageMapPolicy
, UnmapImage
) {
103 const std::string global_image_id
= "global id 1";
106 map_image(global_image_id
);
108 LookupInfo info
= m_policy
->lookup(global_image_id
);
109 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
112 unmap_image(global_image_id
);
114 info
= m_policy
->lookup(global_image_id
);
115 ASSERT_TRUE(info
.instance_id
== UNMAPPED_INSTANCE_ID
);
118 TEST_F(TestImageMapPolicy
, ShuffleImageAddInstance
) {
119 std::set
<std::string
> global_image_ids
{
120 "global id 1", "global id 2", "global id 3", "global id 4", "global id 5", "global id 6"
123 for (auto const &global_image_id
: global_image_ids
) {
125 map_image(global_image_id
);
127 LookupInfo info
= m_policy
->lookup(global_image_id
);
128 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
131 std::set
<std::string
> shuffle_global_image_ids
;
132 m_policy
->add_instances({"9876"}, &shuffle_global_image_ids
);
134 for (auto const &global_image_id
: shuffle_global_image_ids
) {
135 shuffle_image(global_image_id
);
137 LookupInfo info
= m_policy
->lookup(global_image_id
);
138 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
142 TEST_F(TestImageMapPolicy
, ShuffleImageRemoveInstance
) {
143 std::set
<std::string
> global_image_ids
{
144 "global id 1", "global id 2", "global id 3", "global id 4", "global id 5"
147 std::set
<std::string
> shuffle_global_image_ids
;
148 m_policy
->add_instances({stringify(m_local_io_ctx
.get_instance_id())},
149 &shuffle_global_image_ids
);
150 for (auto const &global_image_id
: global_image_ids
) {
152 map_image(global_image_id
);
154 LookupInfo info
= m_policy
->lookup(global_image_id
);
155 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
158 m_policy
->add_instances({"9876"}, &shuffle_global_image_ids
);
160 for (auto const &global_image_id
: shuffle_global_image_ids
) {
161 shuffle_image(global_image_id
);
163 LookupInfo info
= m_policy
->lookup(global_image_id
);
164 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
167 // record which of the images got migrated to the new instance
168 std::set
<std::string
> remapped_global_image_ids
;
169 for (auto const &global_image_id
: shuffle_global_image_ids
) {
170 LookupInfo info
= m_policy
->lookup(global_image_id
);
171 if (info
.instance_id
== "9876") {
172 remapped_global_image_ids
.emplace(global_image_id
);
176 shuffle_global_image_ids
.clear();
177 m_policy
->remove_instances({"9876"}, &shuffle_global_image_ids
);
179 ASSERT_TRUE(shuffle_global_image_ids
== remapped_global_image_ids
);
181 for (auto const &global_image_id
: shuffle_global_image_ids
) {
182 shuffle_image(global_image_id
);
184 LookupInfo info
= m_policy
->lookup(global_image_id
);
185 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
189 TEST_F(TestImageMapPolicy
, RetryMapUpdate
) {
190 const std::string global_image_id
= "global id 1";
192 ASSERT_TRUE(m_policy
->add_image(global_image_id
));
194 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
195 // on-disk map update failed
196 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, -EIO
));
198 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
199 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
201 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
202 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
204 LookupInfo info
= m_policy
->lookup(global_image_id
);
205 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
208 TEST_F(TestImageMapPolicy
, MapFailureAndUnmap
) {
209 const std::string global_image_id
= "global id 1";
211 ASSERT_TRUE(m_policy
->add_image(global_image_id
));
213 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
214 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
216 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
218 std::set
<std::string
> shuffle_global_image_ids
;
219 m_policy
->add_instances({"9876"}, &shuffle_global_image_ids
);
220 ASSERT_TRUE(shuffle_global_image_ids
.empty());
222 m_policy
->remove_instances({stringify(m_local_io_ctx
.get_instance_id())},
223 &shuffle_global_image_ids
);
224 ASSERT_TRUE(shuffle_global_image_ids
.empty());
226 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, -EBLOCKLISTED
));
228 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
229 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, -ENOENT
));
231 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
232 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
234 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
235 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
237 ASSERT_TRUE(m_policy
->remove_image(global_image_id
));
239 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
240 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
242 ASSERT_EQ(ACTION_TYPE_MAP_REMOVE
, m_policy
->start_action(global_image_id
));
243 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
246 TEST_F(TestImageMapPolicy
, ReshuffleWithMapFailure
) {
247 std::set
<std::string
> global_image_ids
{
248 "global id 1", "global id 2", "global id 3", "global id 4", "global id 5",
252 std::set
<std::string
> shuffle_global_image_ids
;
253 m_policy
->add_instances({stringify(m_local_io_ctx
.get_instance_id())},
254 &shuffle_global_image_ids
);
255 for (auto const &global_image_id
: global_image_ids
) {
257 map_image(global_image_id
);
259 LookupInfo info
= m_policy
->lookup(global_image_id
);
260 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
263 m_policy
->add_instances({"9876"}, &shuffle_global_image_ids
);
264 ASSERT_FALSE(shuffle_global_image_ids
.empty());
266 const std::string global_image_id
= *(shuffle_global_image_ids
.begin());
267 shuffle_global_image_ids
.clear();
269 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
270 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
272 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
273 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
275 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
278 m_policy
->remove_instances({"9876"}, &shuffle_global_image_ids
);
279 ASSERT_TRUE(shuffle_global_image_ids
.empty());
281 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, -EBLOCKLISTED
));
283 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
284 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
286 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
287 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
289 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
290 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
293 TEST_F(TestImageMapPolicy
, ShuffleFailureAndRemove
) {
294 std::set
<std::string
> global_image_ids
{
295 "global id 1", "global id 2", "global id 3", "global id 4", "global id 5",
299 std::set
<std::string
> shuffle_global_image_ids
;
300 m_policy
->add_instances({stringify(m_local_io_ctx
.get_instance_id())},
301 &shuffle_global_image_ids
);
302 for (auto const &global_image_id
: global_image_ids
) {
304 map_image(global_image_id
);
306 LookupInfo info
= m_policy
->lookup(global_image_id
);
307 ASSERT_TRUE(info
.instance_id
!= UNMAPPED_INSTANCE_ID
);
310 m_policy
->add_instances({"9876"}, &shuffle_global_image_ids
);
311 ASSERT_FALSE(shuffle_global_image_ids
.empty());
313 std::string global_image_id
= *(shuffle_global_image_ids
.begin());
314 shuffle_global_image_ids
.clear();
316 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
317 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
319 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
320 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
322 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
325 m_policy
->remove_instances({"9876"}, &shuffle_global_image_ids
);
326 ASSERT_TRUE(shuffle_global_image_ids
.empty());
328 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, -EBLOCKLISTED
));
330 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
331 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
333 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
334 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
336 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
337 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
339 ASSERT_TRUE(m_policy
->remove_image(global_image_id
));
341 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
342 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
344 ASSERT_EQ(ACTION_TYPE_MAP_REMOVE
, m_policy
->start_action(global_image_id
));
345 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
347 LookupInfo info
= m_policy
->lookup(global_image_id
);
348 ASSERT_TRUE(info
.instance_id
== UNMAPPED_INSTANCE_ID
);
351 TEST_F(TestImageMapPolicy
, InitialInstanceUpdate
) {
352 const std::string global_image_id
= "global id 1";
354 m_policy
->init({{global_image_id
, {"9876", {}, {}}}});
356 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
358 auto instance_id
= stringify(m_local_io_ctx
.get_instance_id());
359 std::set
<std::string
> shuffle_global_image_ids
;
360 m_policy
->add_instances({instance_id
}, &shuffle_global_image_ids
);
362 ASSERT_EQ(0U, shuffle_global_image_ids
.size());
363 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, -ENOENT
));
365 ASSERT_EQ(ACTION_TYPE_RELEASE
, m_policy
->start_action(global_image_id
));
366 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
368 ASSERT_EQ(ACTION_TYPE_MAP_UPDATE
, m_policy
->start_action(global_image_id
));
369 ASSERT_TRUE(m_policy
->finish_action(global_image_id
, 0));
371 ASSERT_EQ(ACTION_TYPE_ACQUIRE
, m_policy
->start_action(global_image_id
));
372 ASSERT_FALSE(m_policy
->finish_action(global_image_id
, 0));
375 } // namespace image_map
376 } // namespace mirror