#include "common/cmdparse.h"
#include "common/LogEntry.h"
#include "common/Thread.h"
+#include "common/Finisher.h"
#include "mon/health_check.h"
#include "mgr/Gil.h"
std::string m_command_perms;
const MgrSession* m_session = nullptr;
+ std::string fin_thread_name;
+public:
+ Finisher finisher; // per active module finisher to execute commands
public:
ActivePyModule(const PyModuleRef &py_module_,
LogChannelRef clog_)
- : PyModuleRunner(py_module_, clog_)
- {}
+ : PyModuleRunner(py_module_, clog_),
+ fin_thread_name(std::string("m-fin-" + py_module->get_name()).substr(0,15)),
+ finisher(g_ceph_context, thread_name, fin_thread_name)
+
+ {
+ }
int load(ActivePyModules *py_modules);
void notify(const std::string ¬ify_type, const std::string ¬ify_id);
return uri;
}
+ std::string get_fin_thread_name() const
+ {
+ return fin_thread_name;
+ }
+
bool is_authorized(const std::map<std::string, std::string>& arguments) const;
};
dout(4) << "Starting thread for " << name << dendl;
active_module->thread.create(active_module->get_thread_name());
+ dout(4) << "Starting active module " << name <<" finisher thread "
+ << active_module->get_fin_thread_name() << dendl;
+ active_module->finisher.start();
}
}));
}
{
std::lock_guard locker(lock);
+ // Stop per active module finisher thread
+ for (auto& [name, module] : modules) {
+ dout(4) << "Stopping active module " << name << " finisher thread" << dendl;
+ module->finisher.wait_for_empty();
+ module->finisher.stop();
+ }
+
// Signal modules to drop out of serve() and/or tear down resources
for (auto& [name, module] : modules) {
lock.unlock();
// Send all python calls down a Finisher to avoid blocking
// C++ code, and avoid any potential lock cycles.
dout(15) << "queuing notify (" << notify_type << ") to " << name << dendl;
+ Finisher& mod_finisher = py_module_registry.get_active_module_finisher(name);
// workaround for https://bugs.llvm.org/show_bug.cgi?id=35984
- finisher.queue(new LambdaContext([module=module, notify_type, notify_id]
+ mod_finisher.queue(new LambdaContext([module=module, notify_type, notify_id]
(int r){
module->notify(notify_type, notify_id);
}));
// log_entry: we take a copy because caller's instance is
// probably ephemeral.
dout(15) << "queuing notify (clog) to " << name << dendl;
+ Finisher& mod_finisher = py_module_registry.get_active_module_finisher(name);
// workaround for https://bugs.llvm.org/show_bug.cgi?id=35984
- finisher.queue(new LambdaContext([module=module, log_entry](int r){
+ mod_finisher.queue(new LambdaContext([module=module, log_entry](int r){
module->notify_clog(log_entry);
}));
}
// Send all python calls down a Finisher to avoid blocking
// C++ code, and avoid any potential lock cycles.
dout(15) << "notify (config) " << name << dendl;
+ Finisher& mod_finisher = py_module_registry.get_active_module_finisher(name);
// workaround for https://bugs.llvm.org/show_bug.cgi?id=35984
- finisher.queue(new LambdaContext([module=module](int r){
+ mod_finisher.queue(new LambdaContext([module=module](int r){
module->config_notify();
}));
}
const std::string ¬ify_id);
void notify_all(const LogEntry &log_entry);
+ auto& get_module_finisher(const std::string &name) {
+ return modules.at(name)->finisher;
+ }
+
bool is_pending(std::string_view name) const {
return pending_modules.count(name) > 0;
}
return true;
}
+ // Validate that the module is active
+ auto& mod_name = py_command.module_name;
+ if (!py_modules.is_module_active(mod_name)) {
+ ss << "Module '" << mod_name << "' is not enabled/loaded (required by "
+ "command '" << prefix << "'): use `ceph mgr module enable "
+ << mod_name << "` to enable it";
+ dout(4) << ss.str() << dendl;
+ cmdctx->reply(-EOPNOTSUPP, ss);
+ return true;
+ }
+
dout(10) << "passing through command '" << prefix << "' size " << cmdctx->cmdmap.size() << dendl;
- finisher.queue(new LambdaContext([this, cmdctx, session, py_command, prefix]
- (int r_) mutable {
+ Finisher& mod_finisher = py_modules.get_active_module_finisher(mod_name);
+ mod_finisher.queue(new LambdaContext([this, cmdctx, session, py_command, prefix]
+ (int r_) mutable {
std::stringstream ss;
dout(10) << "dispatching command '" << prefix << "' size " << cmdctx->cmdmap.size() << dendl;
return v;
}
+ bool is_module_active(const std::string &name) {
+ ceph_assert(active_modules);
+ return active_modules->module_exists(name);
+ }
+
+ auto& get_active_module_finisher(const std::string &name) {
+ ceph_assert(active_modules);
+ return active_modules->get_module_finisher(name);
+ }
+
// <<< (end of ActivePyModules cheeky call-throughs)
};