]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: add trivial OSDMap wrapper class
authorSage Weil <sage@redhat.com>
Tue, 11 Jul 2017 03:23:19 +0000 (23:23 -0400)
committerSage Weil <sage@redhat.com>
Wed, 6 Sep 2017 20:45:46 +0000 (16:45 -0400)
Signed-off-by: Sage Weil <sage@redhat.com>
src/CMakeLists.txt
src/mgr/MgrPyModule.cc
src/mgr/PyModules.cc
src/mgr/PyModules.h
src/mgr/PyOSDMap.cc [new file with mode: 0644]
src/mgr/PyOSDMap.h [new file with mode: 0644]
src/mgr/PyState.cc
src/pybind/mgr/dashboard/module.py
src/pybind/mgr/mgr_module.py

index 534952e0dfce9ec66153815f9a346f79edd44db7..0eb7ae59afe0d32cffb50f9a09a3fabc43965682 100644 (file)
@@ -699,6 +699,7 @@ if (WITH_MGR)
       mgr/ClusterState.cc
       mgr/PyModules.cc
       mgr/PyFormatter.cc
+      mgr/PyOSDMap.cc
       mgr/PyState.cc
       mgr/MgrPyModule.cc
       mgr/MgrStandby.cc
index a2bf73ca379124c26f2d534efae35a0a884e2e8c..49b70d8a24bbd3047ad34afcfac1f889f5350031 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include "PyState.h"
+#include "PyOSDMap.h"
 #include "Gil.h"
 
 #include "PyFormatter.h"
@@ -109,6 +110,9 @@ MgrPyModule::MgrPyModule(const std::string &module_name_, const std::string &sys
     }
     // 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()));
   }
index d78640d44a0bb672eb9bdefd48462504419bcdfb..7c221d1ab5eb9bc259059063f4b0f1418c86ad37 100644 (file)
@@ -793,6 +793,29 @@ PyObject *PyModules::get_context()
   return capsule;
 }
 
+static void delete_osdmap(PyObject *object)
+{
+  OSDMap *osdmap = static_cast<OSDMap*>(PyCapsule_GetPointer(object, nullptr));
+  assert(osdmap);
+  dout(10) << __func__ << " " << osdmap << dendl;
+  delete osdmap;
+}
+
+PyObject *PyModules::get_osdmap()
+{
+  PyThreadState *tstate = PyEval_SaveThread();
+  Mutex::Locker l(lock);
+  PyEval_RestoreThread(tstate);
+
+  // Construct a capsule containing an OSDMap.
+  OSDMap *newmap = new OSDMap;
+  cluster_state.with_osdmap([&](const OSDMap& o) {
+      newmap->deepish_copy_from(o);
+    });
+  dout(10) << __func__ << " " << newmap << dendl;
+  return PyCapsule_New(newmap, nullptr, &delete_osdmap);
+}
+
 static void _list_modules(
   const std::string path,
   std::set<std::string> *modules)
index c7aad4e5df8859587ac1f7a353e3a930d6d44e16..894c42db3f313f5f007e0dbde2a38fdd3930e287 100644 (file)
@@ -83,6 +83,7 @@ public:
      const std::string svc_type,
      const std::string &svc_id);
   PyObject *get_context();
+  PyObject *get_osdmap();
 
   std::map<std::string, std::string> config_cache;
 
diff --git a/src/mgr/PyOSDMap.cc b/src/mgr/PyOSDMap.cc
new file mode 100644 (file)
index 0000000..9b1bdc4
--- /dev/null
@@ -0,0 +1,125 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "Mgr.h"
+
+#include "osd/OSDMap.h"
+#include "common/errno.h"
+#include "common/version.h"
+
+#include "PyOSDMap.h"
+#include "PyFormatter.h"
+#include "Gil.h"
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_mgr
+
+// ----------
+
+static PyObject *osdmap_get_epoch(PyObject *self, PyObject *obj)
+{
+  OSDMap *osdmap = static_cast<OSDMap*>(PyCapsule_GetPointer(obj, nullptr));
+  return PyInt_FromLong(osdmap->get_epoch());
+}
+
+static PyObject *osdmap_dump(PyObject *self, PyObject *obj)
+{
+  OSDMap *osdmap = static_cast<OSDMap*>(PyCapsule_GetPointer(obj, nullptr));
+  PyFormatter f;
+  osdmap->dump(&f);
+  return f.get();
+}
+
+
+static void delete_osdmap_incremental(PyObject *object)
+{
+  OSDMap::Incremental *inc = static_cast<OSDMap::Incremental*>(
+    PyCapsule_GetPointer(object, nullptr));
+  derr << __func__ << " " << inc << dendl;
+  delete inc;
+}
+
+static PyObject *osdmap_new_incremental(PyObject *self, PyObject *obj)
+{
+  OSDMap *osdmap = static_cast<OSDMap*>(PyCapsule_GetPointer(obj, nullptr));
+
+  // Construct a capsule containing an OSDMap.
+  OSDMap::Incremental *inc = new OSDMap::Incremental;
+  inc->fsid = osdmap->get_fsid();
+  inc->epoch = osdmap->get_epoch() + 1;
+  return PyCapsule_New(inc, nullptr, &delete_osdmap_incremental);
+}
+
+static PyObject *osdmap_calc_pg_upmaps(PyObject *self, PyObject *args)
+{
+  PyObject *mapobj, *incobj, *pool_list;
+  double max_deviation = 0;
+  int max_iterations = 0;
+  if (!PyArg_ParseTuple(args, "OOdiO:calc_pg_upmaps",
+                       &mapobj, &incobj, &max_deviation,
+                       &max_iterations, &pool_list)) {
+    return nullptr;
+  }
+
+  OSDMap *osdmap = static_cast<OSDMap*>(PyCapsule_GetPointer(mapobj, nullptr));
+  OSDMap::Incremental *inc = static_cast<OSDMap::Incremental*>(
+    PyCapsule_GetPointer(incobj, nullptr));
+
+  dout(10) << __func__ << " osdmap " << osdmap << " inc " << inc
+          << " max_deviation " << max_deviation
+          << " max_iterations " << max_iterations
+          << dendl;
+  set<int64_t> pools;
+  // FIXME: unpack pool_list and translate to pools set
+  int r = osdmap->calc_pg_upmaps(g_ceph_context,
+                                max_deviation,
+                                max_iterations,
+                                pools,
+                                inc);
+  dout(10) << __func__ << " r = " << r << dendl;
+  return PyInt_FromLong(r);
+}
+
+PyMethodDef OSDMapMethods[] = {
+  {"get_epoch", osdmap_get_epoch, METH_O, "Get OSDMap epoch"},
+  {"dump", osdmap_dump, METH_O, "Dump OSDMap::Incremental"},
+  {"new_incremental", osdmap_new_incremental, METH_O,
+   "Create OSDMap::Incremental"},
+  {"calc_pg_upmaps", osdmap_calc_pg_upmaps, METH_VARARGS,
+   "Calculate new pg-upmap values"},
+  {NULL, NULL, 0, NULL}
+};
+
+// ----------
+
+static PyObject *osdmap_inc_get_epoch(PyObject *self, PyObject *obj)
+{
+  OSDMap::Incremental *inc = static_cast<OSDMap::Incremental*>(
+    PyCapsule_GetPointer(obj, nullptr));
+  return PyInt_FromLong(inc->epoch);
+}
+
+static PyObject *osdmap_inc_dump(PyObject *self, PyObject *obj)
+{
+  OSDMap::Incremental *inc = static_cast<OSDMap::Incremental*>(
+    PyCapsule_GetPointer(obj, nullptr));
+  PyFormatter f;
+  inc->dump(&f);
+  return f.get();
+}
+
+PyMethodDef OSDMapIncrementalMethods[] = {
+  {"get_epoch", osdmap_inc_get_epoch, METH_O, "Get OSDMap::Incremental epoch"},
+  {"dump", osdmap_inc_dump, METH_O, "Dump OSDMap::Incremental"},
+  {NULL, NULL, 0, NULL}
+};
+
+
+// ----------
+
+
+
+PyMethodDef CRUSHMapMethods[] = {
+//  {"get_epoch", osdmap_get_epoch, METH_O, "Get OSDMap epoch"},
+  {NULL, NULL, 0, NULL}
+};
diff --git a/src/mgr/PyOSDMap.h b/src/mgr/PyOSDMap.h
new file mode 100644 (file)
index 0000000..bfa851c
--- /dev/null
@@ -0,0 +1,10 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include "Python.h"
+
+extern PyMethodDef OSDMapMethods[];
+extern PyMethodDef OSDMapIncrementalMethods[];
+extern PyMethodDef CRUSHMapMethods[];
index fb6b831de727aef0a9d443342728ac60de90dd1d..fe849de107e790a123b775fe2075e310d591fba7 100644 (file)
@@ -454,6 +454,13 @@ get_perf_schema(PyObject *self, PyObject *args)
   return global_handle->get_perf_schema_python(handle, type_str, svc_id);
 }
 
+static PyObject *
+ceph_get_osdmap(PyObject *self, PyObject *args)
+{
+  return global_handle->get_osdmap();
+}
+
+
 PyMethodDef CephStateMethods[] = {
     {"get", ceph_state_get, METH_VARARGS,
      "Get a cluster object"},
@@ -485,6 +492,8 @@ PyMethodDef CephStateMethods[] = {
      "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}
 };
 
index f0ee89d371dad7db221873c8092bb57ec8cf1690..0a7c625be3183a6c0783d160d698accae0559d42 100644 (file)
@@ -857,6 +857,9 @@ class Module(MgrModule):
             'engine.autoreload.on': False
         })
 
+        osdmap = self.get_osdmap()
+        log.info("latest osdmap is %d" % osdmap.get_epoch())
+
         static_dir = os.path.join(current_dir, 'static')
         conf = {
             "/static": {
index 2463bafe75d8a11e73e6d9f012cfbfc277b2cc01..57ea33e16601b90eceae9dbd16e41f325aa9c5bb 100644 (file)
@@ -1,5 +1,8 @@
 
 import ceph_state  #noqa
+import ceph_osdmap  #noqa
+import ceph_osdmap_incremental  #noqa
+import ceph_crushmap  #noqa
 import json
 import logging
 import threading
@@ -30,6 +33,44 @@ class CommandResult(object):
         return self.r, self.outb, self.outs
 
 
+class OSDMap(object):
+    def __init__(self, handle):
+        self._handle = handle
+
+    def get_epoch(self):
+        return ceph_osdmap.get_epoch(self._handle)
+
+    def dump(self):
+        return ceph_osdmap.dump(self._handle)
+
+    def new_incremental(self):
+        return OSDMapIncremental(ceph_osdmap.new_incremental(self._handle))
+
+    def calc_pg_upmaps(self, inc, max_deviation=.01, max_iterations=10, pools=[]):
+        return ceph_osdmap.calc_pg_upmaps(
+            self._handle,
+            inc._handle,
+            max_deviation, max_iterations, pools)
+
+
+class OSDMapIncremental(object):
+    def __init__(self, handle):
+        self._handle = handle
+
+    def get_epoch(self):
+        return ceph_osdmap_incremental.get_epoch(self._handle)
+
+    def dump(self):
+        return ceph_osdmap_incremental.dump(self._handle)
+
+class CRUSHMap(object):
+    def __init__(self, handle):
+        self._handle = handle
+
+#    def get_epoch(self):
+#        return ceph_crushmap.get_epoch(self._handle)
+
+
 class MgrModule(object):
     COMMANDS = []
 
@@ -299,3 +340,11 @@ class MgrModule(object):
         :return: bool
         """
         pass
+
+    def get_osdmap(self):
+        """
+        Get a handle to an OSDMap.  If epoch==0, get a handle for the latest
+        OSDMap.
+        :return: OSDMap
+        """
+        return OSDMap(ceph_state.get_osdmap())