From: John Spray Date: Thu, 26 Apr 2018 09:56:56 +0000 (-0400) Subject: mgr: implement get_store in StandbyPyModules X-Git-Tag: v13.1.0~25^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6185bd66a9e9b23f1d1982b0bc12d672c33c6fcd;p=ceph.git mgr: implement get_store in StandbyPyModules Signed-off-by: John Spray --- diff --git a/src/mgr/BaseMgrStandbyModule.cc b/src/mgr/BaseMgrStandbyModule.cc index b6f6e53255d8..468e970359d2 100644 --- a/src/mgr/BaseMgrStandbyModule.cc +++ b/src/mgr/BaseMgrStandbyModule.cc @@ -89,8 +89,14 @@ ceph_store_get(BaseMgrStandbyModule *self, PyObject *args) return nullptr; } + // Drop GIL for blocking mon command execution + PyThreadState *tstate = PyEval_SaveThread(); + std::string value; bool found = self->this_module->get_store(what, &value); + + PyEval_RestoreThread(tstate); + if (found) { dout(10) << "ceph_store_get " << what << " found: " << value.c_str() << dendl; return PyString_FromString(value.c_str()); diff --git a/src/mgr/MgrStandby.cc b/src/mgr/MgrStandby.cc index 9de2e88abc75..5e267feab693 100644 --- a/src/mgr/MgrStandby.cc +++ b/src/mgr/MgrStandby.cc @@ -400,7 +400,7 @@ void MgrStandby::handle_mgr_map(MMgrMap* mmap) // I am the standby and someone else is active, start modules // in standby mode to do redirects if needed if (!py_module_registry.is_standby_running()) { - py_module_registry.standby_start(); + py_module_registry.standby_start(monc); } } } diff --git a/src/mgr/PyModuleRegistry.cc b/src/mgr/PyModuleRegistry.cc index bd05a68ed737..3ceb4d0e9393 100644 --- a/src/mgr/PyModuleRegistry.cc +++ b/src/mgr/PyModuleRegistry.cc @@ -124,7 +124,7 @@ bool PyModuleRegistry::handle_mgr_map(const MgrMap &mgr_map_) -void PyModuleRegistry::standby_start() +void PyModuleRegistry::standby_start(MonClient &mc) { Mutex::Locker l(lock); assert(active_modules == nullptr); @@ -137,7 +137,7 @@ void PyModuleRegistry::standby_start() dout(4) << "Starting modules in standby mode" << dendl; standby_modules.reset(new StandbyPyModules( - mgr_map, module_config, clog)); + mgr_map, module_config, clog, mc)); std::set failed_modules; for (const auto &i : modules) { diff --git a/src/mgr/PyModuleRegistry.h b/src/mgr/PyModuleRegistry.h index c7563c29b940..5fb0148e7102 100644 --- a/src/mgr/PyModuleRegistry.h +++ b/src/mgr/PyModuleRegistry.h @@ -96,7 +96,7 @@ public: const std::map &kv_store, MonClient &mc, LogChannelRef clog_, Objecter &objecter_, Client &client_, Finisher &f); - void standby_start(); + void standby_start(MonClient &mc); bool is_standby_running() const { diff --git a/src/mgr/StandbyPyModules.cc b/src/mgr/StandbyPyModules.cc index 560902eece30..4909c5d9d1de 100644 --- a/src/mgr/StandbyPyModules.cc +++ b/src/mgr/StandbyPyModules.cc @@ -33,8 +33,10 @@ StandbyPyModules::StandbyPyModules( const MgrMap &mgr_map_, - PyModuleConfig &module_config, LogChannelRef clog_) - : state(module_config), + PyModuleConfig &module_config, + LogChannelRef clog_, + MonClient &monc_) + : state(module_config, monc_), clog(clog_) { state.set_mgr_map(mgr_map_); @@ -123,9 +125,6 @@ int StandbyPyModule::load() bool StandbyPyModule::get_config(const std::string &key, std::string *value) const { - PyThreadState *tstate = PyEval_SaveThread(); - PyEval_RestoreThread(tstate); - const std::string global_key = PyModule::config_prefix + get_name() + "/" + key; @@ -141,6 +140,52 @@ bool StandbyPyModule::get_config(const std::string &key, }); } +bool StandbyPyModule::get_store(const std::string &key, + std::string *value) const +{ + + const std::string global_key = PyModule::config_prefix + + get_name() + "/" + key; + + dout(4) << __func__ << " key: " << global_key << dendl; + + // Active modules use a cache of store values (kept up to date + // as writes pass through the active mgr), but standbys + // fetch values synchronously to get an up to date value. + // It's an acceptable cost because standby modules should not be + // doing a lot. + + MonClient &monc = state.get_monc(); + + std::ostringstream cmd_json; + cmd_json << "{\"prefix\": \"config-key get\", \"key\": \"" + << global_key << "\"}"; + + bufferlist outbl; + std::string outs; + C_SaferCond c; + monc.start_mon_command( + {cmd_json.str()}, + {}, + &outbl, + &outs, + &c); + + int r = c.wait(); + if (r == -ENOENT) { + return false; + } else if (r != 0) { + // This is some internal error, not meaningful to python modules, + // so let them just see no value. + derr << __func__ << " error fetching store key '" << global_key << "': " + << cpp_strerror(r) << " " << outs << dendl; + return false; + } else { + *value = outbl.to_str(); + return true; + } +} + std::string StandbyPyModule::get_active_uri() const { std::string result; diff --git a/src/mgr/StandbyPyModules.h b/src/mgr/StandbyPyModules.h index 2def578b3856..f443ba67e794 100644 --- a/src/mgr/StandbyPyModules.h +++ b/src/mgr/StandbyPyModules.h @@ -35,12 +35,13 @@ class StandbyPyModuleState MgrMap mgr_map; PyModuleConfig &module_config; + MonClient &monc; public: - StandbyPyModuleState(PyModuleConfig &module_config_) - : module_config(module_config_) + StandbyPyModuleState(PyModuleConfig &module_config_, MonClient &monc_) + : module_config(module_config_), monc(monc_) {} void set_mgr_map(const MgrMap &mgr_map_) @@ -50,6 +51,10 @@ public: mgr_map = mgr_map_; } + // MonClient does all its own locking so we're happy to hand out + // references. + MonClient &get_monc() {return monc;}; + template void with_mgr_map(Callback&& cb, Args&&...args) const { @@ -84,6 +89,7 @@ class StandbyPyModule : public PyModuleRunner } bool get_config(const std::string &key, std::string *value) const; + bool get_store(const std::string &key, std::string *value) const; std::string get_active_uri() const; int load(); @@ -104,7 +110,8 @@ public: StandbyPyModules( const MgrMap &mgr_map_, PyModuleConfig &module_config, - LogChannelRef clog_); + LogChannelRef clog_, + MonClient &monc); int start_one(PyModuleRef py_module);