]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rbd-ggate: allow to unmap by image or snap spec
authorMykola Golub <to.my.trociny@gmail.com>
Mon, 25 Dec 2017 11:02:35 +0000 (11:02 +0000)
committerMykola Golub <to.my.trociny@gmail.com>
Wed, 27 Dec 2017 20:29:58 +0000 (20:29 +0000)
(to match the behaviour of krbd unmap)

Signed-off-by: Mykola Golub <to.my.trociny@gmail.com>
qa/workunits/rbd/rbd-ggate.sh
src/tools/rbd/action/Ggate.cc
src/tools/rbd_ggate/main.cc

index 1cc78d12f08f9dd280a81381acc1cc790447b6aa..1c4e504a4d2706b1198ca7b3bc95f77be47cefac 100755 (executable)
@@ -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
index 24ffdfc07a2e5e7209635c6112f142684ce05939..67ed09dbec2f7408dcba65afdfb57f87211ec62f 100644 (file)
@@ -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<const char*> 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"
+     "[<pool-name>/]<image-name>[@<snapshot-name>] or <device-path>");
+  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<const char*> 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);
 }
index d1c4fba93ba35ba3a8785d1e99f58ff92e361c92..b16f5b40aea0c001d34ae9c30d4e221e8d370937 100644 (file)
@@ -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<std::string, rbd::ggate::Driver::DevInfo> 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: