]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: CephBool -> CephChoices in command map for pre-nautilus mons 25470/head
authorSage Weil <sage@redhat.com>
Mon, 10 Dec 2018 14:19:27 +0000 (08:19 -0600)
committerSage Weil <sage@redhat.com>
Mon, 17 Dec 2018 15:01:35 +0000 (09:01 -0600)
If pre-nautilus mons are in quorum, send out a pre-nautilus compatible
set of commands.  Although nautilus mons can do this same translation on
the fly for pre-nautilus clients, pre-nautilus mons can't, so do it for
all mons.  This means the new CephBool behavior will only start working
once you upgrade all mons to nautilus.

Fixes: http://tracker.ceph.com/issues/37583
Signed-off-by: Sage Weil <sage@redhat.com>
src/common/cmdparse.cc
src/common/cmdparse.h
src/mon/Monitor.cc
src/mon/Monitor.h

index 3380178934d6c237341437474c86cd5cb8c1ebb3..5945c0baf766da37759e708ed639172d7b40c2df 100644 (file)
@@ -65,6 +65,55 @@ arg_desc_t cmddesc_get_args(const String& cmddesc)
   return arg_desc;
 }
 
+std::string cmddesc_get_prenautilus_compat(const std::string &cmddesc)
+{
+  std::vector<std::string> out;
+  stringstream ss(cmddesc);
+  std::string word;
+  bool changed = false;
+  while (std::getline(ss, word, ' ')) {
+    // if no , or =, must be a plain word to put out
+    if (word.find_first_of(",=") == string::npos) {
+      out.push_back(word);
+      continue;
+    }
+    auto desckv = cmddesc_get_args(word);
+    auto j = desckv.find("type");
+    if (j != desckv.end() && j->second == "CephBool") {
+      // Instruct legacy clients or mons to send --foo-bar string in place
+      // of a 'true'/'false' value
+      std::ostringstream oss;
+      oss << std::string("--") << desckv["name"];
+      std::string val = oss.str();
+      std::replace(val.begin(), val.end(), '_', '-');
+      desckv["type"] = "CephChoices";
+      desckv["strings"] = val;
+      std::ostringstream fss;
+      for (auto k = desckv.begin(); k != desckv.end(); ++k) {
+       if (k != desckv.begin()) {
+         fss << ",";
+       }
+       fss << k->first << "=" << k->second;
+      }
+      out.push_back(fss.str());
+      changed = true;
+    } else {
+      out.push_back(word);
+    }
+  }
+  if (!changed) {
+    return cmddesc;
+  }
+  std::string o;
+  for (auto i = out.begin(); i != out.end(); ++i) {
+    if (i != out.begin()) {
+      o += " ";
+    }
+    o += *i;
+  }
+  return o;
+}
+
 /**
  * Read a command description list out of cmd, and dump it to f.
  * A signature description is a set of space-separated words;
index 550851b216a8d4c99386af6957f92b1990c0bfc8..2c59567d588d9738a494347c958fc7813c17252d 100644 (file)
@@ -23,6 +23,7 @@ typedef boost::variant<std::string,
 typedef std::map<std::string, cmd_vartype, std::less<>> cmdmap_t;
 
 std::string cmddesc_get_prefix(const std::string &cmddesc);
+std::string cmddesc_get_prenautilus_compat(const std::string &cmddesc);
 void dump_cmd_to_json(ceph::Formatter *f, uint64_t features,
                       const std::string& cmd);
 void dump_cmd_and_help_to_json(ceph::Formatter *f,
index 01c1cc877a08dca49f815988126d60227e5292fa..38875e8a2bdc746ab3e644e693ac0bb34931421d 100644 (file)
@@ -29,6 +29,7 @@
 #include "Monitor.h"
 #include "common/version.h"
 #include "common/blkdev.h"
+#include "common/cmdparse.h"
 
 #include "osd/OSDMap.h"
 
@@ -221,6 +222,16 @@ Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s,
   }
   MonCommand::encode_vector(local_mon_commands, local_mon_commands_bl);
 
+  prenautilus_local_mon_commands = local_mon_commands;
+  for (auto& i : prenautilus_local_mon_commands) {
+    std::string n = cmddesc_get_prenautilus_compat(i.cmdstring);
+    if (n != i.cmdstring) {
+      dout(20) << " pre-nautilus cmd " << i.cmdstring << " -> " << n << dendl;
+      i.cmdstring = n;
+    }
+  }
+  MonCommand::encode_vector(prenautilus_local_mon_commands, prenautilus_local_mon_commands_bl);
+
   // assume our commands until we have an election.  this only means
   // we won't reply with EINVAL before the election; any command that
   // actually matters will wait until we have quorum etc and then
index 3c2685ae45f4774cf0d11187fe343eddcc828903..d30afddad1c800fcb765903c66d9da2307c07ccb 100644 (file)
@@ -165,6 +165,9 @@ public:
   vector<MonCommand> local_mon_commands;  // commands i support
   bufferlist local_mon_commands_bl;       // encoded version of above
 
+  vector<MonCommand> prenautilus_local_mon_commands;
+  bufferlist prenautilus_local_mon_commands_bl;
+
   Messenger *mgr_messenger;
   MgrClient mgr_client;
   uint64_t mgr_proxy_bytes = 0;  // in-flight proxied mgr command message bytes
@@ -967,10 +970,18 @@ public:
                                          bufferlist *rdata);
 
   const std::vector<MonCommand> &get_local_commands(mon_feature_t f) {
-    return local_mon_commands;
+    if (f.contains_all(ceph::features::mon::FEATURE_NAUTILUS)) {
+      return local_mon_commands;
+    } else {
+      return prenautilus_local_mon_commands;
+    }
   }
   const bufferlist& get_local_commands_bl(mon_feature_t f) {
-    return local_mon_commands_bl;
+    if (f.contains_all(ceph::features::mon::FEATURE_NAUTILUS)) {
+      return local_mon_commands_bl;
+    } else {
+      return prenautilus_local_mon_commands_bl;
+    }
   }
   void set_leader_commands(const std::vector<MonCommand>& cmds) {
     leader_mon_commands = cmds;