X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmgr%2FActivePyModule.cc;fp=src%2Fceph%2Fsrc%2Fmgr%2FActivePyModule.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=90040af930d5a1741e09b8da0964a5926b3c9e59;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/mgr/ActivePyModule.cc b/src/ceph/src/mgr/ActivePyModule.cc deleted file mode 100644 index 90040af..0000000 --- a/src/ceph/src/mgr/ActivePyModule.cc +++ /dev/null @@ -1,225 +0,0 @@ -// -*- 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) 2016 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. - */ - -#include "BaseMgrModule.h" - -#include "PyFormatter.h" - -#include "common/debug.h" - -#include "ActivePyModule.h" - -//XXX courtesy of http://stackoverflow.com/questions/1418015/how-to-get-python-exception-text -#include -#include "include/assert.h" // boost clobbers this - - -#define dout_context g_ceph_context -#define dout_subsys ceph_subsys_mgr -#undef dout_prefix -#define dout_prefix *_dout << "mgr " << __func__ << " " - -// decode a Python exception into a string -std::string handle_pyerror() -{ - using namespace boost::python; - using namespace boost; - - PyObject *exc, *val, *tb; - object formatted_list, formatted; - PyErr_Fetch(&exc, &val, &tb); - handle<> hexc(exc), hval(allow_null(val)), htb(allow_null(tb)); - object traceback(import("traceback")); - if (!tb) { - object format_exception_only(traceback.attr("format_exception_only")); - formatted_list = format_exception_only(hexc, hval); - } else { - object format_exception(traceback.attr("format_exception")); - formatted_list = format_exception(hexc,hval, htb); - } - formatted = str("").join(formatted_list); - return extract(formatted); -} - -int ActivePyModule::load(ActivePyModules *py_modules) -{ - assert(py_modules); - Gil gil(pMyThreadState, true); - - // 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(pModuleName); - Py_DECREF(pArgs); - if (pClassInstance == nullptr) { - derr << "Failed to construct class in '" << module_name << "'" << dendl; - derr << handle_pyerror() << dendl; - return -EINVAL; - } else { - dout(1) << "Constructed class from module: " << module_name << dendl; - } - - return load_commands(); -} - -void ActivePyModule::notify(const std::string ¬ify_type, const std::string ¬ify_id) -{ - assert(pClassInstance != nullptr); - - Gil gil(pMyThreadState, true); - - // Execute - auto pValue = PyObject_CallMethod(pClassInstance, - const_cast("notify"), const_cast("(ss)"), - notify_type.c_str(), notify_id.c_str()); - - if (pValue != NULL) { - Py_DECREF(pValue); - } else { - derr << module_name << ".notify:" << dendl; - derr << handle_pyerror() << dendl; - // FIXME: callers can't be expected to handle a python module - // that has spontaneously broken, but Mgr() should provide - // a hook to unload misbehaving modules when they have an - // error somewhere like this - } -} - -void ActivePyModule::notify_clog(const LogEntry &log_entry) -{ - assert(pClassInstance != nullptr); - - Gil gil(pMyThreadState, true); - - // Construct python-ized LogEntry - PyFormatter f; - log_entry.dump(&f); - auto py_log_entry = f.get(); - - // Execute - auto pValue = PyObject_CallMethod(pClassInstance, - const_cast("notify"), const_cast("(sN)"), - "clog", py_log_entry); - - if (pValue != NULL) { - Py_DECREF(pValue); - } else { - derr << module_name << ".notify_clog:" << dendl; - derr << handle_pyerror() << dendl; - // FIXME: callers can't be expected to handle a python module - // that has spontaneously broken, but Mgr() should provide - // a hook to unload misbehaving modules when they have an - // error somewhere like this - } -} - -int ActivePyModule::load_commands() -{ - // Don't need a Gil here -- this is called from ActivePyModule::load(), - // which already has one. - PyObject *command_list = PyObject_GetAttrString(pClassInstance, "COMMANDS"); - if (command_list == nullptr) { - // Even modules that don't define command should still have the COMMANDS - // from the MgrModule definition. Something is wrong! - derr << "Module " << get_name() << " has missing COMMANDS member" << dendl; - return -EINVAL; - } - if (!PyObject_TypeCheck(command_list, &PyList_Type)) { - // Relatively easy mistake for human to make, e.g. defining COMMANDS - // as a {} instead of a [] - derr << "Module " << get_name() << " has COMMANDS member of wrong type (" - "should be a list)" << dendl; - return -EINVAL; - } - const size_t list_size = PyList_Size(command_list); - for (size_t i = 0; i < list_size; ++i) { - PyObject *command = PyList_GetItem(command_list, i); - assert(command != nullptr); - - ModuleCommand item; - - PyObject *pCmd = PyDict_GetItemString(command, "cmd"); - assert(pCmd != nullptr); - item.cmdstring = PyString_AsString(pCmd); - - dout(20) << "loaded command " << item.cmdstring << dendl; - - PyObject *pDesc = PyDict_GetItemString(command, "desc"); - assert(pDesc != nullptr); - item.helpstring = PyString_AsString(pDesc); - - PyObject *pPerm = PyDict_GetItemString(command, "perm"); - assert(pPerm != nullptr); - item.perm = PyString_AsString(pPerm); - - item.handler = this; - - commands.push_back(item); - } - Py_DECREF(command_list); - - dout(10) << "loaded " << commands.size() << " commands" << dendl; - - return 0; -} - -int ActivePyModule::handle_command( - const cmdmap_t &cmdmap, - std::stringstream *ds, - std::stringstream *ss) -{ - assert(ss != nullptr); - assert(ds != nullptr); - - Gil gil(pMyThreadState, true); - - PyFormatter f; - cmdmap_dump(cmdmap, &f); - PyObject *py_cmd = f.get(); - - auto pResult = PyObject_CallMethod(pClassInstance, - const_cast("handle_command"), const_cast("(O)"), py_cmd); - - Py_DECREF(py_cmd); - - int r = 0; - if (pResult != NULL) { - if (PyTuple_Size(pResult) != 3) { - r = -EINVAL; - } else { - r = PyInt_AsLong(PyTuple_GetItem(pResult, 0)); - *ds << PyString_AsString(PyTuple_GetItem(pResult, 1)); - *ss << PyString_AsString(PyTuple_GetItem(pResult, 2)); - } - - Py_DECREF(pResult); - } else { - *ds << ""; - *ss << handle_pyerror(); - r = -EINVAL; - } - - return r; -} - -void ActivePyModule::get_health_checks(health_check_map_t *checks) -{ - checks->merge(health_checks); -} -