]>
Commit | Line | Data |
---|---|---|
3efd9988 FG |
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 | ||
11fdf7f2 TL |
17 | // First because it includes Python.h |
18 | #include "PyModule.h" | |
3efd9988 FG |
19 | |
20 | #include <string> | |
21 | #include <map> | |
11fdf7f2 | 22 | #include <set> |
3efd9988 FG |
23 | #include <memory> |
24 | ||
25 | #include "common/LogClient.h" | |
26 | ||
27 | #include "ActivePyModules.h" | |
28 | #include "StandbyPyModules.h" | |
29 | ||
92f5a8d4 TL |
30 | class MgrSession; |
31 | ||
3efd9988 FG |
32 | /** |
33 | * This class is responsible for setting up the python runtime environment | |
34 | * and importing the python modules. | |
35 | * | |
36 | * It is *not* responsible for constructing instances of their BaseMgrModule | |
11fdf7f2 TL |
37 | * subclasses: that is the job of ActiveMgrModule, which consumes the class |
38 | * references that we load here. | |
3efd9988 FG |
39 | */ |
40 | class PyModuleRegistry | |
41 | { | |
42 | private: | |
9f95a23c | 43 | mutable ceph::mutex lock = ceph::make_mutex("PyModuleRegistry::lock"); |
3efd9988 FG |
44 | LogChannelRef clog; |
45 | ||
11fdf7f2 | 46 | std::map<std::string, PyModuleRef> modules; |
9f95a23c | 47 | std::multimap<std::string, entity_addrvec_t> clients; |
3efd9988 FG |
48 | |
49 | std::unique_ptr<ActivePyModules> active_modules; | |
50 | std::unique_ptr<StandbyPyModules> standby_modules; | |
51 | ||
52 | PyThreadState *pMainThreadState; | |
53 | ||
54 | // We have our own copy of MgrMap, because we are constructed | |
55 | // before ClusterState exists. | |
56 | MgrMap mgr_map; | |
57 | ||
11fdf7f2 TL |
58 | /** |
59 | * Discover python modules from local disk | |
60 | */ | |
20effc67 | 61 | std::vector<std::string> probe_modules(const std::string &path) const; |
3efd9988 | 62 | |
11fdf7f2 | 63 | PyModuleConfig module_config; |
3efd9988 | 64 | |
11fdf7f2 TL |
65 | public: |
66 | void handle_config(const std::string &k, const std::string &v); | |
67 | void handle_config_notify(); | |
68 | ||
f67539c2 TL |
69 | void update_kv_data( |
70 | const std::string prefix, | |
71 | bool incremental, | |
20effc67 | 72 | const map<std::string, std::optional<bufferlist>, std::less<>>& data) { |
f67539c2 TL |
73 | ceph_assert(active_modules); |
74 | active_modules->update_kv_data(prefix, incremental, data); | |
75 | } | |
76 | ||
11fdf7f2 TL |
77 | /** |
78 | * Get references to all modules (whether they have loaded and/or | |
79 | * errored) or not. | |
80 | */ | |
9f95a23c | 81 | auto get_modules() const |
3efd9988 | 82 | { |
9f95a23c | 83 | std::vector<PyModuleRef> modules_out; |
11fdf7f2 | 84 | std::lock_guard l(lock); |
11fdf7f2 TL |
85 | for (const auto &i : modules) { |
86 | modules_out.push_back(i.second); | |
3efd9988 FG |
87 | } |
88 | ||
11fdf7f2 | 89 | return modules_out; |
3efd9988 FG |
90 | } |
91 | ||
11fdf7f2 TL |
92 | explicit PyModuleRegistry(LogChannelRef clog_) |
93 | : clog(clog_) | |
94 | {} | |
95 | ||
96 | /** | |
97 | * @return true if the mgrmap has changed such that the service needs restart | |
98 | */ | |
99 | bool handle_mgr_map(const MgrMap &mgr_map_); | |
100 | ||
b3b6e05e TL |
101 | bool have_standby_modules() const { |
102 | return !!standby_modules; | |
103 | } | |
104 | ||
11fdf7f2 | 105 | void init(); |
3efd9988 | 106 | |
11fdf7f2 TL |
107 | void upgrade_config( |
108 | MonClient *monc, | |
109 | const std::map<std::string, std::string> &old_config); | |
3efd9988 FG |
110 | |
111 | void active_start( | |
11fdf7f2 TL |
112 | DaemonStateIndex &ds, ClusterState &cs, |
113 | const std::map<std::string, std::string> &kv_store, | |
f67539c2 | 114 | bool mon_provides_kv_sub, |
11fdf7f2 TL |
115 | MonClient &mc, LogChannelRef clog_, LogChannelRef audit_clog_, |
116 | Objecter &objecter_, Client &client_, Finisher &f, | |
117 | DaemonServer &server); | |
118 | void standby_start(MonClient &mc, Finisher &f); | |
3efd9988 FG |
119 | |
120 | bool is_standby_running() const | |
121 | { | |
122 | return standby_modules != nullptr; | |
123 | } | |
124 | ||
125 | void active_shutdown(); | |
126 | void shutdown(); | |
127 | ||
11fdf7f2 TL |
128 | std::vector<MonCommand> get_commands() const; |
129 | std::vector<ModuleCommand> get_py_commands() const; | |
130 | ||
131 | /** | |
132 | * Get the specified module. The module does not have to be | |
133 | * loaded or runnable. | |
134 | * | |
135 | * Returns an empty reference if it does not exist. | |
136 | */ | |
137 | PyModuleRef get_module(const std::string &module_name) | |
3efd9988 | 138 | { |
11fdf7f2 TL |
139 | std::lock_guard l(lock); |
140 | auto module_iter = modules.find(module_name); | |
141 | if (module_iter == modules.end()) { | |
142 | return {}; | |
143 | } | |
144 | return module_iter->second; | |
145 | } | |
3efd9988 | 146 | |
11fdf7f2 TL |
147 | /** |
148 | * Pass through command to the named module for execution. | |
149 | * | |
150 | * The command must exist in the COMMANDS reported by the module. If it | |
151 | * doesn't then this will abort. | |
152 | * | |
153 | * If ActivePyModules has not been instantiated yet then this will | |
154 | * return EAGAIN. | |
155 | */ | |
156 | int handle_command( | |
92f5a8d4 TL |
157 | const ModuleCommand& module_command, |
158 | const MgrSession& session, | |
11fdf7f2 TL |
159 | const cmdmap_t &cmdmap, |
160 | const bufferlist &inbuf, | |
161 | std::stringstream *ds, | |
162 | std::stringstream *ss); | |
163 | ||
164 | /** | |
165 | * Pass through health checks reported by modules, and report any | |
166 | * modules that have failed (i.e. unhandled exceptions in serve()) | |
167 | */ | |
168 | void get_health_checks(health_check_map_t *checks); | |
169 | ||
170 | void get_progress_events(map<std::string,ProgressEvent> *events) { | |
171 | if (active_modules) { | |
172 | active_modules->get_progress_events(events); | |
173 | } | |
3efd9988 FG |
174 | } |
175 | ||
176 | // FIXME: breaking interface so that I don't have to go rewrite all | |
177 | // the places that call into these (for now) | |
178 | // >>> | |
179 | void notify_all(const std::string ¬ify_type, | |
180 | const std::string ¬ify_id) | |
181 | { | |
182 | if (active_modules) { | |
183 | active_modules->notify_all(notify_type, notify_id); | |
184 | } | |
185 | } | |
186 | ||
187 | void notify_all(const LogEntry &log_entry) | |
188 | { | |
189 | if (active_modules) { | |
190 | active_modules->notify_all(log_entry); | |
191 | } | |
192 | } | |
193 | ||
20effc67 TL |
194 | bool should_notify(const std::string& name, |
195 | const std::string& notify_type) { | |
196 | return modules.at(name)->should_notify(notify_type); | |
197 | } | |
198 | ||
3efd9988 FG |
199 | std::map<std::string, std::string> get_services() const |
200 | { | |
11fdf7f2 | 201 | ceph_assert(active_modules); |
3efd9988 FG |
202 | return active_modules->get_services(); |
203 | } | |
9f95a23c | 204 | |
aee94f69 | 205 | void register_client(std::string_view name, entity_addrvec_t addrs, bool replace) |
9f95a23c | 206 | { |
1e59de90 | 207 | std::lock_guard l(lock); |
aee94f69 TL |
208 | auto n = std::string(name); |
209 | if (replace) { | |
210 | clients.erase(n); | |
211 | } | |
212 | clients.emplace(n, std::move(addrs)); | |
9f95a23c TL |
213 | } |
214 | void unregister_client(std::string_view name, const entity_addrvec_t& addrs) | |
215 | { | |
1e59de90 | 216 | std::lock_guard l(lock); |
9f95a23c TL |
217 | auto itp = clients.equal_range(std::string(name)); |
218 | for (auto it = itp.first; it != itp.second; ++it) { | |
219 | if (it->second == addrs) { | |
f91f0fd5 TL |
220 | clients.erase(it); |
221 | return; | |
9f95a23c TL |
222 | } |
223 | } | |
224 | } | |
225 | ||
226 | auto get_clients() const | |
227 | { | |
1e59de90 TL |
228 | std::lock_guard l(lock); |
229 | return clients; | |
230 | } | |
231 | ||
232 | bool is_module_active(const std::string &name) { | |
233 | ceph_assert(active_modules); | |
234 | return active_modules->module_exists(name); | |
235 | } | |
236 | ||
237 | auto& get_active_module_finisher(const std::string &name) { | |
238 | ceph_assert(active_modules); | |
239 | return active_modules->get_module_finisher(name); | |
9f95a23c TL |
240 | } |
241 | ||
3efd9988 FG |
242 | // <<< (end of ActivePyModules cheeky call-throughs) |
243 | }; |