f67597141952e4539b9151f6fc278254bbcb0108
[util-vserver.git] / python / _libvserver.c
1 /* $Id$
2  * Copyright (C) 2008 Daniel Hokka Zakrisson
3  * 
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  * 
18  * vim:set ts=2 sw=2 expandtab:
19  */
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <arpa/inet.h>
27 #include <Python.h>
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include "compat.h"
33 #include "vserver.h"
34
35 static inline PyObject *NONE(void)
36 {
37   Py_INCREF(Py_None);
38   return Py_None;
39 }
40
41 static PyObject *
42 pyvserver_get_version(PyObject UNUSED *self, PyObject UNUSED *args)
43 {
44   int ver = vc_get_version();
45   if (ver == -1)
46     return PyErr_SetFromErrno(PyExc_OSError);
47
48   return Py_BuildValue("i", ver);
49 }
50
51 static PyObject *
52 pyvserver_get_vci(PyObject UNUSED *self, PyObject UNUSED *args)
53 {
54   vc_vci_t vci = vc_get_vci();
55   if (vci == (vc_vci_t)-1)
56     return PyErr_SetFromErrno(PyExc_OSError);
57
58   return Py_BuildValue("K", vci);
59 }
60
61 static PyObject *
62 pyvserver_ctx_create(PyObject UNUSED *self, PyObject *args)
63 {
64   xid_t xid, ret;
65   struct vc_ctx_flags flags = { .mask = 0 };
66
67   if (!PyArg_ParseTuple(args, "I|KK", &xid, &flags.flagword, &flags.mask))
68     return NULL;
69
70   if (flags.flagword && !flags.mask)
71     flags.mask = flags.flagword;
72
73   ret = vc_ctx_create(xid, &flags);
74   if (ret == VC_NOXID)
75     return PyErr_SetFromErrno(PyExc_OSError);
76
77   return Py_BuildValue("I", ret);
78 }
79
80 static PyObject *
81 pyvserver_ctx_migrate(PyObject UNUSED *self, PyObject *args)
82 {
83   xid_t xid;
84   uint_least64_t flags;
85
86   if (!PyArg_ParseTuple(args, "IK", &xid, &flags))
87     return NULL;
88
89   if (vc_ctx_migrate(xid, flags) == -1)
90     return PyErr_SetFromErrno(PyExc_OSError);
91
92   return NONE();
93 }
94
95 static PyObject *
96 pyvserver_ctx_stat(PyObject UNUSED *self, PyObject *args)
97 {
98   xid_t xid;
99   struct vc_ctx_stat stats;
100
101   if (!PyArg_ParseTuple(args, "I", &xid))
102     return NULL;
103
104   if (vc_ctx_stat(xid, &stats) == -1)
105     return PyErr_SetFromErrno(PyExc_OSError);
106
107   return Py_BuildValue("(II)", stats.usecnt, stats.tasks);
108 }
109
110 static PyObject *
111 pyvserver_virt_stat(PyObject UNUSED *self, PyObject *args)
112 {
113   xid_t xid;
114   struct vc_virt_stat stats;
115
116   if (!PyArg_ParseTuple(args, "I", &xid))
117     return NULL;
118
119   if (vc_virt_stat(xid, &stats) == -1)
120     return PyErr_SetFromErrno(PyExc_OSError);
121
122   return Py_BuildValue("(KKIIIIIIII)", stats.offset, stats.uptime,
123                        stats.nr_threads, stats.nr_running,
124                        stats.nr_uninterruptible, stats.nr_onhold,
125                        stats.nr_forks, stats.load[0], stats.load[1],
126                        stats.load[2]);
127 }
128
129 static PyObject *
130 pyvserver_ctx_kill(PyObject UNUSED *self, PyObject *args)
131 {
132   xid_t xid;
133   pid_t pid;
134   int signal;
135
136   if (!PyArg_ParseTuple(args, "Iii", &xid, &pid, &signal))
137     return NULL;
138
139   if (vc_ctx_kill(xid, pid, signal) == -1)
140     return PyErr_SetFromErrno(PyExc_OSError);
141
142   return NONE();
143 }
144
145 static PyObject *
146 pyvserver_get_cflags(PyObject UNUSED *self, PyObject *args)
147 {
148   xid_t xid;
149   struct vc_ctx_flags flags;
150
151   if (!PyArg_ParseTuple(args, "I", &xid))
152     return NULL;
153
154   if (vc_get_cflags(xid, &flags) == -1)
155     return PyErr_SetFromErrno(PyExc_OSError);
156
157   return Py_BuildValue("(KK)", flags.flagword, flags.mask);
158 }
159
160 static PyObject *
161 pyvserver_set_cflags(PyObject UNUSED *self, PyObject *args)
162 {
163   xid_t xid;
164   struct vc_ctx_flags flags;
165
166   if (!PyArg_ParseTuple(args, "I(KK)", &xid, &flags.flagword, &flags.mask))
167     return NULL;
168
169   if (vc_set_cflags(xid, &flags) == -1)
170     return PyErr_SetFromErrno(PyExc_OSError);
171
172   return NONE();
173 }
174
175 static PyObject *
176 pyvserver_get_ccaps(PyObject UNUSED *self, PyObject *args)
177 {
178   xid_t xid;
179   struct vc_ctx_caps caps;
180
181   if (!PyArg_ParseTuple(args, "I", &xid))
182     return NULL;
183
184   if (vc_get_ccaps(xid, &caps) == -1)
185     return PyErr_SetFromErrno(PyExc_OSError);
186
187   return Py_BuildValue("(KKKK)", caps.bcaps, caps.bmask, caps.ccaps,
188                        caps.cmask);
189 }
190
191 static PyObject *
192 pyvserver_set_ccaps(PyObject UNUSED *self, PyObject *args)
193 {
194   xid_t xid;
195   struct vc_ctx_caps caps;
196
197   if (!PyArg_ParseTuple(args, "I(KKKK)", &xid, &caps.bcaps, &caps.bmask,
198                         &caps.ccaps, &caps.cmask))
199     return NULL;
200
201   if (vc_set_ccaps(xid, &caps) == -1)
202     return PyErr_SetFromErrno(PyExc_OSError);
203
204   return NONE();
205 }
206
207 static PyObject *
208 pyvserver_get_vx_info(PyObject UNUSED *self, PyObject *args)
209 {
210   xid_t xid;
211   struct vc_vx_info info;
212
213   if (!PyArg_ParseTuple(args, "I", &xid))
214     return NULL;
215
216   if (vc_get_vx_info(xid, &info) == -1)
217     return PyErr_SetFromErrno(PyExc_OSError);
218
219   return Py_BuildValue("(Ii)", info.xid, info.initpid);
220 }
221
222 static PyObject *
223 pyvserver_get_task_xid(PyObject UNUSED *self, PyObject *args)
224 {
225   pid_t pid;
226   xid_t xid;
227
228   if (!PyArg_ParseTuple(args, "i", &pid))
229     return NULL;
230
231   xid = vc_get_task_xid(pid);
232   if (xid == VC_NOXID)
233     return PyErr_SetFromErrno(PyExc_OSError);
234
235   return Py_BuildValue("I", xid);
236 }
237
238 static PyObject *
239 pyvserver_wait_exit(PyObject UNUSED *self, PyObject *args)
240 {
241   xid_t xid;
242
243   if (!PyArg_ParseTuple(args, "I", &xid))
244     return NULL;
245
246   if (vc_wait_exit(xid) == -1)
247     Py_RETURN_FALSE;
248   else
249     Py_RETURN_TRUE;
250 }
251
252 static PyObject *
253 pyvserver_get_rlimit_mask(PyObject UNUSED *self, PyObject *args)
254 {
255   xid_t xid;
256   struct vc_rlimit_mask mask;
257
258   if (!PyArg_ParseTuple(args, "I", &xid))
259     return NULL;
260
261   if (vc_get_rlimit_mask(xid, &mask) == -1)
262     return PyErr_SetFromErrno(PyExc_OSError);
263
264   return Py_BuildValue("(III)", mask.min, mask.soft, mask.hard);
265 }
266
267 static PyObject *
268 pyvserver_get_rlimit(PyObject UNUSED *self, PyObject *args)
269 {
270   xid_t xid;
271   int resource;
272   struct vc_rlimit limit = { .min = 0 };
273
274   if (!PyArg_ParseTuple(args, "Ii", &xid, &resource))
275     return NULL;
276
277   if (vc_get_rlimit(xid, resource, &limit) == -1)
278     return PyErr_SetFromErrno(PyExc_OSError);
279
280   return Py_BuildValue("(LLL)", limit.min, limit.soft, limit.hard);
281 }
282
283 static PyObject *
284 pyvserver_set_rlimit(PyObject UNUSED *self, PyObject *args)
285 {
286   xid_t xid;
287   int resource;
288   struct vc_rlimit limit = {
289     .min = VC_LIM_KEEP,
290     .soft = VC_LIM_KEEP,
291     .hard = VC_LIM_KEEP
292   };
293
294   if (!PyArg_ParseTuple(args, "Ii(KKK)", &xid, &resource, &limit.min,
295                         &limit.soft, &limit.hard))
296     return NULL;
297
298   if (vc_set_rlimit(xid, resource, &limit) == -1)
299     return PyErr_SetFromErrno(PyExc_OSError);
300
301   return NONE();
302 }
303
304 static PyObject *
305 pyvserver_rlimit_stat(PyObject UNUSED *self, PyObject *args)
306 {
307   xid_t xid;
308   int resource;
309   struct vc_rlimit_stat stats;
310
311   if (!PyArg_ParseTuple(args, "Ii", &xid, &resource))
312     return NULL;
313
314   if (vc_rlimit_stat(xid, resource, &stats) == -1)
315     return PyErr_SetFromErrno(PyExc_OSError);
316
317   return Py_BuildValue("(IKKK)", stats.hits, stats.value, stats.minimum,
318                        stats.maximum);
319 }
320
321 static PyObject *
322 pyvserver_reset_minmax(PyObject UNUSED *self, PyObject *args)
323 {
324   xid_t xid;
325
326   if (!PyArg_ParseTuple(args, "I", &xid))
327     return NULL;
328
329   if (vc_reset_minmax(xid) == -1)
330     return PyErr_SetFromErrno(PyExc_OSError);
331
332   return NONE();
333 }
334
335 static PyObject *
336 pyvserver_get_task_nid(PyObject UNUSED *self, PyObject *args)
337 {
338   pid_t pid;
339   nid_t nid;
340
341   if (!PyArg_ParseTuple(args, "i", &pid))
342     return NULL;
343
344   nid = vc_get_task_nid(pid);
345   if (nid == VC_NONID)
346     return PyErr_SetFromErrno(PyExc_OSError);
347
348   return Py_BuildValue("I", nid);
349 }
350
351 static PyObject *
352 pyvserver_get_nx_info(PyObject UNUSED *self, PyObject *args)
353 {
354   nid_t nid;
355   struct vc_nx_info info;
356
357   if (!PyArg_ParseTuple(args, "I", &nid))
358     return NULL;
359
360   if (vc_get_nx_info(nid, &info) == -1)
361     return PyErr_SetFromErrno(PyExc_OSError);
362
363   return Py_BuildValue("(I)", info.nid);
364 }
365
366 static PyObject *
367 pyvserver_net_create(PyObject UNUSED *self, PyObject *args)
368 {
369   nid_t nid, ret;
370
371   if (!PyArg_ParseTuple(args, "I", &nid))
372     return NULL;
373
374   ret = vc_net_create(nid);
375   if (ret == VC_NONID)
376     return PyErr_SetFromErrno(PyExc_OSError);
377
378   return Py_BuildValue("I", ret);
379 }
380
381 static PyObject *
382 pyvserver_net_migrate(PyObject UNUSED *self, PyObject *args)
383 {
384   nid_t nid;
385
386   if (!PyArg_ParseTuple(args, "I", &nid))
387     return NULL;
388
389   if (vc_net_migrate(nid) == -1)
390     return PyErr_SetFromErrno(PyExc_OSError);
391
392   return NONE();
393 }
394
395 static PyObject *
396 pyvserver_net_handle(PyObject UNUSED *self, PyObject *args,
397                       int (*func)(nid_t nid, struct vc_net_addr const *addr))
398 {
399   nid_t nid;
400   struct vc_net_addr addr;
401   char *ip1, *ip2, *mask;
402
403   if (!PyArg_ParseTuple(args, "I(HHHHsss)", &nid, &addr.vna_type,
404                         &addr.vna_flags, &addr.vna_prefix, &addr.vna_parent,
405                         &ip1, &ip2, &mask))
406     return NULL;
407
408   if (addr.vna_type & VC_NXA_TYPE_IPV6) {
409     if (inet_pton(AF_INET6, ip1, &addr.vna_v6_ip) <= 0 ||
410         inet_pton(AF_INET6, ip2, &addr.vna_v6_ip2) <= 0 ||
411         inet_pton(AF_INET6, mask, &addr.vna_v6_mask) <= 0) {
412       PyErr_SetString(PyExc_ValueError, "invalid IPv6 addresses");
413       return NULL;
414     }
415   }
416   else if (addr.vna_type & VC_NXA_TYPE_IPV4) {
417     if (inet_pton(AF_INET, ip1, &addr.vna_v4_ip) <= 0 ||
418         inet_pton(AF_INET, ip2, &addr.vna_v4_ip2) <= 0 ||
419         inet_pton(AF_INET, mask, &addr.vna_v4_mask) <= 0) {
420       PyErr_SetString(PyExc_ValueError, "invalid IPv4 addresses");
421       return NULL;
422     }
423   }
424   else if (addr.vna_type != VC_NXA_TYPE_ANY) {
425     PyErr_SetString(PyExc_ValueError, "type");
426     return NULL;
427   }
428
429   if (func(nid, &addr) == -1)
430     return PyErr_SetFromErrno(PyExc_OSError);
431
432   return NONE();
433 }
434
435 static PyObject *
436 pyvserver_net_add(PyObject UNUSED *self, PyObject *args)
437 {
438   return pyvserver_net_handle(self, args, vc_net_add);
439 }
440
441 static PyObject *
442 pyvserver_net_remove(PyObject UNUSED *self, PyObject *args)
443 {
444   return pyvserver_net_handle(self, args, vc_net_remove);
445 }
446
447 static PyObject *
448 pyvserver_get_nflags(PyObject UNUSED *self, PyObject *args)
449 {
450   nid_t nid;
451   struct vc_net_flags flags;
452
453   if (!PyArg_ParseTuple(args, "I", &nid))
454     return NULL;
455
456   if (vc_get_nflags(nid, &flags) == -1)
457     return PyErr_SetFromErrno(PyExc_OSError);
458
459   return Py_BuildValue("(KK)", flags.flagword, flags.mask);
460 }
461
462 static PyObject *
463 pyvserver_set_nflags(PyObject UNUSED *self, PyObject *args)
464 {
465   nid_t nid;
466   struct vc_net_flags flags;
467
468   if (!PyArg_ParseTuple(args, "I(KK)", &nid, &flags.flagword, &flags.mask))
469     return NULL;
470
471   if (vc_set_nflags(nid, &flags) == -1)
472     return PyErr_SetFromErrno(PyExc_OSError);
473
474   return NONE();
475 }
476
477 static PyObject *
478 pyvserver_get_ncaps(PyObject UNUSED *self, PyObject *args)
479 {
480   nid_t nid;
481   struct vc_net_caps caps;
482
483   if (!PyArg_ParseTuple(args, "I", &nid))
484     return NULL;
485
486   if (vc_get_ncaps(nid, &caps) == -1)
487     return PyErr_SetFromErrno(PyExc_OSError);
488
489   return Py_BuildValue("(KK)", caps.ncaps, caps.cmask);
490 }
491
492 static PyObject *
493 pyvserver_set_ncaps(PyObject UNUSED *self, PyObject *args)
494 {
495   nid_t nid;
496   struct vc_net_caps caps;
497
498   if (!PyArg_ParseTuple(args, "I(KK)", &nid, &caps.ncaps, &caps.cmask))
499     return NULL;
500
501   if (vc_set_ncaps(nid, &caps) == -1)
502     return PyErr_SetFromErrno(PyExc_OSError);
503
504   return NONE();
505 }
506
507 static PyObject *
508 pyvserver_set_iattr(PyObject UNUSED *self, PyObject *args)
509 {
510   char const *filename;
511   tag_t tag;
512   uint_least32_t flags, mask;
513
514   if (!PyArg_ParseTuple(args, "sIII", &filename, &tag, &flags, &mask))
515     return NULL;
516
517   if (vc_set_iattr(filename, tag, flags, mask) == -1)
518     return PyErr_SetFromErrno(PyExc_OSError);
519
520   return NONE();
521 }
522
523 static PyObject *
524 pyvserver_fset_iattr(PyObject UNUSED *self, PyObject *args)
525 {
526   int fd;
527   tag_t tag;
528   uint_least32_t flags, mask;
529
530   if (!PyArg_ParseTuple(args, "iIII", &fd, &tag, &flags, &mask))
531     return NULL;
532
533   if (vc_fset_iattr(fd, tag, flags, mask) == -1)
534     return PyErr_SetFromErrno(PyExc_OSError);
535
536   return NONE();
537 }
538
539 static PyObject *
540 pyvserver_get_iattr(PyObject UNUSED *self, PyObject *args)
541 {
542   char const *filename;
543   tag_t tag;
544   uint_least32_t flags, mask;
545
546   if (!PyArg_ParseTuple(args, "sI", &filename, &mask))
547     return NULL;
548
549   if (vc_get_iattr(filename, &tag, &flags, &mask) == -1)
550     return PyErr_SetFromErrno(PyExc_OSError);
551
552   return Py_BuildValue("(III)", tag, flags, mask);
553 }
554
555 static PyObject *
556 pyvserver_fget_iattr(PyObject UNUSED *self, PyObject *args)
557 {
558   int fd;
559   tag_t tag;
560   uint_least32_t flags, mask;
561
562   if (!PyArg_ParseTuple(args, "iI", &fd, &mask))
563     return NULL;
564
565   if (vc_fget_iattr(fd, &tag, &flags, &mask) == -1)
566     return PyErr_SetFromErrno(PyExc_OSError);
567
568   return Py_BuildValue("(III)", tag, flags, mask);
569 }
570
571 static PyObject *
572 pyvserver_set_vhi_name(PyObject UNUSED *self, PyObject *args)
573 {
574   xid_t xid;
575   vc_uts_type type;
576   char const *val;
577   int len;
578
579   if (!PyArg_ParseTuple(args, "Iis#", &xid, &type, &val, &len))
580     return NULL;
581
582   if (vc_set_vhi_name(xid, type, val, len) == -1)
583     return PyErr_SetFromErrno(PyExc_OSError);
584
585   return NONE();
586 }
587
588 static PyObject *
589 pyvserver_get_vhi_name(PyObject UNUSED *self, PyObject *args)
590 {
591   xid_t xid;
592   vc_uts_type type;
593   char val[65];
594   int i;
595
596   if (!PyArg_ParseTuple(args, "Ii", &xid, &type))
597     return NULL;
598
599   if (vc_get_vhi_name(xid, type, val, sizeof(val)) == -1)
600     return PyErr_SetFromErrno(PyExc_OSError);
601
602   for (i = sizeof(val); i > 0 && val[i - 1] == '\0'; i--)
603     ;
604
605   return Py_BuildValue("s#", val, i);
606 }
607
608 static PyObject *
609 pyvserver_enter_namespace(PyObject UNUSED *self, PyObject *args)
610 {
611   xid_t xid;
612   uint_least64_t mask;
613   uint32_t index;
614
615   if (!PyArg_ParseTuple(args, "IKI", &xid, &mask, &index))
616     return NULL;
617
618   if (vc_enter_namespace(xid, mask, index) == -1)
619     return PyErr_SetFromErrno(PyExc_OSError);
620
621   return NONE();
622 }
623
624 static PyObject *
625 pyvserver_set_namespace(PyObject UNUSED *self, PyObject *args)
626 {
627   xid_t xid;
628   uint_least64_t mask;
629   uint32_t index;
630
631   if (!PyArg_ParseTuple(args, "IKI", &xid, &mask, &index))
632     return NULL;
633
634   if (vc_set_namespace(xid, mask, index) == -1)
635     return PyErr_SetFromErrno(PyExc_OSError);
636
637   return NONE();
638 }
639
640 static PyObject *
641 pyvserver_get_space_mask(PyObject UNUSED *self, PyObject UNUSED *args)
642 {
643   uint_least64_t mask = vc_get_space_mask();
644   return Py_BuildValue("K", mask);
645 }
646
647 static PyObject *
648 pyvserver_get_space_default(PyObject UNUSED *self, PyObject UNUSED *args)
649 {
650   uint_least64_t mask = vc_get_space_default();
651   return Py_BuildValue("K", mask);
652 }
653
654 static PyObject *
655 pyvserver_add_dlimit(PyObject UNUSED *self, PyObject *args)
656 {
657   char const *filename;
658   tag_t tag;
659   uint_least32_t flags;
660
661   if (!PyArg_ParseTuple(args, "sII", &filename, &tag, &flags))
662     return NULL;
663
664   if (vc_add_dlimit(filename, tag, flags) == -1)
665     return PyErr_SetFromErrno(PyExc_OSError);
666
667   return NONE();
668 }
669
670 static PyObject *
671 pyvserver_rem_dlimit(PyObject UNUSED *self, PyObject *args)
672 {
673   char const *filename;
674   tag_t tag;
675   uint_least32_t flags;
676
677   if (!PyArg_ParseTuple(args, "sII", &filename, &tag, &flags))
678     return NULL;
679
680   if (vc_rem_dlimit(filename, tag, flags) == -1)
681     return PyErr_SetFromErrno(PyExc_OSError);
682
683   return NONE();
684 }
685
686 static PyObject *
687 pyvserver_set_dlimit(PyObject UNUSED *self, PyObject *args)
688 {
689   char const *filename;
690   tag_t tag;
691   uint_least32_t flags;
692   struct vc_ctx_dlimit limit;
693
694   if (!PyArg_ParseTuple(args, "sII(IIIII)", &filename, &tag, &flags,
695                         &limit.space_used, &limit.space_total,
696                         &limit.inodes_used, &limit.inodes_total,
697                         &limit.reserved))
698     return NULL;
699
700   if (vc_set_dlimit(filename, tag, flags, &limit) == -1)
701     return PyErr_SetFromErrno(PyExc_OSError);
702
703   return NONE();
704 }
705
706 static PyObject *
707 pyvserver_get_dlimit(PyObject UNUSED *self, PyObject *args)
708 {
709   char const *filename;
710   tag_t tag;
711   uint_least32_t flags;
712   struct vc_ctx_dlimit limit;
713
714   if (!PyArg_ParseTuple(args, "sII", &filename, &tag, &flags))
715     return NULL;
716
717   if (vc_get_dlimit(filename, tag, flags, &limit) == -1)
718     return PyErr_SetFromErrno(PyExc_OSError);
719
720   return Py_BuildValue("(IIIII)", limit.space_used, limit.space_total,
721                        limit.inodes_used, limit.inodes_total, limit.reserved);
722 }
723
724 static PyObject *
725 pyvserver_get_task_tag(PyObject UNUSED *self, PyObject *args)
726 {
727   pid_t pid;
728   tag_t tag;
729
730   if (!PyArg_ParseTuple(args, "i", &pid))
731     return NULL;
732
733   tag = vc_get_task_tag(pid);
734   if (tag == (tag_t) -1)
735     return PyErr_SetFromErrno(PyExc_OSError);
736
737   return Py_BuildValue("I", tag);
738 }
739
740 static PyObject *
741 pyvserver_tag_create(PyObject UNUSED *self, PyObject *args)
742 {
743   tag_t tag;
744
745   if (!PyArg_ParseTuple(args, "I", &tag))
746     return NULL;
747
748   if (vc_tag_create(tag) == -1)
749     return PyErr_SetFromErrno(PyExc_OSError);
750
751   return NONE();
752 }
753
754 static PyObject *
755 pyvserver_tag_migrate(PyObject UNUSED *self, PyObject *args)
756 {
757   tag_t tag;
758
759   if (!PyArg_ParseTuple(args, "I", &tag))
760     return NULL;
761
762   if (vc_tag_migrate(tag) == -1)
763     return PyErr_SetFromErrno(PyExc_OSError);
764
765   return NONE();
766 }
767
768 static PyObject *
769 pyvserver_set_sched(PyObject UNUSED *self, PyObject *args)
770 {
771   xid_t xid;
772   struct vc_set_sched sched;
773
774   if (!PyArg_ParseTuple(args, "I(Iiiiiiiiiii)", &xid, &sched.set_mask,
775                         &sched.fill_rate, &sched.interval, &sched.fill_rate2,
776                         &sched.interval2, &sched.tokens, &sched.tokens_min,
777                         &sched.tokens_max, &sched.priority_bias, &sched.cpu_id,
778                         &sched.bucket_id))
779     return NULL;
780
781   if (vc_set_sched(xid, &sched) == -1)
782     return PyErr_SetFromErrno(PyExc_OSError);
783
784   return NONE();
785 }
786
787 static PyObject *
788 pyvserver_get_sched(PyObject UNUSED *self, PyObject *args)
789 {
790   xid_t xid;
791   struct vc_set_sched sched;
792
793   if (!PyArg_ParseTuple(args, "Iii", &xid, &sched.cpu_id, &sched.bucket_id))
794     return NULL;
795
796   if (vc_get_sched(xid, &sched) == -1)
797     return PyErr_SetFromErrno(PyExc_OSError);
798
799   return Py_BuildValue("(Iiiiiiiiiii)", sched.set_mask, sched.fill_rate,
800                        sched.interval, sched.fill_rate2, sched.interval2,
801                        sched.tokens, sched.tokens_min, sched.tokens_max,
802                        sched.priority_bias, sched.cpu_id, sched.bucket_id);
803 }
804
805 static PyObject *
806 pyvserver_sched_info(PyObject UNUSED *self, PyObject *args)
807 {
808   xid_t xid;
809   struct vc_sched_info info;
810
811   if (!PyArg_ParseTuple(args, "Iii", &xid, &info.cpu_id, &info.bucket_id))
812     return NULL;
813
814   if (vc_sched_info(xid, &info) == -1)
815     return PyErr_SetFromErrno(PyExc_OSError);
816
817   return Py_BuildValue("(iiKKKIi)", info.cpu_id, info.bucket_id,
818                        info.user_msec, info.sys_msec, info.hold_msec,
819                        info.token_usec, info.vavavoom);
820 }
821
822 static PyObject *
823 pyvserver_set_mapping(PyObject UNUSED *self, PyObject *args)
824 {
825   xid_t xid;
826   const char *device, *target;
827   uint32_t flags;
828
829   if (!PyArg_ParseTuple(args, "IssI", &xid, &device, &target, &flags))
830     return NULL;
831
832   if (vc_set_mapping(xid, device, target, flags) == -1)
833     return PyErr_SetFromErrno(PyExc_OSError);
834
835   return NONE();
836 }
837
838 static PyObject *
839 pyvserver_unset_mapping(PyObject UNUSED *self, PyObject *args)
840 {
841   xid_t xid;
842   const char *device, *target;
843   uint32_t flags;
844
845   if (!PyArg_ParseTuple(args, "IssI", &xid, &device, &target, &flags))
846     return NULL;
847
848   if (vc_unset_mapping(xid, device, target, flags) == -1)
849     return PyErr_SetFromErrno(PyExc_OSError);
850
851   return NONE();
852 }
853
854 static PyObject *
855 pyvserver_get_badness(PyObject UNUSED *self, PyObject *args)
856 {
857   xid_t xid;
858   int64_t badness;
859
860   if (!PyArg_ParseTuple(args, "I", &xid))
861     return NULL;
862
863   if (vc_get_badness(xid, &badness) == -1)
864     return PyErr_SetFromErrno(PyExc_OSError);
865
866   return Py_BuildValue("L", badness);
867 }
868
869 static PyObject *
870 pyvserver_set_badness(PyObject UNUSED *self, PyObject *args)
871 {
872   xid_t xid;
873   int64_t badness;
874
875   if (!PyArg_ParseTuple(args, "IL", &xid, &badness))
876     return NULL;
877
878   if (vc_set_badness(xid, badness) == -1)
879     return PyErr_SetFromErrno(PyExc_OSError);
880
881   return NONE();
882 }
883
884 static PyObject *
885 pyvserver_get_insecurebcaps(PyObject UNUSED *self, PyObject UNUSED *args)
886 {
887   uint_least64_t bcaps = vc_get_insecurebcaps();
888   return Py_BuildValue("K", bcaps);
889 }
890
891 static PyObject *
892 pyvserver_get_insecureccaps(PyObject UNUSED *self, PyObject UNUSED *args)
893 {
894   uint_least64_t ccaps = vc_get_insecureccaps();
895   return Py_BuildValue("K", ccaps);
896 }
897
898 static PyObject *
899 pyvserver_isSupported(PyObject UNUSED *self, PyObject *args)
900 {
901   int feature;
902
903   if (!PyArg_ParseTuple(args, "i", &feature))
904     return NULL;
905
906   if (vc_isSupported(feature))
907     Py_RETURN_TRUE;
908   else
909     Py_RETURN_FALSE;
910 }
911
912 static PyObject *
913 pyvserver_isSupportedString(PyObject UNUSED *self, PyObject *args)
914 {
915   char const *feature;
916
917   if (!PyArg_ParseTuple(args, "s", &feature))
918     return NULL;
919
920   if (vc_isSupportedString(feature))
921     Py_RETURN_TRUE;
922   else
923     Py_RETURN_FALSE;
924 }
925
926 static PyObject *
927 pyvserver_getXIDType(PyObject UNUSED *self, PyObject *args)
928 {
929   xid_t xid;
930
931   if (!PyArg_ParseTuple(args, "I", &xid))
932     return NULL;
933
934   return Py_BuildValue("i", vc_getXIDType(xid));
935 }
936
937 static PyObject *
938 pyvserver_xidopt2xid(PyObject UNUSED *self, PyObject *args)
939 {
940   char const *xidopt;
941   PyObject *honor_static;
942   xid_t xid;
943   char const *err_info;
944
945   if (!PyArg_ParseTuple(args, "sO", &xidopt, &honor_static))
946     return NULL;
947
948   xid = vc_xidopt2xid(xidopt, honor_static != Py_False, &err_info);
949   if (xid == VC_NOXID) {
950     PyErr_SetString(PyExc_OSError, err_info);
951     return NULL;
952   }
953
954   return Py_BuildValue("I", xid);
955 }
956
957 static PyObject *
958 pyvserver_nidopt2nid(PyObject UNUSED *self, PyObject *args)
959 {
960   char const *nidopt;
961   PyObject *honor_static;
962   nid_t nid;
963   char const *err_info;
964
965   if (!PyArg_ParseTuple(args, "sO", &nidopt, &honor_static))
966     return NULL;
967
968   nid = vc_nidopt2nid(nidopt, honor_static != Py_False, &err_info);
969   if (nid == VC_NONID) {
970     PyErr_SetString(PyExc_OSError, err_info);
971     return NULL;
972   }
973
974   return Py_BuildValue("I", nid);
975 }
976
977 static PyObject *
978 pyvserver_tagopt2tag(PyObject UNUSED *self, PyObject *args)
979 {
980   char const *tagopt;
981   PyObject *honor_static;
982   tag_t tag;
983   char const *err_info;
984
985   if (!PyArg_ParseTuple(args, "sO", &tagopt, &honor_static))
986     return NULL;
987
988   tag = vc_tagopt2tag(tagopt, honor_static != Py_False, &err_info);
989   if (tag == (tag_t) -1) {
990     PyErr_SetString(PyExc_OSError, err_info);
991     return NULL;
992   }
993
994   return Py_BuildValue("I", tag);
995 }
996
997 #define pyvserver_handle_list(name, list_type, flag_member, mask_member) \
998 static PyObject *  \
999 pyvserver_text2 ## name(PyObject UNUSED *self, PyObject *args) \
1000 { \
1001   char const *str; \
1002   int len; \
1003   uint_least64_t val; \
1004 \
1005   if (!PyArg_ParseTuple(args, "s#", &str, &len)) \
1006     return NULL; \
1007 \
1008   val = vc_text2 ## name(str, len); \
1009   return Py_BuildValue("K", val); \
1010 } \
1011 \
1012 static PyObject * \
1013 pyvserver_lo ## name ## 2text(PyObject UNUSED *self, PyObject *args) \
1014 { \
1015   uint_least64_t val; \
1016   char const *ret; \
1017 \
1018   if (!PyArg_ParseTuple(args, "K", &val)) \
1019     return NULL; \
1020 \
1021   ret = vc_lo ## name ## 2text(&val); \
1022   return Py_BuildValue("(Kz)", val, ret); \
1023 } \
1024 \
1025 static PyObject * \
1026 pyvserver_list2 ## name(PyObject UNUSED *self, PyObject *args) \
1027 { \
1028   char const *str; \
1029   int len; \
1030   struct vc_err_listparser err; \
1031   list_type val = { .mask_member = 0 }; \
1032 \
1033   if (!PyArg_ParseTuple(args, "s#", &str, &len)) \
1034     return NULL; \
1035 \
1036   if (vc_list2 ## name(str, len, &err, &val) == -1) { \
1037     char *error; \
1038     if (asprintf(&error, "unknown value '%.*s'", (int)err.len, err.ptr) == -1) \
1039       return PyErr_SetFromErrno(PyExc_MemoryError); \
1040     PyErr_SetString(PyExc_ValueError, error); \
1041     free(error); \
1042     return NULL; \
1043   } \
1044 \
1045   return Py_BuildValue("(KK)", val.flag_member, val.mask_member); \
1046 }
1047
1048 pyvserver_handle_list(bcap, struct vc_ctx_caps, bcaps, bmask)
1049 pyvserver_handle_list(ccap, struct vc_ctx_caps, ccaps, cmask)
1050 pyvserver_handle_list(cflag, struct vc_ctx_flags, flagword, mask)
1051 pyvserver_handle_list(nflag, struct vc_net_flags, flagword, mask)
1052 pyvserver_handle_list(ncap, struct vc_net_caps, ncaps, cmask)
1053
1054 static PyMethodDef methods[] = {
1055   { "vc_get_version", pyvserver_get_version, METH_NOARGS, "FIXME" },
1056   { "vc_get_vci", pyvserver_get_vci, METH_NOARGS, "FIXME" },
1057   { "vc_ctx_create", pyvserver_ctx_create, METH_VARARGS, "FIXME" },
1058   { "vc_ctx_migrate", pyvserver_ctx_migrate, METH_VARARGS, "FIXME" },
1059   { "vc_ctx_stat", pyvserver_ctx_stat, METH_VARARGS, "FIXME" },
1060   { "vc_virt_stat", pyvserver_virt_stat, METH_VARARGS, "FIXME" },
1061   { "vc_ctx_kill", pyvserver_ctx_kill, METH_VARARGS, "FIXME" },
1062   { "vc_get_cflags", pyvserver_get_cflags, METH_VARARGS, "FIXME" },
1063   { "vc_set_cflags", pyvserver_set_cflags, METH_VARARGS, "FIXME" },
1064   { "vc_get_ccaps", pyvserver_get_ccaps, METH_VARARGS, "FIXME" },
1065   { "vc_set_ccaps", pyvserver_set_ccaps, METH_VARARGS, "FIXME" },
1066   { "vc_get_vx_info", pyvserver_get_vx_info, METH_VARARGS, "FIXME" },
1067   { "vc_get_task_xid", pyvserver_get_task_xid, METH_VARARGS, "FIXME" },
1068   { "vc_wait_exit", pyvserver_wait_exit, METH_VARARGS, "FIXME" },
1069   { "vc_get_rlimit_mask", pyvserver_get_rlimit_mask, METH_VARARGS, "FIXME" },
1070   { "vc_get_rlimit", pyvserver_get_rlimit, METH_VARARGS, "FIXME" },
1071   { "vc_set_rlimit", pyvserver_set_rlimit, METH_VARARGS, "FIXME" },
1072   { "vc_rlimit_stat", pyvserver_rlimit_stat, METH_VARARGS, "FIXME" },
1073   { "vc_reset_minmax", pyvserver_reset_minmax, METH_VARARGS, "FIXME" },
1074   { "vc_get_task_nid", pyvserver_get_task_nid, METH_VARARGS, "FIXME" },
1075   { "vc_get_nx_info", pyvserver_get_nx_info, METH_VARARGS, "FIXME" },
1076   { "vc_net_create", pyvserver_net_create, METH_VARARGS, "FIXME" },
1077   { "vc_net_migrate", pyvserver_net_migrate, METH_VARARGS, "FIXME" },
1078   { "vc_net_add", pyvserver_net_add, METH_VARARGS, "FIXME" },
1079   { "vc_net_remove", pyvserver_net_remove, METH_VARARGS, "FIXME" },
1080   { "vc_get_nflags", pyvserver_get_nflags, METH_VARARGS, "FIXME" },
1081   { "vc_set_nflags", pyvserver_set_nflags, METH_VARARGS, "FIXME" },
1082   { "vc_get_ncaps", pyvserver_get_ncaps, METH_VARARGS, "FIXME" },
1083   { "vc_set_ncaps", pyvserver_set_ncaps, METH_VARARGS, "FIXME" },
1084   { "vc_set_iattr", pyvserver_set_iattr, METH_VARARGS, "FIXME" },
1085   { "vc_fset_iattr", pyvserver_fset_iattr, METH_VARARGS, "FIXME" },
1086   { "vc_get_iattr", pyvserver_get_iattr, METH_VARARGS, "FIXME" },
1087   { "vc_fget_iattr", pyvserver_fget_iattr, METH_VARARGS, "FIXME" },
1088   { "vc_set_vhi_name", pyvserver_set_vhi_name, METH_VARARGS, "FIXME" },
1089   { "vc_get_vhi_name", pyvserver_get_vhi_name, METH_VARARGS, "FIXME" },
1090   { "vc_enter_namespace", pyvserver_enter_namespace, METH_VARARGS, "FIXME" },
1091   { "vc_set_namespace", pyvserver_set_namespace, METH_VARARGS, "FIXME" },
1092   { "vc_get_space_mask", pyvserver_get_space_mask, METH_NOARGS, "FIXME" },
1093   { "vc_get_space_default", pyvserver_get_space_default, METH_NOARGS, "FIXME" },
1094   { "vc_add_dlimit", pyvserver_add_dlimit, METH_VARARGS, "FIXME" },
1095   { "vc_rem_dlimit", pyvserver_rem_dlimit, METH_VARARGS, "FIXME" },
1096   { "vc_set_dlimit", pyvserver_set_dlimit, METH_VARARGS, "FIXME" },
1097   { "vc_get_dlimit", pyvserver_get_dlimit, METH_VARARGS, "FIXME" },
1098   { "vc_get_task_tag", pyvserver_get_task_tag, METH_VARARGS, "FIXME" },
1099   { "vc_tag_create", pyvserver_tag_create, METH_VARARGS, "FIXME" },
1100   { "vc_tag_migrate", pyvserver_tag_migrate, METH_VARARGS, "FIXME" },
1101   { "vc_set_sched", pyvserver_set_sched, METH_VARARGS, "FIXME" },
1102   { "vc_get_sched", pyvserver_get_sched, METH_VARARGS, "FIXME" },
1103   { "vc_sched_info", pyvserver_sched_info, METH_VARARGS, "FIXME" },
1104   { "vc_set_mapping", pyvserver_set_mapping, METH_VARARGS, "FIXME" },
1105   { "vc_unset_mapping", pyvserver_unset_mapping, METH_VARARGS, "FIXME" },
1106   { "vc_get_badness", pyvserver_get_badness, METH_VARARGS, "FIXME" },
1107   { "vc_set_badness", pyvserver_set_badness, METH_VARARGS, "FIXME" },
1108   { "vc_get_insecurebcaps", pyvserver_get_insecurebcaps, METH_NOARGS, "FIXME" },
1109   { "vc_get_insecureccaps", pyvserver_get_insecureccaps, METH_NOARGS, "FIXME" },
1110   { "vc_isSupported", pyvserver_isSupported, METH_VARARGS, "FIXME" },
1111   { "vc_isSupportedString", pyvserver_isSupportedString, METH_VARARGS, "FIXME" },
1112   { "vc_getXIDType", pyvserver_getXIDType, METH_VARARGS, "FIXME" },
1113   { "vc_xidopt2xid", pyvserver_xidopt2xid, METH_VARARGS, "FIXME" },
1114   { "vc_nidopt2nid", pyvserver_nidopt2nid, METH_VARARGS, "FIXME" },
1115   { "vc_tagopt2tag", pyvserver_tagopt2tag, METH_VARARGS, "FIXME" },
1116   { "vc_text2bcap", pyvserver_text2bcap, METH_VARARGS, "FIXME" },
1117   { "vc_lobcap2text", pyvserver_lobcap2text, METH_VARARGS, "FIXME" },
1118   { "vc_list2bcap", pyvserver_list2bcap, METH_VARARGS, "FIXME" },
1119   { "vc_text2ccap", pyvserver_text2ccap, METH_VARARGS, "FIXME" },
1120   { "vc_loccap2text", pyvserver_loccap2text, METH_VARARGS, "FIXME" },
1121   { "vc_list2ccap", pyvserver_list2ccap, METH_VARARGS, "FIXME" },
1122   { "vc_text2cflag", pyvserver_text2cflag, METH_VARARGS, "FIXME" },
1123   { "vc_locflag2text", pyvserver_locflag2text, METH_VARARGS, "FIXME" },
1124   { "vc_list2cflag", pyvserver_list2cflag, METH_VARARGS, "FIXME" },
1125   { "vc_text2nflag", pyvserver_text2nflag, METH_VARARGS, "FIXME" },
1126   { "vc_lonflag2text", pyvserver_lonflag2text, METH_VARARGS, "FIXME" },
1127   { "vc_list2nflag", pyvserver_list2nflag, METH_VARARGS, "FIXME" },
1128   { "vc_text2ncap", pyvserver_text2ncap, METH_VARARGS, "FIXME" },
1129   { "vc_loncap2text", pyvserver_loncap2text, METH_VARARGS, "FIXME" },
1130   { "vc_list2ncap", pyvserver_list2ncap, METH_VARARGS, "FIXME" },
1131   { NULL, NULL, 0, NULL }
1132 };
1133
1134 static void
1135 PyModule_AddLongLongConstant(PyObject *mod, const char *str, long long val)
1136 {
1137         PyObject *o = PyLong_FromLongLong(val);
1138         if (!o || PyModule_AddObject(mod, str, o) == -1)
1139                 /* This ought to be reported somehow... */
1140                 return;
1141 }
1142
1143 PyMODINIT_FUNC init_libvserver(void)
1144 {
1145   PyObject *mod;
1146
1147   mod = Py_InitModule("_libvserver", methods);
1148 #include "_libvserver-constants.c"
1149 }