]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: add 'osd purge'
authorJoao Eduardo Luis <joao@suse.de>
Wed, 12 Apr 2017 13:29:23 +0000 (14:29 +0100)
committerJoao Eduardo Luis <joao@suse.de>
Mon, 5 Jun 2017 14:31:40 +0000 (15:31 +0100)
Signed-off-by: Joao Eduardo Luis <joao@suse.de>
src/mon/MonCommands.h
src/mon/OSDMonitor.cc
src/mon/OSDMonitor.h

index 70de88adc4b0317014980ea2b2901c8895cd4b66..4494d44d6b1b10b5334d9dad41cad686ec938bdc 100644 (file)
@@ -699,6 +699,12 @@ COMMAND("osd destroy " \
         "but removes cephx keys, config-key data and lockbox keys, "\
         "rendering data permanently unreadable.", \
         "osd", "rw", "cli,rest")
+COMMAND("osd purge " \
+        "name=id,type=CephOsdName " \
+        "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
+        "purge all osd data from the monitors. Combines `osd destroy`, " \
+        "`osd rm`, and `osd crush rm`.", \
+        "osd", "rw", "cli,rest")
 COMMAND("osd lost " \
        "name=id,type=CephOsdName " \
        "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
index 38ed0395161eb4f3dc52a64fc35dcecea42101a4..e637ffdeeb3492e161422079a7fb077eb69cb934 100644 (file)
@@ -6375,7 +6375,7 @@ int OSDMonitor::prepare_command_pool_set(map<string,cmd_vartype> &cmdmap,
   return 0;
 }
 
-int OSDMonitor::prepare_command_osd_crush_remove(
+int OSDMonitor::_prepare_command_osd_crush_remove(
     CrushWrapper &newcrush,
     int32_t id,
     int32_t ancestor,
@@ -6390,13 +6390,31 @@ int OSDMonitor::prepare_command_osd_crush_remove(
   } else {
     err = newcrush.remove_item(g_ceph_context, id, unlink_only);
   }
+  return err;
+}
+
+void OSDMonitor::do_osd_crush_remove(CrushWrapper& newcrush)
+{
+  pending_inc.crush.clear();
+  newcrush.encode(pending_inc.crush, mon->get_quorum_con_features());
+}
+
+int OSDMonitor::prepare_command_osd_crush_remove(
+    CrushWrapper &newcrush,
+    int32_t id,
+    int32_t ancestor,
+    bool has_ancestor,
+    bool unlink_only)
+{
+  int err = _prepare_command_osd_crush_remove(
+      newcrush, id, ancestor,
+      has_ancestor, unlink_only);
 
   if (err < 0)
     return err;
 
   assert(err == 0);
-  pending_inc.crush.clear();
-  newcrush.encode(pending_inc.crush, mon->get_quorum_con_features());
+  do_osd_crush_remove(newcrush);
 
   return 0;
 }
@@ -6503,6 +6521,66 @@ int OSDMonitor::prepare_command_osd_destroy(
 
   pending_inc.new_state[id] = CEPH_OSD_DESTROYED;
   pending_inc.new_uuid[id] = uuid_d();
+
+  // we can only propose_pending() once per service, otherwise we'll be
+  // defying PaxosService and all laws of nature. Therefore, as we may
+  // be used during 'osd purge', let's keep the caller responsible for
+  // proposing.
+
+  return 0;
+}
+
+int OSDMonitor::prepare_command_osd_purge(
+    int32_t id,
+    stringstream& ss)
+{
+  assert(paxos->is_plugged());
+  dout(10) << __func__ << " purging osd." << id << dendl;
+
+  assert(!osdmap.is_up(id));
+
+  /*
+   * This may look a bit weird, but this is what's going to happen:
+   *
+   *  1. we make sure that removing from crush works
+   *  2. we call `prepare_command_osd_destroy()`. If it returns an
+   *     error, then we abort the whole operation, as no updates
+   *     have been made. However, we this function will have
+   *     side-effects, thus we need to make sure that all operations
+   *     performed henceforth will *always* succeed.
+   *  3. we call `prepare_command_osd_remove()`. Although this
+   *     function can return an error, it currently only checks if the
+   *     osd is up - and we have made sure that it is not so, so there
+   *     is no conflict, and it is effectively an update.
+   *  4. finally, we call `do_osd_crush_remove()`, which will perform
+   *     the crush update we delayed from before.
+   */
+
+  CrushWrapper newcrush;
+  _get_pending_crush(newcrush);
+
+  int err = _prepare_command_osd_crush_remove(newcrush, id, 0, false, false);
+  if (err == -ENOENT) {
+    err = 0;
+  } else if (err < 0) {
+    ss << "error removing osd." << id << " from crush";
+    return err;
+  }
+
+  // no point destroying the osd again if it has already been marked destroyed
+  if (!osdmap.is_destroyed(id)) {
+    err = prepare_command_osd_destroy(id, ss);
+    if (err < 0) {
+      return err;
+    }
+    assert(0 == err);
+  }
+
+  err = prepare_command_osd_remove(id);
+  // we should not be busy, as we should have made sure this id is not up.
+  assert(0 == err);
+
+  do_osd_crush_remove(newcrush);
   return 0;
 }
 
@@ -8321,7 +8399,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       return true;
     }
 
-  } else if (prefix == "osd destroy") {
+  } else if (prefix == "osd destroy" || prefix == "osd purge") {
     /* Destroying an OSD means that we don't expect to further make use of
      * the OSDs data (which may even become unreadable after this operation),
      * and that we are okay with scrubbing all its cephx keys and config-key
@@ -8350,6 +8428,11 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       goto reply;
     }
 
+    bool is_destroy = (prefix == "osd destroy");
+    if (!is_destroy) {
+      assert("osd purge" == prefix);
+    }
+
     string sure;
     if (!cmd_getval(g_ceph_context, cmdmap, "sure", sure) ||
         sure != "--yes-i-really-mean-it") {
@@ -8366,21 +8449,29 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "osd." << id << " is not `down`.";
       err = -EBUSY;
       goto reply;
-    } else if (osdmap.is_destroyed(id)) {
+    } else if (is_destroy && osdmap.is_destroyed(id)) {
       ss << "destroyed osd." << id;
       err = 0;
       goto reply;
     }
 
     paxos->plug();
-    err = prepare_command_osd_destroy(id, ss);
+    if (is_destroy) {
+      err = prepare_command_osd_destroy(id, ss);
+    } else {
+      err = prepare_command_osd_purge(id, ss);
+    }
     paxos->unplug();
 
     if (err < 0) {
       goto reply;
     }
 
-    ss << "destroyed osd." << id;
+    if (is_destroy) {
+      ss << "destroyed osd." << id;
+    } else {
+      ss << "purged osd." << id;
+    }
     getline(ss, rs);
     wait_for_finished_proposal(op,
         new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1));
index f4aa28803a4bcdf644cb19b4a848b9933c216913..dc44e0653b42028de2b676736b9554f73853a902 100644 (file)
@@ -476,7 +476,15 @@ public:
   bool prepare_command(MonOpRequestRef op);
   bool prepare_command_impl(MonOpRequestRef op, map<string,cmd_vartype>& cmdmap);
 
+  int prepare_command_osd_purge(int32_t id, stringstream& ss);
   int prepare_command_osd_destroy(int32_t id, stringstream& ss);
+  int _prepare_command_osd_crush_remove(
+      CrushWrapper &newcrush,
+      int32_t id,
+      int32_t ancestor,
+      bool has_ancestor,
+      bool unlink_only);
+  void do_osd_crush_remove(CrushWrapper& newcrush);
   int prepare_command_osd_crush_remove(
       CrushWrapper &newcrush,
       int32_t id,