Makes sense to check that this actually compiles
[util-vserver.git] / python / vserverimpl.c
1 /* Copyright 2005 Princeton University
2
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions
5 are met: 
6
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9       
10     * Redistributions in binary form must reproduce the above
11       copyright notice, this list of conditions and the following
12       disclaimer in the documentation and/or other materials provided
13       with the distribution.
14       
15     * Neither the name of the copyright holder nor the names of its
16       contributors may be used to endorse or promote products derived
17       from this software without specific prior written permission.
18       
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PRINCETON
23 UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29 WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE. 
31
32 */
33
34 #include <Python.h>
35
36 #include <errno.h>
37 #include <stdint.h>
38 #include <unistd.h>
39
40 #include "config.h"
41 #include "pathconfig.h"
42 #include "planetlab.h"
43 #include "virtual.h"
44 #include "vserver.h"
45 #include "vserver-internal.h"
46
47 /*
48  * context create
49  */
50 static PyObject *
51 vserver_chcontext(PyObject *self, PyObject *args)
52 {
53   xid_t  ctx;
54   uint32_t  flags = 0;
55   uint32_t  bcaps = ~vc_get_insecurebcaps();
56   rspec_t  rspec = { 32, VC_VXF_SCHED_FLAGS, -1, -1 };
57   PyObject  *resources;
58   PyObject  *cpu_share;
59
60   if (!PyArg_ParseTuple(args, "IO|K", &ctx, &resources, &flags))
61     return NULL;
62   if (!PyMapping_Check(resources))
63     {
64       PyErr_SetString(PyExc_TypeError, "invalid resources object");
65       return NULL;
66     }
67   if ((cpu_share = PyMapping_GetItemString(resources, "nm_cpu_share")) &&
68       (cpu_share = PyNumber_Int(cpu_share)))
69     rspec.cpu_share = PyInt_AsLong(cpu_share);
70
71   if (pl_chcontext(ctx, flags, bcaps, &rspec))
72     PyErr_SetFromErrno(PyExc_OSError);
73
74   return Py_None;
75 }
76
77 static PyObject *
78 vserver_set_rlimit(PyObject *self, PyObject *args) {
79         struct vc_rlimit limits;
80         xid_t xid;
81         int resource;
82         PyObject *ret;
83
84         limits.min = VC_LIM_KEEP;
85         limits.soft = VC_LIM_KEEP;
86         limits.hard = VC_LIM_KEEP;
87
88         if (!PyArg_ParseTuple(args, "IiL", &xid, &resource, &limits.hard))
89                 return NULL;
90
91         ret = Py_None;
92         if (vc_set_rlimit(xid, resource, &limits)) 
93                 ret = PyErr_SetFromErrno(PyExc_OSError);
94         else if (vc_get_rlimit(xid, resource, &limits)==-1)
95                 ret = PyErr_SetFromErrno(PyExc_OSError);
96         else
97                 ret = Py_BuildValue("L",limits.hard);
98
99         return ret;
100 }
101
102 static PyObject *
103 vserver_get_rlimit(PyObject *self, PyObject *args) {
104         struct vc_rlimit limits;
105         xid_t xid;
106         int resource;
107         PyObject *ret;
108
109         limits.min = VC_LIM_KEEP;
110         limits.soft = VC_LIM_KEEP;
111         limits.hard = VC_LIM_KEEP;
112
113         if (!PyArg_ParseTuple(args, "Ii", &xid, &resource))
114                 return NULL;
115
116         ret = Py_None;
117         if (vc_get_rlimit(xid, resource, &limits)==-1)
118                 ret = PyErr_SetFromErrno(PyExc_OSError);
119         else
120                 ret = Py_BuildValue("L",limits.hard);
121
122         return ret;
123 }
124
125 /*
126  * setsched
127  */
128 static PyObject *
129 vserver_setsched(PyObject *self, PyObject *args)
130 {
131   xid_t  ctx;
132   rspec_t  rspec = { 32, VC_VXF_SCHED_FLAGS, -1, -1 };
133   PyObject  *resources;
134   PyObject  *cpu_share;
135
136   if (!PyArg_ParseTuple(args, "IO", &ctx, &resources))
137     return NULL;
138   if (!PyMapping_Check(resources))
139     {
140       PyErr_SetString(PyExc_TypeError, "invalid resources object");
141       return NULL;
142     }
143   if ((cpu_share = PyMapping_GetItemString(resources, "nm_cpu_share")) &&
144       (cpu_share = PyNumber_Int(cpu_share)))
145     rspec.cpu_share = PyInt_AsLong(cpu_share);
146
147   if (pl_setsched(ctx, rspec.cpu_share, rspec.cpu_sched_flags))
148     PyErr_SetFromErrno(PyExc_OSError);
149
150   return Py_None;
151 }
152
153 static PyObject *
154 vserver_get_dlimit(PyObject *self, PyObject *args)
155 {
156         PyObject *res;
157         char* path;
158         unsigned xid;
159         struct vcmd_ctx_dlimit_v0 data;
160         int r;
161
162         if (!PyArg_ParseTuple(args, "si", &path,&xid))
163                 return NULL;
164
165         memset(&data, 0, sizeof(data));
166         data.name = path;
167         data.flags = 0;
168         r = vserver(VCMD_get_dlimit, xid, &data);
169         if (r>=0) {
170                 res = Py_BuildValue("(i,i,i,i,i)",
171                                     data.space_used,
172                                     data.space_total,
173                                     data.inodes_used,
174                                     data.inodes_total,
175                                     data.reserved);
176         } else {
177                 res = PyErr_SetFromErrno(PyExc_OSError);
178         }
179
180         return res;
181 }
182
183
184 static PyObject *
185 vserver_set_dlimit(PyObject *self, PyObject *args)
186 {
187         char* path;
188         unsigned xid;
189         struct vcmd_ctx_dlimit_base_v0 init;
190         struct vcmd_ctx_dlimit_v0 data;
191
192         memset(&data,0,sizeof(data));
193         if (!PyArg_ParseTuple(args, "siiiiii", &path,
194                               &xid,
195                               &data.space_used,
196                               &data.space_total,
197                               &data.inodes_used,
198                               &data.inodes_total,
199                               &data.reserved))
200                 return NULL;
201
202         data.name = path;
203         data.flags = 0;
204
205         memset(&init, 0, sizeof(init));
206         init.name = path;
207         init.flags = 0;
208
209         if ((vserver(VCMD_add_dlimit, xid, &init) && errno != EEXIST) ||
210             vserver(VCMD_set_dlimit, xid, &data))
211           return PyErr_SetFromErrno(PyExc_OSError);
212
213         return Py_None; 
214 }
215
216 static PyObject *
217 vserver_unset_dlimit(PyObject *self, PyObject *args)
218 {
219   char  *path;
220   unsigned  xid;
221   struct vcmd_ctx_dlimit_base_v0  init;
222
223   if (!PyArg_ParseTuple(args, "si", &path, &xid))
224     return NULL;
225
226   memset(&init, 0, sizeof(init));
227   init.name = path;
228   init.flags = 0;
229
230   if (vserver(VCMD_rem_dlimit, xid, &init) && errno != ESRCH)
231     return PyErr_SetFromErrno(PyExc_OSError);
232
233   return Py_None;       
234 }
235
236 static PyMethodDef  methods[] = {
237   { "chcontext", vserver_chcontext, METH_VARARGS,
238     "chcontext to vserver with provided flags" },
239   { "setsched", vserver_setsched, METH_VARARGS,
240     "Change vserver scheduling attributes for given vserver context" },
241   { "setdlimit", vserver_set_dlimit, METH_VARARGS,
242     "Set disk limits for given vserver context" },
243   { "unsetdlimit", vserver_unset_dlimit, METH_VARARGS,
244     "Remove disk limits for given vserver context" },
245   { "getdlimit", vserver_get_dlimit, METH_VARARGS,
246     "Get disk limits for given vserver context" },
247   { "setrlimit", vserver_set_rlimit, METH_VARARGS,
248     "Set resource limits for given resource of a vserver context" },
249   { "getrlimit", vserver_get_rlimit, METH_VARARGS,
250     "Get resource limits for given resource of a vserver context" },
251   { NULL, NULL, 0, NULL }
252 };
253
254 PyMODINIT_FUNC
255 initvserverimpl(void)
256 {
257   PyObject  *mod;
258
259   mod = Py_InitModule("vserverimpl", methods);
260
261   /* export the set of 'safe' capabilities */
262   PyModule_AddIntConstant(mod, "CAP_SAFE", ~vc_get_insecurebcaps());
263
264   /* export the default vserver directory */
265   PyModule_AddStringConstant(mod, "VSERVER_BASEDIR", DEFAULT_VSERVERDIR);
266
267   /* export limit-related constants */
268   PyModule_AddIntConstant(mod, "DLIMIT_KEEP", (int)CDLIM_KEEP);
269   PyModule_AddIntConstant(mod, "DLIMIT_INF", (int)CDLIM_INFINITY);
270 }