]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: do not load disabled modules
authorKefu Chai <kchai@redhat.com>
Thu, 30 Apr 2020 03:34:07 +0000 (11:34 +0800)
committerCory Snyder <csnyder@iland.com>
Tue, 1 Jun 2021 11:38:48 +0000 (07:38 -0400)
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>
(cherry picked from commit 067adbf9a032b5de793fd0b41b071f24f075270a)

CMakeLists.txt
src/common/options.cc
src/include/config-h.in.cmake
src/mgr/PyModuleRegistry.cc

index a2d34ee97dfb0b6c2f209aed73433759cb511b04..fc67de963e473ebc5ff280aa73f5ed650895b4ae 100644 (file)
@@ -440,6 +440,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 b8cc55ef982b31f5e6a8887b57b88954a8331e13..85f4203be3686e466ca32ad73db66417bf47eb1a 100644 (file)
@@ -5256,6 +5256,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 ea0dcadb67f3f9daa17df5dd8ccfb2b6d82415cc..546646ec02325a5a120c8782a41a15c05f0d237e 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 31fa24d8340d8e501bf78b3b2955bb740ea3eef3..7ee218dc06a0b6a8651630ada923cca5b9d9e414 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"
@@ -269,14 +270,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;