]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-nbd: output format support for list-mapped command
authorMykola Golub <mgolub@suse.com>
Wed, 27 Dec 2017 18:50:40 +0000 (20:50 +0200)
committerJason Dillaman <dillaman@redhat.com>
Thu, 10 Oct 2019 22:54:43 +0000 (18:54 -0400)
Signed-off-by: Mykola Golub <mgolub@suse.com>
(cherry picked from commit e372e9492bb7f535c0f15a078f1eab2de3fad113)

qa/workunits/rbd/rbd-nbd.sh
src/test/cli/rbd/help.t
src/tools/rbd/action/Nbd.cc
src/tools/rbd_nbd/rbd-nbd.cc

index def3f15a554ff4cdd3c2357d8167522b9d1a2352..1af2336b8a5bce5f17acf9b877e0ddd9e830965d 100755 (executable)
@@ -74,6 +74,14 @@ function expect_false()
   if "$@"; then return 1; else return 0; fi
 }
 
+function get_pid()
+{
+    PID=$(rbd-nbd --format xml list-mapped | $XMLSTARLET sel -t -v \
+      "//devices/device[pool='${POOL}'][image='${IMAGE}'][device='${DEV}']/id")
+    test -n "${PID}"
+    ps -p ${PID} -o cmd | grep rbd-nbd
+}
+
 #
 # main
 #
@@ -90,12 +98,14 @@ fi
 expect_false _sudo rbd-nbd map INVALIDIMAGE
 expect_false _sudo rbd-nbd --device INVALIDDEV map ${IMAGE}
 
+# list format test
+expect_false rbd-nbd --format INVALID list-mapped
+rbd-nbd --format json --pretty-format list-mapped
+rbd-nbd --format xml list-mapped
+
 # map test using the first unused device
 DEV=`_sudo rbd-nbd map ${POOL}/${IMAGE}`
-PID=$(rbd-nbd list-mapped | awk -v pool=${POOL} -v img=${IMAGE} -v dev=${DEV} \
-    '$2 == pool && $3 == img && $5 == dev {print $1}')
-test -n "${PID}"
-ps -p ${PID} -o cmd | grep rbd-nbd
+get_pid
 # map test specifying the device
 expect_false _sudo rbd-nbd --device ${DEV} map ${POOL}/${IMAGE}
 dev1=${DEV}
@@ -106,10 +116,7 @@ DEV=
 DEV=`_sudo rbd-nbd --device ${dev1} map ${POOL}/${IMAGE}`
 [ "${DEV}" = "${dev1}" ]
 rbd-nbd list-mapped | grep "${IMAGE}"
-PID=$(rbd-nbd list-mapped | awk -v pool=${POOL} -v img=${IMAGE} -v dev=${DEV} \
-    '$2 == pool && $3 == img && $5 == dev {print $1}')
-test -n "${PID}"
-ps -p ${PID} -o cmd | grep rbd-nbd
+get_pid
 
 # read test
 [ "`dd if=${DATA} bs=1M | md5sum`" = "`_sudo dd if=${DEV} bs=1M | md5sum`" ]
@@ -161,10 +168,7 @@ _sudo rbd-nbd unmap ${DEV}
 
 # exclusive option test
 DEV=`_sudo rbd-nbd map --exclusive ${POOL}/${IMAGE}`
-PID=$(rbd-nbd list-mapped | awk -v pool=${POOL} -v img=${IMAGE} -v dev=${DEV} \
-    '$2 == pool && $3 == img && $5 == dev {print $1}')
-test -n "${PID}"
-ps -p ${PID} -o cmd | grep rbd-nbd
+get_pid
 
 _sudo dd if=${DATA} of=${DEV} bs=1M oflag=direct
 expect_false timeout 10 \
@@ -175,10 +179,7 @@ rbd bench ${IMAGE} --io-type write --io-size=1024 --io-total=1024
 
 # unmap by image name test
 DEV=`_sudo rbd-nbd map ${POOL}/${IMAGE}`
-PID=$(rbd-nbd list-mapped | awk -v pool=${POOL} -v img=${IMAGE} -v dev=${DEV} \
-    '$2 == pool && $3 == img && $5 == dev {print $1}')
-test -n "${PID}"
-ps -p ${PID} -o cmd | grep rbd-nbd
+get_pid
 _sudo rbd-nbd unmap "${IMAGE}"
 rbd-nbd list-mapped | expect_false grep "${DEV} $"
 DEV=
@@ -187,10 +188,7 @@ ps -p ${PID} -o cmd | expect_false grep rbd-nbd
 # map/unmap snap test
 rbd snap create ${POOL}/${IMAGE}@snap
 DEV=`_sudo rbd-nbd map ${POOL}/${IMAGE}@snap`
-PID=$(rbd-nbd list-mapped |
-      awk -v pool=${POOL} -v img=${IMAGE} -v snap=snap -v dev=${DEV} \
-          '$2 == pool && $3 == img && $4 == snap && $5 == dev {print $1}')
-test -n "${PID}"
+get_pid
 _sudo rbd-nbd unmap "${IMAGE}@snap"
 rbd-nbd list-mapped | expect_false grep "${DEV} $"
 DEV=
@@ -198,10 +196,7 @@ ps -p ${PID} -o cmd | expect_false grep rbd-nbd
 
 # auto unmap test
 DEV=`_sudo rbd-nbd map ${POOL}/${IMAGE}`
-PID=$(rbd-nbd list-mapped | awk -v pool=${POOL} -v img=${IMAGE} -v dev=${DEV} \
-    '$2 == pool && $3 == img && $5 == dev {print $1}')
-test -n "${PID}"
-ps -p ${PID} -o cmd | grep rbd-nbd
+get_pid
 _sudo kill ${PID}
 for i in `seq 10`; do
   rbd-nbd list-mapped | expect_false grep "^${PID} *${POOL} *${IMAGE}" && break
index ee63e52a44d6495957a65c34e9688e387c9c8f82..c93e4f402411615297db16a3e419af3444471774 100644 (file)
@@ -1024,10 +1024,14 @@ Skip test on FreeBSD as it generates different output there.
     --verbose            be verbose
   
   rbd help nbd list
-  usage: rbd nbd list 
+  usage: rbd nbd list [--format <format>] [--pretty-format] 
   
   List the nbd devices already used.
   
+  Optional arguments
+    --format arg         output format (plain, json, or xml) [default: plain]
+    --pretty-format      pretty formatting (json and xml)
+  
   rbd help nbd map
   usage: rbd nbd map [--pool <pool>] [--image <image>] [--snap <snap>] 
                      [--read-only] [--exclusive] [--device <device>] 
index 43f547704e5fea40db58a17040f52ea3fb450f90..b599f525449ae18c5b777c9cc91c4813e5ba75a2 100644 (file)
@@ -105,8 +105,9 @@ int get_image_or_snap_spec(const po::variables_map &vm, std::string *spec) {
 }
 
 void get_show_arguments(po::options_description *positional,
-                        po::options_description *options)
-{ }
+                        po::options_description *options) {
+  at::add_format_options(options);
+}
 
 int execute_show(const po::variables_map &vm)
 {
@@ -114,6 +115,14 @@ int execute_show(const po::variables_map &vm)
 
   args.push_back("list-mapped");
 
+  if (vm.count("format")) {
+    args.push_back("--format");
+    args.push_back(vm["format"].as<at::Format>().value.c_str());
+  }
+  if (vm["pretty-format"].as<bool>()) {
+    args.push_back("--pretty-format");
+  }
+
   return call_nbd_cmd(vm, args);
 }
 
index e59f95435a542430fdee17ae87595ccbde4b208a..413174aba180741f3c51ee2ce23d26e47040098c 100644 (file)
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 
-#include <iostream>
 #include <fstream>
+#include <iostream>
+#include <memory>
 #include <boost/regex.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 
-#include "mon/MonClient.h"
+#include "common/Formatter.h"
+#include "common/Preforker.h"
+#include "common/TextTable.h"
+#include "common/ceph_argparse.h"
 #include "common/config.h"
 #include "common/dout.h"
-
 #include "common/errno.h"
 #include "common/module.h"
 #include "common/safe_io.h"
-#include "common/TextTable.h"
-#include "common/ceph_argparse.h"
-#include "common/Preforker.h"
 #include "common/version.h"
+
 #include "global/global_init.h"
 #include "global/signal_handler.h"
 
@@ -56,6 +57,8 @@
 #include "include/stringify.h"
 #include "include/xlist.h"
 
+#include "mon/MonClient.h"
+
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -74,20 +77,27 @@ struct Config {
   std::string imgname;
   std::string snapname;
   std::string devpath;
+
+  std::string format;
+  bool pretty_format = false;
 };
 
 static void usage()
 {
   std::cout << "Usage: rbd-nbd [options] map <image-or-snap-spec>  Map an image to nbd device\n"
             << "               unmap <device|image-or-snap-spec>   Unmap nbd device\n"
-            << "               list-mapped                         List mapped nbd devices\n"
-            << "Options:\n"
+            << "               [options] list-mapped               List mapped nbd devices\n"
+            << "Map options:\n"
             << "  --device <device path>  Specify nbd device path\n"
             << "  --read-only             Map read-only\n"
             << "  --nbds_max <limit>      Override for module param nbds_max\n"
             << "  --max_part <limit>      Override for module param max_part\n"
             << "  --exclusive             Forbid writes by other clients\n"
             << "  --timeout <seconds>     Set nbd request timeout\n"
+            << "\n"
+            << "List options:\n"
+            << "  --format plain|json|xml Output format (default: plain)\n"
+            << "  --pretty-format         Pretty formatting (json and xml)\n"
             << std::endl;
   generic_server_usage();
 }
@@ -937,31 +947,59 @@ static int parse_imgpath(const std::string &imgpath, Config *cfg,
   return 0;
 }
 
-static int do_list_mapped_devices()
+static int do_list_mapped_devices(const std::string &format, bool pretty_format)
 {
   bool should_print = false;
+  std::unique_ptr<ceph::Formatter> f;
   TextTable tbl;
 
-  tbl.define_column("pid", TextTable::LEFT, TextTable::LEFT);
-  tbl.define_column("pool", TextTable::LEFT, TextTable::LEFT);
-  tbl.define_column("image", TextTable::LEFT, TextTable::LEFT);
-  tbl.define_column("snap", TextTable::LEFT, TextTable::LEFT);
-  tbl.define_column("device", TextTable::LEFT, TextTable::LEFT);
+  if (format == "json") {
+    f.reset(new JSONFormatter(pretty_format));
+  } else if (format == "xml") {
+    f.reset(new XMLFormatter(pretty_format));
+  } else if (!format.empty() && format != "plain") {
+    std::cerr << "rbd-nbd: invalid output format: " << format << std::endl;
+    return -EINVAL;
+  }
+
+  if (f) {
+    f->open_array_section("devices");
+  } else {
+    tbl.define_column("pid", TextTable::LEFT, TextTable::LEFT);
+    tbl.define_column("pool", TextTable::LEFT, TextTable::LEFT);
+    tbl.define_column("image", TextTable::LEFT, TextTable::LEFT);
+    tbl.define_column("snap", TextTable::LEFT, TextTable::LEFT);
+    tbl.define_column("device", TextTable::LEFT, TextTable::LEFT);
+  }
 
   int pid;
   Config cfg;
   NBDListIterator it;
   while (it.get(&pid, &cfg)) {
-    should_print = true;
-    if (cfg.snapname.empty()) {
-      cfg.snapname = "-";
+    if (f) {
+      f->open_object_section("device");
+      f->dump_int("id", pid);
+      f->dump_string("pool", cfg.poolname);
+      f->dump_string("image", cfg.imgname);
+      f->dump_string("snap", cfg.snapname);
+      f->dump_string("device", cfg.devpath);
+      f->close_section();
+    } else {
+      should_print = true;
+      if (cfg.snapname.empty()) {
+        cfg.snapname = "-";
+      }
+      tbl << pid << cfg.poolname << cfg.imgname << cfg.snapname << cfg.devpath
+          << TextTable::endrow;
     }
-    tbl << pid << cfg.poolname << cfg.imgname << cfg.snapname << cfg.devpath
-        << TextTable::endrow;
   }
 
+  if (f) {
+    f->close_section(); // devices
+    f->flush(std::cout);
+  }
   if (should_print) {
-    cout << tbl;
+    std::cout << tbl;
   }
   return 0;
 }
@@ -1043,6 +1081,10 @@ static int parse_args(vector<const char*>& args, std::ostream *err_msg,
         *err_msg << "rbd-nbd: Invalid argument for timeout!";
         return -EINVAL;
       }
+    } else if (ceph_argparse_witharg(args, i, &cfg->format, err, "--format",
+                                     (char *)NULL)) {
+    } else if (ceph_argparse_flag(args, i, "--pretty-format", (char *)NULL)) {
+      cfg->pretty_format = true;
     } else {
       ++i;
     }
@@ -1149,7 +1191,7 @@ static int rbd_nbd(int argc, const char *argv[])
         return -EINVAL;
       break;
     case List:
-      r = do_list_mapped_devices();
+      r = do_list_mapped_devices(cfg.format, cfg.pretty_format);
       if (r < 0)
         return -EINVAL;
       break;