From: Jason Dillaman Date: Wed, 21 Oct 2020 18:29:15 +0000 (-0400) Subject: rbd: add new 'migration prepare --import-only' CLI optional X-Git-Tag: v16.1.0~702^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4ab2a183ca26a0146669c2b473a5bbc6380967ee;p=ceph.git rbd: add new 'migration prepare --import-only' CLI optional The '--import-only' optional can be combined with either a '--source-spec' or '--source-spec-path' optional to define the source for the read-only import. Signed-off-by: Jason Dillaman --- diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index 7eeb4ab6e4bc..3d89f0bd5484 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -1484,8 +1484,11 @@ --no-progress disable progress output rbd help migration prepare - usage: rbd migration prepare [--pool ] [--namespace ] - [--image ] [--dest-pool ] + usage: rbd migration prepare [--import-only] + [--source-spec-path ] + [--source-spec ] [--pool ] + [--namespace ] [--image ] + [--dest-pool ] [--dest-namespace ] [--dest ] [--image-format ] [--new-format] [--order ] @@ -1509,6 +1512,9 @@ (example: [/[/]]) Optional arguments + --import-only only import data from source + --source-spec-path arg source-spec file (or '-' for stdin) + --source-spec arg source-spec -p [ --pool ] arg source pool name --namespace arg source namespace name --image arg source image name diff --git a/src/tools/rbd/action/Migration.cc b/src/tools/rbd/action/Migration.cc index 5a929a75939d..eef82d1a1b34 100644 --- a/src/tools/rbd/action/Migration.cc +++ b/src/tools/rbd/action/Migration.cc @@ -1,12 +1,16 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include "include/compat.h" #include "common/errno.h" +#include "common/safe_io.h" #include "tools/rbd/ArgumentTypes.h" #include "tools/rbd/Shell.h" #include "tools/rbd/Utils.h" +#include +#include #include #include @@ -17,21 +21,6 @@ namespace migration { namespace at = argument_types; namespace po = boost::program_options; -static int do_prepare(librados::IoCtx& io_ctx, const std::string &image_name, - librados::IoCtx& dest_io_ctx, - const std::string &dest_image_name, - librbd::ImageOptions& opts) { - int r = librbd::RBD().migration_prepare(io_ctx, image_name.c_str(), - dest_io_ctx, dest_image_name.c_str(), - opts); - if (r < 0) { - std::cerr << "rbd: preparing migration failed: " << cpp_strerror(r) - << std::endl; - return r; - } - return 0; -} - static int do_execute(librados::IoCtx& io_ctx, const std::string &image_name, bool no_progress) { utils::ProgressContext pc("Image migration", no_progress); @@ -143,6 +132,12 @@ static int do_commit(librados::IoCtx& io_ctx, const std::string &image_name, void get_prepare_arguments(po::options_description *positional, po::options_description *options) { + options->add_options() + ("import-only", po::bool_switch(), "only import data from source") + ("source-spec-path", po::value(), + "source-spec file (or '-' for stdin)") + ("source-spec", po::value(), + "source-spec"); at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_SOURCE); at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST); at::add_create_image_options(options, true); @@ -163,23 +158,90 @@ int execute_prepare(const po::variables_map &vm, return r; } + std::string dst_pool_name; + std::string dst_namespace_name; + std::string dst_image_name; + r = utils::get_pool_image_snapshot_names( + vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dst_pool_name, + &dst_namespace_name, &dst_image_name, nullptr, false, + utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL); + if (r < 0) { + return r; + } + + bool import_only = vm["import-only"].as(); + std::string source_spec; + if (vm.count("source-spec") && vm.count("source-spec-path")) { + std::cerr << "rbd: cannot specify both source-image-spec and " + << "source-spec/source-spec-file" << std::endl; + return -EINVAL; + } else if (vm.count("source-spec-path")) { + std::string source_spec_path = vm["source-spec-path"].as(); + + int fd = STDIN_FILENO; + if (source_spec_path != "-") { + fd = open(source_spec_path.c_str(), O_RDONLY); + if (fd < 0) { + r = -errno; + std::cerr << "rbd: error opening " << source_spec_path << std::endl; + return r; + } + } + + source_spec.resize(4096); + r = safe_read(fd, source_spec.data(), source_spec.size() - 1); + if (fd != STDIN_FILENO) { + VOID_TEMP_FAILURE_RETRY(close(fd)); + } + + if (r >= 0) { + source_spec.resize(r); + } else { + std::cerr << "rbd: error reading source-spec file: " << cpp_strerror(r) + << std::endl; + return r; + } + } else if (vm.count("source-spec")) { + source_spec = vm["source-spec"].as(); + } + librados::Rados rados; librados::IoCtx io_ctx; r = utils::init(pool_name, namespace_name, &rados, &io_ctx); if (r < 0) { return r; } - io_ctx.set_pool_full_try(); - std::string dest_pool_name; - std::string dest_namespace_name; - std::string dest_image_name; - r = utils::get_pool_image_snapshot_names( - vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dest_pool_name, - &dest_namespace_name, &dest_image_name, nullptr, false, - utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL); - if (r < 0) { - return r; + librados::IoCtx dst_io_ctx; + if (source_spec.empty()) { + utils::normalize_pool_name(&dst_pool_name); + r = utils::init_io_ctx(rados, dst_pool_name, dst_namespace_name, + &dst_io_ctx); + if (r < 0) { + return r; + } + } + + if (import_only && source_spec.empty()) { + std::stringstream ss; + ss << R"({)" + << R"("type":"native",)" + << R"("pool_id":)" << io_ctx.get_id() << R"(,)" + << R"("pool_namespace":")" << io_ctx.get_namespace() << R"(",)" + << R"("image_name":")" << image_name << R"(")" + << R"(})"; + source_spec = ss.str(); + + if (dst_image_name.empty()) { + std::cerr << "rbd: destination image name must be provided" << std::endl; + return -EINVAL; + } + io_ctx = dst_io_ctx; + image_name = dst_image_name; + } else if (!import_only && !source_spec.empty()) { + std::cerr << "rbd: --import-only must be used in combination with " + << "source-spec/source-spec-path" << std::endl; + return -EINVAL; } librbd::ImageOptions opts; @@ -188,18 +250,28 @@ int execute_prepare(const po::variables_map &vm, return r; } - librados::IoCtx dest_io_ctx; - utils::normalize_pool_name(&dest_pool_name); - r = utils::init_io_ctx(rados, dest_pool_name, dest_namespace_name, - &dest_io_ctx); - if (r < 0) { - return r; - } + if (source_spec.empty()) { + if (dst_image_name.empty()) { + dst_image_name = image_name; + } - r = do_prepare(io_ctx, image_name, dest_pool_name.empty() ? io_ctx : - dest_io_ctx, dest_image_name, opts); - if (r < 0) { - return r; + int r = librbd::RBD().migration_prepare(io_ctx, image_name.c_str(), + dst_io_ctx, dst_image_name.c_str(), + opts); + if (r < 0) { + std::cerr << "rbd: preparing migration failed: " << cpp_strerror(r) + << std::endl; + return r; + } + } else { + ceph_assert(import_only); + r = librbd::RBD().migration_prepare_import(source_spec.c_str(), io_ctx, + image_name.c_str(), opts); + if (r < 0) { + std::cerr << "rbd: preparing import migration failed: " << cpp_strerror(r) + << std::endl; + return r; + } } return 0;