1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2017 John Spray <john.spray@redhat.com>
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.
17 // First because it includes Python.h
25 #include "common/LogClient.h"
27 #include "ActivePyModules.h"
28 #include "StandbyPyModules.h"
33 * This class is responsible for setting up the python runtime environment
34 * and importing the python modules.
36 * It is *not* responsible for constructing instances of their BaseMgrModule
37 * subclasses: that is the job of ActiveMgrModule, which consumes the class
38 * references that we load here.
40 class PyModuleRegistry
43 mutable ceph::mutex lock
= ceph::make_mutex("PyModuleRegistry::lock");
46 std::map
<std::string
, PyModuleRef
> modules
;
47 std::multimap
<std::string
, entity_addrvec_t
> clients
;
49 std::unique_ptr
<ActivePyModules
> active_modules
;
50 std::unique_ptr
<StandbyPyModules
> standby_modules
;
52 PyThreadState
*pMainThreadState
;
54 // We have our own copy of MgrMap, because we are constructed
55 // before ClusterState exists.
59 * Discover python modules from local disk
61 std::set
<std::string
> probe_modules(const std::string
&path
) const;
63 PyModuleConfig module_config
;
66 void handle_config(const std::string
&k
, const std::string
&v
);
67 void handle_config_notify();
70 const std::string prefix
,
72 const map
<std::string
, boost::optional
<bufferlist
>, std::less
<>>& data
) {
73 ceph_assert(active_modules
);
74 active_modules
->update_kv_data(prefix
, incremental
, data
);
78 * Get references to all modules (whether they have loaded and/or
81 auto get_modules() const
83 std::vector
<PyModuleRef
> modules_out
;
84 std::lock_guard
l(lock
);
85 for (const auto &i
: modules
) {
86 modules_out
.push_back(i
.second
);
92 explicit PyModuleRegistry(LogChannelRef clog_
)
97 * @return true if the mgrmap has changed such that the service needs restart
99 bool handle_mgr_map(const MgrMap
&mgr_map_
);
101 bool have_standby_modules() const {
102 return !!standby_modules
;
109 const std::map
<std::string
, std::string
> &old_config
);
112 DaemonStateIndex
&ds
, ClusterState
&cs
,
113 const std::map
<std::string
, std::string
> &kv_store
,
114 bool mon_provides_kv_sub
,
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
);
120 bool is_standby_running() const
122 return standby_modules
!= nullptr;
125 void active_shutdown();
128 std::vector
<MonCommand
> get_commands() const;
129 std::vector
<ModuleCommand
> get_py_commands() const;
132 * Get the specified module. The module does not have to be
133 * loaded or runnable.
135 * Returns an empty reference if it does not exist.
137 PyModuleRef
get_module(const std::string
&module_name
)
139 std::lock_guard
l(lock
);
140 auto module_iter
= modules
.find(module_name
);
141 if (module_iter
== modules
.end()) {
144 return module_iter
->second
;
148 * Pass through command to the named module for execution.
150 * The command must exist in the COMMANDS reported by the module. If it
151 * doesn't then this will abort.
153 * If ActivePyModules has not been instantiated yet then this will
157 const ModuleCommand
& module_command
,
158 const MgrSession
& session
,
159 const cmdmap_t
&cmdmap
,
160 const bufferlist
&inbuf
,
161 std::stringstream
*ds
,
162 std::stringstream
*ss
);
165 * Pass through health checks reported by modules, and report any
166 * modules that have failed (i.e. unhandled exceptions in serve())
168 void get_health_checks(health_check_map_t
*checks
);
170 void get_progress_events(map
<std::string
,ProgressEvent
> *events
) {
171 if (active_modules
) {
172 active_modules
->get_progress_events(events
);
176 // FIXME: breaking interface so that I don't have to go rewrite all
177 // the places that call into these (for now)
179 void notify_all(const std::string
¬ify_type
,
180 const std::string
¬ify_id
)
182 if (active_modules
) {
183 active_modules
->notify_all(notify_type
, notify_id
);
187 void notify_all(const LogEntry
&log_entry
)
189 if (active_modules
) {
190 active_modules
->notify_all(log_entry
);
194 std::map
<std::string
, std::string
> get_services() const
196 ceph_assert(active_modules
);
197 return active_modules
->get_services();
200 void register_client(std::string_view name
, entity_addrvec_t addrs
)
202 clients
.emplace(std::string(name
), std::move(addrs
));
204 void unregister_client(std::string_view name
, const entity_addrvec_t
& addrs
)
206 auto itp
= clients
.equal_range(std::string(name
));
207 for (auto it
= itp
.first
; it
!= itp
.second
; ++it
) {
208 if (it
->second
== addrs
) {
215 auto get_clients() const
217 std::scoped_lock
l(lock
);
218 std::vector
<entity_addrvec_t
> v
;
219 for (const auto& p
: clients
) {
220 v
.push_back(p
.second
);
225 // <<< (end of ActivePyModules cheeky call-throughs)