]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 | #pragma once | |
15 | ||
16 | #include <map> | |
17 | #include <memory> | |
18 | #include <string> | |
19 | #include <vector> | |
20 | #include <boost/optional.hpp> | |
9f95a23c | 21 | #include "common/ceph_mutex.h" |
11fdf7f2 TL |
22 | #include "Python.h" |
23 | #include "Gil.h" | |
24 | #include "mon/MgrMap.h" | |
25 | ||
26 | ||
27 | class MonClient; | |
28 | ||
20effc67 TL |
29 | std::string handle_pyerror(bool generate_crash_dump = false, |
30 | std::string module = {}, | |
31 | std::string caller = {}); | |
11fdf7f2 TL |
32 | |
33 | std::string peek_pyerror(); | |
34 | ||
35 | /** | |
36 | * A Ceph CLI command description provided from a Python module | |
37 | */ | |
38 | class ModuleCommand { | |
39 | public: | |
40 | std::string cmdstring; | |
41 | std::string helpstring; | |
42 | std::string perm; | |
43 | bool polling; | |
44 | ||
45 | // Call the ActivePyModule of this name to handle the command | |
46 | std::string module_name; | |
47 | }; | |
48 | ||
49 | class PyModule | |
50 | { | |
9f95a23c | 51 | mutable ceph::mutex lock = ceph::make_mutex("PyModule::lock"); |
11fdf7f2 TL |
52 | private: |
53 | const std::string module_name; | |
54 | std::string get_site_packages(); | |
55 | int load_subclass_of(const char* class_name, PyObject** py_class); | |
56 | ||
57 | // Did the MgrMap identify this module as one that should run? | |
58 | bool enabled = false; | |
59 | ||
60 | // Did the MgrMap flag this module as always on? | |
61 | bool always_on = false; | |
62 | ||
63 | // Did we successfully import this python module and look up symbols? | |
64 | // (i.e. is it possible to instantiate a MgrModule subclass instance?) | |
65 | bool loaded = false; | |
66 | ||
67 | // Did the module identify itself as being able to run? | |
68 | // (i.e. should we expect instantiating and calling serve() to work?) | |
69 | bool can_run = false; | |
70 | ||
71 | // Did the module encounter an unexpected error while running? | |
72 | // (e.g. throwing an exception from serve()) | |
73 | bool failed = false; | |
74 | ||
75 | // Populated if loaded, can_run or failed indicates a problem | |
76 | std::string error_string; | |
77 | ||
78 | // Helper for loading MODULE_OPTIONS and COMMANDS members | |
79 | int walk_dict_list( | |
80 | const std::string &attr_name, | |
81 | std::function<int(PyObject*)> fn); | |
82 | ||
83 | int load_commands(); | |
84 | std::vector<ModuleCommand> commands; | |
85 | ||
9f95a23c | 86 | int register_options(PyObject *cls); |
11fdf7f2 TL |
87 | int load_options(); |
88 | std::map<std::string, MgrMap::ModuleOption> options; | |
89 | ||
20effc67 TL |
90 | int load_notify_types(); |
91 | std::set<std::string> notify_types; | |
92 | ||
11fdf7f2 | 93 | public: |
f67539c2 | 94 | static std::string mgr_store_prefix; |
11fdf7f2 TL |
95 | |
96 | SafeThreadState pMyThreadState; | |
97 | PyObject *pClass = nullptr; | |
98 | PyObject *pStandbyClass = nullptr; | |
99 | ||
100 | explicit PyModule(const std::string &module_name_) | |
101 | : module_name(module_name_) | |
102 | { | |
103 | } | |
104 | ||
105 | ~PyModule(); | |
106 | ||
107 | bool is_option(const std::string &option_name); | |
108 | const std::map<std::string,MgrMap::ModuleOption>& get_options() const { | |
109 | return options; | |
110 | } | |
111 | ||
112 | PyObject *get_typed_option_value( | |
113 | const std::string& option, | |
114 | const std::string& value); | |
115 | ||
116 | int load(PyThreadState *pMainThreadState); | |
11fdf7f2 TL |
117 | static PyObject* init_ceph_logger(); |
118 | static PyObject* init_ceph_module(); | |
11fdf7f2 TL |
119 | |
120 | void set_enabled(const bool enabled_) | |
121 | { | |
122 | enabled = enabled_; | |
123 | } | |
124 | ||
125 | void set_always_on(const bool always_on_) { | |
126 | always_on = always_on_; | |
127 | } | |
128 | ||
129 | /** | |
130 | * Extend `out` with the contents of `this->commands` | |
131 | */ | |
132 | void get_commands(std::vector<ModuleCommand> *out) const | |
133 | { | |
134 | std::lock_guard l(lock); | |
135 | ceph_assert(out != nullptr); | |
136 | out->insert(out->end(), commands.begin(), commands.end()); | |
137 | } | |
138 | ||
139 | ||
140 | /** | |
141 | * Mark the module as failed, recording the reason in the error | |
142 | * string. | |
143 | */ | |
144 | void fail(const std::string &reason) | |
145 | { | |
146 | std::lock_guard l(lock); | |
147 | failed = true; | |
148 | error_string = reason; | |
149 | } | |
150 | ||
151 | bool is_enabled() const { | |
152 | std::lock_guard l(lock); | |
153 | return enabled || always_on; | |
154 | } | |
155 | ||
156 | bool is_failed() const { std::lock_guard l(lock) ; return failed; } | |
157 | bool is_loaded() const { std::lock_guard l(lock) ; return loaded; } | |
158 | bool is_always_on() const { std::lock_guard l(lock) ; return always_on; } | |
159 | ||
20effc67 TL |
160 | bool should_notify(const std::string& notify_type) const { |
161 | return notify_types.count(notify_type); | |
162 | } | |
163 | ||
11fdf7f2 TL |
164 | const std::string &get_name() const { |
165 | std::lock_guard l(lock) ; return module_name; | |
166 | } | |
167 | const std::string &get_error_string() const { | |
168 | std::lock_guard l(lock) ; return error_string; | |
169 | } | |
170 | bool get_can_run() const { | |
171 | std::lock_guard l(lock) ; return can_run; | |
172 | } | |
173 | }; | |
174 | ||
175 | typedef std::shared_ptr<PyModule> PyModuleRef; | |
176 | ||
177 | class PyModuleConfig { | |
178 | public: | |
9f95a23c | 179 | mutable ceph::mutex lock = ceph::make_mutex("PyModuleConfig::lock"); |
11fdf7f2 TL |
180 | std::map<std::string, std::string> config; |
181 | ||
182 | PyModuleConfig(); | |
183 | ||
184 | PyModuleConfig(PyModuleConfig &mconfig); | |
185 | ||
186 | ~PyModuleConfig(); | |
187 | ||
20effc67 | 188 | std::pair<int, std::string> set_config( |
11fdf7f2 TL |
189 | MonClient *monc, |
190 | const std::string &module_name, | |
20effc67 | 191 | const std::string &key, const std::optional<std::string>& val); |
11fdf7f2 TL |
192 | |
193 | }; |