]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | import ceph_state #noqa | |
3 | import json | |
4 | import logging | |
5 | import threading | |
6 | ||
7 | ||
8 | class CommandResult(object): | |
9 | """ | |
10 | Use with MgrModule.send_command | |
11 | """ | |
12 | def __init__(self, tag): | |
13 | self.ev = threading.Event() | |
14 | self.outs = "" | |
15 | self.outb = "" | |
16 | self.r = 0 | |
17 | ||
18 | # This is just a convenience for notifications from | |
19 | # C++ land, to avoid passing addresses around in messages. | |
20 | self.tag = tag | |
21 | ||
22 | def complete(self, r, outb, outs): | |
23 | self.r = r | |
24 | self.outb = outb | |
25 | self.outs = outs | |
26 | self.ev.set() | |
27 | ||
28 | def wait(self): | |
29 | self.ev.wait() | |
30 | return self.r, self.outb, self.outs | |
31 | ||
32 | ||
33 | class MgrModule(object): | |
34 | COMMANDS = [] | |
35 | ||
36 | def __init__(self, handle): | |
37 | self._handle = handle | |
38 | self._logger = logging.getLogger(handle) | |
39 | ||
40 | # Don't filter any logs at the python level, leave it to C++ | |
41 | self._logger.setLevel(logging.DEBUG) | |
42 | ||
43 | # FIXME: we should learn the log level from C++ land, and then | |
44 | # avoid calling ceph_state.log when we know a message is of | |
45 | # an insufficient level to be ultimately output | |
46 | ||
47 | class CPlusPlusHandler(logging.Handler): | |
48 | def emit(self, record): | |
49 | if record.levelno <= logging.DEBUG: | |
50 | ceph_level = 20 | |
51 | elif record.levelno <= logging.INFO: | |
52 | ceph_level = 4 | |
53 | elif record.levelno <= logging.WARNING: | |
54 | ceph_level = 1 | |
55 | else: | |
56 | ceph_level = 0 | |
57 | ||
58 | ceph_state.log(handle, ceph_level, self.format(record)) | |
59 | ||
60 | self._logger.addHandler(CPlusPlusHandler()) | |
61 | ||
62 | self._version = ceph_state.get_version() | |
63 | ||
64 | @property | |
65 | def log(self): | |
66 | return self._logger | |
67 | ||
68 | @property | |
69 | def version(self): | |
70 | return self._version | |
71 | ||
72 | def notify(self, notify_type, notify_id): | |
73 | """ | |
74 | Called by the ceph-mgr service to notify the Python plugin | |
75 | that new state is available. | |
76 | """ | |
77 | pass | |
78 | ||
79 | def serve(self): | |
80 | """ | |
81 | Called by the ceph-mgr service to start any server that | |
82 | is provided by this Python plugin. The implementation | |
83 | of this function should block until ``shutdown`` is called. | |
84 | ||
85 | You *must* implement ``shutdown`` if you implement ``serve`` | |
86 | """ | |
87 | pass | |
88 | ||
89 | def shutdown(self): | |
90 | """ | |
91 | Called by the ceph-mgr service to request that this | |
92 | module drop out of its serve() function. You do not | |
93 | need to implement this if you do not implement serve() | |
94 | ||
95 | :return: None | |
96 | """ | |
97 | pass | |
98 | ||
99 | def get(self, data_name): | |
100 | """ | |
101 | Called by the plugin to load some cluster state from ceph-mgr | |
102 | """ | |
103 | return ceph_state.get(self._handle, data_name) | |
104 | ||
105 | def get_server(self, hostname): | |
106 | """ | |
107 | Called by the plugin to load information about a particular | |
108 | node from ceph-mgr. | |
109 | ||
110 | :param hostname: a hostame | |
111 | """ | |
112 | return ceph_state.get_server(self._handle, hostname) | |
113 | ||
114 | def get_counter(self, svc_type, svc_name, path): | |
115 | """ | |
116 | Called by the plugin to fetch data for a particular perf counter | |
117 | on a particular service. | |
118 | ||
119 | :param svc_type: | |
120 | :param svc_name: | |
121 | :param path: | |
122 | :return: A list of two-element lists containing time and value | |
123 | """ | |
124 | return ceph_state.get_counter(self._handle, svc_type, svc_name, path) | |
125 | ||
126 | def list_servers(self): | |
127 | """ | |
128 | Like ``get_server``, but instead of returning information | |
129 | about just one node, return all the nodes in an array. | |
130 | """ | |
131 | return ceph_state.get_server(self._handle, None) | |
132 | ||
133 | def get_metadata(self, svc_type, svc_id): | |
134 | """ | |
135 | Fetch the metadata for a particular service. | |
136 | ||
224ce89b | 137 | :param svc_type: string (e.g., 'mds', 'osd', 'mon') |
7c673cae FG |
138 | :param svc_id: string |
139 | :return: dict | |
140 | """ | |
141 | return ceph_state.get_metadata(self._handle, svc_type, svc_id) | |
142 | ||
224ce89b WB |
143 | def get_daemon_status(self, svc_type, svc_id): |
144 | """ | |
145 | Fetch the latest status for a particular service daemon. | |
146 | ||
147 | :param svc_type: string (e.g., 'rgw') | |
148 | :param svc_id: string | |
149 | :return: dict | |
150 | """ | |
151 | return ceph_state.get_daemon_status(self._handle, svc_type, svc_id) | |
152 | ||
7c673cae FG |
153 | def send_command(self, *args, **kwargs): |
154 | """ | |
155 | Called by the plugin to send a command to the mon | |
156 | cluster. | |
157 | """ | |
158 | ceph_state.send_command(self._handle, *args, **kwargs) | |
159 | ||
160 | def handle_command(self, cmd): | |
161 | """ | |
162 | Called by ceph-mgr to request the plugin to handle one | |
163 | of the commands that it declared in self.COMMANDS | |
164 | ||
165 | Return a status code, an output buffer, and an | |
166 | output string. The output buffer is for data results, | |
167 | the output string is for informative text. | |
168 | ||
169 | :param cmd: dict, from Ceph's cmdmap_t | |
170 | ||
171 | :return: 3-tuple of (int, str, str) | |
172 | """ | |
173 | ||
174 | # Should never get called if they didn't declare | |
175 | # any ``COMMANDS`` | |
176 | raise NotImplementedError() | |
177 | ||
31f18b77 FG |
178 | def get_mgr_id(self): |
179 | """ | |
180 | Retrieve the mgr id. | |
181 | ||
182 | :return: str | |
183 | """ | |
184 | return ceph_state.get_mgr_id() | |
185 | ||
7c673cae FG |
186 | def get_config(self, key): |
187 | """ | |
188 | Retrieve the value of a persistent configuration setting | |
189 | ||
190 | :param key: str | |
191 | :return: str | |
192 | """ | |
193 | return ceph_state.get_config(self._handle, key) | |
194 | ||
31f18b77 FG |
195 | def get_config_prefix(self, key_prefix): |
196 | """ | |
197 | Retrieve a dict of config values with the given prefix | |
198 | ||
199 | :param key_prefix: str | |
200 | :return: str | |
201 | """ | |
202 | return ceph_state.get_config_prefix(self._handle, key_prefix) | |
203 | ||
224ce89b WB |
204 | def get_localized_config(self, key, default=None): |
205 | """ | |
206 | Retrieve localized configuration for this ceph-mgr instance | |
207 | :param key: str | |
208 | :param default: str | |
209 | :return: str | |
210 | """ | |
211 | r = self.get_config(self.get_mgr_id() + '/' + key) | |
212 | if r is None: | |
213 | r = self.get_config(key) | |
214 | ||
215 | if r is None: | |
216 | r = default | |
217 | return r | |
218 | ||
7c673cae FG |
219 | def set_config(self, key, val): |
220 | """ | |
221 | Set the value of a persistent configuration setting | |
222 | ||
223 | :param key: str | |
224 | :param val: str | |
225 | """ | |
226 | ceph_state.set_config(self._handle, key, val) | |
227 | ||
224ce89b WB |
228 | def set_localized_config(self, key, val): |
229 | """ | |
230 | Set localized configuration for this ceph-mgr instance | |
231 | :param key: str | |
232 | :param default: str | |
233 | :return: str | |
234 | """ | |
235 | return self.set_config(self.get_mgr_id() + '/' + key, val) | |
236 | ||
7c673cae FG |
237 | def set_config_json(self, key, val): |
238 | """ | |
239 | Helper for setting json-serialized-config | |
240 | ||
241 | :param key: str | |
242 | :param val: json-serializable object | |
243 | """ | |
244 | self.set_config(key, json.dumps(val)) | |
245 | ||
246 | def get_config_json(self, key): | |
247 | """ | |
248 | Helper for getting json-serialized config | |
249 | ||
250 | :param key: str | |
251 | :return: object | |
252 | """ | |
253 | raw = self.get_config(key) | |
254 | if raw is None: | |
255 | return None | |
256 | else: | |
257 | return json.loads(raw) | |
224ce89b WB |
258 | |
259 | def self_test(self): | |
260 | """ | |
261 | Run a self-test on the module. Override this function and implement | |
262 | a best as possible self-test for (automated) testing of the module | |
263 | :return: bool | |
264 | """ | |
265 | pass |