]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/common/config.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / common / config.cc
index 53007f925146d65489b0840b6905f528266312aa..b110e99772715d059b03b8968e231a49246b2f53 100644 (file)
  */
 
 #include <boost/type_traits.hpp>
-
+#if __has_include(<filesystem>)
+#include <filesystem>
+namespace fs = std::filesystem;
+#else
+#include <experimental/filesystem>
+namespace fs = std::experimental::filesystem;
+#endif
 #include "common/ceph_argparse.h"
 #include "common/common_init.h"
 #include "common/config.h"
 // set set_mon_vals()
 #define dout_subsys ceph_subsys_monc
 
+using std::cerr;
+using std::cout;
 using std::map;
+using std::less;
 using std::list;
+using std::ostream;
 using std::ostringstream;
 using std::pair;
 using std::string;
+using std::string_view;
+using std::vector;
+
+using ceph::bufferlist;
+using ceph::decode;
+using ceph::encode;
+using ceph::Formatter;
 
-static const char *CEPH_CONF_FILE_DEFAULT = "$data_dir/config, /etc/ceph/$cluster.conf, $home/.ceph/$cluster.conf, $cluster.conf"
+static const char *CEPH_CONF_FILE_DEFAULT = "$data_dir/config,/etc/ceph/$cluster.conf,$home/.ceph/$cluster.conf,$cluster.conf"
 #if defined(__FreeBSD__)
-    ", /usr/local/etc/ceph/$cluster.conf"
+    ",/usr/local/etc/ceph/$cluster.conf"
+#elif defined(_WIN32)
+    ",$programdata/ceph/$cluster.conf"
 #endif
     ;
 
@@ -70,7 +89,7 @@ int ceph_resolve_file_search(const std::string& filename_list,
                             std::string& result)
 {
   list<string> ls;
-  get_str_list(filename_list, ls);
+  get_str_list(filename_list, ";,", ls);
 
   int ret = -ENOENT;
   list<string>::iterator iter;
@@ -335,125 +354,126 @@ int md_config_t::parse_config_files(ConfigValues& values,
                                    std::ostream *warnings,
                                    int flags)
 {
-
   if (safe_to_start_threads)
     return -ENOSYS;
 
-  if (!values.cluster.size() && !conf_files_str) {
-    /*
-     * set the cluster name to 'ceph' when neither cluster name nor
-     * configuration file are specified.
-     */
-    values.cluster = "ceph";
-  }
-
-  if (!conf_files_str) {
-    const char *c = getenv("CEPH_CONF");
-    if (c) {
-      conf_files_str = c;
-    }
-    else {
-      if (flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)
-       return 0;
-      conf_files_str = CEPH_CONF_FILE_DEFAULT;
-    }
-  }
-
-  std::list<std::string> conf_files;
-  get_str_list(conf_files_str, conf_files);
-  auto p = conf_files.begin();
-  while (p != conf_files.end()) {
-    string &s = *p;
-    if (s.find("$data_dir") != string::npos &&
-       data_dir_option.empty()) {
-      // useless $data_dir item, skip
-      p = conf_files.erase(p);
-    } else {
-      early_expand_meta(values, s, warnings);
-      ++p;
-    }
+  if (values.cluster.empty() && !conf_files_str) {
+    values.cluster = get_cluster_name(nullptr);
   }
-
   // open new conf
-  list<string>::const_iterator c;
-  for (c = conf_files.begin(); c != conf_files.end(); ++c) {
-    cf.clear();
-    string fn = *c;
+  string conffile;
+  for (auto& fn : get_conffile_paths(values, conf_files_str, warnings, flags)) {
+    bufferlist bl;
+    std::string error;
+    if (bl.read_file(fn.c_str(), &error)) {
+      parse_error = error;
+      continue;
+    }
     ostringstream oss;
-    int ret = cf.parse_file(fn.c_str(), &oss);
-    parse_error = oss.str();
+    int ret = parse_buffer(values, tracker, bl.c_str(), bl.length(), &oss);
     if (ret == 0) {
+      parse_error.clear();
+      conffile = fn;
       break;
     }
-    if (ret != -ENOENT)
+    parse_error = oss.str();
+    if (ret != -ENOENT) {
       return ret;
+    }
   }
   // it must have been all ENOENTs, that's the only way we got here
-  if (c == conf_files.end())
+  if (conffile.empty()) {
     return -ENOENT;
-
-  if (values.cluster.size() == 0) {
-    /*
-     * If cluster name is not set yet, use the prefix of the
-     * basename of configuration file as cluster name.
-     */
-    auto start = c->rfind('/') + 1;
-    auto end = c->find(".conf", start);
-    if (end == c->npos) {
-        /*
-         * If the configuration file does not follow $cluster.conf
-         * convention, we do the last try and assign the cluster to
-         * 'ceph'.
-         */
-        values.cluster = "ceph";
-    } else {
-      values.cluster = c->substr(start, end - start);
-    }
   }
+  if (values.cluster.empty()) {
+    values.cluster = get_cluster_name(conffile.c_str());
+  }
+  update_legacy_vals(values);
+  return 0;
+}
 
-  std::vector <std::string> my_sections;
-  _get_my_sections(values, my_sections);
+int
+md_config_t::parse_buffer(ConfigValues& values,
+                         const ConfigTracker& tracker,
+                         const char* buf, size_t len,
+                         std::ostream* warnings)
+{
+  if (!cf.parse_buffer(string_view{buf, len}, warnings)) {
+    return -EINVAL;
+  }
+  const auto my_sections = get_my_sections(values);
   for (const auto &i : schema) {
     const auto &opt = i.second;
     std::string val;
-    int ret = _get_val_from_conf_file(my_sections, opt.name, val);
-    if (ret == 0) {
-      std::string error_message;
-      int r = _set_val(values, tracker, val, opt, CONF_FILE, &error_message);
-      if (warnings != nullptr && (r < 0 || !error_message.empty())) {
-        *warnings << "parse error setting '" << opt.name << "' to '" << val
-                  << "'";
+    if (_get_val_from_conf_file(my_sections, opt.name, val)) {
+      continue;
+    }
+    std::string error_message;
+    if (_set_val(values, tracker, val, opt, CONF_FILE, &error_message) < 0) {
+      if (warnings != nullptr) {
+        *warnings << "parse error setting " << std::quoted(opt.name)
+                  << " to " << std::quoted(val);
         if (!error_message.empty()) {
           *warnings << " (" << error_message << ")";
         }
-        *warnings << std::endl;
+        *warnings << '\n';
       }
     }
   }
+  cf.check_old_style_section_names({"mds", "mon", "osd"}, cerr);
+  return 0;
+}
 
-  // Warn about section names that look like old-style section names
-  std::deque < std::string > old_style_section_names;
-  for (auto& [name, section] : cf) {
-    if (((name.find("mds") == 0) || (name.find("mon") == 0) ||
-        (name.find("osd") == 0)) && (name.size() > 3) && (name[3] != '.')) {
-      old_style_section_names.push_back(name);
+std::list<std::string>
+md_config_t::get_conffile_paths(const ConfigValues& values,
+                               const char *conf_files_str,
+                               std::ostream *warnings,
+                               int flags) const
+{
+  if (!conf_files_str) {
+    const char *c = getenv("CEPH_CONF");
+    if (c) {
+      conf_files_str = c;
+    } else {
+      if (flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)
+       return {};
+      conf_files_str = CEPH_CONF_FILE_DEFAULT;
     }
   }
-  if (!old_style_section_names.empty()) {
-    ostringstream oss;
-    cerr << "ERROR! old-style section name(s) found: ";
-    string sep;
-    for (std::deque < std::string >::const_iterator os = old_style_section_names.begin();
-        os != old_style_section_names.end(); ++os) {
-      cerr << sep << *os;
-      sep = ", ";
+
+  std::list<std::string> paths;
+  get_str_list(conf_files_str, ";,", paths);
+  for (auto i = paths.begin(); i != paths.end(); ) {
+    string& path = *i;
+    if (path.find("$data_dir") != path.npos &&
+       data_dir_option.empty()) {
+      // useless $data_dir item, skip
+      i = paths.erase(i);
+    } else {
+      early_expand_meta(values, path, warnings);
+      ++i;
     }
-    cerr << ". Please use the new style section names that include a period.";
   }
+  return paths;
+}
 
-  update_legacy_vals(values);
-
-  return 0;
+std::string md_config_t::get_cluster_name(const char* conffile)
+{
+  if (conffile) {
+    // If cluster name is not set yet, use the prefix of the
+    // basename of configuration file as cluster name.
+    if (fs::path path{conffile}; path.extension() == ".conf") {
+      return path.stem().string();
+    } else {
+      // If the configuration file does not follow $cluster.conf
+      // convention, we do the last try and assign the cluster to
+      // 'ceph'.
+      return "ceph";
+    }
+  } else {
+    // set the cluster name to 'ceph' when configuration file is not specified.
+    return "ceph";
+  }
 }
 
 void md_config_t::parse_env(unsigned entity_type,
@@ -649,9 +669,6 @@ int md_config_t::parse_argv(ConfigValues& values,
     else if (ceph_argparse_flag(args, i, "--no-mon-config", (char*)NULL)) {
       values.no_mon_config = true;
     }
-    else if (ceph_argparse_flag(args, i, "--log-early", (char*)NULL)) {
-      values.log_early = true;
-    }
     else if (ceph_argparse_flag(args, i, "--mon-config", (char*)NULL)) {
       values.no_mon_config = false;
     }
@@ -1201,7 +1218,12 @@ Option::value_t md_config_t::_expand_meta(
       } else if (var == "id") {
        out += values.name.get_id();
       } else if (var == "pid") {
-       out += stringify(getpid());
+        char *_pid = getenv("PID");
+        if (_pid) {
+          out += _pid;
+        } else {
+          out += stringify(getpid());
+        }
         if (o) {
           may_reexpand_meta.push_back(o->name);
         }
@@ -1210,7 +1232,10 @@ Option::value_t md_config_t::_expand_meta(
       } else if (var == "home") {
        const char *home = getenv("HOME");
        out = home ? std::string(home) : std::string();
-      } else {
+      } else if (var == "programdata") {
+        const char *home = getenv("ProgramData");
+        out = home ? std::string(home) : std::string();
+      }else {
        if (var == "data_dir") {
          var = data_dir_option;
        }
@@ -1300,20 +1325,12 @@ void md_config_t::get_all_keys(std::vector<std::string> *keys) const {
  * looking. The lowest priority section is the one we look in only if all
  * others had nothing.  This should always be the global section.
  */
-void md_config_t::get_my_sections(const ConfigValues& values,
-                                 std::vector <std::string> &sections) const
+std::vector <std::string>
+md_config_t::get_my_sections(const ConfigValues& values) const
 {
-  _get_my_sections(values, sections);
-}
-
-void md_config_t::_get_my_sections(const ConfigValues& values,
-                                  std::vector <std::string> &sections) const
-{
-  sections.push_back(values.name.to_str());
-
-  sections.push_back(values.name.get_type_name());
-
-  sections.push_back("global");
+  return {values.name.to_str(),
+         values.name.get_type_name().data(),
+         "global"};
 }
 
 // Return a list of all sections
@@ -1351,7 +1368,7 @@ int md_config_t::_get_val_from_conf_file(
   std::string &out) const
 {
   for (auto &s : sections) {
-    int ret = cf.read(s.c_str(), std::string{key}, out);
+    int ret = cf.read(s, key, out);
     if (ret == 0) {
       return 0;
     } else if (ret != -ENOENT) {