From d0610ee314195cb16e1b251cc1b845bd4a5e3b16 Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Thu, 6 May 2021 12:57:56 +0530 Subject: [PATCH] rbd: promote rbd-nbd attach and detach at rbd integrated cli Example: $ rbd device attach rbd-pool/image --device /dev/nbd0 --device-type nbd --force $ rbd device detach rpool/image --device-type nbd for now returning EOPNOTSUPP with krbd, ggate and wnbd Signed-off-by: Prasanna Kumar Kalever (cherry picked from commit 35e5352f719857bed99caa4c76ae19bb68918c8e) Conflicts: src/tools/rbd/action/Device.cc [ commit e1b4811bc324 ("rbd: add missing switch arguments for recognition by get_command_spec()") already in pacific ] src/tools/rbd/action/Wnbd.cc [ ditto ] --- doc/man/8/rbd.rst | 16 ++++++ src/test/cli/rbd/help.t | 52 +++++++++++++++++ src/tools/rbd/action/Device.cc | 62 ++++++++++++++++++++ src/tools/rbd/action/Ggate.cc | 10 ++++ src/tools/rbd/action/Kernel.cc | 10 ++++ src/tools/rbd/action/Nbd.cc | 100 +++++++++++++++++++++++++++++++++ src/tools/rbd/action/Wnbd.cc | 10 ++++ 7 files changed, 260 insertions(+) diff --git a/doc/man/8/rbd.rst b/doc/man/8/rbd.rst index 7488d1197d2f5..c4ae2507ef6b7 100644 --- a/doc/man/8/rbd.rst +++ b/doc/man/8/rbd.rst @@ -268,6 +268,22 @@ Commands The --options argument is a comma separated list of device type specific options (opt1,opt2=val,...). +:command:`device attach` [-t | --device-type *device-type*] --device *device-path* [--read-only] [--exclusive] [--force] [-o | --options *device-options*] *image-spec* | *snap-spec* + Attach the specified image to the specified block device (currently only + `nbd` on Linux). This operation is unsafe and should not be normally used. + In particular, specifying the wrong image or the wrong block device may + lead to data corruption as no validation is performed by `nbd` kernel driver. + + The --options argument is a comma separated list of device type + specific options (opt1,opt2=val,...). + +:command:`device detach` [-t | --device-type *device-type*] [-o | --options *device-options*] *image-spec* | *snap-spec* | *device-path* + Detach the block device that was mapped or attached (currently only `nbd` + on Linux). This operation is unsafe and should not be normally used. + + The --options argument is a comma separated list of device type + specific options (opt1,opt2=val,...). + :command:`diff` [--from-snap *snap-name*] [--whole-object] *image-spec* | *snap-spec* Dump a list of byte extents in the image that have changed since the specified start snapshot, or since the image was created. Each output line includes the starting offset diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index 98d440213925e..c2ce02e48841b 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -27,6 +27,8 @@ copy (cp) Copy src image to dest. create Create an empty image. deep copy (deep cp) Deep copy src image to dest. + device attach Attach image to device. + device detach Detach image from device. device list (showmapped) List mapped rbd images. device map (map) Map an image to a block device. device unmap (unmap) Unmap a rbd device. @@ -570,6 +572,56 @@ (-) supports disabling-only on existing images (+) enabled by default for new images if features not specified + rbd help device attach + usage: rbd device attach [--device-type ] [--pool ] + [--namespace ] [--image ] + [--snap ] --device [--read-only] + [--force] [--exclusive] [--quiesce] + [--quiesce-hook ] [--options ] + + + Attach image to device. + + Positional arguments + image or snapshot specification + (example: + [/[/]][@ + ]) + + Optional arguments + -t [ --device-type ] arg device type [ggate, krbd (default), nbd] + -p [ --pool ] arg pool name + --namespace arg namespace name + --image arg image name + --snap arg snapshot name + --device arg specify device path + --read-only attach read-only + --force force attach + --exclusive disable automatic exclusive lock transitions + --quiesce use quiesce hooks + --quiesce-hook arg quiesce hook path + -o [ --options ] arg device specific options + + rbd help device detach + usage: rbd device detach [--device-type ] [--pool ] + [--image ] [--snap ] + [--options ] + + + Detach image from device. + + Positional arguments + image, snapshot, or device specification + [/][@] or + + + Optional arguments + -t [ --device-type ] arg device type [ggate, krbd (default), nbd] + -p [ --pool ] arg pool name + --image arg image name + --snap arg snapshot name + -o [ --options ] arg device specific options + rbd help device list usage: rbd device list [--device-type ] [--format ] [--pretty-format] diff --git a/src/tools/rbd/action/Device.cc b/src/tools/rbd/action/Device.cc index d88725f23f8ae..17d286421d301 100644 --- a/src/tools/rbd/action/Device.cc +++ b/src/tools/rbd/action/Device.cc @@ -23,6 +23,10 @@ namespace po = boost::program_options; const std::vector &ceph_global_args); \ int execute_unmap(const po::variables_map &vm, \ const std::vector &ceph_global_args); \ + int execute_attach(const po::variables_map &vm, \ + const std::vector &ceph_global_args); \ + int execute_detach(const po::variables_map &vm, \ + const std::vector &ceph_global_args); \ } DECLARE_DEVICE_OPERATIONS(ggate); @@ -41,30 +45,42 @@ struct DeviceOperations { const std::vector &ceph_global_args); int (*execute_unmap)(const po::variables_map &vm, const std::vector &ceph_global_args); + int (*execute_attach)(const po::variables_map &vm, + const std::vector &ceph_global_args); + int (*execute_detach)(const po::variables_map &vm, + const std::vector &ceph_global_args); }; const DeviceOperations ggate_operations = { ggate::execute_list, ggate::execute_map, ggate::execute_unmap, + ggate::execute_attach, + ggate::execute_detach, }; const DeviceOperations krbd_operations = { kernel::execute_list, kernel::execute_map, kernel::execute_unmap, + kernel::execute_attach, + kernel::execute_detach, }; const DeviceOperations nbd_operations = { nbd::execute_list, nbd::execute_map, nbd::execute_unmap, + nbd::execute_attach, + nbd::execute_detach, }; const DeviceOperations wnbd_operations = { wnbd::execute_list, wnbd::execute_map, wnbd::execute_unmap, + wnbd::execute_attach, + wnbd::execute_detach, }; enum device_type_t { @@ -189,6 +205,44 @@ int execute_unmap(const po::variables_map &vm, return (*get_device_operations(vm)->execute_unmap)(vm, ceph_global_init_args); } +void get_attach_arguments(po::options_description *positional, + po::options_description *options) { + add_device_type_option(options); + at::add_image_or_snap_spec_options(positional, options, + at::ARGUMENT_MODIFIER_NONE); + options->add_options() + ("device", po::value()->required(), "specify device path") + ("read-only", po::bool_switch(), "attach read-only") + ("force", po::bool_switch(), "force attach") + ("exclusive", po::bool_switch(), "disable automatic exclusive lock transitions") + ("quiesce", po::bool_switch(), "use quiesce hooks") + ("quiesce-hook", po::value(), "quiesce hook path"); + add_device_specific_options(options); +} + +int execute_attach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return (*get_device_operations(vm)->execute_attach)(vm, ceph_global_init_args); +} + +void get_detach_arguments(po::options_description *positional, + po::options_description *options) { + add_device_type_option(options); + positional->add_options() + ("image-or-snap-or-device-spec", + "image, snapshot, or device specification\n" + "[/][@] or "); + at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE); + at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE); + at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE); + add_device_specific_options(options); +} + +int execute_detach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return (*get_device_operations(vm)->execute_detach)(vm, ceph_global_init_args); +} + Shell::SwitchArguments switched_arguments({"exclusive", "force", "quiesce", "read-only"}); @@ -208,6 +262,14 @@ Shell::Action action_unmap( {"device", "unmap"}, {"unmap"}, "Unmap a rbd device.", "", &get_unmap_arguments, &execute_unmap); +Shell::Action action_attach( + {"device", "attach"}, {}, "Attach image to device.", "", + &get_attach_arguments, &execute_attach); + +Shell::Action action_detach( + {"device", "detach"}, {}, "Detach image from device.", "", + &get_detach_arguments, &execute_detach); + } // namespace device } // namespace action } // namespace rbd diff --git a/src/tools/rbd/action/Ggate.cc b/src/tools/rbd/action/Ggate.cc index bae9778bbce9f..4ff02d4874819 100644 --- a/src/tools/rbd/action/Ggate.cc +++ b/src/tools/rbd/action/Ggate.cc @@ -207,6 +207,16 @@ int execute_unmap(const po::variables_map &vm, return call_ggate_cmd(vm, args, ceph_global_init_args); } +int execute_attach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return -EOPNOTSUPP; +} + +int execute_detach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return -EOPNOTSUPP; +} + } // namespace ggate } // namespace action } // namespace rbd diff --git a/src/tools/rbd/action/Kernel.cc b/src/tools/rbd/action/Kernel.cc index cb59334652a55..ef6f878546fc7 100644 --- a/src/tools/rbd/action/Kernel.cc +++ b/src/tools/rbd/action/Kernel.cc @@ -656,6 +656,16 @@ int execute_unmap(const po::variables_map &vm, return 0; } +int execute_attach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return -EOPNOTSUPP; +} + +int execute_detach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return -EOPNOTSUPP; +} + } // namespace kernel } // namespace action } // namespace rbd diff --git a/src/tools/rbd/action/Nbd.cc b/src/tools/rbd/action/Nbd.cc index 592ea5194352a..94a5f1701bf8b 100644 --- a/src/tools/rbd/action/Nbd.cc +++ b/src/tools/rbd/action/Nbd.cc @@ -134,6 +134,106 @@ int execute_list(const po::variables_map &vm, return call_nbd_cmd(vm, args, ceph_global_init_args); } +int execute_attach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { +#if defined(__FreeBSD__) || defined(_WIN32) + std::cerr << "rbd: nbd device is not supported" << std::endl; + return -EOPNOTSUPP; +#endif + std::vector args; + std::string device_path; + + args.push_back("attach"); + std::string img; + int r = get_image_or_snap_spec(vm, &img); + if (r < 0) { + return r; + } + args.push_back(img); + + if (vm.count("device")) { + device_path = vm["device"].as(); + args.push_back("--device"); + args.push_back(device_path); + } else { + std::cerr << "rbd: device was not specified" << std::endl; + return -EINVAL; + } + + if (!vm["force"].as()) { + std::cerr << "rbd: could not validate attach request\n"; + std::cerr << "rbd: mismatching the image and the device may lead to data corruption\n"; + std::cerr << "rbd: must specify --force to proceed" << std::endl; + return -EINVAL; + } + + if (vm["quiesce"].as()) { + args.push_back("--quiesce"); + } + + if (vm["read-only"].as()) { + args.push_back("--read-only"); + } + + if (vm["exclusive"].as()) { + args.push_back("--exclusive"); + } + + if (vm.count("quiesce-hook")) { + args.push_back("--quiesce-hook"); + args.push_back(vm["quiesce-hook"].as()); + } + + if (vm.count("options")) { + r = parse_options(vm["options"].as>(), &args); + if (r < 0) { + return r; + } + } + + return call_nbd_cmd(vm, args, ceph_global_init_args); +} + +int execute_detach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { +#if defined(__FreeBSD__) || defined(_WIN32) + std::cerr << "rbd: nbd device is not supported" << std::endl; + return -EOPNOTSUPP; +#endif + std::string device_name = utils::get_positional_argument(vm, 0); + if (!boost::starts_with(device_name, "/dev/")) { + device_name.clear(); + } + + std::string image_name; + if (device_name.empty()) { + int r = get_image_or_snap_spec(vm, &image_name); + if (r < 0) { + return r; + } + } + + if (device_name.empty() && image_name.empty()) { + std::cerr << "rbd: detach requires either image name or device path" + << std::endl; + return -EINVAL; + } + + std::vector args; + + args.push_back("detach"); + args.push_back(device_name.empty() ? image_name : device_name); + + if (vm.count("options")) { + int r = parse_options(vm["options"].as>(), &args); + if (r < 0) { + return r; + } + } + + return call_nbd_cmd(vm, args, ceph_global_init_args); +} + int execute_map(const po::variables_map &vm, const std::vector &ceph_global_init_args) { #if defined(__FreeBSD__) || defined(_WIN32) diff --git a/src/tools/rbd/action/Wnbd.cc b/src/tools/rbd/action/Wnbd.cc index e6c30a5a13482..6a5f34ba7a6a3 100644 --- a/src/tools/rbd/action/Wnbd.cc +++ b/src/tools/rbd/action/Wnbd.cc @@ -187,6 +187,16 @@ int execute_unmap(const po::variables_map &vm, return call_wnbd_cmd(vm, args, ceph_global_init_args); } +int execute_attach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return -EOPNOTSUPP; +} + +int execute_detach(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + return -EOPNOTSUPP; +} + } // namespace wnbd } // namespace action } // namespace rbd -- 2.39.5