]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mon/FSCommands.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / mon / FSCommands.cc
index 51c5876013d80381e5944a5753ad9393d95ce57d..5dd9799c2aac67854e23ea8e2fa9c1244d76f29d 100644 (file)
 
 
 #include "OSDMonitor.h"
-#include "PGMonitor.h"
 
 #include "FSCommands.h"
 #include "MDSMonitor.h"
-
+#include "MgrStatMonitor.h"
 
 
 static const string EXPERIMENTAL_WARNING("Warning! This feature is experimental."
@@ -40,17 +39,17 @@ class FlagSetHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     string flag_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "flag_name", flag_name);
+    cmd_getval(g_ceph_context, cmdmap, "flag_name", flag_name);
 
     string flag_val;
-    cmd_getval_throws(g_ceph_context, cmdmap, "val", flag_val);
+    cmd_getval(g_ceph_context, cmdmap, "val", flag_val);
 
-    string confirm;
-    cmd_getval_throws(g_ceph_context, cmdmap, "confirm", confirm);
+    bool sure = false;
+    cmd_getval(g_ceph_context, cmdmap, "yes_i_really_mean_it", sure);
 
     if (flag_name == "enable_multiple") {
       bool flag_bool = false;
@@ -65,7 +64,7 @@ class FlagSetHandler : public FileSystemCommandHandler
         ss << "Multiple-filesystems are forbidden until all mons are updated";
         return -EINVAL;
       }
-      if (confirm != "--yes-i-really-mean-it") {
+      if (!sure) {
        ss << EXPERIMENTAL_WARNING;
       }
       fsmap.set_enable_multiple(flag_bool);
@@ -77,10 +76,67 @@ class FlagSetHandler : public FileSystemCommandHandler
   }
 };
 
+class FailHandler : public FileSystemCommandHandler
+{
+  public:
+  FailHandler()
+    : FileSystemCommandHandler("fs fail")
+  {
+  }
+
+  int handle(
+      Monitor* mon,
+      FSMap& fsmap,
+      MonOpRequestRef op,
+      const cmdmap_t& cmdmap,
+      std::stringstream& ss) override
+  {
+    if (!mon->osdmon()->is_writeable()) {
+      // not allowed to write yet, so retry when we can
+      mon->osdmon()->wait_for_writeable(op, new PaxosService::C_RetryMessage(mon->mdsmon(), op));
+      return -EAGAIN;
+    }
+
+    std::string fs_name;
+    if (!cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name) || fs_name.empty()) {
+      ss << "Missing filesystem name";
+      return -EINVAL;
+    }
+
+    auto fs = fsmap.get_filesystem(fs_name);
+    if (fs == nullptr) {
+      ss << "Not found: '" << fs_name << "'";
+      return -ENOENT;
+    }
+
+    auto f = [](auto fs) {
+      fs->mds_map.set_flag(CEPH_MDSMAP_NOT_JOINABLE);
+    };
+    fsmap.modify_filesystem(fs->fscid, std::move(f));
+
+    std::vector<mds_gid_t> to_fail;
+    for (const auto& p : fs->mds_map.get_mds_info()) {
+      to_fail.push_back(p.first);
+    }
+
+    for (const auto& gid : to_fail) {
+      mon->mdsmon()->fail_mds_gid(fsmap, gid);
+    }
+    if (!to_fail.empty()) {
+      mon->osdmon()->propose_pending();
+    }
+
+    ss << fs_name;
+    ss << " marked not joinable; MDS cannot join the cluster. All MDS ranks marked failed.";
+
+    return 0;
+  }
+};
+
 class FsNewHandler : public FileSystemCommandHandler
 {
   public:
-  FsNewHandler(Paxos *paxos)
+  explicit FsNewHandler(Paxos *paxos)
     : FileSystemCommandHandler("fs new"), m_paxos(paxos)
   {
   }
@@ -93,34 +149,21 @@ class FsNewHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
-    assert(m_paxos->is_plugged());
+    ceph_assert(m_paxos->is_plugged());
 
     string metadata_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "metadata", metadata_name);
+    cmd_getval(g_ceph_context, cmdmap, "metadata", metadata_name);
     int64_t metadata = mon->osdmon()->osdmap.lookup_pg_pool_name(metadata_name);
     if (metadata < 0) {
       ss << "pool '" << metadata_name << "' does not exist";
       return -ENOENT;
     }
 
-    string force_str;
-    cmd_getval_throws(g_ceph_context,cmdmap, "force", force_str);
-    bool force = (force_str == "--force");
-    const pool_stat_t *stat = mon->pgservice->get_pool_stat(metadata);
-    if (stat) {
-      int64_t metadata_num_objects = stat->stats.sum.num_objects;
-      if (!force && metadata_num_objects > 0) {
-       ss << "pool '" << metadata_name
-          << "' already contains some objects. Use an empty pool instead.";
-       return -EINVAL;
-      }
-    }
-
     string data_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "data", data_name);
+    cmd_getval(g_ceph_context, cmdmap, "data", data_name);
     int64_t data = mon->osdmon()->osdmap.lookup_pg_pool_name(data_name);
     if (data < 0) {
       ss << "pool '" << data_name << "' does not exist";
@@ -132,7 +175,7 @@ class FsNewHandler : public FileSystemCommandHandler
     }
 
     string fs_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name);
+    cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name);
     if (fs_name.empty()) {
         // Ensure fs name is not empty so that we can implement
         // commmands that refer to FS by name in future.
@@ -153,6 +196,19 @@ class FsNewHandler : public FileSystemCommandHandler
       }
     }
 
+    bool force = false;
+    cmd_getval(g_ceph_context,cmdmap, "force", force);
+
+    const pool_stat_t *stat = mon->mgrstatmon()->get_pool_stat(metadata);
+    if (stat) {
+      int64_t metadata_num_objects = stat->stats.sum.num_objects;
+      if (!force && metadata_num_objects > 0) {
+       ss << "pool '" << metadata_name
+          << "' already contains some objects. Use an empty pool instead.";
+       return -EINVAL;
+      }
+    }
+
     if (fsmap.filesystem_count() > 0
         && !fsmap.get_enable_multiple()) {
       ss << "Creation of multiple filesystems is disabled.  To enable "
@@ -161,13 +217,16 @@ class FsNewHandler : public FileSystemCommandHandler
       return -EINVAL;
     }
 
-    for (auto fs : fsmap.get_filesystems()) {
+    for (auto& fs : fsmap.get_filesystems()) {
       const std::vector<int64_t> &data_pools = fs->mds_map.get_data_pools();
-      string sure;
+
+      bool sure = false;
+      cmd_getval(g_ceph_context, cmdmap,
+                 "allow_dangerous_metadata_overlay", sure);
+
       if ((std::find(data_pools.begin(), data_pools.end(), data) != data_pools.end()
           || fs->mds_map.get_metadata_pool() == metadata)
-         && ((!cmd_getval_throws(g_ceph_context, cmdmap, "sure", sure)
-              || sure != "--allow-dangerous-metadata-overlay"))) {
+         && !sure) {
        ss << "Filesystem '" << fs_name
           << "' is already using one of the specified RADOS pools. This should ONLY be done in emergencies and after careful reading of the documentation. Pass --allow-dangerous-metadata-overlay to permit this.";
        return -EEXIST;
@@ -175,9 +234,9 @@ class FsNewHandler : public FileSystemCommandHandler
     }
 
     pg_pool_t const *data_pool = mon->osdmon()->osdmap.get_pg_pool(data);
-    assert(data_pool != NULL);  // Checked it existed above
+    ceph_assert(data_pool != NULL);  // Checked it existed above
     pg_pool_t const *metadata_pool = mon->osdmon()->osdmap.get_pg_pool(metadata);
-    assert(metadata_pool != NULL);  // Checked it existed above
+    ceph_assert(metadata_pool != NULL);  // Checked it existed above
 
     int r = _check_pool(mon->osdmon()->osdmap, data, false, force, &ss);
     if (r < 0) {
@@ -189,25 +248,36 @@ class FsNewHandler : public FileSystemCommandHandler
       return r;
     }
     
-    // if we're running as luminous, we have to set the pool application metadata
-    if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS ||
-       mon->osdmon()->pending_inc.new_require_osd_release >= CEPH_RELEASE_LUMINOUS) {
-      if (!mon->osdmon()->is_writeable()) {
-       // not allowed to write yet, so retry when we can
-       mon->osdmon()->wait_for_writeable(op, new PaxosService::C_RetryMessage(mon->mdsmon(), op));
-       return -EAGAIN;
-      }
-      mon->osdmon()->do_application_enable(data,
-                                          pg_pool_t::APPLICATION_NAME_CEPHFS);
-      mon->osdmon()->do_application_enable(metadata,
-                                          pg_pool_t::APPLICATION_NAME_CEPHFS);
-      mon->osdmon()->propose_pending();
+    if (!mon->osdmon()->is_writeable()) {
+      // not allowed to write yet, so retry when we can
+      mon->osdmon()->wait_for_writeable(op, new PaxosService::C_RetryMessage(mon->mdsmon(), op));
+      return -EAGAIN;
     }
+    mon->osdmon()->do_application_enable(data,
+                                        pg_pool_t::APPLICATION_NAME_CEPHFS,
+                                        "data", fs_name);
+    mon->osdmon()->do_application_enable(metadata,
+                                        pg_pool_t::APPLICATION_NAME_CEPHFS,
+                                        "metadata", fs_name);
+    mon->osdmon()->propose_pending();
 
     // All checks passed, go ahead and create.
-    fsmap.create_filesystem(fs_name, metadata, data,
-                            mon->get_quorum_con_features());
+    auto&& fs = fsmap.create_filesystem(fs_name, metadata, data,
+        mon->get_quorum_con_features());
+
     ss << "new fs with metadata pool " << metadata << " and data pool " << data;
+
+    // assign a standby to rank 0 to avoid health warnings
+    std::string _name;
+    mds_gid_t gid = fsmap.find_replacement_for({fs->fscid, 0}, _name);
+
+    if (gid != MDS_GID_NONE) {
+      const auto &info = fsmap.get_info_gid(gid);
+      mon->clog->info() << info.human_name() << " assigned to filesystem "
+          << fs_name << " as rank 0";
+      fsmap.promote(gid, *fs, 0);
+    }
+
     return 0;
   }
 
@@ -226,11 +296,11 @@ public:
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     std::string fs_name;
-    if (!cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name) || fs_name.empty()) {
+    if (!cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name) || fs_name.empty()) {
       ss << "Missing filesystem name";
       return -EINVAL;
     }
@@ -242,14 +312,14 @@ public:
     }
 
     string var;
-    if (!cmd_getval_throws(g_ceph_context, cmdmap, "var", var) || var.empty()) {
+    if (!cmd_getval(g_ceph_context, cmdmap, "var", var) || var.empty()) {
       ss << "Invalid variable";
       return -EINVAL;
     }
     string val;
     string interr;
     int64_t n = 0;
-    if (!cmd_getval_throws(g_ceph_context, cmdmap, "val", val)) {
+    if (!cmd_getval(g_ceph_context, cmdmap, "val", val)) {
       return -EINVAL;
     }
     // we got a string.  see if it contains an int.
@@ -265,20 +335,23 @@ public:
         ss << "You must specify at least one MDS";
         return -EINVAL;
       }
-
-      if (!fs->mds_map.allows_multimds() && n > fs->mds_map.get_max_mds() &&
-         n > 1) {
-       ss << "multi-MDS clusters are not enabled; set 'allow_multimds' to enable";
-       return -EINVAL;
+      if (n > 1 && n > fs->mds_map.get_max_mds()) {
+       if (fs->mds_map.was_snaps_ever_allowed() &&
+           !fs->mds_map.allows_multimds_snaps()) {
+         ss << "multi-active MDS is not allowed while there are snapshots possibly created by pre-mimic MDS";
+         return -EINVAL;
+       }
       }
       if (n > MAX_MDS) {
         ss << "may not have more than " << MAX_MDS << " MDS ranks";
         return -EINVAL;
       }
+
       fsmap.modify_filesystem(
           fs->fscid,
           [n](std::shared_ptr<Filesystem> fs)
       {
+       fs->mds_map.clear_flag(CEPH_MDSMAP_NOT_JOINABLE);
         fs->mds_map.set_max_mds(n);
       });
     } else if (var == "inline_data") {
@@ -289,9 +362,9 @@ public:
       }
 
       if (enable_inline) {
-       string confirm;
-       if (!cmd_getval_throws(g_ceph_context, cmdmap, "confirm", confirm) ||
-           confirm != "--yes-i-really-mean-it") {
+        bool confirm = false;
+        cmd_getval(g_ceph_context, cmdmap, "yes_i_really_mean_it", confirm);
+       if (!confirm) {
          ss << EXPERIMENTAL_WARNING;
          return -EPERM;
        }
@@ -361,12 +434,6 @@ public:
         });
        ss << "disabled new snapshots";
       } else {
-       string confirm;
-       if (!cmd_getval(g_ceph_context, cmdmap, "confirm", confirm) ||
-           confirm != "--yes-i-really-mean-it") {
-         ss << EXPERIMENTAL_WARNING;
-         return -EPERM;
-       }
         fsmap.modify_filesystem(
             fs->fscid,
             [](std::shared_ptr<Filesystem> fs)
@@ -376,70 +443,106 @@ public:
        ss << "enabled new snapshots";
       }
     } else if (var == "allow_multimds") {
-      bool enable_multimds = false;
-      int r = parse_bool(val, &enable_multimds, ss);
+        ss << "Multiple MDS is always enabled. Use the max_mds"
+           << " parameter to control the number of active MDSs"
+           << " allowed. This command is DEPRECATED and will be"
+           << " REMOVED from future releases.";
+    } else if (var == "allow_multimds_snaps") {
+      bool enable = false;
+      int r = parse_bool(val, &enable, ss);
       if (r != 0) {
-       return r;
+        return r;
       }
 
-      if (!enable_multimds) {
-       fsmap.modify_filesystem(fs->fscid,
-            [](std::shared_ptr<Filesystem> fs)
-               {
-                 fs->mds_map.clear_multimds_allowed();
-               });
-       ss << "disallowed increasing the cluster size past 1";
-      } else {
+      string confirm;
+      if (!cmd_getval(g_ceph_context, cmdmap, "confirm", confirm) ||
+         confirm != "--yes-i-am-really-a-mds") {
+       ss << "Warning! This command is for MDS only. Do not run it manually";
+       return -EPERM;
+      }
+
+      if (enable) {
+       ss << "enabled multimds with snapshot";
         fsmap.modify_filesystem(
             fs->fscid,
             [](std::shared_ptr<Filesystem> fs)
         {
-          fs->mds_map.set_multimds_allowed();
+         fs->mds_map.set_multimds_snaps_allowed();
         });
-       ss << "enabled creation of more than 1 active MDS";
-      }
-    } else if (var == "allow_dirfrags") {
-      bool enable_dirfrags = false;
-      int r = parse_bool(val, &enable_dirfrags, ss);
-      if (r != 0) {
-       return r;
-      }
-
-      if (!enable_dirfrags) {
-       fsmap.modify_filesystem(fs->fscid,
-            [](std::shared_ptr<Filesystem> fs)
-               {
-                 fs->mds_map.clear_dirfrags_allowed();
-               });
-       ss << "disallowed new directory fragmentation";
       } else {
+       ss << "disabled multimds with snapshot";
         fsmap.modify_filesystem(
             fs->fscid,
             [](std::shared_ptr<Filesystem> fs)
         {
-          fs->mds_map.set_dirfrags_allowed();
+         fs->mds_map.clear_multimds_snaps_allowed();
         });
-       ss << "enabled directory fragmentation";
       }
-    } else if (var == "cluster_down") {
+    } else if (var == "allow_dirfrags") {
+        ss << "Directory fragmentation is now permanently enabled."
+           << " This command is DEPRECATED and will be REMOVED from future releases.";
+    } else if (var == "down") {
       bool is_down = false;
       int r = parse_bool(val, &is_down, ss);
       if (r != 0) {
         return r;
       }
 
+      ss << fs->mds_map.get_fs_name();
+
       fsmap.modify_filesystem(
           fs->fscid,
           [is_down](std::shared_ptr<Filesystem> fs)
       {
-        if (is_down) {
-          fs->mds_map.set_flag(CEPH_MDSMAP_DOWN);
-        } else {
-          fs->mds_map.clear_flag(CEPH_MDSMAP_DOWN);
-        }
+       if (is_down) {
+          if (fs->mds_map.get_max_mds() > 0) {
+           fs->mds_map.set_old_max_mds();
+           fs->mds_map.set_max_mds(0);
+          } /* else already down! */
+       } else {
+         mds_rank_t oldmax = fs->mds_map.get_old_max_mds();
+         fs->mds_map.set_max_mds(oldmax ? oldmax : 1);
+       }
+      });
+
+      if (is_down) {
+       ss << " marked down. ";
+      } else {
+       ss << " marked up, max_mds = " << fs->mds_map.get_max_mds();
+      }
+    } else if (var == "cluster_down" || var == "joinable") {
+      bool joinable = true;
+      int r = parse_bool(val, &joinable, ss);
+      if (r != 0) {
+        return r;
+      }
+      if (var == "cluster_down") {
+        joinable = !joinable;
+      }
+
+      ss << fs->mds_map.get_fs_name();
+
+      fsmap.modify_filesystem(
+          fs->fscid,
+          [joinable](std::shared_ptr<Filesystem> fs)
+      {
+       if (joinable) {
+         fs->mds_map.clear_flag(CEPH_MDSMAP_NOT_JOINABLE);
+       } else {
+         fs->mds_map.set_flag(CEPH_MDSMAP_NOT_JOINABLE);
+       }
       });
 
-      ss << "marked " << (is_down ? "down" : "up");
+      if (joinable) {
+       ss << " marked joinable; MDS may join as newly active.";
+      } else {
+       ss << " marked not joinable; MDS cannot join as newly active.";
+      }
+
+      if (var == "cluster_down") {
+        ss << " WARNING: cluster_down flag is deprecated and will be"
+           << " removed in a future version. Please use \"joinable\".";
+      }
     } else if (var == "standby_count_wanted") {
       if (interr.length()) {
        ss << var << " requires an integer value";
@@ -485,6 +588,33 @@ public:
       {
         fs->mds_map.set_session_autoclose((uint32_t)n);
       });
+    } else if (var == "allow_standby_replay") {
+      bool allow = false;
+      int r = parse_bool(val, &allow, ss);
+      if (r != 0) {
+        return r;
+      }
+
+      auto f = [allow](auto& fs) {
+        if (allow) {
+          fs->mds_map.set_standby_replay_allowed();
+        } else {
+          fs->mds_map.clear_standby_replay_allowed();
+        }
+      };
+      fsmap.modify_filesystem(fs->fscid, std::move(f));
+    } else if (var == "min_compat_client") {
+      int vno = ceph_release_from_name(val.c_str());
+      if (vno <= 0) {
+       ss << "version " << val << " is not recognized";
+       return -EINVAL;
+      }
+      fsmap.modify_filesystem(
+         fs->fscid,
+         [vno](std::shared_ptr<Filesystem> fs)
+       {
+         fs->mds_map.set_min_compat_client((uint8_t)vno);
+       });
     } else {
       ss << "unknown variable " << var;
       return -EINVAL;
@@ -497,7 +627,7 @@ public:
 class AddDataPoolHandler : public FileSystemCommandHandler
 {
   public:
-  AddDataPoolHandler(Paxos *paxos)
+  explicit AddDataPoolHandler(Paxos *paxos)
     : FileSystemCommandHandler("fs add_data_pool"), m_paxos(paxos)
   {}
 
@@ -509,16 +639,16 @@ class AddDataPoolHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
-    assert(m_paxos->is_plugged());
+    ceph_assert(m_paxos->is_plugged());
 
     string poolname;
-    cmd_getval_throws(g_ceph_context, cmdmap, "pool", poolname);
+    cmd_getval(g_ceph_context, cmdmap, "pool", poolname);
 
     std::string fs_name;
-    if (!cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name)
+    if (!cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name)
         || fs_name.empty()) {
       ss << "Missing filesystem name";
       return -EINVAL;
@@ -551,17 +681,15 @@ class AddDataPoolHandler : public FileSystemCommandHandler
       return 0;
     }
 
-    // if we're running as luminous, we have to set the pool application metadata
-    if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS ||
-       mon->osdmon()->pending_inc.new_require_osd_release >= CEPH_RELEASE_LUMINOUS) {
-      if (!mon->osdmon()->is_writeable()) {
-       // not allowed to write yet, so retry when we can
-       mon->osdmon()->wait_for_writeable(op, new PaxosService::C_RetryMessage(mon->mdsmon(), op));
-       return -EAGAIN;
-      }
-      mon->osdmon()->do_application_enable(poolid, pg_pool_t::APPLICATION_NAME_CEPHFS);
-      mon->osdmon()->propose_pending();
+    if (!mon->osdmon()->is_writeable()) {
+      // not allowed to write yet, so retry when we can
+      mon->osdmon()->wait_for_writeable(op, new PaxosService::C_RetryMessage(mon->mdsmon(), op));
+      return -EAGAIN;
     }
+    mon->osdmon()->do_application_enable(poolid,
+                                        pg_pool_t::APPLICATION_NAME_CEPHFS,
+                                        "data", fs_name);
+    mon->osdmon()->propose_pending();
 
     fsmap.modify_filesystem(
         fs->fscid,
@@ -590,11 +718,11 @@ class SetDefaultHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     std::string fs_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name);
+    cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name);
     auto fs = fsmap.get_filesystem(fs_name);
     if (fs == nullptr) {
         ss << "filesystem '" << fs_name << "' does not exist";
@@ -617,7 +745,7 @@ class RemoveFilesystemHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     /* We may need to blacklist ranks. */
@@ -631,7 +759,7 @@ class RemoveFilesystemHandler : public FileSystemCommandHandler
     // (redundant while there is only one FS, but command
     //  syntax should apply to multi-FS future)
     string fs_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name);
+    cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name);
     auto fs = fsmap.get_filesystem(fs_name);
     if (fs == nullptr) {
         // Consider absence success to make deletes idempotent
@@ -641,14 +769,14 @@ class RemoveFilesystemHandler : public FileSystemCommandHandler
 
     // Check that no MDS daemons are active
     if (fs->mds_map.get_num_up_mds() > 0) {
-      ss << "all MDS daemons must be inactive before removing filesystem";
+      ss << "all MDS daemons must be inactive/failed before removing filesystem. See `ceph fs fail`.";
       return -EINVAL;
     }
 
     // Check for confirmation flag
-    string sure;
-    cmd_getval_throws(g_ceph_context, cmdmap, "sure", sure);
-    if (sure != "--yes-i-really-mean-it") {
+    bool sure = false;
+    cmd_getval(g_ceph_context, cmdmap, "yes_i_really_mean_it", sure);
+    if (!sure) {
       ss << "this is a DESTRUCTIVE operation and will make data in your filesystem permanently" \
             " inaccessible.  Add --yes-i-really-mean-it if you are sure you wish to continue.";
       return -EPERM;
@@ -661,7 +789,7 @@ class RemoveFilesystemHandler : public FileSystemCommandHandler
     std::vector<mds_gid_t> to_fail;
     // There may be standby_replay daemons left here
     for (const auto &i : fs->mds_map.get_mds_info()) {
-      assert(i.second.state == MDSMap::STATE_STANDBY_REPLAY);
+      ceph_assert(i.second.state == MDSMap::STATE_STANDBY_REPLAY);
       to_fail.push_back(i.first);
     }
 
@@ -691,11 +819,11 @@ class ResetFilesystemHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     string fs_name;
-    cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name);
+    cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name);
     auto fs = fsmap.get_filesystem(fs_name);
     if (fs == nullptr) {
         ss << "filesystem '" << fs_name << "' does not exist";
@@ -711,9 +839,9 @@ class ResetFilesystemHandler : public FileSystemCommandHandler
     }
 
     // Check for confirmation flag
-    string sure;
-    cmd_getval_throws(g_ceph_context, cmdmap, "sure", sure);
-    if (sure != "--yes-i-really-mean-it") {
+    bool sure = false;
+    cmd_getval(g_ceph_context, cmdmap, "yes_i_really_mean_it", sure);
+    if (!sure) {
       ss << "this is a potentially destructive operation, only for use by experts in disaster recovery.  "
         "Add --yes-i-really-mean-it if you are sure you wish to continue.";
       return -EPERM;
@@ -736,14 +864,14 @@ class RemoveDataPoolHandler : public FileSystemCommandHandler
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     string poolname;
-    cmd_getval_throws(g_ceph_context, cmdmap, "pool", poolname);
+    cmd_getval(g_ceph_context, cmdmap, "pool", poolname);
 
     std::string fs_name;
-    if (!cmd_getval_throws(g_ceph_context, cmdmap, "fs_name", fs_name)
+    if (!cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name)
         || fs_name.empty()) {
       ss << "Missing filesystem name";
       return -EINVAL;
@@ -768,7 +896,7 @@ class RemoveDataPoolHandler : public FileSystemCommandHandler
       }
     }
 
-    assert(poolid >= 0);  // Checked by parsing code above
+    ceph_assert(poolid >= 0);  // Checked by parsing code above
 
     if (fs->mds_map.get_first_data_pool() == poolid) {
       ss << "cannot remove default data pool";
@@ -796,48 +924,6 @@ class RemoveDataPoolHandler : public FileSystemCommandHandler
   }
 };
 
-
-/**
- * For commands that refer to a particular filesystem,
- * enable wrapping to implement the legacy version of
- * the command (like "mds add_data_pool" vs "fs add_data_pool")
- *
- * The wrapped handler must expect a fs_name argument in
- * its command map.
- */
-template<typename T>
-class LegacyHandler : public T
-{
-  std::string legacy_prefix;
-
-  public:
-  template <typename... Args>
-  LegacyHandler(const std::string &new_prefix, Args&&... args)
-    : T(std::forward<Args>(args)...)
-  {
-    legacy_prefix = new_prefix;
-  }
-
-  std::string const &get_prefix() override {return legacy_prefix;}
-
-  int handle(
-      Monitor *mon,
-      FSMap &fsmap,
-      MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
-      std::stringstream &ss) override
-  {
-    auto fs = fsmap.get_legacy_filesystem();
-    if (fs == nullptr) {
-      ss << "No filesystem configured";
-      return -ENOENT;
-    }
-    std::map<string, cmd_vartype> modified = cmdmap;
-    modified["fs_name"] = std::string(fs->mds_map.get_fs_name());
-    return T::handle(mon, fsmap, op, modified, ss);
-  }
-};
-
 /**
  * For commands with an alternative prefix
  */
@@ -847,7 +933,7 @@ class AliasHandler : public T
   std::string alias_prefix;
 
   public:
-  AliasHandler(const std::string &new_prefix)
+  explicit AliasHandler(const std::string &new_prefix)
     : T()
   {
     alias_prefix = new_prefix;
@@ -859,7 +945,7 @@ class AliasHandler : public T
       Monitor *mon,
       FSMap &fsmap,
       MonOpRequestRef op,
-      map<string, cmd_vartype> &cmdmap,
+      const cmdmap_t& cmdmap,
       std::stringstream &ss) override
   {
     return T::handle(mon, fsmap, op, cmdmap, ss);
@@ -873,16 +959,10 @@ FileSystemCommandHandler::load(Paxos *paxos)
   std::list<std::shared_ptr<FileSystemCommandHandler> > handlers;
 
   handlers.push_back(std::make_shared<SetHandler>());
-  handlers.push_back(std::make_shared<LegacyHandler<SetHandler> >("mds set"));
+  handlers.push_back(std::make_shared<FailHandler>());
   handlers.push_back(std::make_shared<FlagSetHandler>());
   handlers.push_back(std::make_shared<AddDataPoolHandler>(paxos));
-  handlers.push_back(std::make_shared<LegacyHandler<AddDataPoolHandler> >(
-        "mds add_data_pool", paxos));
   handlers.push_back(std::make_shared<RemoveDataPoolHandler>());
-  handlers.push_back(std::make_shared<LegacyHandler<RemoveDataPoolHandler> >(
-        "mds remove_data_pool"));
-  handlers.push_back(std::make_shared<LegacyHandler<RemoveDataPoolHandler> >(
-        "mds rm_data_pool"));
   handlers.push_back(std::make_shared<FsNewHandler>(paxos));
   handlers.push_back(std::make_shared<RemoveFilesystemHandler>());
   handlers.push_back(std::make_shared<ResetFilesystemHandler>());
@@ -894,30 +974,6 @@ FileSystemCommandHandler::load(Paxos *paxos)
   return handlers;
 }
 
-int FileSystemCommandHandler::parse_bool(
-      const std::string &bool_str,
-      bool *result,
-      std::ostream &ss)
-{
-  assert(result != nullptr);
-
-  string interr;
-  int64_t n = strict_strtoll(bool_str.c_str(), 10, &interr);
-
-  if (bool_str == "false" || bool_str == "no"
-      || (interr.length() == 0 && n == 0)) {
-    *result = false;
-    return 0;
-  } else if (bool_str == "true" || bool_str == "yes"
-      || (interr.length() == 0 && n == 1)) {
-    *result = true;
-    return 0;
-  } else {
-    ss << "value must be false|no|0 or true|yes|1";
-    return -EINVAL;
-  }
-}
-
 int FileSystemCommandHandler::_check_pool(
     OSDMap &osd_map,
     const int64_t pool_id,
@@ -925,7 +981,7 @@ int FileSystemCommandHandler::_check_pool(
     bool force,
     std::stringstream *ss) const
 {
-  assert(ss != NULL);
+  ceph_assert(ss != NULL);
 
   const pg_pool_t *pool = osd_map.get_pg_pool(pool_id);
   if (!pool) {
@@ -952,7 +1008,7 @@ int FileSystemCommandHandler::_check_pool(
     // write operations like modify+truncate we care about support for)
     const pg_pool_t *write_tier = osd_map.get_pg_pool(
         pool->write_tier);
-    assert(write_tier != NULL);  // OSDMonitor shouldn't allow DNE tier
+    ceph_assert(write_tier != NULL);  // OSDMonitor shouldn't allow DNE tier
     if (write_tier->cache_mode == pg_pool_t::CACHEMODE_FORWARD
         || write_tier->cache_mode == pg_pool_t::CACHEMODE_READONLY) {
       *ss << "EC pool '" << pool_name << "' has a write tier ("