X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmgr%2FPyModuleRegistry.h;fp=src%2Fceph%2Fsrc%2Fmgr%2FPyModuleRegistry.h;h=5564e7f1fa5de324b8fa319c9abddabff0c1dc07;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/mgr/PyModuleRegistry.h b/src/ceph/src/mgr/PyModuleRegistry.h new file mode 100644 index 0000000..5564e7f --- /dev/null +++ b/src/ceph/src/mgr/PyModuleRegistry.h @@ -0,0 +1,173 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 John Spray + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + */ + + +#pragma once + +// Python.h comes first because otherwise it clobbers ceph's assert +#include "Python.h" + +#include +#include +#include + +#include "common/LogClient.h" + +#include "ActivePyModules.h" +#include "StandbyPyModules.h" + +class PyModule +{ +private: + const std::string module_name; + std::string get_site_packages(); + +public: + SafeThreadState pMyThreadState; + PyObject *pClass = nullptr; + PyObject *pStandbyClass = nullptr; + + PyModule(const std::string &module_name_) + : module_name(module_name_) + { + } + + ~PyModule(); + + int load(PyThreadState *pMainThreadState); + + std::string get_name() const { + return module_name; + } +}; + +/** + * This class is responsible for setting up the python runtime environment + * and importing the python modules. + * + * It is *not* responsible for constructing instances of their BaseMgrModule + * subclasses. + */ +class PyModuleRegistry +{ +private: + mutable Mutex lock{"PyModuleRegistry::lock"}; + + LogChannelRef clog; + + std::map> modules; + + std::unique_ptr active_modules; + std::unique_ptr standby_modules; + + PyThreadState *pMainThreadState; + + // We have our own copy of MgrMap, because we are constructed + // before ClusterState exists. + MgrMap mgr_map; + +public: + static std::string config_prefix; + + static void list_modules(std::set *modules); + + PyModuleRegistry(LogChannelRef clog_) + : clog(clog_) + {} + + bool handle_mgr_map(const MgrMap &mgr_map_) + { + Mutex::Locker l(lock); + + bool modules_changed = mgr_map_.modules != mgr_map.modules; + mgr_map = mgr_map_; + + if (standby_modules != nullptr) { + standby_modules->handle_mgr_map(mgr_map_); + } + + return modules_changed; + } + + bool is_initialized() const + { + return mgr_map.epoch > 0; + } + + int init(const MgrMap &map); + + void active_start( + PyModuleConfig &config_, + DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, + LogChannelRef clog_, Objecter &objecter_, Client &client_, + Finisher &f); + void standby_start( + MonClient *monc); + + bool is_standby_running() const + { + return standby_modules != nullptr; + } + + void active_shutdown(); + void shutdown(); + + template + void with_active_modules(Callback&& cb, Args&&...args) const + { + Mutex::Locker l(lock); + assert(active_modules != nullptr); + + std::forward(cb)(*active_modules, std::forward(args)...); + } + + // FIXME: breaking interface so that I don't have to go rewrite all + // the places that call into these (for now) + // >>> + void notify_all(const std::string ¬ify_type, + const std::string ¬ify_id) + { + if (active_modules) { + active_modules->notify_all(notify_type, notify_id); + } + } + + void notify_all(const LogEntry &log_entry) + { + if (active_modules) { + active_modules->notify_all(log_entry); + } + } + + std::vector get_commands() const + { + assert(active_modules); + return active_modules->get_commands(); + } + std::vector get_py_commands() const + { + assert(active_modules); + return active_modules->get_py_commands(); + } + void get_health_checks(health_check_map_t *checks) + { + assert(active_modules); + active_modules->get_health_checks(checks); + } + std::map get_services() const + { + assert(active_modules); + return active_modules->get_services(); + } + // <<< (end of ActivePyModules cheeky call-throughs) +};