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