1 /* Copyright 2005 Princeton University
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
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.
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.
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.
39 #include <sys/resource.h>
42 #include "pathconfig.h"
45 #include "planetlab.h"
46 #include "vserver-internal.h"
48 /* I don't like needing to define __KERNEL__ -- mef */
50 #include "kernel/limit.h"
53 #define NONE ({ Py_INCREF(Py_None); Py_None; })
59 vserver_chcontext(PyObject *self, PyObject *args)
64 uint32_t bcaps = ~vc_get_insecurebcaps();
66 if (!PyArg_ParseTuple(args, "I|K", &ctx, &flags))
69 if ((result = pl_chcontext(ctx, flags, bcaps, 0)) < 0)
70 return PyErr_SetFromErrno(PyExc_OSError);
72 return PyBool_FromLong(result);
76 vserver_setup_done(PyObject *self, PyObject *args)
80 if (!PyArg_ParseTuple(args, "I", &ctx))
83 if (pl_setup_done(ctx) < 0)
84 return PyErr_SetFromErrno(PyExc_OSError);
90 vserver_isrunning(PyObject *self, PyObject *args)
92 struct vc_vx_info vx_info;
96 if (!PyArg_ParseTuple(args, "I", &ctx))
99 switch (vc_get_vx_info(ctx, &vx_info)) {
103 return PyErr_SetFromErrno(PyExc_OSError);
105 /* XXX should be boolean */
106 ret = Py_BuildValue("L",0);
109 /* XXX should be boolean */
110 ret = Py_BuildValue("L",1);
117 __vserver_get_rlimit(xid_t xid, int resource) {
118 struct vc_rlimit limits;
121 if (vc_get_rlimit(xid, resource, &limits)==-1)
122 ret = PyErr_SetFromErrno(PyExc_OSError);
124 ret = Py_BuildValue("LLL",limits.hard, limits.soft, limits.min);
130 vserver_get_rlimit(PyObject *self, PyObject *args) {
135 if (!PyArg_ParseTuple(args, "Ii", &xid, &resource))
138 ret = __vserver_get_rlimit(xid, resource);
144 vserver_set_rlimit(PyObject *self, PyObject *args) {
145 struct vc_rlimit limits;
146 struct rlimit olim, nlim;
148 int resource, lresource;
151 limits.min = VC_LIM_KEEP;
152 limits.soft = VC_LIM_KEEP;
153 limits.hard = VC_LIM_KEEP;
155 if (!PyArg_ParseTuple(args, "IiLLL", &xid, &resource, &limits.hard, &limits.soft, &limits.min))
158 lresource = resource;
163 goto do_vc_set_rlimit;
165 lresource = RLIMIT_NOFILE;
170 getrlimit(lresource,&olim);
171 if ((limits.min != VC_LIM_KEEP) && (limits.min > olim.rlim_cur)) {
172 nlim.rlim_cur = limits.min;
173 if (limits.min > olim.rlim_max) {
174 nlim.rlim_max = limits.min;
176 nlim.rlim_max = olim.rlim_max;
178 setrlimit(lresource, &nlim);
182 if (vc_set_rlimit(xid, resource, &limits))
183 ret = PyErr_SetFromErrno(PyExc_OSError);
185 ret = __vserver_get_rlimit(xid, resource);
194 vserver_setsched(PyObject *self, PyObject *args)
198 uint32_t cpu_sched_flags = VC_VXF_SCHED_FLAGS;
200 if (!PyArg_ParseTuple(args, "II|I", &ctx, &cpu_share, &cpu_sched_flags))
203 /* ESRCH indicates that there are no processes in the context */
204 if (pl_setsched(ctx, cpu_share, cpu_sched_flags) &&
206 return PyErr_SetFromErrno(PyExc_OSError);
212 vserver_get_dlimit(PyObject *self, PyObject *args)
217 struct vcmd_ctx_dlimit_v0 data;
220 if (!PyArg_ParseTuple(args, "si", &path,&xid))
223 memset(&data, 0, sizeof(data));
226 r = vserver(VCMD_get_dlimit, xid, &data);
228 res = Py_BuildValue("(i,i,i,i,i)",
235 res = PyErr_SetFromErrno(PyExc_OSError);
243 vserver_set_dlimit(PyObject *self, PyObject *args)
247 struct vcmd_ctx_dlimit_base_v0 init;
248 struct vcmd_ctx_dlimit_v0 data;
250 memset(&data,0,sizeof(data));
251 if (!PyArg_ParseTuple(args, "siiiiii", &path,
263 memset(&init, 0, sizeof(init));
267 if ((vserver(VCMD_add_dlimit, xid, &init) && errno != EEXIST) ||
268 vserver(VCMD_set_dlimit, xid, &data))
269 return PyErr_SetFromErrno(PyExc_OSError);
275 vserver_unset_dlimit(PyObject *self, PyObject *args)
279 struct vcmd_ctx_dlimit_base_v0 init;
281 if (!PyArg_ParseTuple(args, "si", &path, &xid))
284 memset(&init, 0, sizeof(init));
288 if (vserver(VCMD_rem_dlimit, xid, &init) && errno != ESRCH)
289 return PyErr_SetFromErrno(PyExc_OSError);
295 vserver_killall(PyObject *self, PyObject *args)
300 if (!PyArg_ParseTuple(args, "Ii", &ctx, &sig))
303 if (vc_ctx_kill(ctx, 0, sig) && errno != ESRCH)
304 return PyErr_SetFromErrno(PyExc_OSError);
309 static PyMethodDef methods[] = {
310 { "chcontext", vserver_chcontext, METH_VARARGS,
311 "chcontext to vserver with provided flags" },
312 { "setup_done", vserver_setup_done, METH_VARARGS,
313 "Release vserver setup lock" },
314 { "setsched", vserver_setsched, METH_VARARGS,
315 "Change vserver scheduling attributes for given vserver context" },
316 { "setdlimit", vserver_set_dlimit, METH_VARARGS,
317 "Set disk limits for given vserver context" },
318 { "unsetdlimit", vserver_unset_dlimit, METH_VARARGS,
319 "Remove disk limits for given vserver context" },
320 { "getdlimit", vserver_get_dlimit, METH_VARARGS,
321 "Get disk limits for given vserver context" },
322 { "setrlimit", vserver_set_rlimit, METH_VARARGS,
323 "Set resource limits for given resource of a vserver context" },
324 { "getrlimit", vserver_get_rlimit, METH_VARARGS,
325 "Get resource limits for given resource of a vserver context" },
326 { "killall", vserver_killall, METH_VARARGS,
327 "Send signal to all processes in vserver context" },
328 { "isrunning", vserver_isrunning, METH_VARARGS,
329 "Check if vserver is running"},
330 { NULL, NULL, 0, NULL }
334 initvserverimpl(void)
338 mod = Py_InitModule("vserverimpl", methods);
340 /* export the set of 'safe' capabilities */
341 PyModule_AddIntConstant(mod, "CAP_SAFE", ~vc_get_insecurebcaps());
343 /* export the default vserver directory */
344 PyModule_AddStringConstant(mod, "VSERVER_BASEDIR", DEFAULT_VSERVERDIR);
346 /* export limit-related constants */
347 PyModule_AddIntConstant(mod, "DLIMIT_KEEP", (int)CDLIM_KEEP);
348 PyModule_AddIntConstant(mod, "DLIMIT_INF", (int)CDLIM_INFINITY);
349 PyModule_AddIntConstant(mod, "VC_LIM_KEEP", (int)VC_LIM_KEEP);
351 PyModule_AddIntConstant(mod, "RLIMIT_CPU", (int)RLIMIT_CPU);
352 PyModule_AddIntConstant(mod, "RLIMIT_RSS", (int)RLIMIT_RSS);
353 PyModule_AddIntConstant(mod, "RLIMIT_NPROC", (int)RLIMIT_NPROC);
354 PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", (int)RLIMIT_NOFILE);
355 PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", (int)RLIMIT_MEMLOCK);
356 PyModule_AddIntConstant(mod, "RLIMIT_AS", (int)RLIMIT_AS);
357 PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", (int)RLIMIT_LOCKS);
359 PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", (int)RLIMIT_SIGPENDING);
360 PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", (int)RLIMIT_MSGQUEUE);
362 PyModule_AddIntConstant(mod, "VLIMIT_NSOCK", (int)VLIMIT_NSOCK);
363 PyModule_AddIntConstant(mod, "VLIMIT_OPENFD", (int)VLIMIT_OPENFD);
364 PyModule_AddIntConstant(mod, "VLIMIT_ANON", (int)VLIMIT_ANON);
365 PyModule_AddIntConstant(mod, "VLIMIT_SHMEM", (int)VLIMIT_SHMEM);
367 /* scheduler flags */
368 PyModule_AddIntConstant(mod,
369 "VS_SCHED_CPU_GUARANTEED",
370 VS_SCHED_CPU_GUARANTEED);