Use common function to enter vserver context and set resource limits
[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, 4 };
57
58   if (!PyArg_ParseTuple(args, "I|K", &ctx, &flags))
59     return NULL;
60
61   if (pl_chcontext(ctx, flags, bcaps, &rspec))
62     PyErr_SetFromErrno(PyExc_OSError);
63
64   return Py_None;
65 }
66
67 static PyObject *
68 vserver_set_rlimit(PyObject *self, PyObject *args) {
69         struct vc_rlimit limits;
70         xid_t xid;
71         int resource;
72         PyObject *ret;
73
74         limits.min = VC_LIM_KEEP;
75         limits.soft = VC_LIM_KEEP;
76         limits.hard = VC_LIM_KEEP;
77
78         if (!PyArg_ParseTuple(args, "IiL", &xid, &resource, &limits.hard))
79                 return NULL;
80
81         ret = Py_None;
82         if (vc_set_rlimit(xid, resource, &limits)) 
83                 ret = PyErr_SetFromErrno(PyExc_OSError);
84         else if (vc_get_rlimit(xid, resource, &limits)==-1)
85                 ret = PyErr_SetFromErrno(PyExc_OSError);
86         else
87                 ret = Py_BuildValue("L",limits.hard);
88
89         return ret;
90 }
91
92 static PyObject *
93 vserver_get_rlimit(PyObject *self, PyObject *args) {
94         struct vc_rlimit limits;
95         xid_t xid;
96         int resource;
97         PyObject *ret;
98
99         limits.min = VC_LIM_KEEP;
100         limits.soft = VC_LIM_KEEP;
101         limits.hard = VC_LIM_KEEP;
102
103         if (!PyArg_ParseTuple(args, "Ii", &xid, &resource))
104                 return NULL;
105
106         ret = Py_None;
107         if (vc_get_rlimit(xid, resource, &limits)==-1)
108                 ret = PyErr_SetFromErrno(PyExc_OSError);
109         else
110                 ret = Py_BuildValue("L",limits.hard);
111
112         return ret;
113 }
114
115 #if 0
116 /*
117  * setsched
118  */
119 static PyObject *
120 vserver_setsched(PyObject *self, PyObject *args)
121 {
122   xid_t  xid;
123   struct vc_set_sched sched;
124   struct vc_ctx_flags flags;
125   unsigned cpuguaranteed = 0;
126
127   sched.set_mask = (VC_VXSM_FILL_RATE | 
128                     VC_VXSM_INTERVAL | 
129                     VC_VXSM_TOKENS_MIN | 
130                     VC_VXSM_TOKENS_MAX);
131
132   if (!PyArg_ParseTuple(args, "I|I|I|I|I|I|I", &xid, 
133                         &sched.fill_rate,
134                         &sched.interval,
135                         &sched.tokens,
136                         &sched.tokens_min,
137                         &sched.tokens_max,
138                         &cpuguaranteed))
139     return NULL;
140
141   flags.flagword = VC_VXF_SCHED_HARD;
142   flags.mask |= VC_VXF_SCHED_HARD;
143 #define VC_VXF_SCHED_SHARE       0x00000800ull
144   if (cpuguaranteed==0) {
145           flags.flagword |= VC_VXF_SCHED_SHARE;
146           flags.mask |= VC_VXF_SCHED_SHARE;
147   }
148
149   if (vc_set_cflags(xid, &flags) == -1)
150           return PyErr_SetFromErrno(PyExc_OSError);
151
152   if (vc_set_sched(xid, &sched) == -1)
153           return PyErr_SetFromErrno(PyExc_OSError);
154
155   return Py_None;
156 }
157
158 /*
159  * setsched
160  */
161 #endif
162
163 static PyObject *
164 vserver_get_dlimit(PyObject *self, PyObject *args)
165 {
166         PyObject *res;
167         char* path;
168         unsigned xid;
169         struct vcmd_ctx_dlimit_v0 data;
170         int r;
171
172         if (!PyArg_ParseTuple(args, "si", &path,&xid))
173                 return NULL;
174
175         memset(&data, 0, sizeof(data));
176         data.name = path;
177         data.flags = 0;
178         r = vserver(VCMD_get_dlimit, xid, &data);
179         if (r>=0) {
180                 res = Py_BuildValue("(i,i,i,i,i)",
181                                     data.space_used,
182                                     data.space_total,
183                                     data.inodes_used,
184                                     data.inodes_total,
185                                     data.reserved);
186         } else {
187                 res = PyErr_SetFromErrno(PyExc_OSError);
188         }
189
190         return res;
191 }
192
193
194 static PyObject *
195 vserver_set_dlimit(PyObject *self, PyObject *args)
196 {
197         char* path;
198         unsigned xid;
199         struct vcmd_ctx_dlimit_base_v0 init;
200         struct vcmd_ctx_dlimit_v0 data;
201
202         memset(&data,0,sizeof(data));
203         if (!PyArg_ParseTuple(args, "siiiiii", &path,
204                               &xid,
205                               &data.space_used,
206                               &data.space_total,
207                               &data.inodes_used,
208                               &data.inodes_total,
209                               &data.reserved))
210                 return NULL;
211
212         data.name = path;
213         data.flags = 0;
214
215         memset(&init, 0, sizeof(init));
216         init.name = path;
217         init.flags = 0;
218
219         if ((vserver(VCMD_add_dlimit, xid, &init) && errno != EEXIST) ||
220             vserver(VCMD_set_dlimit, xid, &data))
221           return PyErr_SetFromErrno(PyExc_OSError);
222
223         return Py_None; 
224 }
225
226 static PyMethodDef  methods[] = {
227   { "chcontext", vserver_chcontext, METH_VARARGS,
228     "chcontext to vserver with provided flags" },
229 #if 0
230   { "setsched", vserver_setsched, METH_VARARGS,
231     "Change vserver scheduling attributes for given vserver context" },
232 #endif
233   { "setdlimit", vserver_set_dlimit, METH_VARARGS,
234     "Set disk limits for given vserver context" },
235   { "getdlimit", vserver_get_dlimit, METH_VARARGS,
236     "Get disk limits for given vserver context" },
237   { "setrlimit", vserver_set_rlimit, METH_VARARGS,
238     "Set resource limits for given resource of a vserver context" },
239   { "getrlimit", vserver_get_rlimit, METH_VARARGS,
240     "Get resource limits for given resource of a vserver context" },
241   { NULL, NULL, 0, NULL }
242 };
243
244 PyMODINIT_FUNC
245 initvserverimpl(void)
246 {
247   PyObject  *mod;
248
249   mod = Py_InitModule("vserverimpl", methods);
250
251   /* export the set of 'safe' capabilities */
252   PyModule_AddIntConstant(mod, "CAP_SAFE", ~vc_get_insecurebcaps());
253
254   /* export the default vserver directory */
255   PyModule_AddStringConstant(mod, "VSERVER_BASEDIR", DEFAULT_VSERVERDIR);
256
257   /* export limit-related constants */
258   PyModule_AddIntConstant(mod, "DLIMIT_KEEP", (int)CDLIM_KEEP);
259   PyModule_AddIntConstant(mod, "DLIMIT_INF", (int)CDLIM_INFINITY);
260 }