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) 2016 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.
15 * The interface we present to python code that runs within
21 #include "mon/MonClient.h"
22 #include "common/version.h"
26 #define dout_context g_ceph_context
28 PyModules
*global_handle
= NULL
;
31 class MonCommandCompletion
: public Context
33 PyObject
*python_completion
;
34 const std::string tag
;
40 MonCommandCompletion(PyObject
* ev
, const std::string
&tag_
)
41 : python_completion(ev
), tag(tag_
)
43 assert(python_completion
!= nullptr);
44 Py_INCREF(python_completion
);
47 ~MonCommandCompletion() override
49 Py_DECREF(python_completion
);
52 void finish(int r
) override
54 PyGILState_STATE gstate
;
55 gstate
= PyGILState_Ensure();
57 auto set_fn
= PyObject_GetAttrString(python_completion
, "complete");
58 assert(set_fn
!= nullptr);
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
);
68 auto rtn
= PyObject_CallObject(set_fn
, args
);
74 PyGILState_Release(gstate
);
76 global_handle
->notify_all("command", tag
);
82 ceph_send_command(PyObject
*self
, PyObject
*args
)
84 char *handle
= nullptr;
89 // Like "23" for an OSD or "myid" for an MDS
92 char *cmd_json
= nullptr;
94 PyObject
*completion
= nullptr;
95 if (!PyArg_ParseTuple(args
, "sOssss:ceph_send_command",
96 &handle
, &completion
, &type
, &name
, &cmd_json
, &tag
)) {
100 auto set_fn
= PyObject_GetAttrString(completion
, "complete");
101 if (set_fn
== nullptr) {
102 ceph_abort(); // TODO raise python exception instead
104 assert(PyCallable_Check(set_fn
));
108 auto c
= new MonCommandCompletion(completion
, tag
);
109 if (std::string(type
) == "mon") {
110 global_handle
->get_monc().start_mon_command(
116 } else if (std::string(type
) == "osd") {
118 uint64_t osd_id
= strict_strtoll(name
, 10, &err
);
120 // TODO: raise exception
125 global_handle
->get_objecter().osd_command(
133 } else if (std::string(type
) == "mds") {
134 int r
= global_handle
->get_client().mds_command(
142 // TODO: raise exception
145 } else if (std::string(type
) == "pg") {
146 // TODO: expose objecter::pg_command
149 // TODO: raise exception
158 ceph_state_get(PyObject
*self
, PyObject
*args
)
160 char *handle
= nullptr;
162 if (!PyArg_ParseTuple(args
, "ss:ceph_state_get", &handle
, &what
)) {
166 return global_handle
->get_python(what
);
171 ceph_get_server(PyObject
*self
, PyObject
*args
)
173 char *handle
= nullptr;
174 char *hostname
= NULL
;
175 if (!PyArg_ParseTuple(args
, "sz:ceph_get_server", &handle
, &hostname
)) {
180 return global_handle
->get_server_python(hostname
);
182 return global_handle
->list_servers_python();
187 ceph_config_get(PyObject
*self
, PyObject
*args
)
189 char *handle
= nullptr;
190 char *what
= nullptr;
191 if (!PyArg_ParseTuple(args
, "ss:ceph_config_get", &handle
, &what
)) {
192 derr
<< "Invalid args!" << dendl
;
197 bool found
= global_handle
->get_config(handle
, what
, &value
);
199 derr
<< "Found" << dendl
;
200 return PyString_FromString(value
.c_str());
202 derr
<< "Not found" << dendl
;
208 ceph_config_set(PyObject
*self
, PyObject
*args
)
210 char *handle
= nullptr;
212 char *value
= nullptr;
213 if (!PyArg_ParseTuple(args
, "sss:ceph_config_set", &handle
, &key
, &value
)) {
217 global_handle
->set_config(handle
, key
, value
);
222 static entity_type_t
svc_type_from_str(const std::string
&type_str
)
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
;
231 return CEPH_ENTITY_TYPE_ANY
;
236 get_metadata(PyObject
*self
, PyObject
*args
)
238 char *handle
= nullptr;
239 char *type_str
= NULL
;
241 if (!PyArg_ParseTuple(args
, "sss:get_metadata", &handle
, &type_str
, &svc_id
)) {
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
252 return global_handle
->get_metadata_python(handle
, svc_type
, svc_id
);
256 ceph_log(PyObject
*self
, PyObject
*args
)
259 char *record
= nullptr;
260 char *handle
= nullptr;
261 if (!PyArg_ParseTuple(args
, "sis:log", &handle
, &level
, &record
)) {
265 global_handle
->log(handle
, level
, record
);
271 ceph_get_version(PyObject
*self
, PyObject
*args
)
273 return PyString_FromString(pretty_version_to_str().c_str());
277 ceph_get_context(PyObject
*self
, PyObject
*args
)
279 return global_handle
->get_context();
283 get_counter(PyObject
*self
, PyObject
*args
)
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
)) {
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
300 return global_handle
->get_counter_python(
301 handle
, svc_type
, svc_id
, counter_path
);
304 PyMethodDef 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
}