]> git.proxmox.com Git - ceph.git/blame - ceph/src/mgr/PyState.cc
bump version to 12.0.3-pve3
[ceph.git] / ceph / src / mgr / PyState.cc
CommitLineData
7c673cae
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) 2016 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 * The interface we present to python code that runs within
16 * ceph-mgr.
17 */
18
19#include "Mgr.h"
20
21#include "mon/MonClient.h"
22#include "common/version.h"
23
24#include "PyState.h"
25
26#define dout_context g_ceph_context
27
28PyModules *global_handle = NULL;
29
30
31class MonCommandCompletion : public Context
32{
33 PyObject *python_completion;
34 const std::string tag;
35
36public:
37 std::string outs;
38 bufferlist outbl;
39
40 MonCommandCompletion(PyObject* ev, const std::string &tag_)
41 : python_completion(ev), tag(tag_)
42 {
43 assert(python_completion != nullptr);
44 Py_INCREF(python_completion);
45 }
46
47 ~MonCommandCompletion() override
48 {
49 Py_DECREF(python_completion);
50 }
51
52 void finish(int r) override
53 {
54 PyGILState_STATE gstate;
55 gstate = PyGILState_Ensure();
56
57 auto set_fn = PyObject_GetAttrString(python_completion, "complete");
58 assert(set_fn != nullptr);
59
60 auto pyR = PyInt_FromLong(r);
61 auto pyOutBl = PyString_FromString(outbl.to_str().c_str());
62 auto pyOutS = PyString_FromString(outs.c_str());
63 auto args = PyTuple_Pack(3, pyR, pyOutBl, pyOutS);
64 Py_DECREF(pyR);
65 Py_DECREF(pyOutBl);
66 Py_DECREF(pyOutS);
67
68 auto rtn = PyObject_CallObject(set_fn, args);
69 if (rtn != nullptr) {
70 Py_DECREF(rtn);
71 }
72 Py_DECREF(args);
73
74 PyGILState_Release(gstate);
75
76 global_handle->notify_all("command", tag);
77 }
78};
79
80
81static PyObject*
82ceph_send_command(PyObject *self, PyObject *args)
83{
84 char *handle = nullptr;
85
86 // Like mon, osd, mds
87 char *type = nullptr;
88
89 // Like "23" for an OSD or "myid" for an MDS
90 char *name = nullptr;
91
92 char *cmd_json = nullptr;
93 char *tag = nullptr;
94 PyObject *completion = nullptr;
95 if (!PyArg_ParseTuple(args, "sOssss:ceph_send_command",
96 &handle, &completion, &type, &name, &cmd_json, &tag)) {
97 return nullptr;
98 }
99
100 auto set_fn = PyObject_GetAttrString(completion, "complete");
101 if (set_fn == nullptr) {
102 ceph_abort(); // TODO raise python exception instead
103 } else {
104 assert(PyCallable_Check(set_fn));
105 }
106 Py_DECREF(set_fn);
107
108 auto c = new MonCommandCompletion(completion, tag);
109 if (std::string(type) == "mon") {
110 global_handle->get_monc().start_mon_command(
111 {cmd_json},
112 {},
113 &c->outbl,
114 &c->outs,
115 c);
116 } else if (std::string(type) == "osd") {
117 std::string err;
118 uint64_t osd_id = strict_strtoll(name, 10, &err);
119 if (!err.empty()) {
120 // TODO: raise exception
121 return nullptr;
122 }
123
124 ceph_tid_t tid;
125 global_handle->get_objecter().osd_command(
126 osd_id,
127 {cmd_json},
128 {},
129 &tid,
130 &c->outbl,
131 &c->outs,
132 c);
133 } else if (std::string(type) == "mds") {
134 int r = global_handle->get_client().mds_command(
135 name,
136 {cmd_json},
137 {},
138 &c->outbl,
139 &c->outs,
140 c);
141 if (r != 0) {
142 // TODO: raise exception
143 return nullptr;
144 }
145 } else if (std::string(type) == "pg") {
146 // TODO: expose objecter::pg_command
147 return nullptr;
148 } else {
149 // TODO: raise exception
150 return nullptr;
151 }
152
153 Py_RETURN_NONE;
154}
155
156
157static PyObject*
158ceph_state_get(PyObject *self, PyObject *args)
159{
160 char *handle = nullptr;
161 char *what = NULL;
162 if (!PyArg_ParseTuple(args, "ss:ceph_state_get", &handle, &what)) {
163 return NULL;
164 }
165
166 return global_handle->get_python(what);
167}
168
169
170static PyObject*
171ceph_get_server(PyObject *self, PyObject *args)
172{
173 char *handle = nullptr;
174 char *hostname = NULL;
175 if (!PyArg_ParseTuple(args, "sz:ceph_get_server", &handle, &hostname)) {
176 return NULL;
177 }
178
179 if (hostname) {
180 return global_handle->get_server_python(hostname);
181 } else {
182 return global_handle->list_servers_python();
183 }
184}
185
186static PyObject*
187ceph_config_get(PyObject *self, PyObject *args)
188{
189 char *handle = nullptr;
190 char *what = nullptr;
191 if (!PyArg_ParseTuple(args, "ss:ceph_config_get", &handle, &what)) {
192 derr << "Invalid args!" << dendl;
193 return nullptr;
194 }
195
196 std::string value;
197 bool found = global_handle->get_config(handle, what, &value);
198 if (found) {
199 derr << "Found" << dendl;
200 return PyString_FromString(value.c_str());
201 } else {
202 derr << "Not found" << dendl;
203 Py_RETURN_NONE;
204 }
205}
206
207static PyObject*
208ceph_config_set(PyObject *self, PyObject *args)
209{
210 char *handle = nullptr;
211 char *key = nullptr;
212 char *value = nullptr;
213 if (!PyArg_ParseTuple(args, "sss:ceph_config_set", &handle, &key, &value)) {
214 return nullptr;
215 }
216
217 global_handle->set_config(handle, key, value);
218
219 Py_RETURN_NONE;
220}
221
222static entity_type_t svc_type_from_str(const std::string &type_str)
223{
224 if (type_str == std::string("mds")) {
225 return CEPH_ENTITY_TYPE_MDS;
226 } else if (type_str == std::string("osd")) {
227 return CEPH_ENTITY_TYPE_OSD;
228 } else if (type_str == std::string("mon")) {
229 return CEPH_ENTITY_TYPE_MON;
230 } else {
231 return CEPH_ENTITY_TYPE_ANY;
232 }
233}
234
235static PyObject*
236get_metadata(PyObject *self, PyObject *args)
237{
238 char *handle = nullptr;
239 char *type_str = NULL;
240 char *svc_id = NULL;
241 if (!PyArg_ParseTuple(args, "sss:get_metadata", &handle, &type_str, &svc_id)) {
242 return nullptr;
243 }
244
245 entity_type_t svc_type = svc_type_from_str(type_str);
246 if (svc_type == CEPH_ENTITY_TYPE_ANY) {
247 // FIXME: form a proper exception
248 return nullptr;
249 }
250
251
252 return global_handle->get_metadata_python(handle, svc_type, svc_id);
253}
254
255static PyObject*
256ceph_log(PyObject *self, PyObject *args)
257{
258 int level = 0;
259 char *record = nullptr;
260 char *handle = nullptr;
261 if (!PyArg_ParseTuple(args, "sis:log", &handle, &level, &record)) {
262 return nullptr;
263 }
264
265 global_handle->log(handle, level, record);
266
267 Py_RETURN_NONE;
268}
269
270static PyObject *
271ceph_get_version(PyObject *self, PyObject *args)
272{
273 return PyString_FromString(pretty_version_to_str().c_str());
274}
275
276static PyObject *
277ceph_get_context(PyObject *self, PyObject *args)
278{
279 return global_handle->get_context();
280}
281
282static PyObject*
283get_counter(PyObject *self, PyObject *args)
284{
285 char *handle = nullptr;
286 char *type_str = nullptr;
287 char *svc_id = nullptr;
288 char *counter_path = nullptr;
289 if (!PyArg_ParseTuple(args, "ssss:get_counter", &handle, &type_str,
290 &svc_id, &counter_path)) {
291 return nullptr;
292 }
293
294 entity_type_t svc_type = svc_type_from_str(type_str);
295 if (svc_type == CEPH_ENTITY_TYPE_ANY) {
296 // FIXME: form a proper exception
297 return nullptr;
298 }
299
300 return global_handle->get_counter_python(
301 handle, svc_type, svc_id, counter_path);
302}
303
304PyMethodDef CephStateMethods[] = {
305 {"get", ceph_state_get, METH_VARARGS,
306 "Get a cluster object"},
307 {"get_server", ceph_get_server, METH_VARARGS,
308 "Get a server object"},
309 {"get_metadata", get_metadata, METH_VARARGS,
310 "Get a service's metadata"},
311 {"send_command", ceph_send_command, METH_VARARGS,
312 "Send a mon command"},
313 {"get_config", ceph_config_get, METH_VARARGS,
314 "Get a configuration value"},
315 {"set_config", ceph_config_set, METH_VARARGS,
316 "Set a configuration value"},
317 {"get_counter", get_counter, METH_VARARGS,
318 "Get a performance counter"},
319 {"log", ceph_log, METH_VARARGS,
320 "Emit a (local) log message"},
321 {"get_version", ceph_get_version, METH_VARARGS,
322 "Get the ceph version of this process"},
323 {"get_context", ceph_get_context, METH_NOARGS,
324 "Get a CephContext* in a python capsule"},
325 {NULL, NULL, 0, NULL}
326};
327