]> git.proxmox.com Git - ceph.git/blame - ceph/src/mgr/PyModuleRegistry.h
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / mgr / PyModuleRegistry.h
CommitLineData
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
30class 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 */
40class PyModuleRegistry
41{
42private:
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
65public:
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 &notify_type,
180 const std::string &notify_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};