server(server), py_module_registry(pmr)
{
store_cache = std::move(store_data);
+ // we can only trust our ConfigMap if the mon cluster has provided
+ // kv sub since our startup.
+ have_local_config_map = mon_provides_kv_sub;
+ _refresh_config_map();
cmd_finisher.start();
}
const map<std::string, boost::optional<bufferlist>, std::less<>>& data)
{
std::lock_guard l(lock);
+ bool do_config = false;
if (!incremental) {
dout(10) << "full update on " << prefix << dendl;
auto p = store_cache.lower_bound(prefix);
dout(20) << " rm " << i.first << dendl;
store_cache.erase(i.first);
}
+ if (i.first.find("config/") == 0) {
+ do_config = true;
+ }
+ }
+ if (do_config) {
+ _refresh_config_map();
+ }
+}
+
+void ActivePyModules::_refresh_config_map()
+{
+ dout(10) << dendl;
+ config_map.clear();
+ for (auto p = store_cache.lower_bound("config/");
+ p != store_cache.end() && p->first.find("config/") == 0;
+ ++p) {
+ string key = p->first.substr(7);
+ if (key.find("mgr/") == 0) {
+ // NOTE: for now, we ignore module options. see also ceph_foreign_option_get().
+ continue;
+ }
+ string value = p->second;
+ string name;
+ string who;
+ config_map.parse_key(key, &name, &who);
+
+ const Option *opt = g_conf().find_option(name);
+ if (!opt) {
+ config_map.stray_options.push_back(
+ std::unique_ptr<Option>(
+ new Option(name, Option::TYPE_STR, Option::LEVEL_UNKNOWN)));
+ opt = config_map.stray_options.back().get();
+ }
+
+ 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;
+ string section_name;
+ if (who.size() &&
+ !ConfigMap::parse_mask(who, §ion_name, &mopt.mask)) {
+ derr << __func__ << " invalid mask for key " << key << dendl;
+ } else if (opt->has_flag(Option::FLAG_NO_MON_UPDATE)) {
+ dout(10) << __func__ << " NO_MON_UPDATE option '"
+ << name << "' = '" << value << "' for " << name
+ << dendl;
+ } else {
+ Section *section = &config_map.global;;
+ if (section_name.size() && section_name != "global") {
+ 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)));
+ }
}
}
#include "mon/MgrMap.h"
#include "mon/MonCommand.h"
#include "mon/mon_types.h"
+#include "mon/ConfigMap.h"
#include "DaemonState.h"
#include "ClusterState.h"
PyModuleConfig &module_config;
bool have_local_config_map = false;
std::map<std::string, std::string> store_cache;
+ ConfigMap config_map; ///< derived from store_cache config/ keys
DaemonStateIndex &daemon_state;
ClusterState &cluster_state;
MonClient &monc;
const std::string prefix,
bool incremental,
const map<std::string, boost::optional<bufferlist>, std::less<>>& data);
+ void _refresh_config_map();
// Public so that MonCommandCompletion can use it
// FIXME: for send_command completion notifications,