]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: do not load disabled modules 34846/head
authorKefu Chai <kchai@redhat.com>
Thu, 30 Apr 2020 03:34:07 +0000 (11:34 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 30 Apr 2020 11:11:22 +0000 (19:11 +0800)
an option named "mgr_disabled_modules" is added in this change to
prevent mgr from loading modules listed in this option. because mgr
loads *all* modules found in the configured path, and per
https://tracker.ceph.com/issues/45147, python subinterpreter could hang
when loading numpy, so this behavior practically creates a deadlock
in mgr.

this issue is found when mgr uses python3.8 runtime. in development
environment, it'd be inconvenient to disable the offending mgr module
without changing the source code, even if we can choose to not install
them, for instance, the enduser can workaround this issue by
uninstalling `ceph-mgr-diskprediction-local`.

an option would be useful in this case, so we can add the module to the
list before mgr tries to load it.

as this issue is found with python3.8 + diskprediction_local (numpy), so
this mgr module is disabled by default if mgr is compiled with python3.8
runtime.

Fixes: https://tracker.ceph.com/issues/45147
Signed-off-by: Kefu Chai <kchai@redhat.com>
CMakeLists.txt
src/common/options.cc
src/include/config-h.in.cmake
src/mgr/PyModuleRegistry.cc

index 0f7e86414c2d25fa6889f614c796abc4c587114f..fa00d1316bcc017dd001699f7fb4829d53672faf 100644 (file)
@@ -442,6 +442,11 @@ if(WITH_MGR)
   set(MGR_PYTHON_LIBRARIES ${Python3_LIBRARIES})
   set(MGR_PYTHON_VERSION_MAJOR ${Python3_VERSION_MAJOR})
   set(MGR_PYTHON_VERSION_MINOR ${Python3_VERSION_MINOR})
+  # https://tracker.ceph.com/issues/45147
+  if(Python3_VERSION VERSION_GREATER_EQUAL 3.8)
+    set(MGR_DISABLED_MODULES "diskprediction_local")
+    message(STATUS "mgr module disabled for ${Python3_VERSION}: ${MGR_DISABLED_MODULES}")
+  endif()
   # Boost dependency check deferred to Boost section
 endif(WITH_MGR)
 
index be1e955ab51ea75d7390d007984c6c682a331caa..c78d9b69d7591e0ac287a94e04967b1b00a98730 100644 (file)
@@ -5169,6 +5169,20 @@ std::vector<Option> get_global_options() {
     .add_service("mgr")
     .set_description("Filesystem path to manager modules."),
 
+    Option("mgr_disabled_modules", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+#ifdef MGR_DISABLED_MODULES
+    .set_default(MGR_DISABLED_MODULES)
+#endif
+    .set_flag(Option::FLAG_STARTUP)
+    .add_service("mgr")
+    .set_description("List of manager modules never get loaded")
+    .set_long_description("A comma delimited list of module names. This list "
+        "is read by manager when it starts. By default, manager loads all "
+        "modules found in specified 'mgr_module_path', and it starts the "
+        "enabled ones as instructed. The modules in this list will not be "
+        "loaded at all.")
+    .add_see_also("mgr_module_path"),
+
     Option("mgr_initial_modules", Option::TYPE_STR, Option::LEVEL_BASIC)
     .set_default("restful iostat")
     .set_flag(Option::FLAG_NO_MON_UPDATE)
index dc213938f5c9c7e4e5a62fd0bb3d45287923f6ab..ea550c81e3a0e018828a61f1d6d8093655f72cd9 100644 (file)
 
 #cmakedefine MGR_PYTHON_EXECUTABLE "@MGR_PYTHON_EXECUTABLE@"
 
+/* the default value of "mgr_disabled_module" option */
+#cmakedefine MGR_DISABLED_MODULES "@MGR_DISABLED_MODULES@"
+
 /* Define to 1 if you have the `getprogname' function. */
 #cmakedefine HAVE_GETPROGNAME 1
 
index 466da5d404964a5af87de153b6063d3bf57f3461..2e2e080aa76c00939b8f8ca4c96219cd91850cc4 100644 (file)
@@ -25,6 +25,7 @@ namespace fs = std::experimental::filesystem;
 
 #include "include/stringify.h"
 #include "common/errno.h"
+#include "common/split.h"
 
 #include "BaseMgrModule.h"
 #include "PyOSDMap.h"
@@ -267,14 +268,22 @@ void PyModuleRegistry::shutdown()
 
 std::set<std::string> PyModuleRegistry::probe_modules(const std::string &path) const
 {
+  const auto opt = g_conf().get_val<std::string>("mgr_disabled_modules");
+  const auto disabled_modules = ceph::split(opt);
+
   std::set<std::string> modules;
   for (const auto& entry: fs::directory_iterator(path)) {
     if (!fs::is_directory(entry)) {
       continue;
     }
+    const std::string name = entry.path().filename();
+    if (std::count(disabled_modules.begin(), disabled_modules.end(), name)) {
+      dout(10) << "ignoring disabled module " << name << dendl;
+      continue;
+    }
     auto module_path = entry.path() / "module.py";
     if (fs::exists(module_path)) {
-      modules.emplace(entry.path().filename());
+      modules.emplace(name);
     }
   }
   return modules;