*/
#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
;
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;
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,
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;
}
} 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);
}
} 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;
}
* 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> §ions) 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> §ions) 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
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) {