From be87e8b118e4cbc24bdcdf556cf3267430f473d1 Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Mon, 25 Dec 2017 11:02:35 +0000 Subject: [PATCH] rbd-ggate: allow to unmap by image or snap spec (to match the behaviour of krbd unmap) Signed-off-by: Mykola Golub --- qa/workunits/rbd/rbd-ggate.sh | 15 ++++++++ src/tools/rbd/action/Ggate.cc | 66 ++++++++++++++++++++++++----------- src/tools/rbd_ggate/main.cc | 48 +++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 23 deletions(-) diff --git a/qa/workunits/rbd/rbd-ggate.sh b/qa/workunits/rbd/rbd-ggate.sh index 1cc78d12f08..1c4e504a4d2 100755 --- a/qa/workunits/rbd/rbd-ggate.sh +++ b/qa/workunits/rbd/rbd-ggate.sh @@ -184,4 +184,19 @@ _sudo rbd-ggate unmap ${DEV} DEV= rbd bench -p ${POOL} ${IMAGE} --io-type=write --io-size=1024 --io-total=1024 +# unmap by image name test +DEV=`_sudo rbd-ggate map ${POOL}/${IMAGE}` +_sudo rbd-ggate list | grep " ${DEV} *$" +_sudo rbd-ggate unmap "${POOL}/${IMAGE}" +rbd-ggate list-mapped | expect_false grep " ${DEV} *$" +DEV= + +# map/unmap snap test +rbd snap create ${POOL}/${IMAGE}@snap +DEV=`_sudo rbd-ggate map ${POOL}/${IMAGE}@snap` +_sudo rbd-ggate list | grep " ${DEV} *$" +_sudo rbd-ggate unmap "${POOL}/${IMAGE}@snap" +rbd-ggate list-mapped | expect_false grep " ${DEV} *$" +DEV= + echo OK diff --git a/src/tools/rbd/action/Ggate.cc b/src/tools/rbd/action/Ggate.cc index 24ffdfc07a2..67ed09dbec2 100644 --- a/src/tools/rbd/action/Ggate.cc +++ b/src/tools/rbd/action/Ggate.cc @@ -76,6 +76,30 @@ static int call_ggate_cmd(const po::variables_map &vm, return 0; } +int get_image_or_snap_spec(const po::variables_map &vm, std::string *spec) { + size_t arg_index = 0; + std::string pool_name; + std::string image_name; + std::string snap_name; + int r = utils::get_pool_image_snapshot_names( + vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name, + &snap_name, utils::SNAPSHOT_PRESENCE_PERMITTED, + utils::SPEC_VALIDATION_NONE); + if (r < 0) { + return r; + } + + spec->append(pool_name); + spec->append("/"); + spec->append(image_name); + if (!snap_name.empty()) { + spec->append("@"); + spec->append(snap_name); + } + + return 0; +} + void get_list_arguments(po::options_description *positional, po::options_description *options) { at::add_format_options(options); @@ -111,28 +135,13 @@ void get_map_arguments(po::options_description *positional, int execute_map(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string image_name; - std::string snap_name; - int r = utils::get_pool_image_snapshot_names( - vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name, - &snap_name, utils::SNAPSHOT_PRESENCE_PERMITTED, - utils::SPEC_VALIDATION_NONE); - if (r < 0) { - return r; - } - std::vector args; args.push_back("map"); std::string img; - img.append(pool_name); - img.append("/"); - img.append(image_name); - if (!snap_name.empty()) { - img.append("@"); - img.append(snap_name); + int r = get_image_or_snap_spec(vm, &img); + if (r < 0) { + return r; } args.push_back(img.c_str()); @@ -154,7 +163,12 @@ void get_unmap_arguments(po::options_description *positional, po::options_description *options) { positional->add_options() - ("device-spec", "specify ggate device"); + ("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); } int execute_unmap(const po::variables_map &vm) @@ -164,15 +178,25 @@ int execute_unmap(const po::variables_map &vm) device_name.clear(); } + std::string image_name; if (device_name.empty()) { - std::cerr << "rbd: ggate unmap requires device path" << std::endl; + 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: unmap requires either image name or device path" + << std::endl; return -EINVAL; } std::vector args; args.push_back("unmap"); - args.push_back(device_name.c_str()); + args.push_back(device_name.empty() ? image_name.c_str() : + device_name.c_str()); return call_ggate_cmd(vm, args); } diff --git a/src/tools/rbd_ggate/main.cc b/src/tools/rbd_ggate/main.cc index d1c4fba93ba..b16f5b40aea 100644 --- a/src/tools/rbd_ggate/main.cc +++ b/src/tools/rbd_ggate/main.cc @@ -273,6 +273,46 @@ static int parse_imgpath(const std::string &imgpath, std::string *poolname, return 0; } +static bool find_mapped_dev_by_spec(const std::string &spec, + std::string *devname) { + std::string poolname, imgname, snapname; + int r = parse_imgpath(spec, &poolname, &imgname, &snapname); + if (r < 0) { + return false; + } + if (poolname.empty()) { + // We could use rbd_default_pool config to set pool name but then + // we would need to initialize the global context. So right now it + // is mandatory for the user to specify a pool. Fortunately the + // preferred way for users to call rbd-ggate is via rbd, which + // cares to set the pool name. + return false; + } + + std::map devs; + r = rbd::ggate::Driver::list(&devs); + if (r < 0) { + return false; + } + + for (auto &it : devs) { + auto &name = it.second.first; + auto &info = it.second.second; + if (!boost::starts_with(info, "RBD ")) { + continue; + } + + std::string p, i, s; + parse_imgpath(info.substr(4), &p, &i, &s); + if (p == poolname && i == imgname && s == snapname) { + *devname = name; + return true; + } + } + + return false; +} + static int do_list(const std::string &format, bool pretty_format) { rbd::ggate::Driver::load(); @@ -413,10 +453,14 @@ int main(int argc, const char *argv[]) { break; case Disconnect: if (args.begin() == args.end()) { - cerr << "rbd-ggate: must specify ggate device path" << std::endl; + std::cerr << "rbd-ggate: must specify ggate device or image-or-snap-spec" + << std::endl; return EXIT_FAILURE; } - devpath = *args.begin(); + if (boost::starts_with(*args.begin(), "/dev/") || + !find_mapped_dev_by_spec(*args.begin(), &devpath)) { + devpath = *args.begin(); + } args.erase(args.begin()); break; default: -- 2.39.5