]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr: refactor python interface
authorJohn Spray <john.spray@redhat.com>
Wed, 26 Jul 2017 11:44:00 +0000 (07:44 -0400)
committerJohn Spray <john.spray@redhat.com>
Wed, 1 Nov 2017 12:20:19 +0000 (08:20 -0400)
Expose a python class instead of a module,
so that we have a place to carry our reference
to our MgrPyModule* and to PyModules*, rather than
passing a handle for the former and using
a global pointer for the latter.

Signed-off-by: John Spray <john.spray@redhat.com>
src/mgr/MgrPyModule.cc
src/mgr/MgrPyModule.h
src/mgr/PyModules.cc
src/mgr/PyModules.h
src/mgr/PyState.cc
src/mgr/PyState.h

index 50165e71187bdaf8b7abeb992dad9c95741182ec..e3e3160de130ee84fbecfee2a384d319459802d2 100644 (file)
@@ -107,13 +107,31 @@ MgrPyModule::MgrPyModule(const std::string &module_name_, const std::string &sys
       PySys_SetObject(const_cast<char*>("stdout"), py_logger);
 #endif
     }
+
+    PySys_SetPath(const_cast<char*>(sys_path.c_str()));
+
     // Populate python namespace with callable hooks
-    Py_InitModule("ceph_state", CephStateMethods);
     Py_InitModule("ceph_osdmap", OSDMapMethods);
     Py_InitModule("ceph_osdmap_incremental", OSDMapIncrementalMethods);
     Py_InitModule("ceph_crushmap", CRUSHMapMethods);
 
-    PySys_SetPath(const_cast<char*>(sys_path.c_str()));
+    PyMethodDef ModuleMethods[] = {
+      {nullptr}
+    };
+
+    // Initialize module
+    PyObject *ceph_module = Py_InitModule("ceph_module", ModuleMethods);
+    assert(ceph_module != nullptr);
+
+    // Initialize base class
+    BaseMgrModuleType.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&BaseMgrModuleType) < 0) {
+        assert(0);
+    }
+
+    Py_INCREF(&BaseMgrModuleType);
+    PyModule_AddObject(ceph_module, "BaseMgrModule",
+                       (PyObject *)&BaseMgrModuleType);
   }
 }
 
@@ -150,7 +168,7 @@ MgrPyModule::~MgrPyModule()
   }
 }
 
-int MgrPyModule::load()
+int MgrPyModule::load(PyModules *py_modules)
 {
   if (pMyThreadState.ts == nullptr) {
     derr << "No python sub-interpreter exists for module '" << module_name << "'" << dendl;
@@ -166,6 +184,8 @@ int MgrPyModule::load()
   if (pModule == nullptr) {
     derr << "Module not found: '" << module_name << "'" << dendl;
     derr << handle_pyerror() << dendl;
+
+    assert(0);
     return -ENOENT;
   }
 
@@ -178,15 +198,18 @@ int MgrPyModule::load()
     derr << handle_pyerror() << dendl;
     return -EINVAL;
   }
-
   
-  // Just using the module name as the handle, replace with a
-  // uuidish thing if needed
-  auto pyHandle = PyString_FromString(module_name.c_str());
-  auto pArgs = PyTuple_Pack(1, pyHandle);
+  // We tell the module how we name it, so that it can be consistent
+  // with us in logging etc.
+  
+  auto pThisPtr = PyCapsule_New(this, nullptr, nullptr);
+  auto pPyModules = PyCapsule_New(py_modules, nullptr, nullptr);
+  
+  auto pModuleName = PyString_FromString(module_name.c_str());
+  auto pArgs = PyTuple_Pack(3, pModuleName, pPyModules, pThisPtr);
   pClassInstance = PyObject_CallObject(pClass, pArgs);
   Py_DECREF(pClass);
-  Py_DECREF(pyHandle);
+  Py_DECREF(pModuleName);
   Py_DECREF(pArgs);
   if (pClassInstance == nullptr) {
     derr << "Failed to construct class in '" << module_name << "'" << dendl;
index 9f5a5ef53ac483972ee5f92bb94064dfad5acc5c..232d4ebac9233e1432e97cedfabd5f77652be4c9 100644 (file)
@@ -30,6 +30,7 @@
 
 
 class MgrPyModule;
+class PyModules;
 
 /**
  * A Ceph CLI command description provided from a Python module
@@ -60,7 +61,7 @@ public:
   MgrPyModule(const std::string &module_name, const std::string &sys_path, PyThreadState *main_ts);
   ~MgrPyModule();
 
-  int load();
+  int load(PyModules *py_modules);
   int serve();
   void shutdown();
   void notify(const std::string &notify_type, const std::string &notify_id);
index 11865eff28edbb364c2f642d6fcd6706268e16ea..87d4b873372c8587d8bdc05db3f75ae110d67d57 100644 (file)
@@ -120,7 +120,6 @@ PyObject *PyModules::list_servers_python()
 }
 
 PyObject *PyModules::get_metadata_python(
-  std::string const &handle,
   const std::string &svc_type,
   const std::string &svc_id)
 {
@@ -141,7 +140,6 @@ PyObject *PyModules::get_metadata_python(
 }
 
 PyObject *PyModules::get_daemon_status_python(
-  std::string const &handle,
   const std::string &svc_type,
   const std::string &svc_id)
 {
@@ -395,7 +393,6 @@ int PyModules::init()
 {
   Mutex::Locker locker(lock);
 
-  global_handle = this;
   // namespace in config-key prefixed by "mgr/"
   config_prefix = std::string(g_conf->name.get_type_str()) + "/";
 
@@ -429,7 +426,7 @@ int PyModules::init()
   for (const auto& module_name : ls) {
     dout(1) << "Loading python module '" << module_name << "'" << dendl;
     auto mod = std::unique_ptr<MgrPyModule>(new MgrPyModule(module_name, sys_path, pMainThreadState));
-    int r = mod->load();
+    int r = mod->load(this);
     if (r != 0) {
       // Don't use handle_pyerror() here; we don't have the GIL
       // or the right thread state (this is deliberate).
@@ -495,7 +492,6 @@ void PyModules::start()
 void PyModules::shutdown()
 {
   Mutex::Locker locker(lock);
-  assert(global_handle);
 
   // Signal modules to drop out of serve() and/or tear down resources
   for (auto &i : modules) {
@@ -521,9 +517,6 @@ void PyModules::shutdown()
 
   PyEval_RestoreThread(pMainThreadState);
   Py_Finalize();
-
-  // nobody needs me anymore.
-  global_handle = nullptr;
 }
 
 void PyModules::notify_all(const std::string &notify_type,
@@ -565,14 +558,14 @@ void PyModules::notify_all(const LogEntry &log_entry)
   }
 }
 
-bool PyModules::get_config(const std::string &handle,
+bool PyModules::get_config(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 = config_prefix + handle + "/" + key;
+  const std::string global_key = config_prefix + module_name + "/" + key;
 
   dout(4) << __func__ << "key: " << global_key << dendl;
 
@@ -584,14 +577,14 @@ bool PyModules::get_config(const std::string &handle,
   }
 }
 
-PyObject *PyModules::get_config_prefix(const std::string &handle,
+PyObject *PyModules::get_config_prefix(const std::string &module_name,
     const std::string &prefix) const
 {
   PyThreadState *tstate = PyEval_SaveThread();
   Mutex::Locker l(lock);
   PyEval_RestoreThread(tstate);
 
-  const std::string base_prefix = config_prefix + handle + "/";
+  const std::string base_prefix = config_prefix + module_name + "/";
   const std::string global_prefix = base_prefix + prefix;
   dout(4) << __func__ << "prefix: " << global_prefix << dendl;
 
@@ -604,10 +597,10 @@ PyObject *PyModules::get_config_prefix(const std::string &handle,
   return f.get();
 }
 
-void PyModules::set_config(const std::string &handle,
+void PyModules::set_config(const std::string &module_name,
     const std::string &key, const boost::optional<std::string>& val)
 {
-  const std::string global_key = config_prefix + handle + "/" + key;
+  const std::string global_key = config_prefix + module_name + "/" + key;
 
   Command set_cmd;
   {
@@ -683,18 +676,17 @@ void PyModules::insert_config(const std::map<std::string,
   config_cache = new_config;
 }
 
-void PyModules::log(const std::string &handle,
+void PyModules::log(const std::string &module_name,
     int level, const std::string &record)
 {
 #undef dout_prefix
-#define dout_prefix *_dout << "mgr[" << handle << "] "
+#define dout_prefix *_dout << "mgr[" << module_name << "] "
   dout(level) << record << dendl;
 #undef dout_prefix
 #define dout_prefix *_dout << "mgr " << __func__ << " "
 }
 
 PyObject* PyModules::get_counter_python(
-    const std::string &handle,
     const std::string &svc_name,
     const std::string &svc_id,
     const std::string &path)
@@ -736,7 +728,6 @@ PyObject* PyModules::get_counter_python(
 }
 
 PyObject* PyModules::get_perf_schema_python(
-    const std::string &handle,
     const std::string svc_type,
     const std::string &svc_id)
 {
@@ -857,11 +848,11 @@ void PyModules::list_modules(std::set<std::string> *modules)
   _list_modules(g_conf->get_val<std::string>("mgr_module_path"), modules);
 }
 
-void PyModules::set_health_checks(const std::string& handle,
+void PyModules::set_health_checks(const std::string& module_name,
                                  health_check_map_t&& checks)
 {
   Mutex::Locker l(lock);
-  auto p = modules.find(handle);
+  auto p = modules.find(module_name);
   if (p != modules.end()) {
     p->second->set_health_checks(std::move(checks));
   }
index 3bb5449d156b3ec94c4113d73266214580222a9f..521ee757db0f8cbfc8cc5205c0616baa5946cf5f 100644 (file)
@@ -68,23 +68,33 @@ public:
   PyObject *get_server_python(const std::string &hostname);
   PyObject *list_servers_python();
   PyObject *get_metadata_python(
-    std::string const &handle,
     const std::string &svc_type, const std::string &svc_id);
   PyObject *get_daemon_status_python(
-    std::string const &handle,
     const std::string &svc_type, const std::string &svc_id);
   PyObject *get_counter_python(
-    std::string const &handle,
-    const std::string &svc_name,
+    const std::string &svc_type,
     const std::string &svc_id,
     const std::string &path);
   PyObject *get_perf_schema_python(
-     const std::string &handle,
      const std::string svc_type,
      const std::string &svc_id);
   PyObject *get_context();
   PyObject *get_osdmap();
 
+  bool get_config(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_config(const std::string &module_name,
+      const std::string &key, const boost::optional<std::string> &val);
+
+  void set_health_checks(const std::string& module_name,
+                        health_check_map_t&& checks);
+  void get_health_checks(health_check_map_t *checks);
+
+  void log(const std::string &module_name,
+           int level, const std::string &record);
+
   std::map<std::string, std::string> config_cache;
 
   // Python command definitions, including callback
@@ -110,20 +120,6 @@ public:
                    const DaemonStateCollection &dmc,
                    Formatter *f);
 
-  bool get_config(const std::string &handle,
-      const std::string &key, std::string *val) const;
-  PyObject *get_config_prefix(const std::string &handle,
-                             const std::string &prefix) const;
-  void set_config(const std::string &handle,
-      const std::string &key, const boost::optional<std::string> &val);
-
-  void set_health_checks(const std::string& handle,
-                        health_check_map_t&& checks);
-  void get_health_checks(health_check_map_t *checks);
-
-  void log(const std::string &handle,
-           int level, const std::string &record);
-
   static void list_modules(std::set<std::string> *modules);
 };
 
index 31340f678cc93ba21ffd73f18e8e5b2d80f52f62..b701b5fe95802a6a296007b44e01310540d1e817 100644 (file)
@@ -13,7 +13,9 @@
 
 /**
  * The interface we present to python code that runs within
- * ceph-mgr.
+ * ceph-mgr.  This is implemented as a Python class from which
+ * all modules must inherit -- access to the Ceph state is then
+ * available as methods on that object.
  */
 
 #include "Mgr.h"
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_mgr
 
-PyModules *global_handle = NULL;
+#define PLACEHOLDER ""
 
 
+typedef struct {
+  PyObject_HEAD
+  PyModules *py_modules;
+  MgrPyModule *this_module;
+} BaseMgrModule;
+
 class MonCommandCompletion : public Context
 {
   PyObject *python_completion;
@@ -79,16 +87,14 @@ public:
       }
       Py_DECREF(args);
     }
-    global_handle->notify_all("command", tag);
+    //global_handle->notify_all("command", tag);
   }
 };
 
 
 static PyObject*
-ceph_send_command(PyObject *self, PyObject *args)
+ceph_send_command(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
-
   // Like mon, osd, mds
   char *type = nullptr;
 
@@ -98,8 +104,8 @@ ceph_send_command(PyObject *self, PyObject *args)
   char *cmd_json = nullptr;
   char *tag = nullptr;
   PyObject *completion = nullptr;
-  if (!PyArg_ParseTuple(args, "sOssss:ceph_send_command",
-        &handle, &completion, &type, &name, &cmd_json, &tag)) {
+  if (!PyArg_ParseTuple(args, "Ossss:ceph_send_command",
+        &completion, &type, &name, &cmd_json, &tag)) {
     return nullptr;
   }
 
@@ -113,7 +119,7 @@ ceph_send_command(PyObject *self, PyObject *args)
 
   auto c = new MonCommandCompletion(completion, tag, PyThreadState_Get());
   if (std::string(type) == "mon") {
-    global_handle->get_monc().start_mon_command(
+    self->py_modules->get_monc().start_mon_command(
         {cmd_json},
         {},
         &c->outbl,
@@ -131,7 +137,7 @@ ceph_send_command(PyObject *self, PyObject *args)
     }
 
     ceph_tid_t tid;
-    global_handle->get_objecter().osd_command(
+    self->py_modules->get_objecter().osd_command(
         osd_id,
         {cmd_json},
         {},
@@ -140,7 +146,7 @@ ceph_send_command(PyObject *self, PyObject *args)
         &c->outs,
         c);
   } else if (std::string(type) == "mds") {
-    int r = global_handle->get_client().mds_command(
+    int r = self->py_modules->get_client().mds_command(
         name,
         {cmd_json},
         {},
@@ -164,7 +170,7 @@ ceph_send_command(PyObject *self, PyObject *args)
     }
 
     ceph_tid_t tid;
-    global_handle->get_objecter().pg_command(
+    self->py_modules->get_objecter().pg_command(
         pgid,
         {cmd_json},
         {},
@@ -185,11 +191,10 @@ ceph_send_command(PyObject *self, PyObject *args)
 }
 
 static PyObject*
-ceph_set_health_checks(PyObject *self, PyObject *args)
+ceph_set_health_checks(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   PyObject *checks = NULL;
-  if (!PyArg_ParseTuple(args, "sO:ceph_set_health_checks", &handle, &checks)) {
+  if (!PyArg_ParseTuple(args, "O:ceph_set_health_checks", &checks)) {
     return NULL;
   }
   if (!PyDict_Check(checks)) {
@@ -275,64 +280,64 @@ ceph_set_health_checks(PyObject *self, PyObject *args)
   }
 
   JSONFormatter jf(true);
-  dout(10) << "module " << handle << " health checks:\n";
+  dout(10) << "module " << self->this_module->get_name()
+          << " health checks:\n";
   out_checks.dump(&jf);
   jf.flush(*_dout);
   *_dout << dendl;
 
-  global_handle->set_health_checks(handle, std::move(out_checks));
+  self->py_modules->set_health_checks(self->this_module->get_name(),
+                                      std::move(out_checks));
   
   Py_RETURN_NONE;
 }
 
 
 static PyObject*
-ceph_state_get(PyObject *self, PyObject *args)
+ceph_state_get(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *what = NULL;
-  if (!PyArg_ParseTuple(args, "ss:ceph_state_get", &handle, &what)) {
+  if (!PyArg_ParseTuple(args, "s:ceph_state_get", &what)) {
     return NULL;
   }
 
-  return global_handle->get_python(what);
+  return self->py_modules->get_python(what);
 }
 
 
 static PyObject*
-ceph_get_server(PyObject *self, PyObject *args)
+ceph_get_server(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *hostname = NULL;
-  if (!PyArg_ParseTuple(args, "sz:ceph_get_server", &handle, &hostname)) {
+  if (!PyArg_ParseTuple(args, "z:ceph_get_server", &hostname)) {
     return NULL;
   }
 
   if (hostname) {
-    return global_handle->get_server_python(hostname);
+    return self->py_modules->get_server_python(hostname);
   } else {
-    return global_handle->list_servers_python();
+    return self->py_modules->list_servers_python();
   }
 }
 
 static PyObject*
-ceph_get_mgr_id(PyObject *self, PyObject *args)
+ceph_get_mgr_id(BaseMgrModule *self, PyObject *args)
 {
   return PyString_FromString(g_conf->name.get_id().c_str());
 }
 
 static PyObject*
-ceph_config_get(PyObject *self, PyObject *args)
+ceph_config_get(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *what = nullptr;
-  if (!PyArg_ParseTuple(args, "ss:ceph_config_get", &handle, &what)) {
+  if (!PyArg_ParseTuple(args, "s:ceph_config_get", &what)) {
     derr << "Invalid args!" << dendl;
     return nullptr;
   }
 
   std::string value;
-  bool found = global_handle->get_config(handle, what, &value);
+  bool found = self->py_modules->get_config(self->this_module->get_name(),
+      what, &value);
   if (found) {
     dout(10) << "ceph_config_get " << what << " found: " << value.c_str() << dendl;
     return PyString_FromString(value.c_str());
@@ -343,157 +348,245 @@ ceph_config_get(PyObject *self, PyObject *args)
 }
 
 static PyObject*
-ceph_config_get_prefix(PyObject *self, PyObject *args)
+ceph_config_get_prefix(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *prefix = nullptr;
-  if (!PyArg_ParseTuple(args, "ss:ceph_config_get", &handle, &prefix)) {
+  if (!PyArg_ParseTuple(args, "s:ceph_config_get", &prefix)) {
     derr << "Invalid args!" << dendl;
     return nullptr;
   }
 
-  return global_handle->get_config_prefix(handle, prefix);
+  return self->py_modules->get_config_prefix(self->this_module->get_name(),
+      prefix);
 }
 
 static PyObject*
-ceph_config_set(PyObject *self, PyObject *args)
+ceph_config_set(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *key = nullptr;
   char *value = nullptr;
-  if (!PyArg_ParseTuple(args, "ssz:ceph_config_set", &handle, &key, &value)) {
+  if (!PyArg_ParseTuple(args, "sz:ceph_config_set", &key, &value)) {
     return nullptr;
   }
   boost::optional<string> val;
   if (value) {
     val = value;
   }
-  global_handle->set_config(handle, key, val);
+  global_handle->set_config(self->this_module->get_name(), key, val);
 
   Py_RETURN_NONE;
 }
 
 static PyObject*
-get_metadata(PyObject *self, PyObject *args)
+get_metadata(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *svc_name = NULL;
   char *svc_id = NULL;
-  if (!PyArg_ParseTuple(args, "sss:get_metadata", &handle, &svc_name, &svc_id)) {
+  if (!PyArg_ParseTuple(args, "ss:get_metadata", &svc_name, &svc_id)) {
     return nullptr;
   }
-  return global_handle->get_metadata_python(handle, svc_name, svc_id);
+  return self->py_modules->get_metadata_python(svc_name, svc_id);
 }
 
 static PyObject*
-get_daemon_status(PyObject *self, PyObject *args)
+get_daemon_status(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *svc_name = NULL;
   char *svc_id = NULL;
-  if (!PyArg_ParseTuple(args, "sss:get_daemon_status", &handle, &svc_name,
+  if (!PyArg_ParseTuple(args, "ss:get_daemon_status", &svc_name,
                        &svc_id)) {
     return nullptr;
   }
-  return global_handle->get_daemon_status_python(handle, svc_name, svc_id);
+  return self->py_modules->get_daemon_status_python(svc_name, svc_id);
 }
 
 static PyObject*
-ceph_log(PyObject *self, PyObject *args)
+ceph_log(BaseMgrModule *self, PyObject *args)
 {
   int level = 0;
   char *record = nullptr;
-  char *handle = nullptr;
-  if (!PyArg_ParseTuple(args, "sis:log", &handle, &level, &record)) {
+  if (!PyArg_ParseTuple(args, "is:log", &level, &record)) {
     return nullptr;
   }
 
-  global_handle->log(handle, level, record);
+  assert(self->this_module);
+
+  self->py_modules->log(self->this_module->get_name(), level, record);
 
   Py_RETURN_NONE;
 }
 
 static PyObject *
-ceph_get_version(PyObject *self, PyObject *args)
+ceph_get_version(BaseMgrModule *self, PyObject *args)
 {
   return PyString_FromString(pretty_version_to_str().c_str());
 }
 
 static PyObject *
-ceph_get_context(PyObject *self, PyObject *args)
+ceph_get_context(BaseMgrModule *self, PyObject *args)
 {
-  return global_handle->get_context();
+  return self->py_modules->get_context();
 }
 
 static PyObject*
-get_counter(PyObject *self, PyObject *args)
+get_counter(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *svc_name = nullptr;
   char *svc_id = nullptr;
   char *counter_path = nullptr;
-  if (!PyArg_ParseTuple(args, "ssss:get_counter", &handle, &svc_name,
+  if (!PyArg_ParseTuple(args, "sss:get_counter", &svc_name,
                                                   &svc_id, &counter_path)) {
     return nullptr;
   }
-  return global_handle->get_counter_python(
-      handle, svc_name, svc_id, counter_path);
+  return self->py_modules->get_counter_python(
+      svc_name, svc_id, counter_path);
 }
 
 static PyObject*
-get_perf_schema(PyObject *self, PyObject *args)
+get_perf_schema(BaseMgrModule *self, PyObject *args)
 {
-  char *handle = nullptr;
   char *type_str = nullptr;
   char *svc_id = nullptr;
-  if (!PyArg_ParseTuple(args, "sss:get_perf_schema", &handle, &type_str,
-                                                     &svc_id)) {
+  if (!PyArg_ParseTuple(args, "ss:get_perf_schema", &type_str,
+                                                    &svc_id)) {
     return nullptr;
   }
 
-  return global_handle->get_perf_schema_python(handle, type_str, svc_id);
+  return self->py_modules->get_perf_schema_python(type_str, svc_id);
 }
 
+
+static PyObject *
+ceph_get_osdmap(BaseMgrModule *self, PyObject *args)
+{
+  return self->py_modules->get_osdmap();
+}
+
+
+
+PyMethodDef BaseMgrModule_methods[] = {
+  {"_ceph_get", (PyCFunction)ceph_state_get, METH_VARARGS,
+   "Get a cluster object"},
+
+  {"_ceph_get_server", (PyCFunction)ceph_get_server, METH_VARARGS,
+   "Get a server object"},
+
+  {"_ceph_get_metadata", (PyCFunction)get_metadata, METH_VARARGS,
+   "Get a service's metadata"},
+
+  {"_ceph_get_daemon_status", (PyCFunction)get_daemon_status, METH_VARARGS,
+   "Get a service's status"},
+
+  {"_ceph_send_command", (PyCFunction)ceph_send_command, METH_VARARGS,
+   "Send a mon command"},
+
+  {"_ceph_set_health_checks", (PyCFunction)ceph_set_health_checks, METH_VARARGS,
+   "Set health checks for this module"},
+
+  {"_ceph_get_mgr_id", (PyCFunction)ceph_get_mgr_id, METH_NOARGS,
+   "Get the name of the Mgr daemon where we are running"},
+
+  {"_ceph_get_config", (PyCFunction)ceph_config_get, METH_VARARGS,
+   "Get a configuration value"},
+
+  {"_ceph_get_config_prefix", (PyCFunction)ceph_config_get_prefix, METH_VARARGS,
+   "Get all configuration values with a given prefix"},
+
+  {"_ceph_set_config", (PyCFunction)ceph_config_set, METH_VARARGS,
+   "Set a configuration value"},
+
+  {"_ceph_get_counter", (PyCFunction)get_counter, METH_VARARGS,
+    "Get a performance counter"},
+
+  {"_ceph_get_perf_schema", (PyCFunction)get_perf_schema, METH_VARARGS,
+    "Get the performance counter schema"},
+
+  {"_ceph_log", (PyCFunction)ceph_log, METH_VARARGS,
+   "Emit a (local) log message"},
+
+  {"_ceph_get_version", (PyCFunction)ceph_get_version, METH_VARARGS,
+   "Get the ceph version of this process"},
+
+  {"_ceph_get_context", (PyCFunction)ceph_get_context, METH_NOARGS,
+    "Get a CephContext* in a python capsule"},
+
+  {"_ceph_get_osdmap", (PyCFunction)ceph_get_osdmap, METH_NOARGS,
+    "Get an OSDMap* in a python capsule"},
+
+  {NULL, NULL, 0, NULL}
+};
+
+
 static PyObject *
-ceph_get_osdmap(PyObject *self, PyObject *args)
+BaseMgrModule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-  return global_handle->get_osdmap();
+    BaseMgrModule *self;
+
+    self = (BaseMgrModule *)type->tp_alloc(type, 0);
+
+    return (PyObject *)self;
 }
 
+static int
+BaseMgrModule_init(BaseMgrModule *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *py_modules_capsule = nullptr;
+    PyObject *this_module_capsule = nullptr;
+    static const char *kwlist[] = {"py_modules", "this_module", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO",
+                                      const_cast<char**>(kwlist),
+                                      &py_modules_capsule,
+                                      &this_module_capsule)) {
+        return -1;
+    }
+
+    self->py_modules = (PyModules*)PyCapsule_GetPointer(py_modules_capsule, nullptr);
+    assert(self->py_modules);
+    self->this_module = (MgrPyModule*)PyCapsule_GetPointer(this_module_capsule, nullptr);
+    assert(self->this_module);
+
+    return 0;
+}
 
-PyMethodDef CephStateMethods[] = {
-    {"get", ceph_state_get, METH_VARARGS,
-     "Get a cluster object"},
-    {"get_server", ceph_get_server, METH_VARARGS,
-     "Get a server object"},
-    {"get_metadata", get_metadata, METH_VARARGS,
-     "Get a service's metadata"},
-    {"get_daemon_status", get_daemon_status, METH_VARARGS,
-     "Get a service's status"},
-    {"send_command", ceph_send_command, METH_VARARGS,
-     "Send a mon command"},
-    {"set_health_checks", ceph_set_health_checks, METH_VARARGS,
-     "Set health checks for this module"},
-    {"get_mgr_id", ceph_get_mgr_id, METH_NOARGS,
-     "Get the mgr id"},
-    {"get_config", ceph_config_get, METH_VARARGS,
-     "Get a configuration value"},
-    {"get_config_prefix", ceph_config_get_prefix, METH_VARARGS,
-     "Get all configuration values with a given prefix"},
-    {"set_config", ceph_config_set, METH_VARARGS,
-     "Set a configuration value"},
-    {"get_counter", get_counter, METH_VARARGS,
-      "Get a performance counter"},
-    {"get_perf_schema", get_perf_schema, METH_VARARGS,
-      "Get the performance counter schema"},
-    {"log", ceph_log, METH_VARARGS,
-     "Emit a (local) log message"},
-    {"get_version", ceph_get_version, METH_VARARGS,
-     "Get the ceph version of this process"},
-    {"get_context", ceph_get_context, METH_NOARGS,
-      "Get a CephContext* in a python capsule"},
-    {"get_osdmap", ceph_get_osdmap, METH_NOARGS,
-     "Get an OSDMap handle"},
-    {NULL, NULL, 0, NULL}
+PyTypeObject BaseMgrModuleType = {
+  PyVarObject_HEAD_INIT(NULL, 0)
+  "ceph_module.BaseMgrModule", /* tp_name */
+  sizeof(BaseMgrModule),     /* tp_basicsize */
+  0,                         /* tp_itemsize */
+  0,                         /* tp_dealloc */
+  0,                         /* tp_print */
+  0,                         /* tp_getattr */
+  0,                         /* tp_setattr */
+  0,                         /* tp_compare */
+  0,                         /* tp_repr */
+  0,                         /* tp_as_number */
+  0,                         /* tp_as_sequence */
+  0,                         /* tp_as_mapping */
+  0,                         /* tp_hash */
+  0,                         /* tp_call */
+  0,                         /* tp_str */
+  0,                         /* tp_getattro */
+  0,                         /* tp_setattro */
+  0,                         /* tp_as_buffer */
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /* tp_flags */
+  "ceph-mgr Python Plugin", /* tp_doc */
+  0,                         /* tp_traverse */
+  0,                         /* tp_clear */
+  0,                         /* tp_richcompare */
+  0,                         /* tp_weaklistoffset */
+  0,                         /* tp_iter */
+  0,                         /* tp_iternext */
+  BaseMgrModule_methods,     /* tp_methods */
+  0,                         /* tp_members */
+  0,                         /* tp_getset */
+  0,                         /* tp_base */
+  0,                         /* tp_dict */
+  0,                         /* tp_descr_get */
+  0,                         /* tp_descr_set */
+  0,                         /* tp_dictoffset */
+  (initproc)BaseMgrModule_init,                         /* tp_init */
+  0,                         /* tp_alloc */
+  BaseMgrModule_new,     /* tp_new */
 };
 
index e53296b07fa2fd2ad086d1b231924479625abc30..32eb5502175b9b87e03bd8b57e8174404d1ac1b6 100644 (file)
@@ -6,7 +6,7 @@
 class PyModules;
 
 extern PyModules *global_handle;
-extern PyMethodDef CephStateMethods[];
+extern PyTypeObject BaseMgrModuleType;
 
 #endif