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.
38 #include <sys/resource.h>
39 #include <sys/types.h>
44 #include "pathconfig.h"
47 #include "planetlab.h"
48 #include "vserver-internal.h"
50 /* I don't like needing to define __KERNEL__ -- mef */
52 #include "kernel/limit.h"
55 #define NONE ({ Py_INCREF(Py_None); Py_None; })
61 vserver_chcontext(PyObject *self, PyObject *args)
66 uint32_t bcaps = ~vc_get_insecurebcaps();
68 if (!PyArg_ParseTuple(args, "I|K", &ctx, &flags))
71 if ((result = pl_chcontext(ctx, flags, bcaps, 0)) < 0)
72 return PyErr_SetFromErrno(PyExc_OSError);
74 return PyBool_FromLong(result);
78 vserver_setup_done(PyObject *self, PyObject *args)
82 if (!PyArg_ParseTuple(args, "I", &ctx))
85 if (pl_setup_done(ctx) < 0)
86 return PyErr_SetFromErrno(PyExc_OSError);
92 vserver_isrunning(PyObject *self, PyObject *args)
99 if (!PyArg_ParseTuple(args, "I", &ctx))
102 sprintf(fname,"/proc/virtual/%d", ctx);
104 if(stat(&fname[0],&statbuf)==0)
105 ret = PyBool_FromLong(1);
107 ret = PyBool_FromLong(0);
113 __vserver_get_rlimit(xid_t xid, int resource) {
114 struct vc_rlimit limits;
118 if (vc_get_rlimit(xid, resource, &limits)==-1)
119 ret = PyErr_SetFromErrno(PyExc_OSError);
121 ret = Py_BuildValue("LLL",limits.hard, limits.soft, limits.min);
127 vserver_get_rlimit(PyObject *self, PyObject *args) {
132 if (!PyArg_ParseTuple(args, "Ii", &xid, &resource))
135 ret = __vserver_get_rlimit(xid, resource);
141 vserver_set_rlimit(PyObject *self, PyObject *args) {
142 struct vc_rlimit limits;
145 int resource, lresource;
148 limits.min = VC_LIM_KEEP;
149 limits.soft = VC_LIM_KEEP;
150 limits.hard = VC_LIM_KEEP;
152 if (!PyArg_ParseTuple(args, "IiLLL", &xid, &resource, &limits.hard, &limits.soft, &limits.min))
155 lresource = resource;
160 goto do_vc_set_rlimit;
162 lresource = RLIMIT_NOFILE;
168 getrlimit(lresource,&lim);
169 if (adjust_lim(&limits,&lim)) {
170 setrlimit(lresource, &lim);
175 if (vc_set_rlimit(xid, resource, &limits)==-1)
176 ret = PyErr_SetFromErrno(PyExc_OSError);
178 ret = __vserver_get_rlimit(xid, resource);
187 vserver_setsched(PyObject *self, PyObject *args)
191 uint32_t cpu_sched_flags = VC_VXF_SCHED_FLAGS;
193 if (!PyArg_ParseTuple(args, "II|I", &ctx, &cpu_share, &cpu_sched_flags))
196 /* ESRCH indicates that there are no processes in the context */
197 if (pl_setsched(ctx, cpu_share, cpu_sched_flags) &&
199 return PyErr_SetFromErrno(PyExc_OSError);
205 vserver_get_dlimit(PyObject *self, PyObject *args)
210 struct vcmd_ctx_dlimit_v0 data;
213 if (!PyArg_ParseTuple(args, "si", &path,&xid))
216 memset(&data, 0, sizeof(data));
219 r = vserver(VCMD_get_dlimit, xid, &data);
221 res = Py_BuildValue("(i,i,i,i,i)",
228 res = PyErr_SetFromErrno(PyExc_OSError);
236 vserver_set_dlimit(PyObject *self, PyObject *args)
240 struct vcmd_ctx_dlimit_base_v0 init;
241 struct vcmd_ctx_dlimit_v0 data;
243 memset(&data,0,sizeof(data));
244 if (!PyArg_ParseTuple(args, "siiiiii", &path,
256 memset(&init, 0, sizeof(init));
260 if ((vserver(VCMD_add_dlimit, xid, &init) && errno != EEXIST) ||
261 vserver(VCMD_set_dlimit, xid, &data))
262 return PyErr_SetFromErrno(PyExc_OSError);
268 vserver_unset_dlimit(PyObject *self, PyObject *args)
272 struct vcmd_ctx_dlimit_base_v0 init;
274 if (!PyArg_ParseTuple(args, "si", &path, &xid))
277 memset(&init, 0, sizeof(init));
281 if (vserver(VCMD_rem_dlimit, xid, &init) && errno != ESRCH)
282 return PyErr_SetFromErrno(PyExc_OSError);
288 vserver_killall(PyObject *self, PyObject *args)
293 if (!PyArg_ParseTuple(args, "Ii", &ctx, &sig))
296 if (vc_ctx_kill(ctx, 0, sig) && errno != ESRCH)
297 return PyErr_SetFromErrno(PyExc_OSError);
302 static PyMethodDef methods[] = {
303 { "chcontext", vserver_chcontext, METH_VARARGS,
304 "chcontext to vserver with provided flags" },
305 { "setup_done", vserver_setup_done, METH_VARARGS,
306 "Release vserver setup lock" },
307 { "setsched", vserver_setsched, METH_VARARGS,
308 "Change vserver scheduling attributes for given vserver context" },
309 { "setdlimit", vserver_set_dlimit, METH_VARARGS,
310 "Set disk limits for given vserver context" },
311 { "unsetdlimit", vserver_unset_dlimit, METH_VARARGS,
312 "Remove disk limits for given vserver context" },
313 { "getdlimit", vserver_get_dlimit, METH_VARARGS,
314 "Get disk limits for given vserver context" },
315 { "setrlimit", vserver_set_rlimit, METH_VARARGS,
316 "Set resource limits for given resource of a vserver context" },
317 { "getrlimit", vserver_get_rlimit, METH_VARARGS,
318 "Get resource limits for given resource of a vserver context" },
319 { "killall", vserver_killall, METH_VARARGS,
320 "Send signal to all processes in vserver context" },
321 { "isrunning", vserver_isrunning, METH_VARARGS,
322 "Check if vserver is running"},
323 { NULL, NULL, 0, NULL }
327 initvserverimpl(void)
331 mod = Py_InitModule("vserverimpl", methods);
333 /* export the set of 'safe' capabilities */
334 PyModule_AddIntConstant(mod, "CAP_SAFE", ~vc_get_insecurebcaps());
336 /* export the default vserver directory */
337 PyModule_AddStringConstant(mod, "VSERVER_BASEDIR", DEFAULT_VSERVERDIR);
339 /* export limit-related constants */
340 PyModule_AddIntConstant(mod, "DLIMIT_KEEP", (int)CDLIM_KEEP);
341 PyModule_AddIntConstant(mod, "DLIMIT_INF", (int)CDLIM_INFINITY);
342 PyModule_AddIntConstant(mod, "VC_LIM_KEEP", (int)VC_LIM_KEEP);
344 PyModule_AddIntConstant(mod, "RLIMIT_CPU", (int)RLIMIT_CPU);
345 PyModule_AddIntConstant(mod, "RLIMIT_RSS", (int)RLIMIT_RSS);
346 PyModule_AddIntConstant(mod, "RLIMIT_NPROC", (int)RLIMIT_NPROC);
347 PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", (int)RLIMIT_NOFILE);
348 PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", (int)RLIMIT_MEMLOCK);
349 PyModule_AddIntConstant(mod, "RLIMIT_AS", (int)RLIMIT_AS);
350 PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", (int)RLIMIT_LOCKS);
352 PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", (int)RLIMIT_SIGPENDING);
353 PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", (int)RLIMIT_MSGQUEUE);
355 PyModule_AddIntConstant(mod, "VLIMIT_NSOCK", (int)VLIMIT_NSOCK);
356 PyModule_AddIntConstant(mod, "VLIMIT_OPENFD", (int)VLIMIT_OPENFD);
357 PyModule_AddIntConstant(mod, "VLIMIT_ANON", (int)VLIMIT_ANON);
358 PyModule_AddIntConstant(mod, "VLIMIT_SHMEM", (int)VLIMIT_SHMEM);
360 /* scheduler flags */
361 PyModule_AddIntConstant(mod,
362 "VS_SCHED_CPU_GUARANTEED",
363 VS_SCHED_CPU_GUARANTEED);