]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/Migration.cc
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / tools / rbd / action / Migration.cc
CommitLineData
11fdf7f2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "common/errno.h"
5
6#include "tools/rbd/ArgumentTypes.h"
7#include "tools/rbd/Shell.h"
8#include "tools/rbd/Utils.h"
9
10#include <iostream>
11#include <boost/program_options.hpp>
12
13namespace rbd {
14namespace action {
15namespace migration {
16
17namespace at = argument_types;
18namespace po = boost::program_options;
19
20static int do_prepare(librados::IoCtx& io_ctx, const std::string &image_name,
21 librados::IoCtx& dest_io_ctx,
22 const std::string &dest_image_name,
23 librbd::ImageOptions& opts) {
24 int r = librbd::RBD().migration_prepare(io_ctx, image_name.c_str(),
25 dest_io_ctx, dest_image_name.c_str(),
26 opts);
27 if (r < 0) {
28 std::cerr << "rbd: preparing migration failed: " << cpp_strerror(r)
29 << std::endl;
30 return r;
31 }
32 return 0;
33}
34
35static int do_execute(librados::IoCtx& io_ctx, const std::string &image_name,
36 bool no_progress) {
37 utils::ProgressContext pc("Image migration", no_progress);
38 int r = librbd::RBD().migration_execute_with_progress(io_ctx,
39 image_name.c_str(), pc);
40 if (r < 0) {
41 pc.fail();
42 std::cerr << "rbd: migration failed: " << cpp_strerror(r) << std::endl;
43 return r;
44 }
45 pc.finish();
46 return 0;
47}
48
49static int do_abort(librados::IoCtx& io_ctx, const std::string &image_name,
50 bool no_progress) {
51 utils::ProgressContext pc("Abort image migration", no_progress);
52 int r = librbd::RBD().migration_abort_with_progress(io_ctx,
53 image_name.c_str(), pc);
54 if (r < 0) {
55 pc.fail();
56 std::cerr << "rbd: aborting migration failed: " << cpp_strerror(r)
57 << std::endl;
58 return r;
59 }
60 pc.finish();
61 return 0;
62}
63
64static int do_commit(librados::IoCtx& io_ctx, const std::string &image_name,
65 bool force, bool no_progress) {
66 librbd::image_migration_status_t migration_status;
67 int r = librbd::RBD().migration_status(io_ctx, image_name.c_str(),
68 &migration_status,
69 sizeof(migration_status));
70 if (r < 0) {
71 std::cerr << "rbd: getting migration status failed: " << cpp_strerror(r)
72 << std::endl;
73 return r;
74 }
75
76 librados::IoCtx dst_io_ctx;
77 r = librados::Rados(io_ctx).ioctx_create2(migration_status.dest_pool_id, dst_io_ctx);
78 if (r < 0) {
79 std::cerr << "rbd: accessing source pool id="
80 << migration_status.dest_pool_id << " failed: "
81 << cpp_strerror(r) << std::endl;
82 return r;
83 }
84
85 r = utils::set_namespace(migration_status.dest_pool_namespace, &dst_io_ctx);
86 if (r < 0) {
87 return r;
88 }
89
90 librbd::Image image;
91 r = utils::open_image_by_id(dst_io_ctx, migration_status.dest_image_id,
92 true, &image);
93 if (r < 0) {
94 return r;
95 }
96
97 std::vector<librbd::linked_image_spec_t> children;
98 r = image.list_descendants(&children);
99 if (r < 0) {
100 std::cerr << "rbd: listing descendants failed: " << cpp_strerror(r)
101 << std::endl;
102 return r;
103 }
104
105 if (children.size() > 0) {
106 std::cerr << "rbd: the image has "
107 << (children.size() == 1 ? "a descendant" : "descendants") << ": "
108 << std::endl;
109 for (auto& child : children) {
110 std::cerr << " " << child.pool_name << "/";
111 if (!child.pool_namespace.empty()) {
112 std::cerr << child.pool_namespace << "/";
113 }
114 std::cerr << child.image_name;
115 if (child.trash) {
116 std::cerr << " (trash " << child.image_id << ")";
117 }
118 std::cerr << std::endl;
119 }
120 std::cerr << "Warning: in-use, read-only descendant images"
121 << " will not detect the parent update." << std::endl;
122 if (force) {
123 std::cerr << "Proceeding anyway due to force flag set." << std::endl;
124 } else {
125 std::cerr << "Ensure no descendant images are opened read-only"
126 << " and run again with force flag." << std::endl;
127 return -EBUSY;
128 }
129 }
130
131 utils::ProgressContext pc("Commit image migration", no_progress);
132 r = librbd::RBD().migration_commit_with_progress(io_ctx, image_name.c_str(),
133 pc);
134 if (r < 0) {
135 pc.fail();
136 std::cerr << "rbd: committing migration failed: " << cpp_strerror(r)
137 << std::endl;
138 return r;
139 }
140 pc.finish();
141 return 0;
142}
143
144void get_prepare_arguments(po::options_description *positional,
145 po::options_description *options) {
146 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_SOURCE);
147 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
148 at::add_create_image_options(options, true);
149 at::add_flatten_option(options);
150}
151
152int execute_prepare(const po::variables_map &vm,
153 const std::vector<std::string> &ceph_global_init_args) {
154 size_t arg_index = 0;
155 std::string pool_name;
156 std::string namespace_name;
157 std::string image_name;
158 int r = utils::get_pool_image_snapshot_names(
159 vm, at::ARGUMENT_MODIFIER_SOURCE, &arg_index, &pool_name, &namespace_name,
160 &image_name, nullptr, true, utils::SNAPSHOT_PRESENCE_NONE,
161 utils::SPEC_VALIDATION_NONE);
162 if (r < 0) {
163 return r;
164 }
165
166 librados::Rados rados;
167 librados::IoCtx io_ctx;
168 r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
169 if (r < 0) {
170 return r;
171 }
9f95a23c 172 io_ctx.set_pool_full_try();
11fdf7f2
TL
173
174 std::string dest_pool_name;
175 std::string dest_namespace_name;
176 std::string dest_image_name;
177 r = utils::get_pool_image_snapshot_names(
178 vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dest_pool_name,
179 &dest_namespace_name, &dest_image_name, nullptr, false,
180 utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL);
181 if (r < 0) {
182 return r;
183 }
184
185 librbd::ImageOptions opts;
186 r = utils::get_image_options(vm, true, &opts);
187 if (r < 0) {
188 return r;
189 }
190
191 librados::IoCtx dest_io_ctx;
192 if (!dest_pool_name.empty()) {
193 r = utils::init_io_ctx(rados, dest_pool_name, dest_namespace_name,
194 &dest_io_ctx);
195 if (r < 0) {
196 return r;
197 }
198 }
199
200 r = do_prepare(io_ctx, image_name, dest_pool_name.empty() ? io_ctx :
201 dest_io_ctx, dest_image_name, opts);
202 if (r < 0) {
203 return r;
204 }
205
206 return 0;
207}
208
209void get_execute_arguments(po::options_description *positional,
210 po::options_description *options) {
211 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
212 at::add_no_progress_option(options);
213}
214
215int execute_execute(const po::variables_map &vm,
216 const std::vector<std::string> &ceph_global_init_args) {
217 size_t arg_index = 0;
218 std::string pool_name;
219 std::string namespace_name;
220 std::string image_name;
221 int r = utils::get_pool_image_snapshot_names(
222 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
223 &image_name, nullptr, true, utils::SNAPSHOT_PRESENCE_NONE,
224 utils::SPEC_VALIDATION_NONE);
225 if (r < 0) {
226 return r;
227 }
228
229 librados::Rados rados;
230 librados::IoCtx io_ctx;
231 r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
232 if (r < 0) {
233 return r;
234 }
9f95a23c 235 io_ctx.set_pool_full_try();
11fdf7f2
TL
236
237 r = do_execute(io_ctx, image_name, vm[at::NO_PROGRESS].as<bool>());
238 if (r < 0) {
239 return r;
240 }
241
242 return 0;
243}
244
245void get_abort_arguments(po::options_description *positional,
246 po::options_description *options) {
247 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
248 at::add_no_progress_option(options);
249}
250
251int execute_abort(const po::variables_map &vm,
252 const std::vector<std::string> &ceph_global_init_args) {
253 size_t arg_index = 0;
254 std::string pool_name;
255 std::string namespace_name;
256 std::string image_name;
257 int r = utils::get_pool_image_snapshot_names(
258 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
259 &image_name, nullptr, true, utils::SNAPSHOT_PRESENCE_NONE,
260 utils::SPEC_VALIDATION_NONE);
261 if (r < 0) {
262 return r;
263 }
264
265 librados::Rados rados;
266 librados::IoCtx io_ctx;
267 r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
268 if (r < 0) {
269 return r;
270 }
9f95a23c 271 io_ctx.set_pool_full_try();
11fdf7f2
TL
272
273 r = do_abort(io_ctx, image_name, vm[at::NO_PROGRESS].as<bool>());
274 if (r < 0) {
275 return r;
276 }
277
278 return 0;
279}
280
281void get_commit_arguments(po::options_description *positional,
282 po::options_description *options) {
283 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
284 at::add_no_progress_option(options);
285 options->add_options()
286 ("force", po::bool_switch(), "proceed even if the image has children");
287}
288
289int execute_commit(const po::variables_map &vm,
290 const std::vector<std::string> &ceph_global_init_args) {
291 size_t arg_index = 0;
292 std::string pool_name;
293 std::string namespace_name;
294 std::string image_name;
295 int r = utils::get_pool_image_snapshot_names(
296 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
297 &image_name, nullptr, true, utils::SNAPSHOT_PRESENCE_NONE,
298 utils::SPEC_VALIDATION_NONE);
299 if (r < 0) {
300 return r;
301 }
302
303 librados::Rados rados;
304 librados::IoCtx io_ctx;
305 r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
306 if (r < 0) {
307 return r;
308 }
9f95a23c 309 io_ctx.set_pool_full_try();
11fdf7f2
TL
310
311 r = do_commit(io_ctx, image_name, vm["force"].as<bool>(),
312 vm[at::NO_PROGRESS].as<bool>());
313 if (r < 0) {
314 return r;
315 }
316
317 return 0;
318}
319
320Shell::Action action_prepare(
321 {"migration", "prepare"}, {}, "Prepare image migration.",
322 at::get_long_features_help(), &get_prepare_arguments, &execute_prepare);
323
324Shell::Action action_execute(
325 {"migration", "execute"}, {}, "Execute image migration.", "",
326 &get_execute_arguments, &execute_execute);
327
328Shell::Action action_abort(
329 {"migration", "abort"}, {}, "Cancel interrupted image migration.", "",
330 &get_abort_arguments, &execute_abort);
331
332Shell::Action action_commit(
333 {"migration", "commit"}, {}, "Commit image migration.", "",
334 &get_commit_arguments, &execute_commit);
335
336} // namespace migration
337} // namespace action
338} // namespace rbd