]>
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 | } | |
124 | ||
125 | dout(10) << __func__ << " osdmap " << self->osdmap << " inc " << incobj->inc | |
126 | << " max_deviation " << max_deviation | |
127 | << " max_iterations " << max_iterations | |
128 | << dendl; | |
129 | set<int64_t> pools; | |
130 | // FIXME: unpack pool_list and translate to pools set | |
131 | int r = self->osdmap->calc_pg_upmaps(g_ceph_context, | |
132 | max_deviation, | |
133 | max_iterations, | |
134 | pools, | |
135 | incobj->inc); | |
136 | dout(10) << __func__ << " r = " << r << dendl; | |
137 | return PyInt_FromLong(r); | |
138 | } | |
139 | ||
140 | static PyObject *osdmap_map_pool_pgs_up(BasePyOSDMap* self, PyObject *args) | |
141 | { | |
142 | int poolid; | |
143 | if (!PyArg_ParseTuple(args, "i:map_pool_pgs_up", | |
144 | &poolid)) { | |
145 | return nullptr; | |
146 | } | |
147 | auto pi = self->osdmap->get_pg_pool(poolid); | |
148 | if (!pi) | |
149 | return nullptr; | |
150 | map<pg_t,vector<int>> pm; | |
151 | for (unsigned ps = 0; ps < pi->get_pg_num(); ++ps) { | |
152 | pg_t pgid(ps, poolid); | |
153 | self->osdmap->pg_to_up_acting_osds(pgid, &pm[pgid], nullptr, nullptr, nullptr); | |
154 | } | |
155 | PyFormatter f; | |
156 | for (auto p : pm) { | |
157 | string pg = stringify(p.first); | |
158 | f.open_array_section(pg.c_str()); | |
159 | for (auto o : p.second) { | |
160 | f.dump_int("osd", o); | |
161 | } | |
162 | f.close_section(); | |
163 | } | |
164 | return f.get(); | |
165 | } | |
166 | ||
167 | static int | |
168 | BasePyOSDMap_init(BasePyOSDMap *self, PyObject *args, PyObject *kwds) | |
169 | { | |
170 | PyObject *osdmap_capsule = nullptr; | |
171 | static const char *kwlist[] = {"osdmap_capsule", NULL}; | |
172 | ||
173 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
174 | const_cast<char**>(kwlist), | |
175 | &osdmap_capsule)) { | |
176 | assert(0); | |
177 | return -1; | |
178 | } | |
179 | assert(PyObject_TypeCheck(osdmap_capsule, &PyCapsule_Type)); | |
180 | ||
181 | self->osdmap = (OSDMap*)PyCapsule_GetPointer( | |
182 | osdmap_capsule, nullptr); | |
183 | assert(self->osdmap); | |
184 | ||
185 | return 0; | |
186 | } | |
187 | ||
188 | ||
189 | static void | |
190 | BasePyOSDMap_dealloc(BasePyOSDMap *self) | |
191 | { | |
192 | if (self->osdmap) { | |
193 | delete self->osdmap; | |
194 | self->osdmap = nullptr; | |
195 | } else { | |
196 | derr << "Destroying improperly initialized BasePyOSDMap " << self << dendl; | |
197 | } | |
198 | Py_TYPE(self)->tp_free(self); | |
199 | } | |
200 | ||
201 | ||
202 | PyMethodDef BasePyOSDMap_methods[] = { | |
203 | {"_get_epoch", (PyCFunction)osdmap_get_epoch, METH_NOARGS, "Get OSDMap epoch"}, | |
204 | {"_get_crush_version", (PyCFunction)osdmap_get_crush_version, METH_NOARGS, | |
205 | "Get CRUSH version"}, | |
206 | {"_dump", (PyCFunction)osdmap_dump, METH_NOARGS, "Dump OSDMap::Incremental"}, | |
207 | {"_new_incremental", (PyCFunction)osdmap_new_incremental, METH_NOARGS, | |
208 | "Create OSDMap::Incremental"}, | |
209 | {"_apply_incremental", (PyCFunction)osdmap_apply_incremental, METH_O, | |
210 | "Apply OSDMap::Incremental and return the resulting OSDMap"}, | |
211 | {"_get_crush", (PyCFunction)osdmap_get_crush, METH_NOARGS, "Get CrushWrapper"}, | |
212 | {"_get_pools_by_take", (PyCFunction)osdmap_get_pools_by_take, METH_VARARGS, | |
213 | "Get pools that have CRUSH rules that TAKE the given root"}, | |
214 | {"_calc_pg_upmaps", (PyCFunction)osdmap_calc_pg_upmaps, METH_VARARGS, | |
215 | "Calculate new pg-upmap values"}, | |
216 | {"_map_pool_pgs_up", (PyCFunction)osdmap_map_pool_pgs_up, METH_VARARGS, | |
217 | "Calculate up set mappings for all PGs in a pool"}, | |
218 | {NULL, NULL, 0, NULL} | |
219 | }; | |
220 | ||
221 | PyTypeObject BasePyOSDMapType = { | |
222 | PyVarObject_HEAD_INIT(NULL, 0) | |
223 | "ceph_module.BasePyOSDMap", /* tp_name */ | |
224 | sizeof(BasePyOSDMap), /* tp_basicsize */ | |
225 | 0, /* tp_itemsize */ | |
226 | (destructor)BasePyOSDMap_dealloc, /* tp_dealloc */ | |
227 | 0, /* tp_print */ | |
228 | 0, /* tp_getattr */ | |
229 | 0, /* tp_setattr */ | |
230 | 0, /* tp_compare */ | |
231 | 0, /* tp_repr */ | |
232 | 0, /* tp_as_number */ | |
233 | 0, /* tp_as_sequence */ | |
234 | 0, /* tp_as_mapping */ | |
235 | 0, /* tp_hash */ | |
236 | 0, /* tp_call */ | |
237 | 0, /* tp_str */ | |
238 | 0, /* tp_getattro */ | |
239 | 0, /* tp_setattro */ | |
240 | 0, /* tp_as_buffer */ | |
241 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
242 | "Ceph OSDMap", /* tp_doc */ | |
243 | 0, /* tp_traverse */ | |
244 | 0, /* tp_clear */ | |
245 | 0, /* tp_richcompare */ | |
246 | 0, /* tp_weaklistoffset */ | |
247 | 0, /* tp_iter */ | |
248 | 0, /* tp_iternext */ | |
249 | BasePyOSDMap_methods, /* tp_methods */ | |
250 | 0, /* tp_members */ | |
251 | 0, /* tp_getset */ | |
252 | 0, /* tp_base */ | |
253 | 0, /* tp_dict */ | |
254 | 0, /* tp_descr_get */ | |
255 | 0, /* tp_descr_set */ | |
256 | 0, /* tp_dictoffset */ | |
257 | (initproc)BasePyOSDMap_init, /* tp_init */ | |
258 | 0, /* tp_alloc */ | |
259 | 0, /* tp_new */ | |
260 | }; | |
261 | ||
262 | // ---------- | |
263 | ||
264 | ||
265 | static int | |
266 | BasePyOSDMapIncremental_init(BasePyOSDMapIncremental *self, | |
267 | PyObject *args, PyObject *kwds) | |
268 | { | |
269 | PyObject *inc_capsule = nullptr; | |
270 | static const char *kwlist[] = {"inc_capsule", NULL}; | |
271 | ||
272 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
273 | const_cast<char**>(kwlist), | |
274 | &inc_capsule)) { | |
275 | assert(0); | |
276 | return -1; | |
277 | } | |
278 | assert(PyObject_TypeCheck(inc_capsule, &PyCapsule_Type)); | |
279 | ||
280 | self->inc = (OSDMap::Incremental*)PyCapsule_GetPointer( | |
281 | inc_capsule, nullptr); | |
282 | assert(self->inc); | |
283 | ||
284 | return 0; | |
285 | } | |
286 | ||
287 | static void | |
288 | BasePyOSDMapIncremental_dealloc(BasePyOSDMapIncremental *self) | |
289 | { | |
290 | if (self->inc) { | |
291 | delete self->inc; | |
292 | self->inc = nullptr; | |
293 | } else { | |
294 | derr << "Destroying improperly initialized BasePyOSDMap " << self << dendl; | |
295 | } | |
296 | Py_TYPE(self)->tp_free(self); | |
297 | } | |
298 | ||
299 | static PyObject *osdmap_inc_get_epoch(BasePyOSDMapIncremental *self, | |
300 | PyObject *obj) | |
301 | { | |
302 | return PyInt_FromLong(self->inc->epoch); | |
303 | } | |
304 | ||
305 | static PyObject *osdmap_inc_dump(BasePyOSDMapIncremental *self, | |
306 | PyObject *obj) | |
307 | { | |
308 | PyFormatter f; | |
309 | self->inc->dump(&f); | |
310 | return f.get(); | |
311 | } | |
312 | ||
313 | static int get_int_float_map(PyObject *obj, map<int,double> *out) | |
314 | { | |
315 | PyObject *ls = PyDict_Items(obj); | |
316 | for (int j = 0; j < PyList_Size(ls); ++j) { | |
317 | PyObject *pair = PyList_GET_ITEM(ls, j); | |
318 | if (!PyTuple_Check(pair)) { | |
319 | derr << __func__ << " item " << j << " not a tuple" << dendl; | |
320 | Py_DECREF(ls); | |
321 | return -1; | |
322 | } | |
323 | int k; | |
324 | double v; | |
325 | if (!PyArg_ParseTuple(pair, "id:pair", &k, &v)) { | |
326 | derr << __func__ << " item " << j << " not a size 2 tuple" << dendl; | |
327 | Py_DECREF(ls); | |
328 | return -1; | |
329 | } | |
330 | (*out)[k] = v; | |
331 | } | |
332 | ||
333 | Py_DECREF(ls); | |
334 | return 0; | |
335 | } | |
336 | ||
337 | static PyObject *osdmap_inc_set_osd_reweights(BasePyOSDMapIncremental *self, | |
338 | PyObject *weightobj) | |
339 | { | |
340 | map<int,double> wm; | |
341 | if (get_int_float_map(weightobj, &wm) < 0) { | |
342 | return nullptr; | |
343 | } | |
344 | ||
345 | for (auto i : wm) { | |
346 | self->inc->new_weight[i.first] = std::max(0.0, std::min(1.0, i.second)) * 0x10000; | |
347 | } | |
348 | Py_RETURN_NONE; | |
349 | } | |
350 | ||
351 | static PyObject *osdmap_inc_set_compat_weight_set_weights( | |
352 | BasePyOSDMapIncremental *self, PyObject *weightobj) | |
353 | { | |
354 | map<int,double> wm; | |
355 | if (get_int_float_map(weightobj, &wm) < 0) { | |
356 | return nullptr; | |
357 | } | |
358 | ||
359 | CrushWrapper crush; | |
360 | assert(self->inc->crush.length()); // see new_incremental | |
361 | auto p = self->inc->crush.begin(); | |
362 | ::decode(crush, p); | |
363 | crush.create_choose_args(CrushWrapper::DEFAULT_CHOOSE_ARGS, 1); | |
364 | for (auto i : wm) { | |
365 | crush.choose_args_adjust_item_weightf( | |
366 | g_ceph_context, | |
367 | crush.choose_args_get(CrushWrapper::DEFAULT_CHOOSE_ARGS), | |
368 | i.first, | |
369 | { i.second }, | |
370 | nullptr); | |
371 | } | |
372 | self->inc->crush.clear(); | |
373 | crush.encode(self->inc->crush, CEPH_FEATURES_ALL); | |
374 | Py_RETURN_NONE; | |
375 | } | |
376 | ||
377 | PyMethodDef BasePyOSDMapIncremental_methods[] = { | |
378 | {"_get_epoch", (PyCFunction)osdmap_inc_get_epoch, METH_NOARGS, | |
379 | "Get OSDMap::Incremental epoch"}, | |
380 | {"_dump", (PyCFunction)osdmap_inc_dump, METH_NOARGS, | |
381 | "Dump OSDMap::Incremental"}, | |
382 | {"_set_osd_reweights", (PyCFunction)osdmap_inc_set_osd_reweights, | |
383 | METH_O, "Set osd reweight values"}, | |
384 | {"_set_crush_compat_weight_set_weights", | |
385 | (PyCFunction)osdmap_inc_set_compat_weight_set_weights, METH_O, | |
386 | "Set weight values in the pending CRUSH compat weight-set"}, | |
387 | {NULL, NULL, 0, NULL} | |
388 | }; | |
389 | ||
390 | PyTypeObject BasePyOSDMapIncrementalType = { | |
391 | PyVarObject_HEAD_INIT(NULL, 0) | |
392 | "ceph_module.BasePyOSDMapIncremental", /* tp_name */ | |
393 | sizeof(BasePyOSDMapIncremental), /* tp_basicsize */ | |
394 | 0, /* tp_itemsize */ | |
395 | (destructor)BasePyOSDMapIncremental_dealloc, /* tp_dealloc */ | |
396 | 0, /* tp_print */ | |
397 | 0, /* tp_getattr */ | |
398 | 0, /* tp_setattr */ | |
399 | 0, /* tp_compare */ | |
400 | 0, /* tp_repr */ | |
401 | 0, /* tp_as_number */ | |
402 | 0, /* tp_as_sequence */ | |
403 | 0, /* tp_as_mapping */ | |
404 | 0, /* tp_hash */ | |
405 | 0, /* tp_call */ | |
406 | 0, /* tp_str */ | |
407 | 0, /* tp_getattro */ | |
408 | 0, /* tp_setattro */ | |
409 | 0, /* tp_as_buffer */ | |
410 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
411 | "Ceph OSDMapIncremental", /* tp_doc */ | |
412 | 0, /* tp_traverse */ | |
413 | 0, /* tp_clear */ | |
414 | 0, /* tp_richcompare */ | |
415 | 0, /* tp_weaklistoffset */ | |
416 | 0, /* tp_iter */ | |
417 | 0, /* tp_iternext */ | |
418 | BasePyOSDMapIncremental_methods, /* tp_methods */ | |
419 | 0, /* tp_members */ | |
420 | 0, /* tp_getset */ | |
421 | 0, /* tp_base */ | |
422 | 0, /* tp_dict */ | |
423 | 0, /* tp_descr_get */ | |
424 | 0, /* tp_descr_set */ | |
425 | 0, /* tp_dictoffset */ | |
426 | (initproc)BasePyOSDMapIncremental_init, /* tp_init */ | |
427 | 0, /* tp_alloc */ | |
428 | 0, /* tp_new */ | |
429 | }; | |
430 | ||
431 | ||
432 | // ---------- | |
433 | ||
434 | static int | |
435 | BasePyCRUSH_init(BasePyCRUSH *self, | |
436 | PyObject *args, PyObject *kwds) | |
437 | { | |
438 | PyObject *crush_capsule = nullptr; | |
439 | static const char *kwlist[] = {"crush_capsule", NULL}; | |
440 | ||
441 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", | |
442 | const_cast<char**>(kwlist), | |
443 | &crush_capsule)) { | |
444 | assert(0); | |
445 | return -1; | |
446 | } | |
447 | assert(PyObject_TypeCheck(crush_capsule, &PyCapsule_Type)); | |
448 | ||
449 | auto ptr_ref = (ceph::shared_ptr<CrushWrapper>*)( | |
450 | PyCapsule_GetPointer(crush_capsule, nullptr)); | |
451 | ||
452 | // We passed a pointer to a shared pointer, which is weird, but | |
453 | // just enough to get it into the constructor: this is a real shared | |
454 | // pointer construction now, and then we throw away that pointer to | |
455 | // the shared pointer. | |
456 | self->crush = *ptr_ref; | |
457 | assert(self->crush); | |
458 | ||
459 | return 0; | |
460 | } | |
461 | ||
462 | static void | |
463 | BasePyCRUSH_dealloc(BasePyCRUSH *self) | |
464 | { | |
465 | self->crush.reset(); | |
466 | Py_TYPE(self)->tp_free(self); | |
467 | } | |
468 | ||
469 | static PyObject *crush_dump(BasePyCRUSH *self, PyObject *obj) | |
470 | { | |
471 | PyFormatter f; | |
472 | self->crush->dump(&f); | |
473 | return f.get(); | |
474 | } | |
475 | ||
476 | static PyObject *crush_get_item_name(BasePyCRUSH *self, PyObject *args) | |
477 | { | |
478 | int item; | |
479 | if (!PyArg_ParseTuple(args, "i:get_item_name", &item)) { | |
480 | return nullptr; | |
481 | } | |
482 | if (!self->crush->item_exists(item)) { | |
483 | Py_RETURN_NONE; | |
484 | } | |
485 | return PyString_FromString(self->crush->get_item_name(item)); | |
486 | } | |
487 | ||
488 | static PyObject *crush_get_item_weight(BasePyCRUSH *self, PyObject *args) | |
489 | { | |
490 | int item; | |
491 | if (!PyArg_ParseTuple(args, "i:get_item_weight", &item)) { | |
492 | return nullptr; | |
493 | } | |
494 | if (!self->crush->item_exists(item)) { | |
495 | Py_RETURN_NONE; | |
496 | } | |
497 | return PyFloat_FromDouble(self->crush->get_item_weightf(item)); | |
498 | } | |
499 | ||
500 | static PyObject *crush_find_takes(BasePyCRUSH *self, PyObject *obj) | |
501 | { | |
502 | set<int> takes; | |
503 | self->crush->find_takes(&takes); | |
504 | PyFormatter f; | |
505 | f.open_array_section("takes"); | |
506 | for (auto root : takes) { | |
507 | f.dump_int("root", root); | |
508 | } | |
509 | f.close_section(); | |
510 | return f.get(); | |
511 | } | |
512 | ||
513 | static PyObject *crush_get_take_weight_osd_map(BasePyCRUSH *self, PyObject *args) | |
514 | { | |
515 | int root; | |
516 | if (!PyArg_ParseTuple(args, "i:get_take_weight_osd_map", | |
517 | &root)) { | |
518 | return nullptr; | |
519 | } | |
520 | map<int,float> wmap; | |
521 | ||
522 | if (!self->crush->item_exists(root)) { | |
523 | return nullptr; | |
524 | } | |
525 | ||
526 | self->crush->get_take_weight_osd_map(root, &wmap); | |
527 | PyFormatter f; | |
528 | f.open_object_section("weights"); | |
529 | for (auto& p : wmap) { | |
530 | string n = stringify(p.first); // ick | |
531 | f.dump_float(n.c_str(), p.second); | |
532 | } | |
533 | f.close_section(); | |
534 | return f.get(); | |
535 | } | |
536 | ||
537 | PyMethodDef BasePyCRUSH_methods[] = { | |
538 | {"_dump", (PyCFunction)crush_dump, METH_NOARGS, "Dump map"}, | |
539 | {"_get_item_name", (PyCFunction)crush_get_item_name, METH_VARARGS, | |
540 | "Get item name"}, | |
541 | {"_get_item_weight", (PyCFunction)crush_get_item_weight, METH_VARARGS, | |
542 | "Get item weight"}, | |
543 | {"_find_takes", (PyCFunction)crush_find_takes, METH_NOARGS, | |
544 | "Find distinct TAKE roots"}, | |
545 | {"_get_take_weight_osd_map", (PyCFunction)crush_get_take_weight_osd_map, | |
546 | METH_VARARGS, "Get OSD weight map for a given TAKE root node"}, | |
547 | {NULL, NULL, 0, NULL} | |
548 | }; | |
549 | ||
550 | PyTypeObject BasePyCRUSHType = { | |
551 | PyVarObject_HEAD_INIT(NULL, 0) | |
552 | "ceph_module.BasePyCRUSH", /* tp_name */ | |
553 | sizeof(BasePyCRUSH), /* tp_basicsize */ | |
554 | 0, /* tp_itemsize */ | |
555 | (destructor)BasePyCRUSH_dealloc, /* tp_dealloc */ | |
556 | 0, /* tp_print */ | |
557 | 0, /* tp_getattr */ | |
558 | 0, /* tp_setattr */ | |
559 | 0, /* tp_compare */ | |
560 | 0, /* tp_repr */ | |
561 | 0, /* tp_as_number */ | |
562 | 0, /* tp_as_sequence */ | |
563 | 0, /* tp_as_mapping */ | |
564 | 0, /* tp_hash */ | |
565 | 0, /* tp_call */ | |
566 | 0, /* tp_str */ | |
567 | 0, /* tp_getattro */ | |
568 | 0, /* tp_setattro */ | |
569 | 0, /* tp_as_buffer */ | |
570 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
571 | "Ceph OSDMapIncremental", /* tp_doc */ | |
572 | 0, /* tp_traverse */ | |
573 | 0, /* tp_clear */ | |
574 | 0, /* tp_richcompare */ | |
575 | 0, /* tp_weaklistoffset */ | |
576 | 0, /* tp_iter */ | |
577 | 0, /* tp_iternext */ | |
578 | BasePyCRUSH_methods, /* tp_methods */ | |
579 | 0, /* tp_members */ | |
580 | 0, /* tp_getset */ | |
581 | 0, /* tp_base */ | |
582 | 0, /* tp_dict */ | |
583 | 0, /* tp_descr_get */ | |
584 | 0, /* tp_descr_set */ | |
585 | 0, /* tp_dictoffset */ | |
586 | (initproc)BasePyCRUSH_init, /* tp_init */ | |
587 | 0, /* tp_alloc */ | |
588 | 0, /* tp_new */ | |
589 | }; |