]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: new command to disconnect journal client
authorMykola Golub <mgolub@mirantis.com>
Wed, 3 Aug 2016 11:19:51 +0000 (14:19 +0300)
committerJason Dillaman <dillaman@redhat.com>
Tue, 11 Oct 2016 16:40:45 +0000 (12:40 -0400)
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
(cherry picked from commit fc3ba54b3c101498a08a3f34ac8f7eab0152ad7c)

src/test/cli/rbd/help.t
src/tools/rbd/action/Journal.cc

index 346345c7d97fa146d6df19f5371b71a37f613753..6c86a413a3d5bc537a6379699173141391d9c7d1 100644 (file)
@@ -30,6 +30,7 @@
       import-diff                 Import an incremental diff.
       info                        Show information about image size, striping,
                                   etc.
+      journal client disconnect   Flag image journal client as disconnected.
       journal export              Export image journal.
       journal import              Import image journal.
       journal info                Show information about image journal.
     --format arg          output format [plain, json, or xml]
     --pretty-format       pretty formatting (json and xml)
   
+  rbd help journal client disconnect
+  usage: rbd journal client disconnect [--pool <pool>] [--image <image>] 
+                                       [--journal <journal>] 
+                                       [--client-id <client-id>] 
+                                       <journal-spec> 
+  
+  Flag image journal client as disconnected.
+  
+  Positional arguments
+    <journal-spec>       journal specification
+                         (example: [<pool-name>/]<journal-name>)
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --image arg          image name
+    --journal arg        journal name
+    --client-id arg      client ID (or leave unspecified to disconnect all)
+  
   rbd help journal export
   usage: rbd journal export [--pool <pool>] [--image <image>] 
                             [--journal <journal>] [--path <path>] [--verbose] 
index ca2620a81278319582ff31abce9cbd5de601f1af..cf8ec554353a68d9ddd7aa63ae793dea23487df8 100644 (file)
@@ -168,6 +168,66 @@ static int do_reset_journal(librados::IoCtx& io_ctx,
   return 0;
 }
 
+static int do_disconnect_journal_client(librados::IoCtx& io_ctx,
+                                       const std::string& journal_id,
+                                       const std::string& client_id)
+{
+  int r;
+
+  C_SaferCond cond;
+  uint64_t minimum_set;
+  uint64_t active_set;
+  std::set<cls::journal::Client> registered_clients;
+  std::string oid = ::journal::Journaler::header_oid(journal_id);
+
+  cls::journal::client::get_mutable_metadata(io_ctx, oid, &minimum_set,
+                                            &active_set, &registered_clients,
+                                            &cond);
+  r = cond.wait();
+  if (r < 0) {
+    std::cerr << "warning: failed to get journal metadata" << std::endl;
+    return r;
+  }
+
+  static const std::string IMAGE_CLIENT_ID("");
+
+  bool found = false;
+  for (auto &c : registered_clients) {
+    if (c.id == IMAGE_CLIENT_ID || (!client_id.empty() && client_id != c.id)) {
+      continue;
+    }
+    r = cls::journal::client::client_update_state(io_ctx, oid, c.id,
+                                 cls::journal::CLIENT_STATE_DISCONNECTED);
+    if (r < 0) {
+      std::cerr << "warning: failed to disconnect client " << c.id << ": "
+               << cpp_strerror(r) << std::endl;
+      return r;
+    }
+    std::cout << "client " << c.id << " disconnected" << std::endl;
+    found = true;
+  }
+
+  if (!found) {
+    if (!client_id.empty()) {
+      std::cerr << "warning: client " << client_id << " is not registered"
+               << std::endl;
+    } else {
+      std::cerr << "no registered clients to disconnect" << std::endl;
+    }
+    return -ENOENT;
+  }
+
+  bufferlist bl;
+  r = io_ctx.notify2(oid, bl, 5000, NULL);
+  if (r < 0) {
+    std::cerr << "warning: failed to notify state change:" << ": "
+             << cpp_strerror(r) << std::endl;
+    return r;
+  }
+
+  return 0;
+}
+
 class Journaler : public ::journal::Journaler {
 public:
   Journaler(librados::IoCtx& io_ctx, const std::string& journal_id,
@@ -843,6 +903,45 @@ int execute_reset(const po::variables_map &vm) {
   return 0;
 }
 
+void get_client_disconnect_arguments(po::options_description *positional,
+                                    po::options_description *options) {
+  at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+  options->add_options()
+    ("client-id", po::value<std::string>(),
+     "client ID (or leave unspecified to disconnect all)");
+}
+
+int execute_client_disconnect(const po::variables_map &vm) {
+  size_t arg_index = 0;
+  std::string pool_name;
+  std::string journal_name;
+  int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE,
+                                       &arg_index, &pool_name, &journal_name);
+  if (r < 0) {
+    return r;
+  }
+
+  std::string client_id;
+  if (vm.count("client-id")) {
+    client_id = vm["client-id"].as<std::string>();
+  }
+
+  librados::Rados rados;
+  librados::IoCtx io_ctx;
+  r = utils::init(pool_name, &rados, &io_ctx);
+  if (r < 0) {
+    return r;
+  }
+
+  r = do_disconnect_journal_client(io_ctx, journal_name, client_id);
+  if (r < 0) {
+    std::cerr << "rbd: journal client disconnect: " << cpp_strerror(r)
+             << std::endl;
+    return r;
+  }
+  return 0;
+}
+
 void get_inspect_arguments(po::options_description *positional,
                           po::options_description *options) {
   at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
@@ -981,6 +1080,11 @@ Shell::Action action_import(
   {"journal", "import"}, {}, "Import image journal.", "",
   &get_import_arguments, &execute_import);
 
+Shell::Action action_disconnect(
+  {"journal", "client", "disconnect"}, {},
+  "Flag image journal client as disconnected.", "",
+  &get_client_disconnect_arguments, &execute_client_disconnect);
+
 } // namespace journal
 } // namespace action
 } // namespace rbd