]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/MonClient: one-shot mon connection on started to fetch config
authorSage Weil <sage@redhat.com>
Tue, 5 Dec 2017 17:43:43 +0000 (11:43 -0600)
committerSage Weil <sage@redhat.com>
Tue, 6 Mar 2018 20:44:48 +0000 (14:44 -0600)
This is not particularly efficient, but it works:

 - connect to the monitor to get the monmap and config
 - tear it all down
 - proceed with normal startup (which presumably involves reconnecting
   to the mon all over again).

This allows us to set config options that may affect the mon communication
itself, like ms_type.

Signed-off-by: Sage Weil <sage@redhat.com>
13 files changed:
src/ceph_fuse.cc
src/ceph_mgr.cc
src/ceph_mon.cc
src/ceph_osd.cc
src/common/ceph_argparse.cc
src/common/ceph_argparse.h
src/common/common_init.h
src/global/global_init.cc
src/libcephfs.cc
src/librados/RadosClient.cc
src/mon/MonClient.cc
src/mon/MonClient.h
src/tools/ceph_conf.cc

index 35e3509bf7021312338d6b9e48f8459106e7dd88..2b3dfb86e7bfa96e1c521b7b315bb30a8bceb623 100644 (file)
@@ -80,7 +80,8 @@ int main(int argc, const char **argv, const char *envp[]) {
   env_to_vec(args);
 
   std::map<std::string,std::string> defaults = {
-    { "pid_file", "" }
+    { "pid_file", "" },
+    { "chdir", "/" }  // FUSE will chdir("/"); be ready.
   };
 
   auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT,
@@ -107,10 +108,6 @@ int main(int argc, const char **argv, const char *envp[]) {
   int newargc;
   vec_to_argv(argv[0], args, &newargc, &newargv);
 
-  // FUSE will chdir("/"); be ready.
-  g_ceph_context->_conf->set_val("chdir", "/");
-  g_ceph_context->_conf->apply_changes(nullptr);
-
   // check for 32-bit arch
 #ifndef __LP64__
     cerr << std::endl;
index 5e8f6798e3924271ba21ed375b25931ed0cba81e..77e3933666c652c092ded4386a43c705054d1194 100644 (file)
@@ -47,14 +47,16 @@ int main(int argc, const char **argv)
   argv_to_vec(argc, argv, args);
   env_to_vec(args);
 
-  auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_MGR,
+  map<string,string> defaults = {
+    { "keyring", "$mgr_data/keyring" }
+  };
+  auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_MGR,
                         CODE_ENVIRONMENT_DAEMON, 0,
                         "mgr_data");
-  // For consumption by KeyRing::from_ceph_context in MonClient
-  g_conf->set_val_or_die("keyring", "$mgr_data/keyring");
 
   // Handle --help
-  if ((args.size() == 1 && (std::string(args[0]) == "--help" || std::string(args[0]) == "-h"))) {
+  if ((args.size() == 1 && (std::string(args[0]) == "--help" ||
+                           std::string(args[0]) == "-h"))) {
     usage();
   }
 
index 8683000af9cd3ab62aeb6fb45659dcb906afac15..d0791955f0f4f8c8de56fa5dee7a4af8e95b4167 100644 (file)
@@ -242,6 +242,9 @@ int main(int argc, const char **argv)
     }
   }
 
+  // don't try to get config from mon cluster during startup
+  flags |= CINIT_FLAG_NO_MON_CONFIG;
+
   auto cct = global_init(&defaults, args,
                         CEPH_ENTITY_TYPE_MON, CODE_ENVIRONMENT_DAEMON,
                         flags, "mon_data");
index c7f887ae87a6c8ab0ef5345db8dd30a884d99d17..37feada6e1be4a60a5117e35deb3009f73f06e6e 100644 (file)
@@ -328,18 +328,14 @@ int main(int argc, const char **argv)
   }
   if (mkfs) {
     common_init_finish(g_ceph_context);
-    MonClient mc(g_ceph_context);
-    if (mc.build_initial_monmap() < 0)
-      return -1;
-    if (mc.get_monmap_privately() < 0)
-      return -1;
 
-    if (mc.monmap.fsid.is_zero()) {
+    if (g_conf->get_val<uuid_d>("fsid").is_zero()) {
       derr << "must specify cluster fsid" << dendl;
       forker.exit(-EINVAL);
     }
 
-    int err = OSD::mkfs(g_ceph_context, store, data_path, mc.monmap.fsid,
+    int err = OSD::mkfs(g_ceph_context, store, data_path,
+                       g_conf->get_val<uuid_d>("fsid"),
                         whoami);
     if (err < 0) {
       derr << TEXT_RED << " ** ERROR: error creating empty object store in "
@@ -347,7 +343,9 @@ int main(int argc, const char **argv)
       forker.exit(1);
     }
     dout(0) << "created object store " << data_path
-           << " for osd." << whoami << " fsid " << mc.monmap.fsid << dendl;
+           << " for osd." << whoami
+           << " fsid " << g_conf->get_val<uuid_d>("fsid")
+           << dendl;
   }
   if (mkfs || mkkey) {
     forker.exit(0);
index a89de95f6e405fb2988e8dc8918128efaa02e184..5f86a002cc3bcba452bbf5de345e6b4d70c805d6 100644 (file)
@@ -484,6 +484,9 @@ CephInitParameters ceph_argparse_early_args
     else if (ceph_argparse_witharg(args, i, &val, "--conf", "-c", (char*)NULL)) {
       *conf_file_list = val;
     }
+    else if (ceph_argparse_flag(args, i, "--no-mon-config", (char*)NULL)) {
+      iparams.no_mon_config = true;
+    }
     else if (ceph_argparse_witharg(args, i, &val, "--cluster", (char*)NULL)) {
       *cluster = val;
     }
index 900b18f31a797134d544bbfc580a6298a8d1d6cb..ba9462acfc17ecb469d71f0424f17841fe2cb739 100644 (file)
@@ -37,6 +37,8 @@ public:
 
   uint32_t module_type;
   EntityName name;
+
+  bool no_mon_config = false;
 };
 
 /////////////////////// Functions ///////////////////////
index f66c4df42110fb98aba3ab0f3af782c845881630..bd004b0e60eb7bec545ebeaa4fb1a2a0d952e126 100644 (file)
@@ -26,7 +26,7 @@ enum common_init_flags_t {
   // Set up defaults that make sense for an unprivileged daemon
   CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS = 0x1,
 
-  // By default, don't read a configuration file
+  // By default, don't read a configuration file OR contact mons
   CINIT_FLAG_NO_DEFAULT_CONFIG_FILE = 0x2,
 
   // Don't close stderr (in daemonize)
@@ -37,6 +37,9 @@ enum common_init_flags_t {
 
   // don't drop privileges
   CINIT_FLAG_DEFER_DROP_PRIVILEGES = 0x10,
+
+  // do'nt contact mons for config
+  CINIT_FLAG_NO_MON_CONFIG = 0x20,
 };
 
 /*
index daaaf955668ae1ab8c9dcfe1207121e1efbb5fc4..716104c71f80d9d7b06224f1abd30df39da744ea 100644 (file)
@@ -26,6 +26,7 @@
 #include "global/signal_handler.h"
 #include "include/compat.h"
 #include "include/str_list.h"
+#include "mon/MonClient.h"
 
 #include <pwd.h>
 #include <grp.h>
@@ -88,8 +89,15 @@ void global_pre_init(
 {
   std::string conf_file_list;
   std::string cluster = "";
-  CephInitParameters iparams = ceph_argparse_early_args(args, module_type,
-                                                       &cluster, &conf_file_list);
+
+  CephInitParameters iparams = ceph_argparse_early_args(
+    args, module_type,
+    &cluster, &conf_file_list);
+  if (flags & (CINIT_FLAG_NO_DEFAULT_CONFIG_FILE|
+              CINIT_FLAG_NO_MON_CONFIG)) {
+    iparams.no_mon_config = true;
+  }
+
   CephContext *cct = common_preinit(iparams, code_env, flags);
   cct->_conf->cluster = cluster;
   global_init_set_globals(cct);
@@ -130,6 +138,15 @@ void global_pre_init(
 
   conf->parse_argv(args); // argv override
 
+  if (!iparams.no_mon_config) {
+    MonClient mc_bootstrap(g_ceph_context);
+    if (mc_bootstrap.get_monmap_and_config() < 0) {
+      derr << "failed to fetch mon config (--no-mon-config to skip)" << dendl;
+      cct->_log->flush();
+      _exit(1);
+    }
+  }
+
   // Now we're ready to complain about config file parse errors
   g_conf->complain_about_parse_errors(g_ceph_context);
 }
index df687e5db3a2f9ba117a91e350329d29356e9d7f..9f1a27eb73f19abbaf46e439e9ca91f0cbb20dea 100644 (file)
@@ -77,6 +77,13 @@ public:
 
     int ret;
 
+    {
+      MonClient mc_bootstrap(cct);
+      ret = mc_bootstrap.get_monmap_and_config();
+      if (ret < 0)
+       return ret;
+    }
+
     //monmap
     monclient = new MonClient(cct);
     ret = -CEPHFS_ERROR_MON_MAP_BUILD; //defined in libcephfs.h;
index 3fcd2523daf52159105ecb9e68a3c21d0c98ebc7..efbd6b563fb893ec571214a9efdfc96655727ffd 100644 (file)
@@ -248,6 +248,13 @@ int librados::RadosClient::connect()
     return -EISCONN;
   state = CONNECTING;
 
+  {
+    MonClient mc_bootstrap(cct);
+    err = mc_bootstrap.get_monmap_and_config();
+    if (err < 0)
+      return err;
+  }
+
   // get monmap
   err = monclient.build_initial_monmap();
   if (err < 0)
index cee5bb206154dd274b9317470bfa70cb35d94142..75a66b8d0981e8e9deb0e49202d2d6c0f94af22c 100644 (file)
@@ -22,6 +22,7 @@
 #include "messages/MMonGetVersionReply.h"
 #include "messages/MMonMap.h"
 #include "messages/MConfig.h"
+#include "messages/MGetConfig.h"
 #include "messages/MAuth.h"
 #include "messages/MLogAck.h"
 #include "messages/MAuthReply.h"
@@ -92,67 +93,71 @@ int MonClient::get_monmap()
   return 0;
 }
 
-int MonClient::get_monmap_privately()
+int MonClient::get_monmap_and_config()
 {
   ldout(cct, 10) << __func__ << dendl;
-  Mutex::Locker l(monc_lock);
+  assert(!messenger);
 
-  bool temp_msgr = false;
-  Messenger* smessenger = NULL;
-  if (!messenger) {
-    messenger = smessenger = Messenger::create_client_messenger(cct, "temp_mon_client");
-    if (NULL == messenger) {
-        return -1;
-    }
-    messenger->add_dispatcher_head(this);
-    smessenger->start();
-    temp_msgr = true;
-  }
+  utime_t interval;
+  interval.set_from_double(cct->_conf->mon_client_hunt_interval * 10);
 
-  int attempt = 10;
+  cct->init_crypto();
 
-  ldout(cct, 10) << "have " << monmap.epoch << " fsid " << monmap.fsid << dendl;
+  int r = build_initial_monmap();
+  if (r < 0) {
+    lderr(cct) << __func__ << " cannot identify monitors to contact" << dendl;
+    goto out;
+  }
 
-  std::random_device rd;
-  std::mt19937 rng(rd());
-  assert(monmap.size() > 0);
-  std::uniform_int_distribution<unsigned> ranks(0, monmap.size() - 1);
-  while (monmap.fsid.is_zero()) {
-    auto rank = ranks(rng);
-    auto& pending_con = _add_conn(rank, 0);
-    auto con = pending_con.get_con();
-    ldout(cct, 10) << "querying mon." << monmap.get_name(rank) << " "
-                  << con->get_peer_addr() << dendl;
-    con->send_message(new MMonGetMap);
-
-    if (--attempt == 0)
-      break;
-
-    utime_t interval;
-    interval.set_from_double(cct->_conf->mon_client_hunt_interval);
-    map_cond.WaitInterval(monc_lock, interval);
-
-    if (monmap.fsid.is_zero() && con) {
-      con->mark_down();  // nope, clean that connection up
+  messenger = Messenger::create_client_messenger(
+    cct, "temp_mon_client");
+  assert(messenger);
+  messenger->add_dispatcher_head(this);
+  messenger->start();
+
+  r = init();
+  if (r < 0) {
+    goto out_msgr;
+  }
+  r = authenticate(cct->_conf->client_mount_timeout);
+  if (r < 0) {
+    goto out_shutdown;
+  }
+  if (!monmap.persistent_features.contains_all(
+       ceph::features::mon::FEATURE_MIMIC)) {
+    ldout(cct,10) << __func__ << " pre-mimic monitor, no config to fetch"
+                 << dendl;
+  } else {
+    Mutex::Locker l(monc_lock);
+    while (!got_config) {
+      ldout(cct,20) << __func__ << " waiting for config" << dendl;
+      map_cond.WaitInterval(monc_lock, interval);
     }
   }
-
-  if (temp_msgr) {
-    pending_cons.clear();
-    monc_lock.Unlock();
-    messenger->shutdown();
-    if (smessenger)
-      smessenger->wait();
-    delete messenger;
-    messenger = 0;
-    monc_lock.Lock();
+  if (got_config) {
+    ldout(cct,10) << __func__ << " success" << dendl;
+    r = 0;
+  } else {
+    lderr(cct) << __func__ << " failed to get config" << dendl;
+    r = -EIO;
   }
 
-  pending_cons.clear();
+out_shutdown:
+  shutdown();
 
-  if (!monmap.fsid.is_zero())
-    return 0;
-  return -1;
+out_msgr:
+  messenger->shutdown();
+  messenger->wait();
+  delete messenger;
+  messenger = nullptr;
+
+  if (!monmap.fsid.is_zero()) {
+    cct->_conf->set_val("fsid", stringify(monmap.fsid));
+  }
+
+out:
+  cct->shutdown_crypto();
+  return r;
 }
 
 
@@ -360,6 +365,8 @@ void MonClient::handle_config(MConfig *m)
   ldout(cct,10) << __func__ << " " << *m << dendl;
   cct->_conf->set_mon_vals(cct, m->config);
   m->put();
+  got_config = true;
+  map_cond.Signal();
 }
 
 // ----------------------
@@ -449,6 +456,7 @@ void MonClient::shutdown()
   if (initialized) {
     finisher.wait_for_empty();
     finisher.stop();
+    initialized = false;
   }
   monc_lock.Lock();
   timer.shutdown();
index 7ca35016892e95b7c43dfb63b4265059829858ed..6caf57360e4e0e7d7d23ce64989ee133ff865d28 100644 (file)
@@ -190,6 +190,7 @@ private:
   bool want_monmap;
   Cond map_cond;
   bool passthrough_monmap = false;
+  bool got_config = false;
 
   // authenticate
   std::unique_ptr<AuthClientHandler> auth;
@@ -344,7 +345,7 @@ public:
 
   int build_initial_monmap();
   int get_monmap();
-  int get_monmap_privately();
+  int get_monmap_and_config();
   /**
    * If you want to see MonMap messages, set this and
    * the MonClient will tell the Messenger it hasn't
index 40cbf946d4bf7fa562893b703aae9dd2fb31f072..12399c0099b9d7225f3f1b12a239c188002eefce 100644 (file)
@@ -178,7 +178,8 @@ int main(int argc, const char **argv)
   vector<const char*> orig_args = args;
 
   global_pre_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
-                 CINIT_FLAG_NO_DAEMON_ACTIONS);
+                 CINIT_FLAG_NO_DAEMON_ACTIONS |
+                 CINIT_FLAG_NO_MON_CONFIG);
   std::unique_ptr<CephContext,
                  std::function<void(CephContext*)> > cct_deleter{
       g_ceph_context,