]> git.proxmox.com Git - ceph.git/blob - ceph/src/mgr/PyModuleRegistry.h
import ceph nautilus 14.2.2
[ceph.git] / ceph / src / mgr / PyModuleRegistry.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2017 John Spray <john.spray@redhat.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 */
13
14
15 #pragma once
16
17 // First because it includes Python.h
18 #include "PyModule.h"
19
20 #include <string>
21 #include <map>
22 #include <set>
23 #include <memory>
24
25 #include "common/LogClient.h"
26
27 #include "ActivePyModules.h"
28 #include "StandbyPyModules.h"
29
30 /**
31 * This class is responsible for setting up the python runtime environment
32 * and importing the python modules.
33 *
34 * It is *not* responsible for constructing instances of their BaseMgrModule
35 * subclasses: that is the job of ActiveMgrModule, which consumes the class
36 * references that we load here.
37 */
38 class PyModuleRegistry
39 {
40 private:
41 mutable Mutex lock{"PyModuleRegistry::lock"};
42 LogChannelRef clog;
43
44 std::map<std::string, PyModuleRef> modules;
45
46 std::unique_ptr<ActivePyModules> active_modules;
47 std::unique_ptr<StandbyPyModules> standby_modules;
48
49 PyThreadState *pMainThreadState;
50
51 // We have our own copy of MgrMap, because we are constructed
52 // before ClusterState exists.
53 MgrMap mgr_map;
54
55 /**
56 * Discover python modules from local disk
57 */
58 std::set<std::string> probe_modules(const std::string &path) const;
59
60 PyModuleConfig module_config;
61
62 public:
63 void handle_config(const std::string &k, const std::string &v);
64 void handle_config_notify();
65
66 /**
67 * Get references to all modules (whether they have loaded and/or
68 * errored) or not.
69 */
70 std::list<PyModuleRef> get_modules() const
71 {
72 std::lock_guard l(lock);
73 std::list<PyModuleRef> modules_out;
74 for (const auto &i : modules) {
75 modules_out.push_back(i.second);
76 }
77
78 return modules_out;
79 }
80
81 explicit PyModuleRegistry(LogChannelRef clog_)
82 : clog(clog_)
83 {}
84
85 /**
86 * @return true if the mgrmap has changed such that the service needs restart
87 */
88 bool handle_mgr_map(const MgrMap &mgr_map_);
89
90 void init();
91
92 void upgrade_config(
93 MonClient *monc,
94 const std::map<std::string, std::string> &old_config);
95
96 void active_start(
97 DaemonStateIndex &ds, ClusterState &cs,
98 const std::map<std::string, std::string> &kv_store,
99 MonClient &mc, LogChannelRef clog_, LogChannelRef audit_clog_,
100 Objecter &objecter_, Client &client_, Finisher &f,
101 DaemonServer &server);
102 void standby_start(MonClient &mc, Finisher &f);
103
104 bool is_standby_running() const
105 {
106 return standby_modules != nullptr;
107 }
108
109 void active_shutdown();
110 void shutdown();
111
112 std::vector<MonCommand> get_commands() const;
113 std::vector<ModuleCommand> get_py_commands() const;
114
115 /**
116 * Get the specified module. The module does not have to be
117 * loaded or runnable.
118 *
119 * Returns an empty reference if it does not exist.
120 */
121 PyModuleRef get_module(const std::string &module_name)
122 {
123 std::lock_guard l(lock);
124 auto module_iter = modules.find(module_name);
125 if (module_iter == modules.end()) {
126 return {};
127 }
128 return module_iter->second;
129 }
130
131 /**
132 * Pass through command to the named module for execution.
133 *
134 * The command must exist in the COMMANDS reported by the module. If it
135 * doesn't then this will abort.
136 *
137 * If ActivePyModules has not been instantiated yet then this will
138 * return EAGAIN.
139 */
140 int handle_command(
141 std::string const &module_name,
142 const cmdmap_t &cmdmap,
143 const bufferlist &inbuf,
144 std::stringstream *ds,
145 std::stringstream *ss);
146
147 /**
148 * Pass through health checks reported by modules, and report any
149 * modules that have failed (i.e. unhandled exceptions in serve())
150 */
151 void get_health_checks(health_check_map_t *checks);
152
153 void get_progress_events(map<std::string,ProgressEvent> *events) {
154 if (active_modules) {
155 active_modules->get_progress_events(events);
156 }
157 }
158
159 // FIXME: breaking interface so that I don't have to go rewrite all
160 // the places that call into these (for now)
161 // >>>
162 void notify_all(const std::string &notify_type,
163 const std::string &notify_id)
164 {
165 if (active_modules) {
166 active_modules->notify_all(notify_type, notify_id);
167 }
168 }
169
170 void notify_all(const LogEntry &log_entry)
171 {
172 if (active_modules) {
173 active_modules->notify_all(log_entry);
174 }
175 }
176
177 std::map<std::string, std::string> get_services() const
178 {
179 ceph_assert(active_modules);
180 return active_modules->get_services();
181 }
182 // <<< (end of ActivePyModules cheeky call-throughs)
183 };