]>
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 | ||
29 | std::string handle_pyerror(); | |
30 | ||
31 | std::string peek_pyerror(); | |
32 | ||
33 | /** | |
34 | * A Ceph CLI command description provided from a Python module | |
35 | */ | |
36 | class ModuleCommand { | |
37 | public: | |
38 | std::string cmdstring; | |
39 | std::string helpstring; | |
40 | std::string perm; | |
41 | bool polling; | |
42 | ||
43 | // Call the ActivePyModule of this name to handle the command | |
44 | std::string module_name; | |
45 | }; | |
46 | ||
47 | class PyModule | |
48 | { | |
9f95a23c | 49 | mutable ceph::mutex lock = ceph::make_mutex("PyModule::lock"); |
11fdf7f2 TL |
50 | private: |
51 | const std::string module_name; | |
52 | std::string get_site_packages(); | |
53 | int load_subclass_of(const char* class_name, PyObject** py_class); | |
54 | ||
55 | // Did the MgrMap identify this module as one that should run? | |
56 | bool enabled = false; | |
57 | ||
58 | // Did the MgrMap flag this module as always on? | |
59 | bool always_on = false; | |
60 | ||
61 | // Did we successfully import this python module and look up symbols? | |
62 | // (i.e. is it possible to instantiate a MgrModule subclass instance?) | |
63 | bool loaded = false; | |
64 | ||
65 | // Did the module identify itself as being able to run? | |
66 | // (i.e. should we expect instantiating and calling serve() to work?) | |
67 | bool can_run = false; | |
68 | ||
69 | // Did the module encounter an unexpected error while running? | |
70 | // (e.g. throwing an exception from serve()) | |
71 | bool failed = false; | |
72 | ||
73 | // Populated if loaded, can_run or failed indicates a problem | |
74 | std::string error_string; | |
75 | ||
76 | // Helper for loading MODULE_OPTIONS and COMMANDS members | |
77 | int walk_dict_list( | |
78 | const std::string &attr_name, | |
79 | std::function<int(PyObject*)> fn); | |
80 | ||
81 | int load_commands(); | |
82 | std::vector<ModuleCommand> commands; | |
83 | ||
9f95a23c | 84 | int register_options(PyObject *cls); |
11fdf7f2 TL |
85 | int load_options(); |
86 | std::map<std::string, MgrMap::ModuleOption> options; | |
87 | ||
88 | public: | |
89 | static std::string config_prefix; | |
90 | ||
91 | SafeThreadState pMyThreadState; | |
92 | PyObject *pClass = nullptr; | |
93 | PyObject *pStandbyClass = nullptr; | |
94 | ||
95 | explicit PyModule(const std::string &module_name_) | |
96 | : module_name(module_name_) | |
97 | { | |
98 | } | |
99 | ||
100 | ~PyModule(); | |
101 | ||
102 | bool is_option(const std::string &option_name); | |
103 | const std::map<std::string,MgrMap::ModuleOption>& get_options() const { | |
104 | return options; | |
105 | } | |
106 | ||
107 | PyObject *get_typed_option_value( | |
108 | const std::string& option, | |
109 | const std::string& value); | |
110 | ||
111 | int load(PyThreadState *pMainThreadState); | |
112 | #if PY_MAJOR_VERSION >= 3 | |
113 | static PyObject* init_ceph_logger(); | |
114 | static PyObject* init_ceph_module(); | |
115 | #else | |
116 | static void init_ceph_logger(); | |
117 | static void init_ceph_module(); | |
118 | #endif | |
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 | ||
160 | const std::string &get_name() const { | |
161 | std::lock_guard l(lock) ; return module_name; | |
162 | } | |
163 | const std::string &get_error_string() const { | |
164 | std::lock_guard l(lock) ; return error_string; | |
165 | } | |
166 | bool get_can_run() const { | |
167 | std::lock_guard l(lock) ; return can_run; | |
168 | } | |
169 | }; | |
170 | ||
171 | typedef std::shared_ptr<PyModule> PyModuleRef; | |
172 | ||
173 | class PyModuleConfig { | |
174 | public: | |
9f95a23c | 175 | mutable ceph::mutex lock = ceph::make_mutex("PyModuleConfig::lock"); |
11fdf7f2 TL |
176 | std::map<std::string, std::string> config; |
177 | ||
178 | PyModuleConfig(); | |
179 | ||
180 | PyModuleConfig(PyModuleConfig &mconfig); | |
181 | ||
182 | ~PyModuleConfig(); | |
183 | ||
184 | void set_config( | |
185 | MonClient *monc, | |
186 | const std::string &module_name, | |
187 | const std::string &key, const boost::optional<std::string>& val); | |
188 | ||
189 | }; |