]>
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 | #include "Mgr.h" | |
5 | ||
6 | #include "osd/OSDMap.h" | |
7 | #include "common/errno.h" | |
8 | #include "common/version.h" | |
9 | #include "include/stringify.h" | |
10 | ||
11 | #include "PyOSDMap.h" | |
12 | #include "PyFormatter.h" | |
13 | #include "Gil.h" | |
14 | ||
15 | #define dout_context g_ceph_context | |
16 | #define dout_subsys ceph_subsys_mgr | |
17 | ||
18 | ||
19 | typedef struct { | |
20 | PyObject_HEAD | |
21 | OSDMap *osdmap; | |
22 | } BasePyOSDMap; | |
23 | ||
24 | typedef struct { | |
25 | PyObject_HEAD | |
26 | OSDMap::Incremental *inc; | |
27 | } BasePyOSDMapIncremental; | |
28 | ||
29 | typedef struct { | |
30 | PyObject_HEAD | |
31 | ceph::shared_ptr<CrushWrapper> crush; | |
32 | } BasePyCRUSH; | |
33 | ||
34 | // ---------- | |
35 | ||
36 | static PyObject *osdmap_get_epoch(BasePyOSDMap *self, PyObject *obj) | |
37 | { | |
38 | return PyInt_FromLong(self->osdmap->get_epoch()); | |
39 | } | |
40 | ||
41 | static PyObject *osdmap_get_crush_version(BasePyOSDMap* self, PyObject *obj) | |
42 | { | |
43 | return PyInt_FromLong(self->osdmap->get_crush_version()); | |
44 | } | |
45 | ||
46 | static PyObject *osdmap_dump(BasePyOSDMap* self, PyObject *obj) | |
47 | { | |
48 | PyFormatter f; | |
49 | self->osdmap->dump(&f); | |
50 | return f.get(); | |
51 | } | |
52 | ||
53 | static PyObject *osdmap_new_incremental(BasePyOSDMap *self, PyObject *obj) | |
54 | { | |
55 | OSDMap::Incremental *inc = new OSDMap::Incremental; | |
56 | ||
57 | inc->fsid = self->osdmap->get_fsid(); | |
58 | inc->epoch = self->osdmap->get_epoch() + 1; | |
59 | // always include latest crush map here... this is okay since we never | |
60 | // actually use this map in the real world (and even if we did it would | |
61 | // be a no-op). | |
62 | self->osdmap->crush->encode(inc->crush, CEPH_FEATURES_ALL); | |
63 | dout(10) << __func__ << " " << inc << dendl; | |
64 | ||
65 | return construct_with_capsule("mgr_module", "OSDMapIncremental", | |
66 | (void*)(inc)); | |
67 | } | |
68 | ||
69 | static PyObject *osdmap_apply_incremental(BasePyOSDMap *self, | |
70 | BasePyOSDMapIncremental *incobj) | |
71 | { | |
72 | if (!PyObject_TypeCheck(incobj, &BasePyOSDMapIncrementalType)) { | |
73 | derr << "Wrong type in osdmap_apply_incremental!" << dendl; | |
74 | return nullptr; | |
75 | } | |
76 | ||
77 | bufferlist bl; | |
78 | self->osdmap->encode(bl, CEPH_FEATURES_ALL|CEPH_FEATURE_RESERVED); | |
79 | OSDMap *next = new OSDMap; | |
80 | next->decode(bl); | |
81 | next->apply_incremental(*(incobj->inc)); | |
82 | dout(10) << __func__ << " map " << self->osdmap << " inc " << incobj->inc | |
83 | << " next " << next << dendl; | |
84 | ||
85 | return construct_with_capsule("mgr_module", "OSDMap", (void*)next); | |
86 | } | |
87 | ||
88 | static PyObject *osdmap_get_crush(BasePyOSDMap* self, PyObject *obj) | |
89 | { | |
90 | return construct_with_capsule("mgr_module", "CRUSHMap", | |
91 | (void*)(&(self->osdmap->crush))); | |
92 | } | |
93 | ||
94 | static PyObject *osdmap_get_pools_by_take(BasePyOSDMap* self, PyObject *args) | |
95 | { | |
96 | int take; | |
97 | if (!PyArg_ParseTuple(args, "i:get_pools_by_take", | |
98 | &take)) { | |
99 | return nullptr; | |
100 | } | |
101 | ||
102 | PyFormatter f; | |
103 | f.open_array_section("pools"); | |
104 | for (auto& p : self->osdmap->get_pools()) { | |
105 | if (self->osdmap->crush->rule_has_take(p.second.crush_rule, take)) { | |
106 | f.dump_int("pool", p.first); | |
107 | } | |
108 | } | |
109 | f.close_section(); | |
110 | return f.get(); | |
111 | } | |
112 | ||
113 | static PyObject *osdmap_calc_pg_upmaps(BasePyOSDMap* self, PyObject *args) | |
114 | { | |
115 | PyObject *pool_list; | |
116 | BasePyOSDMapIncremental *incobj; | |
117 | double max_deviation = 0; | |
118 | int max_iterations = 0; | |
119 | if (!PyArg_ParseTuple(args, "OdiO:calc_pg_upmaps", | |
120 | &incobj, &max_deviation, | |
121 | &max_iterations, &pool_list)) { | |
122 | return nullptr; | |
123 | } | |
94b18763 FG |
124 | if (!PyList_CheckExact(pool_list)) { |
125 | derr << __func__ << " pool_list not a list" << dendl; | |
126 | return nullptr; | |
127 | } | |
128 | set<int64_t> pools; | |
129 | for (auto i = 0; i < PyList_Size(pool_list); ++i) { | |
130 | PyObject *pool_name = PyList_GET_ITEM(pool_list, i); | |
131 | if (!PyString_Check(pool_name)) { | |
132 | derr << __func__ << " " << pool_name << " not a string" << dendl; | |
133 | return nullptr; | |
134 | } | |
135 | auto pool_id = self->osdmap->lookup_pg_pool_name( | |
136 | PyString_AsString(pool_name)); | |
137 | if (pool_id < 0) { | |
138 | derr << __func__ << " pool '" << PyString_AsString(pool_name) | |
139 | << "' does not exist" << dendl; | |
140 | return nullptr; | |
141 | } | |
142 | pools.insert(pool_id); | |
143 | } | |
3efd9988 FG |
144 | |
145 | dout(10) << __func__ << " osdmap " << self->osdmap << " inc " << incobj->inc | |
146 | << " max_deviation " << max_deviation | |
147 | << " max_iterations " << max_iterations | |
94b18763 | 148 | << " pools " << pools |
3efd9988 | 149 | << dendl; |
3efd9988 FG |
150 | int r = self->osdmap->calc_pg_upmaps(g_ceph_context, |
151 | max_deviation, | |
152 | max_iterations, | |
153 | pools, | |
154 | incobj->inc); | |
155 | dout(10) << __func__ << " r = " << r << dendl; | |
156 | return PyInt_FromLong(r); | |
157 | } | |
158 | ||
159 | static PyObject *osdmap_map_pool_pgs_up(BasePyOSDMap* self, PyObject *args) | |
160 | { | |
161 | int poolid; | |
162 | if (!PyArg_ParseTuple(args, "i:map_pool_pgs_up", | |
163 | &poolid)) { | |
164 | return nullptr; | |
165 | } | |
166 | auto pi = self->osdmap->get_pg_pool(poolid); | |
167 | if (!pi) | |
168 | return nullptr; | |
169 | map<pg_t,vector<int>> pm; | |
170 | for (unsigned ps = 0; ps < pi->get_pg_num(); ++ps) { | |
171 | pg_t pgid(ps, poolid); | |
172 | self->osdmap->pg_to_up_acting_osds(pgid, &pm[pgid], nullptr, nullptr, nullptr); | |
173 | } | |
174 | PyFormatter f; | |
175 | for (auto p : pm) { | |
176 | string pg = stringify(p.first); | |
177 | f.open_array_section(pg.c_str()); | |
178 | for (auto o : p.second) { | |
179 | f.dump_int("osd", o); | |
180 | } | |
181 | f.close_section(); | |
182 | } | |
183 | return f.get(); | |
184 | } | |
185 | ||
186 | static int | |
187 | BasePyOSDMap_init(BasePyOSDMap *self, PyObject *args, PyObject *kwds) | |
188 | { | |
189 | PyObject *osdmap_capsule = nullptr; | |
190 | static const char *kwlist[] = {"osdmap_capsule", NULL}; | |
191 | ||
192 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
193 | const_cast<char**>(kwlist), | |
194 | &osdmap_capsule)) { | |
195 | assert(0); | |
196 | return -1; | |
197 | } | |
198 | assert(PyObject_TypeCheck(osdmap_capsule, &PyCapsule_Type)); | |
199 | ||
200 | self->osdmap = (OSDMap*)PyCapsule_GetPointer( | |
201 | osdmap_capsule, nullptr); | |
202 | assert(self->osdmap); | |
203 | ||
204 | return 0; | |
205 | } | |
206 | ||
207 | ||
208 | static void | |
209 | BasePyOSDMap_dealloc(BasePyOSDMap *self) | |
210 | { | |
211 | if (self->osdmap) { | |
212 | delete self->osdmap; | |
213 | self->osdmap = nullptr; | |
214 | } else { | |
215 | derr << "Destroying improperly initialized BasePyOSDMap " << self << dendl; | |
216 | } | |
217 | Py_TYPE(self)->tp_free(self); | |
218 | } | |
219 | ||
220 | ||
221 | PyMethodDef BasePyOSDMap_methods[] = { | |
222 | {"_get_epoch", (PyCFunction)osdmap_get_epoch, METH_NOARGS, "Get OSDMap epoch"}, | |
223 | {"_get_crush_version", (PyCFunction)osdmap_get_crush_version, METH_NOARGS, | |
224 | "Get CRUSH version"}, | |
225 | {"_dump", (PyCFunction)osdmap_dump, METH_NOARGS, "Dump OSDMap::Incremental"}, | |
226 | {"_new_incremental", (PyCFunction)osdmap_new_incremental, METH_NOARGS, | |
227 | "Create OSDMap::Incremental"}, | |
228 | {"_apply_incremental", (PyCFunction)osdmap_apply_incremental, METH_O, | |
229 | "Apply OSDMap::Incremental and return the resulting OSDMap"}, | |
230 | {"_get_crush", (PyCFunction)osdmap_get_crush, METH_NOARGS, "Get CrushWrapper"}, | |
231 | {"_get_pools_by_take", (PyCFunction)osdmap_get_pools_by_take, METH_VARARGS, | |
232 | "Get pools that have CRUSH rules that TAKE the given root"}, | |
233 | {"_calc_pg_upmaps", (PyCFunction)osdmap_calc_pg_upmaps, METH_VARARGS, | |
234 | "Calculate new pg-upmap values"}, | |
235 | {"_map_pool_pgs_up", (PyCFunction)osdmap_map_pool_pgs_up, METH_VARARGS, | |
236 | "Calculate up set mappings for all PGs in a pool"}, | |
237 | {NULL, NULL, 0, NULL} | |
238 | }; | |
239 | ||
240 | PyTypeObject BasePyOSDMapType = { | |
241 | PyVarObject_HEAD_INIT(NULL, 0) | |
242 | "ceph_module.BasePyOSDMap", /* tp_name */ | |
243 | sizeof(BasePyOSDMap), /* tp_basicsize */ | |
244 | 0, /* tp_itemsize */ | |
245 | (destructor)BasePyOSDMap_dealloc, /* tp_dealloc */ | |
246 | 0, /* tp_print */ | |
247 | 0, /* tp_getattr */ | |
248 | 0, /* tp_setattr */ | |
249 | 0, /* tp_compare */ | |
250 | 0, /* tp_repr */ | |
251 | 0, /* tp_as_number */ | |
252 | 0, /* tp_as_sequence */ | |
253 | 0, /* tp_as_mapping */ | |
254 | 0, /* tp_hash */ | |
255 | 0, /* tp_call */ | |
256 | 0, /* tp_str */ | |
257 | 0, /* tp_getattro */ | |
258 | 0, /* tp_setattro */ | |
259 | 0, /* tp_as_buffer */ | |
260 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
261 | "Ceph OSDMap", /* tp_doc */ | |
262 | 0, /* tp_traverse */ | |
263 | 0, /* tp_clear */ | |
264 | 0, /* tp_richcompare */ | |
265 | 0, /* tp_weaklistoffset */ | |
266 | 0, /* tp_iter */ | |
267 | 0, /* tp_iternext */ | |
268 | BasePyOSDMap_methods, /* tp_methods */ | |
269 | 0, /* tp_members */ | |
270 | 0, /* tp_getset */ | |
271 | 0, /* tp_base */ | |
272 | 0, /* tp_dict */ | |
273 | 0, /* tp_descr_get */ | |
274 | 0, /* tp_descr_set */ | |
275 | 0, /* tp_dictoffset */ | |
276 | (initproc)BasePyOSDMap_init, /* tp_init */ | |
277 | 0, /* tp_alloc */ | |
278 | 0, /* tp_new */ | |
279 | }; | |
280 | ||
281 | // ---------- | |
282 | ||
283 | ||
284 | static int | |
285 | BasePyOSDMapIncremental_init(BasePyOSDMapIncremental *self, | |
286 | PyObject *args, PyObject *kwds) | |
287 | { | |
288 | PyObject *inc_capsule = nullptr; | |
289 | static const char *kwlist[] = {"inc_capsule", NULL}; | |
290 | ||
291 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
292 | const_cast<char**>(kwlist), | |
293 | &inc_capsule)) { | |
294 | assert(0); | |
295 | return -1; | |
296 | } | |
297 | assert(PyObject_TypeCheck(inc_capsule, &PyCapsule_Type)); | |
298 | ||
299 | self->inc = (OSDMap::Incremental*)PyCapsule_GetPointer( | |
300 | inc_capsule, nullptr); | |
301 | assert(self->inc); | |
302 | ||
303 | return 0; | |
304 | } | |
305 | ||
306 | static void | |
307 | BasePyOSDMapIncremental_dealloc(BasePyOSDMapIncremental *self) | |
308 | { | |
309 | if (self->inc) { | |
310 | delete self->inc; | |
311 | self->inc = nullptr; | |
312 | } else { | |
313 | derr << "Destroying improperly initialized BasePyOSDMap " << self << dendl; | |
314 | } | |
315 | Py_TYPE(self)->tp_free(self); | |
316 | } | |
317 | ||
318 | static PyObject *osdmap_inc_get_epoch(BasePyOSDMapIncremental *self, | |
319 | PyObject *obj) | |
320 | { | |
321 | return PyInt_FromLong(self->inc->epoch); | |
322 | } | |
323 | ||
324 | static PyObject *osdmap_inc_dump(BasePyOSDMapIncremental *self, | |
325 | PyObject *obj) | |
326 | { | |
327 | PyFormatter f; | |
328 | self->inc->dump(&f); | |
329 | return f.get(); | |
330 | } | |
331 | ||
332 | static int get_int_float_map(PyObject *obj, map<int,double> *out) | |
333 | { | |
334 | PyObject *ls = PyDict_Items(obj); | |
335 | for (int j = 0; j < PyList_Size(ls); ++j) { | |
336 | PyObject *pair = PyList_GET_ITEM(ls, j); | |
337 | if (!PyTuple_Check(pair)) { | |
338 | derr << __func__ << " item " << j << " not a tuple" << dendl; | |
339 | Py_DECREF(ls); | |
340 | return -1; | |
341 | } | |
342 | int k; | |
343 | double v; | |
344 | if (!PyArg_ParseTuple(pair, "id:pair", &k, &v)) { | |
345 | derr << __func__ << " item " << j << " not a size 2 tuple" << dendl; | |
346 | Py_DECREF(ls); | |
347 | return -1; | |
348 | } | |
349 | (*out)[k] = v; | |
350 | } | |
351 | ||
352 | Py_DECREF(ls); | |
353 | return 0; | |
354 | } | |
355 | ||
356 | static PyObject *osdmap_inc_set_osd_reweights(BasePyOSDMapIncremental *self, | |
357 | PyObject *weightobj) | |
358 | { | |
359 | map<int,double> wm; | |
360 | if (get_int_float_map(weightobj, &wm) < 0) { | |
361 | return nullptr; | |
362 | } | |
363 | ||
364 | for (auto i : wm) { | |
365 | self->inc->new_weight[i.first] = std::max(0.0, std::min(1.0, i.second)) * 0x10000; | |
366 | } | |
367 | Py_RETURN_NONE; | |
368 | } | |
369 | ||
370 | static PyObject *osdmap_inc_set_compat_weight_set_weights( | |
371 | BasePyOSDMapIncremental *self, PyObject *weightobj) | |
372 | { | |
373 | map<int,double> wm; | |
374 | if (get_int_float_map(weightobj, &wm) < 0) { | |
375 | return nullptr; | |
376 | } | |
377 | ||
378 | CrushWrapper crush; | |
379 | assert(self->inc->crush.length()); // see new_incremental | |
380 | auto p = self->inc->crush.begin(); | |
381 | ::decode(crush, p); | |
382 | crush.create_choose_args(CrushWrapper::DEFAULT_CHOOSE_ARGS, 1); | |
383 | for (auto i : wm) { | |
384 | crush.choose_args_adjust_item_weightf( | |
385 | g_ceph_context, | |
386 | crush.choose_args_get(CrushWrapper::DEFAULT_CHOOSE_ARGS), | |
387 | i.first, | |
388 | { i.second }, | |
389 | nullptr); | |
390 | } | |
391 | self->inc->crush.clear(); | |
392 | crush.encode(self->inc->crush, CEPH_FEATURES_ALL); | |
393 | Py_RETURN_NONE; | |
394 | } | |
395 | ||
396 | PyMethodDef BasePyOSDMapIncremental_methods[] = { | |
397 | {"_get_epoch", (PyCFunction)osdmap_inc_get_epoch, METH_NOARGS, | |
398 | "Get OSDMap::Incremental epoch"}, | |
399 | {"_dump", (PyCFunction)osdmap_inc_dump, METH_NOARGS, | |
400 | "Dump OSDMap::Incremental"}, | |
401 | {"_set_osd_reweights", (PyCFunction)osdmap_inc_set_osd_reweights, | |
402 | METH_O, "Set osd reweight values"}, | |
403 | {"_set_crush_compat_weight_set_weights", | |
404 | (PyCFunction)osdmap_inc_set_compat_weight_set_weights, METH_O, | |
405 | "Set weight values in the pending CRUSH compat weight-set"}, | |
406 | {NULL, NULL, 0, NULL} | |
407 | }; | |
408 | ||
409 | PyTypeObject BasePyOSDMapIncrementalType = { | |
410 | PyVarObject_HEAD_INIT(NULL, 0) | |
411 | "ceph_module.BasePyOSDMapIncremental", /* tp_name */ | |
412 | sizeof(BasePyOSDMapIncremental), /* tp_basicsize */ | |
413 | 0, /* tp_itemsize */ | |
414 | (destructor)BasePyOSDMapIncremental_dealloc, /* tp_dealloc */ | |
415 | 0, /* tp_print */ | |
416 | 0, /* tp_getattr */ | |
417 | 0, /* tp_setattr */ | |
418 | 0, /* tp_compare */ | |
419 | 0, /* tp_repr */ | |
420 | 0, /* tp_as_number */ | |
421 | 0, /* tp_as_sequence */ | |
422 | 0, /* tp_as_mapping */ | |
423 | 0, /* tp_hash */ | |
424 | 0, /* tp_call */ | |
425 | 0, /* tp_str */ | |
426 | 0, /* tp_getattro */ | |
427 | 0, /* tp_setattro */ | |
428 | 0, /* tp_as_buffer */ | |
429 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
430 | "Ceph OSDMapIncremental", /* tp_doc */ | |
431 | 0, /* tp_traverse */ | |
432 | 0, /* tp_clear */ | |
433 | 0, /* tp_richcompare */ | |
434 | 0, /* tp_weaklistoffset */ | |
435 | 0, /* tp_iter */ | |
436 | 0, /* tp_iternext */ | |
437 | BasePyOSDMapIncremental_methods, /* tp_methods */ | |
438 | 0, /* tp_members */ | |
439 | 0, /* tp_getset */ | |
440 | 0, /* tp_base */ | |
441 | 0, /* tp_dict */ | |
442 | 0, /* tp_descr_get */ | |
443 | 0, /* tp_descr_set */ | |
444 | 0, /* tp_dictoffset */ | |
445 | (initproc)BasePyOSDMapIncremental_init, /* tp_init */ | |
446 | 0, /* tp_alloc */ | |
447 | 0, /* tp_new */ | |
448 | }; | |
449 | ||
450 | ||
451 | // ---------- | |
452 | ||
453 | static int | |
454 | BasePyCRUSH_init(BasePyCRUSH *self, | |
455 | PyObject *args, PyObject *kwds) | |
456 | { | |
457 | PyObject *crush_capsule = nullptr; | |
458 | static const char *kwlist[] = {"crush_capsule", NULL}; | |
459 | ||
460 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
461 | const_cast<char**>(kwlist), | |
462 | &crush_capsule)) { | |
463 | assert(0); | |
464 | return -1; | |
465 | } | |
466 | assert(PyObject_TypeCheck(crush_capsule, &PyCapsule_Type)); | |
467 | ||
468 | auto ptr_ref = (ceph::shared_ptr<CrushWrapper>*)( | |
469 | PyCapsule_GetPointer(crush_capsule, nullptr)); | |
470 | ||
471 | // We passed a pointer to a shared pointer, which is weird, but | |
472 | // just enough to get it into the constructor: this is a real shared | |
473 | // pointer construction now, and then we throw away that pointer to | |
474 | // the shared pointer. | |
475 | self->crush = *ptr_ref; | |
476 | assert(self->crush); | |
477 | ||
478 | return 0; | |
479 | } | |
480 | ||
481 | static void | |
482 | BasePyCRUSH_dealloc(BasePyCRUSH *self) | |
483 | { | |
484 | self->crush.reset(); | |
485 | Py_TYPE(self)->tp_free(self); | |
486 | } | |
487 | ||
488 | static PyObject *crush_dump(BasePyCRUSH *self, PyObject *obj) | |
489 | { | |
490 | PyFormatter f; | |
491 | self->crush->dump(&f); | |
492 | return f.get(); | |
493 | } | |
494 | ||
495 | static PyObject *crush_get_item_name(BasePyCRUSH *self, PyObject *args) | |
496 | { | |
497 | int item; | |
498 | if (!PyArg_ParseTuple(args, "i:get_item_name", &item)) { | |
499 | return nullptr; | |
500 | } | |
501 | if (!self->crush->item_exists(item)) { | |
502 | Py_RETURN_NONE; | |
503 | } | |
504 | return PyString_FromString(self->crush->get_item_name(item)); | |
505 | } | |
506 | ||
507 | static PyObject *crush_get_item_weight(BasePyCRUSH *self, PyObject *args) | |
508 | { | |
509 | int item; | |
510 | if (!PyArg_ParseTuple(args, "i:get_item_weight", &item)) { | |
511 | return nullptr; | |
512 | } | |
513 | if (!self->crush->item_exists(item)) { | |
514 | Py_RETURN_NONE; | |
515 | } | |
516 | return PyFloat_FromDouble(self->crush->get_item_weightf(item)); | |
517 | } | |
518 | ||
519 | static PyObject *crush_find_takes(BasePyCRUSH *self, PyObject *obj) | |
520 | { | |
521 | set<int> takes; | |
522 | self->crush->find_takes(&takes); | |
523 | PyFormatter f; | |
524 | f.open_array_section("takes"); | |
525 | for (auto root : takes) { | |
526 | f.dump_int("root", root); | |
527 | } | |
528 | f.close_section(); | |
529 | return f.get(); | |
530 | } | |
531 | ||
532 | static PyObject *crush_get_take_weight_osd_map(BasePyCRUSH *self, PyObject *args) | |
533 | { | |
534 | int root; | |
535 | if (!PyArg_ParseTuple(args, "i:get_take_weight_osd_map", | |
536 | &root)) { | |
537 | return nullptr; | |
538 | } | |
539 | map<int,float> wmap; | |
540 | ||
541 | if (!self->crush->item_exists(root)) { | |
542 | return nullptr; | |
543 | } | |
544 | ||
545 | self->crush->get_take_weight_osd_map(root, &wmap); | |
546 | PyFormatter f; | |
547 | f.open_object_section("weights"); | |
548 | for (auto& p : wmap) { | |
549 | string n = stringify(p.first); // ick | |
550 | f.dump_float(n.c_str(), p.second); | |
551 | } | |
552 | f.close_section(); | |
553 | return f.get(); | |
554 | } | |
555 | ||
556 | PyMethodDef BasePyCRUSH_methods[] = { | |
557 | {"_dump", (PyCFunction)crush_dump, METH_NOARGS, "Dump map"}, | |
558 | {"_get_item_name", (PyCFunction)crush_get_item_name, METH_VARARGS, | |
559 | "Get item name"}, | |
560 | {"_get_item_weight", (PyCFunction)crush_get_item_weight, METH_VARARGS, | |
561 | "Get item weight"}, | |
562 | {"_find_takes", (PyCFunction)crush_find_takes, METH_NOARGS, | |
563 | "Find distinct TAKE roots"}, | |
564 | {"_get_take_weight_osd_map", (PyCFunction)crush_get_take_weight_osd_map, | |
565 | METH_VARARGS, "Get OSD weight map for a given TAKE root node"}, | |
566 | {NULL, NULL, 0, NULL} | |
567 | }; | |
568 | ||
569 | PyTypeObject BasePyCRUSHType = { | |
570 | PyVarObject_HEAD_INIT(NULL, 0) | |
571 | "ceph_module.BasePyCRUSH", /* tp_name */ | |
572 | sizeof(BasePyCRUSH), /* tp_basicsize */ | |
573 | 0, /* tp_itemsize */ | |
574 | (destructor)BasePyCRUSH_dealloc, /* tp_dealloc */ | |
575 | 0, /* tp_print */ | |
576 | 0, /* tp_getattr */ | |
577 | 0, /* tp_setattr */ | |
578 | 0, /* tp_compare */ | |
579 | 0, /* tp_repr */ | |
580 | 0, /* tp_as_number */ | |
581 | 0, /* tp_as_sequence */ | |
582 | 0, /* tp_as_mapping */ | |
583 | 0, /* tp_hash */ | |
584 | 0, /* tp_call */ | |
585 | 0, /* tp_str */ | |
586 | 0, /* tp_getattro */ | |
587 | 0, /* tp_setattro */ | |
588 | 0, /* tp_as_buffer */ | |
589 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
590 | "Ceph OSDMapIncremental", /* tp_doc */ | |
591 | 0, /* tp_traverse */ | |
592 | 0, /* tp_clear */ | |
593 | 0, /* tp_richcompare */ | |
594 | 0, /* tp_weaklistoffset */ | |
595 | 0, /* tp_iter */ | |
596 | 0, /* tp_iternext */ | |
597 | BasePyCRUSH_methods, /* tp_methods */ | |
598 | 0, /* tp_members */ | |
599 | 0, /* tp_getset */ | |
600 | 0, /* tp_base */ | |
601 | 0, /* tp_dict */ | |
602 | 0, /* tp_descr_get */ | |
603 | 0, /* tp_descr_set */ | |
604 | 0, /* tp_dictoffset */ | |
605 | (initproc)BasePyCRUSH_init, /* tp_init */ | |
606 | 0, /* tp_alloc */ | |
607 | 0, /* tp_new */ | |
608 | }; |