]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/global/global_init.cc
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / global / global_init.cc
index 126d3c59321d5bcafaabb16707ef9c7332f41ce9..0110bbdb1d6b84832cbfa558f535c9b5d817c249 100644 (file)
@@ -26,7 +26,7 @@
 #include "global/signal_handler.h"
 #include "include/compat.h"
 #include "include/str_list.h"
-#include "common/admin_socket.h"
+#include "mon/MonClient.h"
 
 #include <pwd.h>
 #include <grp.h>
@@ -42,7 +42,7 @@
 static void global_init_set_globals(CephContext *cct)
 {
   g_ceph_context = cct;
-  g_conf = cct->_conf;
+  get_process_name(g_process_name, sizeof(g_process_name));
 }
 
 static void output_ceph_version()
@@ -81,57 +81,97 @@ static int chown_path(const std::string &pathname, const uid_t owner, const gid_
   return r;
 }
 
-void global_pre_init(std::vector < const char * > *alt_def_args,
-                    std::vector < const char* >& args,
-                    uint32_t module_type, code_environment_t code_env,
-                    int flags)
+void global_pre_init(
+  const std::map<std::string,std::string> *defaults,
+  std::vector < const char* >& args,
+  uint32_t module_type, code_environment_t code_env,
+  int flags)
 {
   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);
+
   CephContext *cct = common_preinit(iparams, code_env, flags);
   cct->_conf->cluster = cluster;
   global_init_set_globals(cct);
-  md_config_t *conf = cct->_conf;
+  auto& conf = cct->_conf;
 
-  if (alt_def_args)
-    conf->parse_argv(*alt_def_args);  // alternative default args
+  if (flags & (CINIT_FLAG_NO_DEFAULT_CONFIG_FILE|
+              CINIT_FLAG_NO_MON_CONFIG)) {
+    conf->no_mon_config = true;
+  }
 
-  int ret = conf->parse_config_files(c_str_or_null(conf_file_list),
-                                    &cerr, flags);
+  // alternate defaults
+  if (defaults) {
+    for (auto& i : *defaults) {
+      conf.set_val_default(i.first, i.second);
+    }
+  }
+
+  int ret = conf.parse_config_files(c_str_or_null(conf_file_list),
+                                   &cerr, flags);
   if (ret == -EDOM) {
-    dout_emergency("global_init: error parsing config file.\n");
+    cct->_log->flush();
+    cerr << "global_init: error parsing config file." << std::endl;
     _exit(1);
   }
   else if (ret == -ENOENT) {
     if (!(flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)) {
       if (conf_file_list.length()) {
-       ostringstream oss;
-       oss << "global_init: unable to open config file from search list "
-           << conf_file_list << "\n";
-        dout_emergency(oss.str());
+       cct->_log->flush();
+       cerr << "global_init: unable to open config file from search list "
+            << conf_file_list << std::endl;
         _exit(1);
       } else {
-        derr << "did not load config file, using default settings." << dendl;
+       cerr << "did not load config file, using default settings." << std::endl;
       }
     }
   }
   else if (ret) {
-    dout_emergency("global_init: error reading config file.\n");
+    cct->_log->flush();
+    cerr << "global_init: error reading config file." << std::endl;
     _exit(1);
   }
 
-  conf->parse_env(); // environment variables override
+  // environment variables override (CEPH_ARGS, CEPH_KEYRING)
+  conf.parse_env(cct->get_module_type());
+
+  // command line (as passed by caller)
+  conf.parse_argv(args);
+
+  if (conf->log_early &&
+      !cct->_log->is_started()) {
+    cct->_log->start();
+  }
+
+  if (!conf->no_mon_config) {
+    // make sure our mini-session gets legacy values
+    conf.apply_changes(nullptr);
 
-  conf->parse_argv(args); // argv override
+    MonClient mc_bootstrap(g_ceph_context);
+    if (mc_bootstrap.get_monmap_and_config() < 0) {
+      cct->_log->flush();
+      cerr << "failed to fetch mon config (--no-mon-config to skip)"
+          << std::endl;
+      _exit(1);
+    }
+  }
+  if (!cct->_log->is_started()) {
+    cct->_log->start();
+  }
+
+  // do the --show-config[-val], if present in argv
+  conf.do_argv_commands();
 
   // Now we're ready to complain about config file parse errors
-  g_conf->complain_about_parse_errors(g_ceph_context);
+  g_conf().complain_about_parse_errors(g_ceph_context);
 }
 
 boost::intrusive_ptr<CephContext>
-global_init(std::vector < const char * > *alt_def_args,
+global_init(const std::map<std::string,std::string> *defaults,
            std::vector < const char* >& args,
            uint32_t module_type, code_environment_t code_env,
            int flags,
@@ -141,11 +181,11 @@ global_init(std::vector < const char * > *alt_def_args,
   static bool first_run = true;
   if (run_pre_init) {
     // We will run pre_init from here (default).
-    assert(!g_ceph_context && first_run);
-    global_pre_init(alt_def_args, args, module_type, code_env, flags);
+    ceph_assert(!g_ceph_context && first_run);
+    global_pre_init(defaults, args, module_type, code_env, flags);
   } else {
     // Caller should have invoked pre_init manually.
-    assert(g_ceph_context && first_run);
+    ceph_assert(g_ceph_context && first_run);
   }
   first_run = false;
 
@@ -159,10 +199,12 @@ global_init(std::vector < const char * > *alt_def_args,
   int siglist[] = { SIGPIPE, 0 };
   block_signals(siglist, NULL);
 
-  if (g_conf->fatal_signal_handlers)
+  if (g_conf()->fatal_signal_handlers) {
     install_standard_sighandlers();
+  }
+  register_assert_context(g_ceph_context);
 
-  if (g_conf->log_flush_on_exit)
+  if (g_conf()->log_flush_on_exit)
     g_ceph_context->_log->set_flush_on_exit();
 
   // drop privileges?
@@ -170,63 +212,72 @@ global_init(std::vector < const char * > *alt_def_args,
  
   // consider --setuser root a no-op, even if we're not root
   if (getuid() != 0) {
-    if (g_conf->setuser.length()) {
-      cerr << "ignoring --setuser " << g_conf->setuser << " since I am not root"
+    if (g_conf()->setuser.length()) {
+      cerr << "ignoring --setuser " << g_conf()->setuser << " since I am not root"
           << std::endl;
     }
-    if (g_conf->setgroup.length()) {
-      cerr << "ignoring --setgroup " << g_conf->setgroup
+    if (g_conf()->setgroup.length()) {
+      cerr << "ignoring --setgroup " << g_conf()->setgroup
           << " since I am not root" << std::endl;
     }
-  } else if (g_conf->setgroup.length() ||
-             g_conf->setuser.length()) {
+  } else if (g_conf()->setgroup.length() ||
+             g_conf()->setuser.length()) {
     uid_t uid = 0;  // zero means no change; we can only drop privs here.
     gid_t gid = 0;
     std::string uid_string;
     std::string gid_string;
-    if (g_conf->setuser.length()) {
-      uid = atoi(g_conf->setuser.c_str());
-      if (!uid) {
-       char buf[4096];
-       struct passwd pa;
-       struct passwd *p = 0;
-       getpwnam_r(g_conf->setuser.c_str(), &pa, buf, sizeof(buf), &p);
-       if (!p) {
-         cerr << "unable to look up user '" << g_conf->setuser << "'"
+    std::string home_directory;
+    if (g_conf()->setuser.length()) {
+      char buf[4096];
+      struct passwd pa;
+      struct passwd *p = 0;
+
+      uid = atoi(g_conf()->setuser.c_str());
+      if (uid) {
+        getpwuid_r(uid, &pa, buf, sizeof(buf), &p);
+      } else {
+       getpwnam_r(g_conf()->setuser.c_str(), &pa, buf, sizeof(buf), &p);
+        if (!p) {
+         cerr << "unable to look up user '" << g_conf()->setuser << "'"
               << std::endl;
          exit(1);
-       }
-       uid = p->pw_uid;
-       gid = p->pw_gid;
-       uid_string = g_conf->setuser;
+        }
+
+        uid = p->pw_uid;
+        gid = p->pw_gid;
+        uid_string = g_conf()->setuser;
+      }
+
+      if (p && p->pw_dir != nullptr) {
+        home_directory = std::string(p->pw_dir);
       }
     }
-    if (g_conf->setgroup.length() > 0) {
-      gid = atoi(g_conf->setgroup.c_str());
+    if (g_conf()->setgroup.length() > 0) {
+      gid = atoi(g_conf()->setgroup.c_str());
       if (!gid) {
        char buf[4096];
        struct group gr;
        struct group *g = 0;
-       getgrnam_r(g_conf->setgroup.c_str(), &gr, buf, sizeof(buf), &g);
+       getgrnam_r(g_conf()->setgroup.c_str(), &gr, buf, sizeof(buf), &g);
        if (!g) {
-         cerr << "unable to look up group '" << g_conf->setgroup << "'"
+         cerr << "unable to look up group '" << g_conf()->setgroup << "'"
               << ": " << cpp_strerror(errno) << std::endl;
          exit(1);
        }
        gid = g->gr_gid;
-       gid_string = g_conf->setgroup;
+       gid_string = g_conf()->setgroup;
       }
     }
     if ((uid || gid) &&
-       g_conf->setuser_match_path.length()) {
+       g_conf()->setuser_match_path.length()) {
       // induce early expansion of setuser_match_path config option
-      string match_path = g_conf->setuser_match_path;
-      g_conf->early_expand_meta(match_path, &cerr);
+      string match_path = g_conf()->setuser_match_path;
+      g_conf().early_expand_meta(match_path, &cerr);
       struct stat st;
       int r = ::stat(match_path.c_str(), &st);
       if (r < 0) {
        cerr << "unable to stat setuser_match_path "
-            << g_conf->setuser_match_path
+            << g_conf()->setuser_match_path
             << ": " << cpp_strerror(errno) << std::endl;
        exit(1);
       }
@@ -259,6 +310,10 @@ global_init(std::vector < const char * > *alt_def_args,
             << std::endl;
        exit(1);
       }
+      if (setenv("HOME", home_directory.c_str(), 1) != 0) {
+       cerr << "warning: unable to set HOME to " << home_directory << ": "
+             << cpp_strerror(errno) << std::endl;
+      }
       priv_ss << "set uid:gid to " << uid << ":" << gid << " (" << uid_string << ":" << gid_string << ")";
     } else {
       priv_ss << "deferred set uid:gid to " << uid << ":" << gid << " (" << uid_string << ":" << gid_string << ")";
@@ -269,25 +324,28 @@ global_init(std::vector < const char * > *alt_def_args,
   if (prctl(PR_SET_DUMPABLE, 1) == -1) {
     cerr << "warning: unable to set dumpable flag: " << cpp_strerror(errno) << std::endl;
   }
+#  if defined(PR_SET_THP_DISABLE)
+  if (!g_conf().get_val<bool>("thp") && prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0) == -1) {
+    cerr << "warning: unable to disable THP: " << cpp_strerror(errno) << std::endl;
+  }
+#  endif
 #endif
 
   // Expand metavariables. Invoke configuration observers. Open log file.
-  g_conf->apply_changes(NULL);
+  g_conf().apply_changes(nullptr);
 
-  if (g_conf->run_dir.length() &&
+  if (g_conf()->run_dir.length() &&
       code_env == CODE_ENVIRONMENT_DAEMON &&
       !(flags & CINIT_FLAG_NO_DAEMON_ACTIONS)) {
-    int r = ::mkdir(g_conf->run_dir.c_str(), 0755);
+    int r = ::mkdir(g_conf()->run_dir.c_str(), 0755);
     if (r < 0 && errno != EEXIST) {
-      cerr << "warning: unable to create " << g_conf->run_dir << ": " << cpp_strerror(errno) << std::endl;
+      cerr << "warning: unable to create " << g_conf()->run_dir << ": " << cpp_strerror(errno) << std::endl;
     }
   }
 
-  register_assert_context(g_ceph_context);
-
   // call all observers now.  this has the side-effect of configuring
   // and opening the log file immediately.
-  g_conf->call_all_observers();
+  g_conf().call_all_observers();
 
   if (priv_ss.str().length()) {
     dout(0) << priv_ss.str() << dendl;
@@ -298,7 +356,7 @@ global_init(std::vector < const char * > *alt_def_args,
     // Fix ownership on log files and run directories if needed.
     // Admin socket files are chown()'d during the common init path _after_
     // the service thread has been started. This is sadly a bit of a hack :(
-    chown_path(g_conf->run_dir,
+    chown_path(g_conf()->run_dir,
               g_ceph_context->get_set_uid(),
               g_ceph_context->get_set_gid(),
               g_ceph_context->get_set_uid_string(),
@@ -309,10 +367,10 @@ global_init(std::vector < const char * > *alt_def_args,
   }
 
   // Now we're ready to complain about config file parse errors
-  g_conf->complain_about_parse_errors(g_ceph_context);
+  g_conf().complain_about_parse_errors(g_ceph_context);
 
   // test leak checking
-  if (g_conf->debug_deliberately_leak_memory) {
+  if (g_conf()->debug_deliberately_leak_memory) {
     derr << "deliberately leaking some memory" << dendl;
     char *s = new char[1234567];
     (void)s;
@@ -350,7 +408,7 @@ int global_init_prefork(CephContext *cct)
   if (g_code_env != CODE_ENVIRONMENT_DAEMON)
     return -1;
 
-  const md_config_t *conf = cct->_conf;
+  const auto& conf = cct->_conf;
   if (!conf->daemonize) {
 
     if (pidfile_write(conf) < 0)
@@ -433,7 +491,7 @@ void global_init_postfork_start(CephContext *cct)
    */
   reopen_as_null(cct, STDIN_FILENO);
 
-  const md_config_t *conf = cct->_conf;
+  const auto& conf = cct->_conf;
   if (pidfile_write(conf) < 0)
     exit(1);
 
@@ -467,7 +525,7 @@ void global_init_postfork_finish(CephContext *cct)
 
 void global_init_chdir(const CephContext *cct)
 {
-  const md_config_t *conf = cct->_conf;
+  const auto& conf = cct->_conf;
   if (conf->chdir.empty())
     return;
   if (::chdir(conf->chdir.c_str())) {
@@ -484,13 +542,14 @@ void global_init_chdir(const CephContext *cct)
 int global_init_shutdown_stderr(CephContext *cct)
 {
   reopen_as_null(cct, STDERR_FILENO);
-  cct->_log->set_stderr_level(-1, -1);
+  int l = cct->_conf->err_to_stderr ? -1 : -2;
+  cct->_log->set_stderr_level(l, l);
   return 0;
 }
 
 int global_init_preload_erasure_code(const CephContext *cct)
 {
-  const md_config_t *conf = cct->_conf;
+  const auto& conf = cct->_conf;
   string plugins = conf->osd_erasure_code_plugins;
 
   // validate that this is a not a legacy plugin
@@ -525,7 +584,7 @@ int global_init_preload_erasure_code(const CephContext *cct)
   stringstream ss;
   int r = ErasureCodePluginRegistry::instance().preload(
     plugins,
-    conf->get_val<std::string>("erasure_code_dir"),
+    conf.get_val<std::string>("erasure_code_dir"),
     &ss);
   if (r)
     derr << ss.str() << dendl;