From d2b41d4095074447df247907934626f4287cd91b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 26 Jun 2018 07:00:33 -0500 Subject: [PATCH] mon,mgr: guard 'osd destroy' with 'osd safe-to-destroy' check Rename actual command 'osd destroy-actual', and map 'osd destroy' to the mgr code so that we first check safe-to-destroy. Signed-off-by: Sage Weil --- src/mgr/DaemonServer.cc | 58 ++++++++++++++++++++++++++++++++--------- src/mgr/MgrCommands.h | 8 ++++++ src/mon/MonCommands.h | 2 +- src/mon/OSDMonitor.cc | 13 ++++++--- 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/mgr/DaemonServer.cc b/src/mgr/DaemonServer.cc index d94e663ae1e0e..ae427392e6df7 100644 --- a/src/mgr/DaemonServer.cc +++ b/src/mgr/DaemonServer.cc @@ -1201,17 +1201,28 @@ bool DaemonServer::handle_command(MCommand *m) cmdctx->reply(r, ss); return true; } - } else if (prefix == "osd safe-to-destroy") { - vector ids; - cmd_getval(g_ceph_context, cmdctx->cmdmap, "ids", ids); + } else if (prefix == "osd safe-to-destroy" || + prefix == "osd destroy") { set osds; - int r; - cluster_state.with_osdmap([&](const OSDMap& osdmap) { - r = osdmap.parse_osd_id_list(ids, &osds, &ss); - }); - if (!r && osds.empty()) { - ss << "must specify one or more OSDs"; - r = -EINVAL; + int r = 0; + if (prefix == "osd safe-to-destroy") { + vector ids; + cmd_getval(g_ceph_context, cmdctx->cmdmap, "ids", ids); + cluster_state.with_osdmap([&](const OSDMap& osdmap) { + r = osdmap.parse_osd_id_list(ids, &osds, &ss); + }); + if (!r && osds.empty()) { + ss << "must specify one or more OSDs"; + r = -EINVAL; + } + } else { + int64_t id; + if (!cmd_getval(g_ceph_context, cmdctx->cmdmap, "id", id)) { + r = -EINVAL; + ss << "must specify OSD id"; + } else { + osds.insert(id); + } } if (r < 0) { cmdctx->reply(r, ss); @@ -1272,13 +1283,34 @@ bool DaemonServer::handle_command(MCommand *m) << " aren't still needed."; r = -EBUSY; } + + if (r && prefix == "osd destroy") { + string sure; + if (!cmd_getval(cct, cmdctx->cmdmap, "sure", sure) || + sure != "--force") { + ss << "\nYou can proceed with OSD removal by passing --force, but be warned that this will likely mean real, permanent data loss."; + } else { + r = 0; + } + } if (r) { cmdctx->reply(r, ss); return true; } - ss << "OSD(s) " << osds << " are safe to destroy without reducing data" - << " durability."; - cmdctx->reply(0, ss); + if (prefix == "osd destroy") { + const string cmd = + "{" + "\"prefix\": \"osd destroy-actual\", " + "\"id\": " + stringify(osds) + ", " + "\"sure\": \"--yes-i-really-mean-it\"" + "}"; + auto on_finish = new ReplyOnFinish(cmdctx); + monc->start_mon_command({cmd}, {}, nullptr, &on_finish->outs, on_finish); + } else { + ss << "OSD(s) " << osds << " are safe to destroy without reducing data" + << " durability."; + cmdctx->reply(0, ss); + } return true; } else if (prefix == "osd ok-to-stop") { vector ids; diff --git a/src/mgr/MgrCommands.h b/src/mgr/MgrCommands.h index 17a3671aa926c..6d532237ed0bb 100644 --- a/src/mgr/MgrCommands.h +++ b/src/mgr/MgrCommands.h @@ -107,6 +107,14 @@ COMMAND("osd test-reweight-by-pg " \ "dry run of reweight OSDs by PG distribution [overload-percentage-for-consideration, default 120]", \ "osd", "r", "cli,rest") +COMMAND("osd destroy " \ + "name=id,type=CephOsdName " \ + "name=sure,type=CephString,req=False", + "mark osd as being destroyed. Keeps the ID intact (allowing reuse), " \ + "but removes cephx keys, config-key data and lockbox keys, "\ + "rendering data permanently unreadable.", \ + "osd", "rw", "cli,rest") + COMMAND("osd safe-to-destroy name=ids,type=CephString,n=N", "check whether osd(s) can be safely destroyed without reducing data durability", "osd", "r", "cli,rest") diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index cc484a3a820b6..56626085ec267 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -870,7 +870,7 @@ COMMAND("osd primary-affinity " \ "type=CephFloat,name=weight,range=0.0|1.0", \ "adjust osd primary-affinity from 0.0 <= <= 1.0", \ "osd", "rw", "cli,rest") -COMMAND("osd destroy " \ +COMMAND("osd destroy-actual " \ "name=id,type=CephOsdName " \ "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ "mark osd as being destroyed. Keeps the ID intact (allowing reuse), " \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 03d84df25f146..ff5dd5fbb9e0f 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -10640,7 +10640,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, return true; } - } else if (prefix == "osd destroy" || + } else if (prefix == "osd destroy-actual" || prefix == "osd purge" || prefix == "osd purge-new") { /* Destroying an OSD means that we don't expect to further make use of @@ -10665,13 +10665,18 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, int64_t id; if (!cmd_getval(cct, cmdmap, "id", id)) { - ss << "unable to parse osd id value '" - << cmd_vartype_stringify(cmdmap.at("id")) << ""; + auto p = cmdmap.find("id"); + if (p == cmdmap.end()) { + ss << "no osd id specified"; + } else { + ss << "unable to parse osd id value '" + << cmd_vartype_stringify(cmdmap.at("id")) << ""; + } err = -EINVAL; goto reply; } - bool is_destroy = (prefix == "osd destroy"); + bool is_destroy = (prefix == "osd destroy-actual"); if (!is_destroy) { assert("osd purge" == prefix || "osd purge-new" == prefix); -- 2.39.5