repr here is wrong
[util-vserver.git] / python / libvserver.py
1 #!/usr/bin/python -tt
2
3 # $Id$
4 # Copyright (C) 2008 Daniel Hokka Zakrisson
5 # vim:set ts=4 sw=4 expandtab:
6
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21 import _libvserver
22
23 class struct:
24     _default_ = 0
25     def __init__(self, *args, **kwargs):
26         l = len(args)
27         if l > len(self._fields_):
28             raise KeyError, "%s has only %d fields" % (self.__class__,
29                                                        len(self._fields_))
30         for i in range(0, l):
31             self.__dict__[self._fields_[i]] = args[i]
32         for i in kwargs.iterkeys():
33             if i not in self._fields_:
34                 raise KeyError, "%s has no such field '%s'" % (self.__class__,
35                                                                i)
36             self.__dict__[i] = kwargs[i]
37     def __totuple(self):
38         return tuple(self.__dict__.get(f, self._default_) for f in self._fields_)
39     def __iter__(self):
40         return self.__totuple().__iter__()
41     def __repr__(self):
42         return repr(self.__dict__)
43     def __addsub(self, other, negator):
44         import copy
45         c = copy.deepcopy(self)
46         for i in vars(other):
47             if i in self._fields_:
48                 c.__dict__[i] = (self.__dict__.get(i, self._default_) +
49                                  (negator * getattr(other, i)))
50         return c
51     def __add__(self, other):
52         return self.__addsub(other, 1)
53     def __sub__(self, other):
54         return self.__addsub(other, -1)
55
56 get_vci = _libvserver.vc_get_vci
57
58 class struct_ctx_flags(struct):
59     _fields_ = ["flagword", "mask"]
60
61 def ctx_create(xid, flags=None):
62     if flags is None:
63         flags = (0, 0)
64     elif not isinstance(flags, struct_ctx_flags):
65         raise TypeError, "flags must be of type struct_ctx_flags"
66     return _libvserver.vc_ctx_create(xid, *flags)
67 def ctx_migrate(xid, flags=0L):
68     return _libvserver.vc_ctx_migrate(xid, flags)
69
70 class struct_ctx_stat(struct):
71     _fields_ = ["usecnt", "tasks"]
72 def ctx_stat(xid):
73     return struct_ctx_stat(*_libvserver.vc_ctx_stat(xid))
74
75 class struct_virt_stat(struct):
76     _fields_ = ["offset", "uptime", "nr_threads", "nr_running",
77                 "nr_uninterruptible", "nr_onhold", "nr_forks",
78                 "load0", "load1", "load2"]
79 def virt_stat(xid):
80     return struct_virt_stat(*_libvserver.vc_virt_stat(xid))
81
82 ctx_kill = _libvserver.vc_ctx_kill
83 def get_cflags(xid):
84     return struct_ctx_flags(*_libvserver.vc_get_cflags(xid))
85 def set_cflags(xid, flags):
86     if not isinstance(flags, struct_ctx_flags):
87         raise TypeError, "flags must be of type struct_ctx_flags"
88     _libvserver.vc_set_cflags(xid, *flags)
89
90 class struct_ctx_caps(struct):
91     _fields_ = ["bcaps", "bmask", "ccaps", "cmask"]
92 def get_ccaps(xid):
93     return struct_ctx_caps(*_libvserver.vc_get_ccaps(xid))
94 def set_ccaps(xid, caps):
95     if not isinstance(caps, struct_ctx_caps):
96         raise TypeError, "caps must be of type struct_ctx_caps"
97     _libvserver.vc_set_ccaps(xid, *caps)
98
99 class struct_vx_info(struct):
100     _fields_ = ["xid", "initpid"]
101 def get_vx_info(xid):
102     return struct_vx_info(*_libvserver.vc_get_vx_info(xid))
103
104 get_task_xid = _libvserver.vc_get_task_xid
105 wait_exit = _libvserver.vc_wait_exit
106
107 class struct_rlimit_mask(struct):
108     _fields_ = ["min", "soft", "hard"]
109 def get_rlimit_mask(xid):
110     return struct_rlimit_mask(*_libvserver.vc_get_rlimit_mask(xid))
111
112 class struct_rlimit(struct):
113     _fields_ = ["min", "soft", "hard"]
114     _default_ = _libvserver.VC_LIM_KEEP
115 def get_rlimit(xid, resource):
116     return struct_rlimit(*_libvserver.vc_get_rlimit(xid, resource))
117 def set_rlimit(xid, resource, limit):
118     if not isinstance(limit, struct_rlimit):
119         raise TypeError, "limit must be of type struct_rlimit"
120     _libvserver.vc_set_rlimit(xid, resource, *limit)
121
122 class stuct_rlimit_stat(struct):
123     _fields_ = ["hits", "value", "minimum", "maximum"]
124 def rlimit_stat(xid, resource):
125     return struct_rlimit_stat(*_libvserver.vc_rlimit_stat(xid, resource))
126
127 reset_minmax = _libvserver.vc_reset_minmax
128
129 get_task_nid = _libvserver.vc_get_task_nid
130 net_create = _libvserver.vc_net_create
131 net_migrate = _libvserver.vc_net_migrate
132
133 class struct_net_addr(struct):
134     _fields_ = ["vna_type", "vna_flags", "vna_prefix", "vna_parent", "ip1",
135                 "ip2", "mask"]
136
137 def net_add(nid, addr):
138     if not isinstance(addr, struct_net_addr):
139         raise TypeError, "addr must be of type struct_net_addr"
140     _libvserver.vc_net_add(nid, *addr)
141
142 def net_remove(nid, addr):
143     if not isinstance(addr, struct_net_addr):
144         raise TypeError, "addr must be of type struct_net_addr"
145     _libvserver.vc_net_remove(nid, *addr)
146
147 class struct_net_flags(struct):
148     _fields_ = ["flagword", "mask"]
149 def get_nflags(nid):
150     return struct_net_flags(*_libvserver.vc_get_nflags(nid))
151 def set_nflags(nid, flags):
152     if not isinstance(flags, struct_net_flags):
153         raise TypeError, "flags must be of type struct_net_flags"
154     _libvserver.vc_set_nflags(nid, *flags)
155
156 class struct_net_caps(struct):
157     _fields_ = ["ncaps", "cmask"]
158 def get_ncaps(nid):
159     return struct_net_caps(*_libvserver.vc_get_ncaps(nid))
160 def set_ncaps(nid, caps):
161     if not isinstance(caps, struct_net_caps):
162         raise TypeError, "caps must be of type struct_net_caps"
163     _libvserver.vc_set_ncaps(nid, *caps)
164
165 def _vc_set_iattr(f, obj, tag, flags, mask):
166     if tag is None:
167         tag = 0
168     else:
169         mask |= _libvserver.VC_IATTR_XID
170     f(obj, tag, flags, mask)
171 def set_iattr(filename, tag=None, flags=0, mask=0):
172     _vc_set_iattr(_libvserver.vc_set_iattr, filename, tag, flags, mask)
173 def fset_iattr(fd, tag=None, flags=0, mask=0):
174     _vc_set_iattr(_libvserver.vc_fset_iattr, fd, tag, flags, mask)
175 get_iattr = lambda f: _libvserver.vc_get_iattr(f, -1)
176 fget_iattr = lambda f: _libvserver.vc_fget_iattr(f, -1)
177
178 def vhi_type(type):
179     if isinstance(type, int):
180         return type
181     else:
182         return _libvserver.__dict__["vcVHI_%s" % type]
183 def set_vhi_name(xid, type, val):
184     _libvserver.vc_set_vhi_name(xid, vhi_type(type), val)
185 def get_vhi_name(xid, type):
186     return _libvserver.vc_get_vhi_name(xid, vhi_type(type))
187
188 enter_namespace = _libvserver.vc_enter_namespace
189 set_namespace = _libvserver.vc_set_namespace
190 get_space_mask = _libvserver.vc_get_space_mask
191 get_space_default = _libvserver.vc_get_space_default
192
193 def add_dlimit(path, tag, flags=0):
194     _libvserver.vc_add_dlimit(path, tag, flags)
195 def rem_dlimit(path, tag, flags=0):
196     _libvserver.vc_rem_dlimit(path, tag, flags)
197 class struct_ctx_dlimit(struct):
198     _fields_ = ["space_used", "space_total", "inodes_used", "inodes_total",
199                 "reserved"]
200     _default_ = _libvserver.VC_CDLIM_KEEP
201 def set_dlimit(path, tag, limit, flags=0):
202     if not isinstance(limit, struct_ctx_dlimit):
203         raise TypeError, "limit must be of type struct_ctx_dlimit"
204     _libvserver.vc_set_dlimit(path, tag, flags, *limit)
205 def get_dlimit(path, tag, flags=0):
206     return struct_ctx_dlimit(*_libvserver.vc_get_dlimit(path, tag, flags))
207
208 get_task_tag = _libvserver.vc_get_task_tag
209 tag_create = _libvserver.vc_tag_create
210 tag_migrate = _libvserver.vc_tag_migrate
211
212 class struct_set_sched(struct):
213     _fields_ = ["set_mask", "fill_rate", "interval", "fill_rate2", "interval2",
214                 "tokens", "tokens_min", "tokens_max", "priority_bias",
215                 "cpu_id", "bucket_id"]
216     def fill_set_mask(self):
217         if "set_mask" not in self.__dict__:
218             self.set_mask = 0
219         for field in self.__dict__:
220             f = field.replace("priority", "prio").upper()
221             self.set_mask |= _libvserver.__dict__.get("VC_VXSM_" + f, 0)
222 def set_sched(xid, sched):
223     if not isinstance(sched, struct_set_sched):
224         raise TypeError, "sched must be of type struct_set_sched"
225     sched.fill_set_mask()
226     _libvserver.vc_set_sched(xid, *sched)
227 def get_sched(xid, cpu_id=0, bucket_id=0):
228     return struct_set_sched(*_libvserver.vc_get_sched(xid, cpu_id, bucket_id))
229
230 class struct_sched_info(struct):
231     _fields_ = ["cpu_id", "bucket_id", "user_msec", "sys_msec", "hold_msec",
232                 "token_usec", "vavavoom"]
233 def sched_info(xid, cpu_id=-1, bucket_id=0):
234     if cpu_id == -1:
235         import os
236         ret = struct_sched_info()
237         ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
238         seen = 0
239         # * 2 is to make sure we get all the processors. CPU hot-plug...
240         for cpu in range(0, ncpus * 2):
241             try:
242                 ret += struct_sched_info(*_libvserver.vc_sched_info(xid,
243                                                                     cpu, 0))
244                 seen += 1
245             except:
246                 pass
247             if seen == ncpus:
248                 break
249         return ret
250     else:
251         return struct_sched_info(*_libvserver.vc_sched_info(xid, cpu_id,
252                                                                bucket_id))
253
254 set_mapping = _libvserver.vc_set_mapping
255 unset_mapping = _libvserver.vc_unset_mapping
256
257 get_badness = _libvserver.vc_get_badness
258 set_badness = _libvserver.vc_set_badness
259
260 get_insecurebcaps = _libvserver.vc_get_insecurebcaps
261 get_insecureccaps = _libvserver.vc_get_insecureccaps
262
263 isSupported = _libvserver.vc_isSupported
264 isSupportedString = _libvserver.vc_isSupportedString
265
266 getXIDType = _libvserver.vc_getXIDType
267
268 def xidopt2xid(opt, honor_static=True):
269     return _libvserver.vc_xidopt2xid(opt, honor_static)
270 def nidopt2nid(opt, honor_static=True):
271     return _libvserver.vc_nidopt2nid(opt, honor_static)
272 def tagopt2tag(opt, honor_static=True):
273     return _libvserver.vc_tagopt2tag(opt, honor_static)
274
275 # XXX: bcap, ccap, cflag, nflag, ncap could all use the same code here.
276 def text2bcap(text):
277     ret = _libvserver.vc_text2bcap(text)
278     if ret == 0:
279         raise ValueError, "%s is not a valid bcap" % text
280     return ret
281 lobcap2text = _libvserver.vc_lobcap2text
282 def bcap2list(bcaps):
283     list = []
284     while True:
285         bcaps, text = _libvserver.vc_lobcap2text(bcaps)
286         if text is None:
287             break
288         list.append(text)
289     return ",".join(list)
290 def list2bcap(list):
291     bcaps, bmask = _libvserver.vc_list2bcap(list)
292     return struct_ctx_caps(bcaps=bcaps, bmask=bmask)
293
294 def text2ccap(text):
295     ret = _libvserver.vc_text2ccap(text)
296     if ret == 0:
297         raise ValueError, "%s is not a valid ccap" % text
298     return ret
299 loccap2text = _libvserver.vc_loccap2text
300 def ccap2list(ccaps):
301     list = []
302     while True:
303         ccaps, text = _libvserver.vc_loccap2text(ccaps)
304         if text is None:
305             break
306         list.append(text)
307     return ",".join(list)
308 def list2ccap(list):
309     ccaps, cmask = _libvserver.vc_list2ccap(list)
310     return struct_ctx_caps(ccaps=ccaps, cmask=cmask)
311
312 def text2cflag(text):
313     ret = _libvserver.vc_text2cflag(text)
314     if ret == 0:
315         raise ValueError, "%s is not a valid cflag" % text
316     return ret
317 locflag2text = _libvserver.vc_locflag2text
318 def cflag2list(cflags):
319     list = []
320     while True:
321         cflags, text = _libvserver.vc_locflag2text(cflags)
322         if text is None:
323             break
324         list.append(text)
325     return ",".join(list)
326 def list2cflag(list):
327     return struct_ctx_flags(*_libvserver.vc_list2cflag(list))
328
329 def text2nflag(text):
330     ret = _libvserver.vc_text2nflag(text)
331     if ret == 0:
332         raise ValueError, "%s is not a valid nflag" % text
333     return ret
334 lonflag2text = _libvserver.vc_lonflag2text
335 def nflag2list(nflags):
336     list = []
337     while True:
338         nflags, text = _libvserver.vc_lonflag2text(nflags)
339         if text is None:
340             break
341         list.append(text)
342     return ",".join(list)
343 def list2nflag(list):
344     return struct_net_flags(*_libvserver.vc_list2nflag(list))
345
346 def text2ncap(text):
347     ret = _libvserver.vc_text2ncap(text)
348     if ret == 0:
349         raise ValueError, "%s is not a valid ncap" % text
350     return ret
351 loncap2text = _libvserver.vc_loncap2text
352 def ncap2list(ncaps):
353     list = []
354     while True:
355         ncaps, text = _libvserver.vc_loncap2text(ncaps)
356         if text is None:
357             break
358         list.append(text)
359     return ",".join(list)
360 def list2ncap(list):
361     return struct_net_caps(*_libvserver.vc_list2ncap(list))
362