From 3193d40d0daf766d5e210e7b1117afbfebd71f31 Mon Sep 17 00:00:00 2001 From: Rubab-Syed Date: Fri, 16 Feb 2018 15:51:11 +0500 Subject: [PATCH] mgr: centralized setting/getting of mgr configs Signed-off-by: Rubab Syed --- src/common/config.cc | 15 ++++- src/common/config.h | 9 ++- src/mgr/ActivePyModules.cc | 109 +++++++++++++++++++++++++++++++----- src/mgr/ActivePyModules.h | 12 ++-- src/mgr/Mgr.cc | 9 +-- src/mgr/MgrStandby.cc | 15 +++++ src/mgr/MgrStandby.h | 1 + src/mgr/PyModule.cc | 7 +++ src/mgr/PyModule.h | 11 ++++ src/mgr/PyModuleRegistry.cc | 18 +++++- src/mgr/PyModuleRegistry.h | 9 +-- src/mgr/StandbyPyModules.cc | 58 +++---------------- src/mgr/StandbyPyModules.h | 45 ++++----------- src/mon/ConfigMonitor.cc | 86 +++++++++++++++++----------- src/mon/MonClient.cc | 19 +++++-- src/mon/MonClient.h | 12 ++-- 16 files changed, 276 insertions(+), 159 deletions(-) diff --git a/src/common/config.cc b/src/common/config.cc index 60af9e0682e65..d4649ae2fe8be 100644 --- a/src/common/config.cc +++ b/src/common/config.cc @@ -260,11 +260,24 @@ void md_config_t::set_val_default(const string& name, const std::string& val) assert(r >= 0); } -int md_config_t::set_mon_vals(CephContext *cct, const map& kv) +int md_config_t::set_mon_vals(CephContext *cct, + const map& kv, + config_callback config_cb) { Mutex::Locker l(lock); ignored_mon_values.clear(); + + if (!config_cb) { + ldout(cct, 4) << __func__ << " no callback set" << dendl; + } + for (auto& i : kv) { + if (config_cb && config_cb(i.first, i.second)) { + ldout(cct, 4) << __func__ << " callback consumed " << i.first << dendl; + continue; + } else { + ldout(cct, 4) << __func__ << " callback ignored " << i.first << dendl; + } const Option *o = find_option(i.first); if (!o) { ldout(cct,10) << __func__ << " " << i.first << " = " << i.second diff --git a/src/common/config.h b/src/common/config.h index 56f25f0186d45..a3adf29c7ce14 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -78,6 +78,11 @@ public: bool md_config_t::*, entity_addr_t md_config_t::*, uuid_d md_config_t::*> member_ptr_t; + + // For use when intercepting configuration updates + typedef std::function config_callback; + /// true if we are a daemon (as per CephContext::code_env) const bool is_daemon; @@ -171,7 +176,9 @@ public: void set_val_default(const std::string& key, const std::string &val); /// Set a values from mon - int set_mon_vals(CephContext *cct, const map& kv); + int set_mon_vals(CephContext *cct, + const map& kv, + config_callback config_cb); // Called by the Ceph daemons to make configuration changes at runtime int injectargs(const std::string &s, std::ostream *oss); diff --git a/src/mgr/ActivePyModules.cc b/src/mgr/ActivePyModules.cc index 215ae3ca1915e..4c6cb05443c7f 100644 --- a/src/mgr/ActivePyModules.cc +++ b/src/mgr/ActivePyModules.cc @@ -26,23 +26,30 @@ // For ::config_prefix #include "PyModuleRegistry.h" +#include "PyModule.h" #include "ActivePyModules.h" #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mgr #undef dout_prefix -#define dout_prefix *_dout << "mgr " << __func__ << " " +#define dout_prefix *_dout << "mgr " << __func__ << " " - -ActivePyModules::ActivePyModules(PyModuleConfig const &config_, +ActivePyModules::ActivePyModules(PyModuleConfig &module_config, DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, LogChannelRef clog_, Objecter &objecter_, Client &client_, Finisher &f) - : config_cache(config_), daemon_state(ds), cluster_state(cs), + : config_cache(module_config), daemon_state(ds), cluster_state(cs), monc(mc), clog(clog_), objecter(objecter_), client(client_), finisher(f), lock("ActivePyModules") -{} +{ + for(auto &i: config_cache.config) { + auto last_slash = i.first.rfind('/'); + const std::string module_name = i.first.substr(4, i.first.substr(4).find('/')); + const std::string key = i.first.substr(last_slash + 1); + set_config(module_name, key, i.second); + } +} ActivePyModules::~ActivePyModules() = default; @@ -418,6 +425,29 @@ void ActivePyModules::notify_all(const LogEntry &log_entry) } } +bool ActivePyModules::get_store(const std::string &module_name, + const std::string &key, std::string *val) const +{ + PyThreadState *tstate = PyEval_SaveThread(); + Mutex::Locker l(lock); + PyEval_RestoreThread(tstate); + + const std::string global_key = PyModuleRegistry::config_prefix + + module_name + "/" + key; + + dout(4) << __func__ << "key: " << global_key << dendl; + + + Mutex::Locker lock(config_cache.lock); + + if (config_cache.config.count(global_key)) { + *val = config_cache.config.at(global_key); + return true; + } else { + return false; + } +} + bool ActivePyModules::get_config(const std::string &module_name, const std::string &key, std::string *val) const { @@ -430,8 +460,11 @@ bool ActivePyModules::get_config(const std::string &module_name, dout(4) << __func__ << " key: " << global_key << dendl; - if (config_cache.count(global_key)) { - *val = config_cache.at(global_key); + + Mutex::Locker lock(config_cache.lock); + + if (config_cache.config.count(global_key)) { + *val = config_cache.config.at(global_key); return true; } else { return false; @@ -451,29 +484,35 @@ PyObject *ActivePyModules::get_config_prefix(const std::string &module_name, dout(4) << __func__ << " prefix: " << global_prefix << dendl; PyFormatter f; - for (auto p = config_cache.lower_bound(global_prefix); - p != config_cache.end() && p->first.find(global_prefix) == 0; + + Mutex::Locker lock(config_cache.lock); + + for (auto p = config_cache.config.lower_bound(global_prefix); + p != config_cache.config.end() && p->first.find(global_prefix) == 0; ++p) { f.dump_string(p->first.c_str() + base_prefix.size(), p->second); } return f.get(); } -void ActivePyModules::set_config(const std::string &module_name, +void ActivePyModules::set_store(const std::string &module_name, const std::string &key, const boost::optional& val) { const std::string global_key = PyModuleRegistry::config_prefix + module_name + "/" + key; - + Command set_cmd; { PyThreadState *tstate = PyEval_SaveThread(); Mutex::Locker l(lock); PyEval_RestoreThread(tstate); + + Mutex::Locker lock(config_cache.lock); + if (val) { - config_cache[global_key] = *val; + config_cache.config[global_key] = *val; } else { - config_cache.erase(global_key); + config_cache.config.erase(global_key); } std::ostringstream cmd_json; @@ -503,6 +542,50 @@ void ActivePyModules::set_config(const std::string &module_name, } } +void ActivePyModules::set_config(const std::string &module_name, + const std::string &key, const boost::optional& val) +{ + const std::string global_key = PyModuleRegistry::config_prefix + + module_name + "/" + key; + + Command set_cmd; + { + PyThreadState *tstate = PyEval_SaveThread(); + Mutex::Locker l(lock); + PyEval_RestoreThread(tstate); + + Mutex::Locker lock(config_cache.lock); + + if (val) { + config_cache.config[global_key] = *val; + } else { + config_cache.config.erase(global_key); + } + + std::ostringstream cmd_json; + JSONFormatter jf; + jf.open_object_section("cmd"); + if (val) { + jf.dump_string("prefix", "config set mgr"); + jf.dump_string("key", global_key); + jf.dump_string("val", *val); + } else { + jf.dump_string("prefix", "config rm"); + jf.dump_string("key", global_key); + } + jf.close_section(); + jf.flush(cmd_json); + set_cmd.run(&monc, cmd_json.str()); + } + set_cmd.wait(); + + if (set_cmd.r != 0) { + dout(0) << "`config set mgr" << global_key << " " << val << "` failed: " + << cpp_strerror(set_cmd.r) << dendl; + dout(0) << "mon returned " << set_cmd.r << ": " << set_cmd.outs << dendl; + } +} + std::map ActivePyModules::get_services() const { std::map result; diff --git a/src/mgr/ActivePyModules.h b/src/mgr/ActivePyModules.h index c5befc9de2fc3..cdd5ab44d3752 100644 --- a/src/mgr/ActivePyModules.h +++ b/src/mgr/ActivePyModules.h @@ -29,8 +29,6 @@ class health_check_map_t; -typedef std::map PyModuleConfig; - class ActivePyModules { @@ -48,7 +46,7 @@ class ActivePyModules mutable Mutex lock{"ActivePyModules::lock"}; public: - ActivePyModules(PyModuleConfig const &config_, + ActivePyModules(PyModuleConfig &module_config, DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, LogChannelRef clog_, Objecter &objecter_, Client &client_, Finisher &f); @@ -59,7 +57,6 @@ public: MonClient &get_monc() {return monc;} Objecter &get_objecter() {return objecter;} Client &get_client() {return client;} - PyObject *get_python(const std::string &what); PyObject *get_server_python(const std::string &hostname); PyObject *list_servers_python(); @@ -77,10 +74,15 @@ public: PyObject *get_context(); PyObject *get_osdmap(); - bool get_config(const std::string &module_name, + bool get_store(const std::string &module_name, const std::string &key, std::string *val) const; PyObject *get_config_prefix(const std::string &module_name, const std::string &prefix) const; + void set_store(const std::string &module_name, + const std::string &key, const boost::optional &val); + + bool get_config(const std::string &module_name, + const std::string &key, std::string *val) const; void set_config(const std::string &module_name, const std::string &key, const boost::optional &val); diff --git a/src/mgr/Mgr.cc b/src/mgr/Mgr.cc index 0c901a6933e2b..c20513e1e85c8 100644 --- a/src/mgr/Mgr.cc +++ b/src/mgr/Mgr.cc @@ -30,7 +30,7 @@ #include "messages/MCommandReply.h" #include "messages/MLog.h" #include "messages/MServiceMap.h" - +#include "PyModule.h" #include "Mgr.h" #define dout_context g_ceph_context @@ -315,7 +315,7 @@ void Mgr::load_all_metadata() } } -std::map Mgr::load_config() +PyModuleConfig Mgr::load_config() { assert(lock.is_locked_by_me()); @@ -327,10 +327,11 @@ std::map Mgr::load_config() lock.Lock(); assert(cmd.r == 0); - std::map loaded; + PyModuleConfig loaded; for (auto &key_str : cmd.json_result.get_array()) { std::string const key = key_str.get_str(); + dout(20) << "saw key '" << key << "'" << dendl; const std::string config_prefix = PyModuleRegistry::config_prefix; @@ -345,7 +346,7 @@ std::map Mgr::load_config() get_cmd.wait(); lock.Lock(); assert(get_cmd.r == 0); - loaded[key] = get_cmd.outbl.to_str(); + loaded.config[key] = get_cmd.outbl.to_str(); } } diff --git a/src/mgr/MgrStandby.cc b/src/mgr/MgrStandby.cc index 90773ab5f8abb..46d809974eed9 100644 --- a/src/mgr/MgrStandby.cc +++ b/src/mgr/MgrStandby.cc @@ -125,6 +125,21 @@ int MgrStandby::init() monc.set_want_keys(CEPH_ENTITY_TYPE_MON|CEPH_ENTITY_TYPE_OSD |CEPH_ENTITY_TYPE_MDS|CEPH_ENTITY_TYPE_MGR); monc.set_messenger(client_messenger.get()); + + // We must register our config callback before calling init(), so + // that we see the initial configuration message + monc.register_config_callback([this](const std::string &k, const std::string &v){ + dout(10) << "config_callback: " << k << " : " << v << dendl; + if (k.substr(0, 4) == "mgr/") { + const std::string global_key = PyModuleRegistry::config_prefix + k.substr(4); + py_module_registry.handle_config(global_key, v); + + return true; + } + return false; + }); + dout(4) << "Registered monc callback" << dendl; + int r = monc.init(); if (r < 0) { monc.shutdown(); diff --git a/src/mgr/MgrStandby.h b/src/mgr/MgrStandby.h index 4d4cc364c312e..bfeca66b35f27 100644 --- a/src/mgr/MgrStandby.h +++ b/src/mgr/MgrStandby.h @@ -28,6 +28,7 @@ class MMgrMap; class Mgr; +class PyModuleConfig; class MgrStandby : public Dispatcher, public md_config_obs_t { diff --git a/src/mgr/PyModule.cc b/src/mgr/PyModule.cc index 53ca84c703e7c..da7b0adc403a9 100644 --- a/src/mgr/PyModule.cc +++ b/src/mgr/PyModule.cc @@ -123,6 +123,13 @@ namespace { #endif } +PyModuleConfig::PyModuleConfig() = default; + +PyModuleConfig::PyModuleConfig(PyModuleConfig &mconfig) + : config(mconfig.config) +{} + +PyModuleConfig::~PyModuleConfig() = default; std::string PyModule::get_site_packages() { diff --git a/src/mgr/PyModule.h b/src/mgr/PyModule.h index df79e8e9a6d6a..7a314af979677 100644 --- a/src/mgr/PyModule.h +++ b/src/mgr/PyModule.h @@ -132,3 +132,14 @@ public: typedef std::shared_ptr PyModuleRef; +class PyModuleConfig { +public: + mutable Mutex lock{"PyModuleConfig::lock"}; + std::map config; + + PyModuleConfig(); + + PyModuleConfig(PyModuleConfig &mconfig); + + ~PyModuleConfig(); +}; diff --git a/src/mgr/PyModuleRegistry.cc b/src/mgr/PyModuleRegistry.cc index dac80005c365e..686dbfc872c01 100644 --- a/src/mgr/PyModuleRegistry.cc +++ b/src/mgr/PyModuleRegistry.cc @@ -141,7 +141,8 @@ void PyModuleRegistry::standby_start(MonClient *monc) dout(4) << "Starting modules in standby mode" << dendl; - standby_modules.reset(new StandbyPyModules(monc, mgr_map, clog)); + standby_modules.reset(new StandbyPyModules( + monc, mgr_map, module_config, clog)); std::set failed_modules; for (const auto &i : modules) { @@ -172,7 +173,7 @@ void PyModuleRegistry::standby_start(MonClient *monc) } void PyModuleRegistry::active_start( - PyModuleConfig &config_, + PyModuleConfig &module_config, DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, LogChannelRef clog_, Objecter &objecter_, Client &client_, Finisher &f) @@ -193,7 +194,7 @@ void PyModuleRegistry::active_start( } active_modules.reset(new ActivePyModules( - config_, ds, cs, mc, clog_, objecter_, client_, f)); + module_config, ds, cs, mc, clog_, objecter_, client_, f)); for (const auto &i : modules) { // Anything we're skipping because of !can_run will be flagged @@ -387,3 +388,14 @@ void PyModuleRegistry::get_health_checks(health_check_map_t *checks) } } +void PyModuleRegistry::handle_config(const std::string &k, const std::string &v) +{ + Mutex::Locker l(module_config.lock); + + if (!v.empty()) { + module_config.config[k] = v; + } else { + module_config.config.erase(k); + } +} + diff --git a/src/mgr/PyModuleRegistry.h b/src/mgr/PyModuleRegistry.h index e2221affe479f..8f64cf1d76fd1 100644 --- a/src/mgr/PyModuleRegistry.h +++ b/src/mgr/PyModuleRegistry.h @@ -26,8 +26,6 @@ #include "ActivePyModules.h" #include "StandbyPyModules.h" - - /** * This class is responsible for setting up the python runtime environment * and importing the python modules. @@ -40,7 +38,6 @@ class PyModuleRegistry { private: mutable Mutex lock{"PyModuleRegistry::lock"}; - LogChannelRef clog; std::map modules; @@ -59,9 +56,13 @@ private: */ std::set probe_modules() const; + PyModuleConfig module_config; + public: static std::string config_prefix; + void handle_config(const std::string &k, const std::string &v); + /** * Get references to all modules (whether they have loaded and/or * errored) or not. @@ -89,7 +90,7 @@ public: void init(); void active_start( - PyModuleConfig &config_, + PyModuleConfig &module_config, DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, LogChannelRef clog_, Objecter &objecter_, Client &client_, Finisher &f); diff --git a/src/mgr/StandbyPyModules.cc b/src/mgr/StandbyPyModules.cc index 756b8be74294f..3d7298206f753 100644 --- a/src/mgr/StandbyPyModules.cc +++ b/src/mgr/StandbyPyModules.cc @@ -31,9 +31,12 @@ #define dout_prefix *_dout << "mgr " << __func__ << " " -StandbyPyModules::StandbyPyModules(MonClient *monc_, const MgrMap &mgr_map_, - LogChannelRef clog_) - : monc(monc_), load_config_thread(monc, &state), clog(clog_) +StandbyPyModules::StandbyPyModules( + MonClient *monc_, const MgrMap &mgr_map_, + PyModuleConfig &module_config, LogChannelRef clog_) + : monc(monc_), + state(module_config), + clog(clog_) { state.set_mgr_map(mgr_map_); } @@ -43,13 +46,6 @@ void StandbyPyModules::shutdown() { Mutex::Locker locker(lock); - if (!state.is_config_loaded && load_config_thread.is_started()) { - // FIXME: handle cases where initial load races with shutdown - // this is actually not super rare because - assert(0); - //load_config_thread.kill(SIGKILL); - } - // Signal modules to drop out of serve() and/or tear down resources for (auto &i : modules) { auto module = i.second.get(); @@ -85,10 +81,6 @@ int StandbyPyModules::start_one(PyModuleRef py_module) state, py_module, clog)); - if (modules.size() == 1) { - load_config_thread.create("LoadConfig"); - } - int r = modules[module_name]->load(); if (r != 0) { modules.erase(module_name); @@ -129,38 +121,6 @@ int StandbyPyModule::load() } } -void *StandbyPyModules::LoadConfigThread::entry() -{ - dout(10) << "listing keys" << dendl; - JSONCommand cmd; - cmd.run(monc, "{\"prefix\": \"config-key ls\"}"); - cmd.wait(); - assert(cmd.r == 0); - - std::map loaded; - - for (auto &key_str : cmd.json_result.get_array()) { - std::string const key = key_str.get_str(); - dout(20) << "saw key '" << key << "'" << dendl; - - const std::string config_prefix = PyModuleRegistry::config_prefix; - - if (key.substr(0, config_prefix.size()) == config_prefix) { - dout(20) << "fetching '" << key << "'" << dendl; - Command get_cmd; - std::ostringstream cmd_json; - cmd_json << "{\"prefix\": \"config-key get\", \"key\": \"" << key << "\"}"; - get_cmd.run(monc, cmd_json.str()); - get_cmd.wait(); - assert(get_cmd.r == 0); - loaded[key] = get_cmd.outbl.to_str(); - } - } - state->loaded_config(loaded); - - return nullptr; -} - bool StandbyPyModule::get_config(const std::string &key, std::string *value) const { @@ -171,10 +131,10 @@ bool StandbyPyModule::get_config(const std::string &key, + get_name() + "/" + key; dout(4) << __func__ << " key: " << global_key << dendl; - + return state.with_config([global_key, value](const PyModuleConfig &config){ - if (config.count(global_key)) { - *value = config.at(global_key); + if (config.config.count(global_key)) { + *value = config.config.at(global_key); return true; } else { return false; diff --git a/src/mgr/StandbyPyModules.h b/src/mgr/StandbyPyModules.h index 6c5286addb528..b115cee13e4e4 100644 --- a/src/mgr/StandbyPyModules.h +++ b/src/mgr/StandbyPyModules.h @@ -26,7 +26,7 @@ #include "mon/MgrMap.h" #include "mgr/PyModuleRunner.h" -typedef std::map PyModuleConfig; +//typedef std::map PyModuleConfig; /** * State that is read by all modules running in standby mode @@ -36,13 +36,17 @@ class StandbyPyModuleState mutable Mutex lock{"StandbyPyModuleState::lock"}; MgrMap mgr_map; - PyModuleConfig config_cache; + //PyModuleConfig config_cache; - mutable Cond config_loaded; + public: - bool is_config_loaded = false; + PyModuleConfig &module_config; + + StandbyPyModuleState(PyModuleConfig &module_config_) + : module_config(module_config_) + {} void set_mgr_map(const MgrMap &mgr_map_) { @@ -51,15 +55,6 @@ public: mgr_map = mgr_map_; } - void loaded_config(const PyModuleConfig &config_) - { - Mutex::Locker l(lock); - - config_cache = config_; - is_config_loaded = true; - config_loaded.Signal(); - } - template void with_mgr_map(Callback&& cb, Args&&...args) const { @@ -69,14 +64,10 @@ public: template auto with_config(Callback&& cb, Args&&... args) const -> - decltype(cb(config_cache, std::forward(args)...)) { + decltype(cb(module_config, std::forward(args)...)) { Mutex::Locker l(lock); - if (!is_config_loaded) { - config_loaded.Wait(lock); - } - - return std::forward(cb)(config_cache, std::forward(args)...); + return std::forward(cb)(module_config, std::forward(args)...); } }; @@ -113,21 +104,6 @@ private: StandbyPyModuleState state; - void load_config(); - class LoadConfigThread : public Thread - { - protected: - MonClient *monc; - StandbyPyModuleState *state; - public: - LoadConfigThread(MonClient *monc_, StandbyPyModuleState *state_) - : monc(monc_), state(state_) - {} - void *entry() override; - }; - - LoadConfigThread load_config_thread; - LogChannelRef clog; public: @@ -135,6 +111,7 @@ public: StandbyPyModules( MonClient *monc_, const MgrMap &mgr_map_, + PyModuleConfig &module_config, LogChannelRef clog_); int start_one(PyModuleRef py_module); diff --git a/src/mon/ConfigMonitor.cc b/src/mon/ConfigMonitor.cc index f7caa5c826db3..c2627c076011e 100644 --- a/src/mon/ConfigMonitor.cc +++ b/src/mon/ConfigMonitor.cc @@ -398,19 +398,21 @@ bool ConfigMonitor::prepare_command(MonOpRequestRef op) cmd_getval(g_ceph_context, cmdmap, "value", value); if (prefix == "config set") { - const Option *opt = g_conf->find_option(name); - if (!opt) { - ss << "unrecognized config option '" << name << "'"; - err = -EINVAL; - goto reply; - } - - Option::value_t real_value; - string errstr; - err = opt->parse_value(value, &real_value, &errstr, &value); - if (err < 0) { - ss << "error parsing value: " << errstr; - goto reply; + if (name.substr(0, 4) != "mgr/") { + const Option *opt = g_conf->find_option(name); + if (!opt) { + ss << "unrecognized config option '" << name << "'"; + err = -EINVAL; + goto reply; + } + + Option::value_t real_value; + string errstr; + err = opt->parse_value(value, &real_value, &errstr, &value); + if (err < 0) { + ss << "error parsing value: " << errstr; + goto reply; + } } } @@ -630,26 +632,13 @@ void ConfigMonitor::load_config() who = key.substr(0, last_slash); } - const Option *opt = g_conf->find_option(name); - if (!opt) { - dout(10) << __func__ << " unrecognized option '" << name << "'" << dendl; - opt = new Option(name, Option::TYPE_STR, Option::LEVEL_UNKNOWN); - } - string err; - int r = opt->pre_validate(&value, &err); - if (r < 0) { - dout(10) << __func__ << " pre-validate failed on '" << name << "' = '" - << value << "' for " << name << dendl; - } - string section_name; - MaskedOption mopt(opt); - mopt.raw_value = value; - if (who.size() && - !ConfigMap::parse_mask(who, §ion_name, &mopt.mask)) { - derr << __func__ << " ignoring key " << key << dendl; - } else { + if (key.find("mgr") == 0) { + name = key.substr(key.find('/') + 1); + MaskedOption mopt(new Option(name, Option::TYPE_STR, Option::LEVEL_UNKNOWN)); + mopt.raw_value = value; Section *section = &config_map.global;; + section_name = "mgr"; if (section_name.size()) { if (section_name.find('.') != std::string::npos) { section = &config_map.by_id[section_name]; @@ -658,7 +647,37 @@ void ConfigMonitor::load_config() } } section->options.insert(make_pair(name, std::move(mopt))); - ++num; + ++num; + } else { + const Option *opt = g_conf->find_option(name); + if (!opt) { + dout(10) << __func__ << " unrecognized option '" << name << "'" << dendl; + opt = new Option(name, Option::TYPE_STR, Option::LEVEL_UNKNOWN); + } + string err; + int r = opt->pre_validate(&value, &err); + if (r < 0) { + dout(10) << __func__ << " pre-validate failed on '" << name << "' = '" + << value << "' for " << name << dendl; + } + + MaskedOption mopt(opt); + mopt.raw_value = value; + if (who.size() && + !ConfigMap::parse_mask(who, §ion_name, &mopt.mask)) { + derr << __func__ << " ignoring key " << key << dendl; + } else { + Section *section = &config_map.global;; + if (section_name.size()) { + if (section_name.find('.') != std::string::npos) { + section = &config_map.by_id[section_name]; + } else { + section = &config_map.by_type[section_name]; + } + } + section->options.insert(make_pair(name, std::move(mopt))); + ++num; + } } it->next(); } @@ -683,7 +702,7 @@ void ConfigMonitor::load_config() osdmap.crush.get(), string(), // no device class &out); - g_conf->set_mon_vals(g_ceph_context, out); + g_conf->set_mon_vals(g_ceph_context, out, nullptr); } } @@ -720,7 +739,6 @@ void ConfigMonitor::load_changeset(version_t v, ConfigChangeSet *ch) bool ConfigMonitor::refresh_config(MonSession *s) { const OSDMap& osdmap = mon->osdmon()->osdmap; - map crush_location; if (s->remote_host.size()) { osdmap.crush->get_full_location(s->remote_host, &crush_location); diff --git a/src/mon/MonClient.cc b/src/mon/MonClient.cc index b246c064006dd..5f31182a7614b 100644 --- a/src/mon/MonClient.cc +++ b/src/mon/MonClient.cc @@ -64,8 +64,7 @@ MonClient::MonClient(CephContext *cct_) : cct_->_conf->get_val("mon_client_hunt_interval_min_multiple")), last_mon_command_tid(0), version_req_id(0) -{ -} +{} MonClient::~MonClient() { @@ -354,8 +353,8 @@ void MonClient::handle_monmap(MMonMap *m) decode(monmap, p); ldout(cct, 10) << " got monmap " << monmap.epoch - << ", mon." << cur_mon << " is now rank " << monmap.get_rank(cur_mon) - << dendl; + << ", mon." << cur_mon << " is now rank " << monmap.get_rank(cur_mon) + << dendl; ldout(cct, 10) << "dump:\n"; monmap.print(*_dout); *_dout << dendl; @@ -375,7 +374,7 @@ void MonClient::handle_monmap(MMonMap *m) void MonClient::handle_config(MConfig *m) { ldout(cct,10) << __func__ << " " << *m << dendl; - cct->_conf->set_mon_vals(cct, m->config); + cct->_conf->set_mon_vals(cct, m->config, config_cb); m->put(); got_config = true; map_cond.Signal(); @@ -484,7 +483,6 @@ int MonClient::authenticate(double timeout) ldout(cct, 5) << "already authenticated" << dendl; return 0; } - _sub_want("monmap", monmap.get_epoch() ? monmap.get_epoch() + 1 : 0, 0); _sub_want("config", 0, 0); if (!_opened()) @@ -1329,3 +1327,12 @@ int MonConnection::authenticate(MAuthReply *m) } return ret; } + +void MonClient::register_config_callback(md_config_t::config_callback fn) { + assert(!config_cb); + config_cb = fn; +} + +md_config_t::config_callback MonClient::get_config_callback() { + return config_cb; +} diff --git a/src/mon/MonClient.h b/src/mon/MonClient.h index 6caf57360e4e0..eb8268838b94c 100644 --- a/src/mon/MonClient.h +++ b/src/mon/MonClient.h @@ -11,7 +11,6 @@ * Foundation. See file COPYING. * */ - #ifndef CEPH_MONCLIENT_H #define CEPH_MONCLIENT_H @@ -25,7 +24,6 @@ #include "common/Finisher.h" #include "common/config.h" - class MMonMap; class MConfig; class MMonGetVersionReply; @@ -148,6 +146,7 @@ private: class MonClient : public Dispatcher { public: MonMap monmap; + map config_mgr; private: Messenger *messenger; @@ -205,7 +204,7 @@ private: std::unique_ptr session_established_context; bool had_a_connection; double reopen_interval_multiplier; - + bool _opened() const; bool _hunting() const; void _start_hunting(); @@ -433,6 +432,7 @@ public: // admin commands private: uint64_t last_mon_command_tid; + struct MonCommand { string target_name; int target_rank; @@ -484,7 +484,6 @@ public: * @return (via context) 0 on success, -EAGAIN if we need to resubmit our request */ void get_version(string map, version_t *newest, version_t *oldest, Context *onfinish); - /** * Run a callback within our lock, with a reference * to the MonMap @@ -496,6 +495,9 @@ public: return std::forward(cb)(monmap, std::forward(args)...); } + void register_config_callback(md_config_t::config_callback fn); + md_config_t::config_callback get_config_callback(); + private: struct version_req_d { Context *context; @@ -507,7 +509,7 @@ private: ceph_tid_t version_req_id; void handle_get_version_reply(MMonGetVersionReply* m); - + md_config_t::config_callback config_cb; }; #endif -- 2.39.5