]>
Commit | Line | Data |
---|---|---|
3efd9988 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 | #include "BaseMgrStandbyModule.h" | |
16 | ||
17 | #include "StandbyPyModules.h" | |
b3b6e05e | 18 | #include "PyFormatter.h" |
3efd9988 FG |
19 | |
20 | ||
21 | #define dout_context g_ceph_context | |
22 | #define dout_subsys ceph_subsys_mgr | |
23 | ||
20effc67 TL |
24 | using std::string; |
25 | ||
3efd9988 FG |
26 | typedef struct { |
27 | PyObject_HEAD | |
28 | StandbyPyModule *this_module; | |
29 | } BaseMgrStandbyModule; | |
30 | ||
31 | static PyObject * | |
32 | BaseMgrStandbyModule_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
33 | { | |
34 | BaseMgrStandbyModule *self; | |
35 | ||
36 | self = (BaseMgrStandbyModule *)type->tp_alloc(type, 0); | |
37 | ||
38 | return (PyObject *)self; | |
39 | } | |
40 | ||
41 | static int | |
42 | BaseMgrStandbyModule_init(BaseMgrStandbyModule *self, PyObject *args, PyObject *kwds) | |
43 | { | |
44 | PyObject *this_module_capsule = nullptr; | |
45 | static const char *kwlist[] = {"this_module", NULL}; | |
46 | ||
47 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
48 | const_cast<char**>(kwlist), | |
49 | &this_module_capsule)) { | |
50 | return -1; | |
51 | } | |
52 | ||
11fdf7f2 TL |
53 | self->this_module = static_cast<StandbyPyModule*>(PyCapsule_GetPointer( |
54 | this_module_capsule, nullptr)); | |
55 | ceph_assert(self->this_module); | |
3efd9988 FG |
56 | |
57 | return 0; | |
58 | } | |
59 | ||
60 | static PyObject* | |
61 | ceph_get_mgr_id(BaseMgrStandbyModule *self, PyObject *args) | |
62 | { | |
9f95a23c | 63 | return PyUnicode_FromString(g_conf()->name.get_id().c_str()); |
3efd9988 FG |
64 | } |
65 | ||
66 | static PyObject* | |
11fdf7f2 | 67 | ceph_get_module_option(BaseMgrStandbyModule *self, PyObject *args) |
3efd9988 FG |
68 | { |
69 | char *what = nullptr; | |
11fdf7f2 TL |
70 | char *prefix = nullptr; |
71 | if (!PyArg_ParseTuple(args, "s|s:ceph_get_module_option", &what, &prefix)) { | |
72 | derr << "Invalid args!" << dendl; | |
73 | return nullptr; | |
74 | } | |
eafe8130 | 75 | PyThreadState *tstate = PyEval_SaveThread(); |
11fdf7f2 TL |
76 | std::string final_key; |
77 | std::string value; | |
78 | bool found = false; | |
79 | if (prefix) { | |
80 | final_key = std::string(prefix) + "/" + what; | |
81 | found = self->this_module->get_config(final_key, &value); | |
82 | } | |
83 | if (!found) { | |
84 | final_key = what; | |
85 | found = self->this_module->get_config(final_key, &value); | |
86 | } | |
eafe8130 | 87 | PyEval_RestoreThread(tstate); |
11fdf7f2 TL |
88 | if (found) { |
89 | dout(10) << __func__ << " " << final_key << " found: " << value | |
90 | << dendl; | |
91 | return self->this_module->py_module->get_typed_option_value(what, value); | |
92 | } else { | |
93 | if (prefix) { | |
94 | dout(4) << __func__ << " [" << prefix << "/]" << what << " not found " | |
95 | << dendl; | |
96 | } else { | |
97 | dout(4) << __func__ << " " << what << " not found " << dendl; | |
98 | } | |
99 | Py_RETURN_NONE; | |
100 | } | |
101 | } | |
102 | ||
103 | static PyObject* | |
104 | ceph_option_get(BaseMgrStandbyModule *self, PyObject *args) | |
105 | { | |
106 | char *what = nullptr; | |
107 | if (!PyArg_ParseTuple(args, "s:ceph_option_get", &what)) { | |
3efd9988 FG |
108 | derr << "Invalid args!" << dendl; |
109 | return nullptr; | |
110 | } | |
111 | ||
112 | std::string value; | |
11fdf7f2 TL |
113 | int r = g_conf().get_val(string(what), &value); |
114 | if (r >= 0) { | |
115 | dout(10) << "ceph_option_get " << what << " found: " << value << dendl; | |
9f95a23c | 116 | return PyUnicode_FromString(value.c_str()); |
11fdf7f2 TL |
117 | } else { |
118 | dout(4) << "ceph_option_get " << what << " not found " << dendl; | |
119 | Py_RETURN_NONE; | |
120 | } | |
121 | } | |
122 | ||
123 | static PyObject* | |
124 | ceph_store_get(BaseMgrStandbyModule *self, PyObject *args) | |
125 | { | |
126 | char *what = nullptr; | |
127 | if (!PyArg_ParseTuple(args, "s:ceph_store_get", &what)) { | |
128 | derr << "Invalid args!" << dendl; | |
129 | return nullptr; | |
130 | } | |
131 | ||
132 | // Drop GIL for blocking mon command execution | |
133 | PyThreadState *tstate = PyEval_SaveThread(); | |
134 | ||
135 | std::string value; | |
136 | bool found = self->this_module->get_store(what, &value); | |
137 | ||
138 | PyEval_RestoreThread(tstate); | |
139 | ||
3efd9988 | 140 | if (found) { |
11fdf7f2 | 141 | dout(10) << "ceph_store_get " << what << " found: " << value.c_str() << dendl; |
9f95a23c | 142 | return PyUnicode_FromString(value.c_str()); |
3efd9988 | 143 | } else { |
11fdf7f2 | 144 | dout(4) << "ceph_store_get " << what << " not found " << dendl; |
3efd9988 FG |
145 | Py_RETURN_NONE; |
146 | } | |
147 | } | |
148 | ||
149 | static PyObject* | |
150 | ceph_get_active_uri(BaseMgrStandbyModule *self, PyObject *args) | |
151 | { | |
9f95a23c | 152 | return PyUnicode_FromString(self->this_module->get_active_uri().c_str()); |
3efd9988 FG |
153 | } |
154 | ||
155 | static PyObject* | |
156 | ceph_log(BaseMgrStandbyModule *self, PyObject *args) | |
157 | { | |
3efd9988 | 158 | char *record = nullptr; |
9f95a23c | 159 | if (!PyArg_ParseTuple(args, "s:log", &record)) { |
3efd9988 FG |
160 | return nullptr; |
161 | } | |
162 | ||
11fdf7f2 | 163 | ceph_assert(self->this_module); |
3efd9988 | 164 | |
9f95a23c | 165 | self->this_module->log(record); |
3efd9988 FG |
166 | |
167 | Py_RETURN_NONE; | |
168 | } | |
169 | ||
b3b6e05e TL |
170 | static PyObject* |
171 | ceph_standby_state_get(BaseMgrStandbyModule *self, PyObject *args) | |
172 | { | |
173 | char *whatc = NULL; | |
174 | if (!PyArg_ParseTuple(args, "s:ceph_state_get", &whatc)) { | |
175 | return NULL; | |
176 | } | |
177 | std::string what(whatc); | |
178 | ||
179 | PyFormatter f; | |
180 | ||
181 | // Drop the GIL, as most of the following blocks will block on | |
182 | // a mutex -- they are all responsible for re-taking the GIL before | |
183 | // touching the PyFormatter instance or returning from the function. | |
184 | without_gil_t no_gil; | |
185 | ||
186 | if (what == "mgr_ips") { | |
187 | entity_addrvec_t myaddrs = self->this_module->get_myaddrs(); | |
188 | with_gil_t with_gil{no_gil}; | |
189 | f.open_array_section("ips"); | |
190 | std::set<std::string> did; | |
191 | for (auto& i : myaddrs.v) { | |
192 | std::string ip = i.ip_only_to_str(); | |
193 | if (auto [where, inserted] = did.insert(ip); inserted) { | |
194 | f.dump_string("ip", ip); | |
195 | } | |
196 | } | |
197 | f.close_section(); | |
198 | return f.get(); | |
199 | } else { | |
200 | derr << "Python module requested unknown data '" << what << "'" << dendl; | |
201 | with_gil_t with_gil{no_gil}; | |
202 | Py_RETURN_NONE; | |
203 | } | |
204 | } | |
205 | ||
206 | ||
3efd9988 | 207 | PyMethodDef BaseMgrStandbyModule_methods[] = { |
b3b6e05e TL |
208 | {"_ceph_get", (PyCFunction)ceph_standby_state_get, METH_VARARGS, |
209 | "Get a cluster object (standby)"}, | |
3efd9988 FG |
210 | |
211 | {"_ceph_get_mgr_id", (PyCFunction)ceph_get_mgr_id, METH_NOARGS, | |
212 | "Get the name of the Mgr daemon where we are running"}, | |
213 | ||
11fdf7f2 TL |
214 | {"_ceph_get_module_option", (PyCFunction)ceph_get_module_option, METH_VARARGS, |
215 | "Get a module configuration option value"}, | |
216 | ||
217 | {"_ceph_get_option", (PyCFunction)ceph_option_get, METH_VARARGS, | |
218 | "Get a native configuration option value"}, | |
219 | ||
220 | {"_ceph_get_store", (PyCFunction)ceph_store_get, METH_VARARGS, | |
221 | "Get a KV store value"}, | |
3efd9988 FG |
222 | |
223 | {"_ceph_get_active_uri", (PyCFunction)ceph_get_active_uri, METH_NOARGS, | |
224 | "Get the URI of the active instance of this module, if any"}, | |
225 | ||
226 | {"_ceph_log", (PyCFunction)ceph_log, METH_VARARGS, | |
227 | "Emit a log message"}, | |
228 | ||
229 | {NULL, NULL, 0, NULL} | |
230 | }; | |
231 | ||
232 | PyTypeObject BaseMgrStandbyModuleType = { | |
233 | PyVarObject_HEAD_INIT(NULL, 0) | |
234 | "ceph_module.BaseMgrStandbyModule", /* tp_name */ | |
235 | sizeof(BaseMgrStandbyModule), /* tp_basicsize */ | |
236 | 0, /* tp_itemsize */ | |
237 | 0, /* tp_dealloc */ | |
238 | 0, /* tp_print */ | |
239 | 0, /* tp_getattr */ | |
240 | 0, /* tp_setattr */ | |
241 | 0, /* tp_compare */ | |
242 | 0, /* tp_repr */ | |
243 | 0, /* tp_as_number */ | |
244 | 0, /* tp_as_sequence */ | |
245 | 0, /* tp_as_mapping */ | |
246 | 0, /* tp_hash */ | |
247 | 0, /* tp_call */ | |
248 | 0, /* tp_str */ | |
249 | 0, /* tp_getattro */ | |
250 | 0, /* tp_setattro */ | |
251 | 0, /* tp_as_buffer */ | |
252 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
253 | "ceph-mgr Standby Python Plugin", /* tp_doc */ | |
254 | 0, /* tp_traverse */ | |
255 | 0, /* tp_clear */ | |
256 | 0, /* tp_richcompare */ | |
257 | 0, /* tp_weaklistoffset */ | |
258 | 0, /* tp_iter */ | |
259 | 0, /* tp_iternext */ | |
260 | BaseMgrStandbyModule_methods, /* tp_methods */ | |
261 | 0, /* tp_members */ | |
262 | 0, /* tp_getset */ | |
263 | 0, /* tp_base */ | |
264 | 0, /* tp_dict */ | |
265 | 0, /* tp_descr_get */ | |
266 | 0, /* tp_descr_set */ | |
267 | 0, /* tp_dictoffset */ | |
268 | (initproc)BaseMgrStandbyModule_init, /* tp_init */ | |
269 | 0, /* tp_alloc */ | |
270 | BaseMgrStandbyModule_new, /* tp_new */ | |
271 | }; |