diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh index 048ae113b66..576d6da652e 100755 --- a/qa/workunits/cephtool/test.sh +++ b/qa/workunits/cephtool/test.sh @@ -715,6 +715,11 @@ function test_mon_mds() metadata_poolnum=$(ceph osd dump | grep "pool.* 'fs_metadata" | awk '{print $2;}') fail_all_mds + + # Check that 'fs reset' runs + ceph fs reset cephfs --yes-i-really-mean-it + + # Clean up to enable subsequent newfs tests ceph fs rm cephfs --yes-i-really-mean-it set +e diff --git a/src/mon/MDSMonitor.cc b/src/mon/MDSMonitor.cc index 399dd2e3870..394793a22a8 100644 --- a/src/mon/MDSMonitor.cc +++ b/src/mon/MDSMonitor.cc @@ -1212,6 +1212,53 @@ int MDSMonitor::management_command( pending_mdsmap.created = ceph_clock_now(g_ceph_context); return 0; + } else if (prefix == "fs reset") { + string fs_name; + cmd_getval(g_ceph_context, cmdmap, "fs_name", fs_name); + if (!pending_mdsmap.get_enabled() || fs_name != pending_mdsmap.fs_name) { + ss << "filesystem '" << fs_name << "' does not exist"; + // Unlike fs rm, we consider this case an error + return -ENOENT; + } + + // Check that no MDS daemons are active + if (!pending_mdsmap.up.empty()) { + ss << "all MDS daemons must be inactive before resetting filesystem: set the cluster_down flag" + " and use `ceph mds fail` to make this so"; + return -EINVAL; + } + + // Check for confirmation flag + string sure; + cmd_getval(g_ceph_context, cmdmap, "sure", sure); + if (sure != "--yes-i-really-mean-it") { + 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; + } + + MDSMap newmap; + + // Populate rank 0 as existing (so don't go into CREATING) + // but failed (so that next available MDS is assigned the rank) + newmap.in.insert(mds_rank_t(0)); + newmap.failed.insert(mds_rank_t(0)); + + // Carry forward what makes sense + newmap.data_pools = mdsmap.data_pools; + newmap.metadata_pool = mdsmap.metadata_pool; + newmap.cas_pool = mdsmap.cas_pool; + newmap.fs_name = mdsmap.fs_name; + newmap.created = ceph_clock_now(g_ceph_context); + newmap.epoch = mdsmap.epoch + 1; + newmap.inc = mdsmap.inc; + newmap.enabled = mdsmap.enabled; + newmap.inline_data_enabled = mdsmap.inline_data_enabled; + + // Persist the new MDSMap + pending_mdsmap = newmap; + return 0; + } else { return -ENOSYS; } diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index cdac6d1096a..6292e302d6a 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -307,6 +307,11 @@ COMMAND("fs rm " \ "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ "disable the named filesystem", \ "fs", "rw", "cli,rest") +COMMAND("fs reset " \ + "name=fs_name,type=CephString " \ + "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ + "disaster recovery only: reset to a single-MDS map", \ + "fs", "rw", "cli,rest") COMMAND("fs ls ", \ "list filesystems", \ "fs", "r", "cli,rest")