From 2ef005196ba2eb49c34c32def624938c7a8beb03 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 10 Jul 2017 23:23:19 -0400 Subject: [PATCH] mgr: add trivial OSDMap wrapper class Signed-off-by: Sage Weil --- src/CMakeLists.txt | 1 + src/mgr/MgrPyModule.cc | 4 + src/mgr/PyModules.cc | 23 ++++++ src/mgr/PyModules.h | 1 + src/mgr/PyOSDMap.cc | 125 +++++++++++++++++++++++++++++ src/mgr/PyOSDMap.h | 10 +++ src/mgr/PyState.cc | 9 +++ src/pybind/mgr/dashboard/module.py | 3 + src/pybind/mgr/mgr_module.py | 49 +++++++++++ 9 files changed, 225 insertions(+) create mode 100644 src/mgr/PyOSDMap.cc create mode 100644 src/mgr/PyOSDMap.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 534952e0dfc..0eb7ae59afe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/mgr/MgrPyModule.cc b/src/mgr/MgrPyModule.cc index a2bf73ca379..49b70d8a24b 100644 --- a/src/mgr/MgrPyModule.cc +++ b/src/mgr/MgrPyModule.cc @@ -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(sys_path.c_str())); } diff --git a/src/mgr/PyModules.cc b/src/mgr/PyModules.cc index d78640d44a0..7c221d1ab5e 100644 --- a/src/mgr/PyModules.cc +++ b/src/mgr/PyModules.cc @@ -793,6 +793,29 @@ PyObject *PyModules::get_context() return capsule; } +static void delete_osdmap(PyObject *object) +{ + OSDMap *osdmap = static_cast(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 *modules) diff --git a/src/mgr/PyModules.h b/src/mgr/PyModules.h index c7aad4e5df8..894c42db3f3 100644 --- a/src/mgr/PyModules.h +++ b/src/mgr/PyModules.h @@ -83,6 +83,7 @@ public: const std::string svc_type, const std::string &svc_id); PyObject *get_context(); + PyObject *get_osdmap(); std::map config_cache; diff --git a/src/mgr/PyOSDMap.cc b/src/mgr/PyOSDMap.cc new file mode 100644 index 00000000000..9b1bdc4e3b7 --- /dev/null +++ b/src/mgr/PyOSDMap.cc @@ -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(PyCapsule_GetPointer(obj, nullptr)); + return PyInt_FromLong(osdmap->get_epoch()); +} + +static PyObject *osdmap_dump(PyObject *self, PyObject *obj) +{ + OSDMap *osdmap = static_cast(PyCapsule_GetPointer(obj, nullptr)); + PyFormatter f; + osdmap->dump(&f); + return f.get(); +} + + +static void delete_osdmap_incremental(PyObject *object) +{ + OSDMap::Incremental *inc = static_cast( + PyCapsule_GetPointer(object, nullptr)); + derr << __func__ << " " << inc << dendl; + delete inc; +} + +static PyObject *osdmap_new_incremental(PyObject *self, PyObject *obj) +{ + OSDMap *osdmap = static_cast(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(PyCapsule_GetPointer(mapobj, nullptr)); + OSDMap::Incremental *inc = static_cast( + PyCapsule_GetPointer(incobj, nullptr)); + + dout(10) << __func__ << " osdmap " << osdmap << " inc " << inc + << " max_deviation " << max_deviation + << " max_iterations " << max_iterations + << dendl; + set 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( + PyCapsule_GetPointer(obj, nullptr)); + return PyInt_FromLong(inc->epoch); +} + +static PyObject *osdmap_inc_dump(PyObject *self, PyObject *obj) +{ + OSDMap::Incremental *inc = static_cast( + 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 index 00000000000..bfa851cd660 --- /dev/null +++ b/src/mgr/PyOSDMap.h @@ -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[]; diff --git a/src/mgr/PyState.cc b/src/mgr/PyState.cc index fb6b831de72..fe849de107e 100644 --- a/src/mgr/PyState.cc +++ b/src/mgr/PyState.cc @@ -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} }; diff --git a/src/pybind/mgr/dashboard/module.py b/src/pybind/mgr/dashboard/module.py index f0ee89d371d..0a7c625be31 100644 --- a/src/pybind/mgr/dashboard/module.py +++ b/src/pybind/mgr/dashboard/module.py @@ -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": { diff --git a/src/pybind/mgr/mgr_module.py b/src/pybind/mgr/mgr_module.py index 2463bafe75d..57ea33e1660 100644 --- a/src/pybind/mgr/mgr_module.py +++ b/src/pybind/mgr/mgr_module.py @@ -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()) -- 2.39.5