direct-io.hg

view tools/python/xen/lowlevel/xc/xc.c @ 12765:2dd4569e0640

[LIBXC] Add an error reporting API to the libxc library.

- An 'xc_error' struct is used to pass around error
details. Currently contains two members 'code' an enumeration of
error types, and 'message' a free text description of the specific
problem.

- The xc_get_last_error() method returns a const pointer to the
internal instance of this struct manged by libxc. By returning a
const pointer we can add extra members to the end of the struct at
any time without worrying about ABI of callers. This will let us
provide more fine-grained info if needed in the future.

- The xc_error instance is statically defined inside libxc and marked
__thread. This ensures that errors are recorded per-thread, and
that when dealing with errors we never need to call malloc - all
storage needed is statically allocated.

- The xc_clear_last_error() method resets any currently recorded
error details

- The xc_error_code_to_desc() method converts the integer error code
into a generic user facing messsage. eg "Invalid kernel". Together
with the 'message' field from xc_error, this provides the user
visible feedback. eg "Invalid kernel: Non PAE-kernel on PAE host."

- A callback can be registered with xc_set_error_handler to receive
notification whenever an error is recorded, rather than querying
for error details after the fact with xc_get_last_error

- If built with -DDEBUG set, a default error handler will be
registered which calls fprintf(stderr), thus maintaining current
behaviour of logging errors to stderr during developer builds.

- The python binding for libxc is updated to use xc_get_last_error
to pull out error details whenever appropriate, instead of
returning info based on 'errno'

- The xc_set_error method is private to libxc internals, and is used
for setting error details

- The ERROR and PERROR macros have been updated to call xc_set_error
automatically specifying XC_INTERNAL_ERROR as the error code. This
gives a generic error report for all current failure points

- Some uses of the ERROR macro have been replaced with explicit
calls to xc_set_error to enable finer grained error reporting. In
particular the code dealing with invalid kernel types uses this
to report about PAE/architecture/wordsize mismatches

The patch has been tested by calling xm create against a varietry of
config files defining invalid kernels of various kinds. It has also
been tested with libvirt talking to xend. In both cases the error
messages were propagated all the way back up the stack.

There is only one place where I need to do further work. The suspend
& restore APIs in Xend invoke external helper programs rather than
calling libxc directly. This means that error details are essentially
lost. Since there is already code in XenD which scans STDERR from
these programs I will investigate adapting this to extract actual
error messages from these helpers.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author kfraser@localhost.localdomain
date Thu Dec 07 11:36:26 2006 +0000 (2006-12-07)
parents b7095209e31a
children 5aea6a32fc8b
line source
1 /******************************************************************************
2 * Xc.c
3 *
4 * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
5 */
7 #include <Python.h>
8 #include <xenctrl.h>
9 #include <xenguest.h>
10 #include <zlib.h>
11 #include <fcntl.h>
12 #include <netinet/in.h>
13 #include <netinet/tcp.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/mman.h>
17 #include <netdb.h>
18 #include <arpa/inet.h>
20 #include "xenctrl.h"
21 #include <xen/hvm/hvm_info_table.h>
22 #include <xen/hvm/params.h>
24 /* Needed for Python versions earlier than 2.3. */
25 #ifndef PyMODINIT_FUNC
26 #define PyMODINIT_FUNC DL_EXPORT(void)
27 #endif
29 #define PKG "xen.lowlevel.xc"
30 #define CLS "xc"
32 static PyObject *xc_error_obj, *zero;
34 typedef struct {
35 PyObject_HEAD;
36 int xc_handle;
37 } XcObject;
40 static PyObject *dom_op(XcObject *self, PyObject *args,
41 int (*fn)(int, uint32_t));
43 static PyObject *pyxc_error_to_exception(void)
44 {
45 PyObject *pyerr;
46 const xc_error const *err = xc_get_last_error();
47 const char *desc = xc_error_code_to_desc(err->code);
49 if (err->message[1])
50 pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
51 else
52 pyerr = Py_BuildValue("(is)", err->code, desc);
54 xc_clear_last_error();
56 PyErr_SetObject(xc_error_obj, pyerr);
58 return NULL;
59 }
61 static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args)
62 {
63 uint32_t dom;
64 char *corefile;
66 if (!PyArg_ParseTuple(args, "is", &dom, &corefile))
67 return NULL;
69 if ( (corefile == NULL) || (corefile[0] == '\0') )
70 return NULL;
72 if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0)
73 return pyxc_error_to_exception();
75 Py_INCREF(zero);
76 return zero;
77 }
79 static PyObject *pyxc_handle(XcObject *self)
80 {
81 return PyInt_FromLong(self->xc_handle);
82 }
84 static PyObject *pyxc_domain_create(XcObject *self,
85 PyObject *args,
86 PyObject *kwds)
87 {
88 uint32_t dom = 0, ssidref = 0, flags = 0;
89 int ret, i, hvm = 0;
90 PyObject *pyhandle = NULL;
91 xen_domain_handle_t handle = {
92 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
93 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef };
95 static char *kwd_list[] = { "domid", "ssidref", "handle", "hvm", NULL };
97 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiOi", kwd_list,
98 &dom, &ssidref, &pyhandle, &hvm))
99 return NULL;
101 if ( pyhandle != NULL )
102 {
103 if ( !PyList_Check(pyhandle) ||
104 (PyList_Size(pyhandle) != sizeof(xen_domain_handle_t)) )
105 goto out_exception;
107 for ( i = 0; i < sizeof(xen_domain_handle_t); i++ )
108 {
109 PyObject *p = PyList_GetItem(pyhandle, i);
110 if ( !PyInt_Check(p) )
111 goto out_exception;
112 handle[i] = (uint8_t)PyInt_AsLong(p);
113 }
114 }
116 if ( hvm )
117 flags |= XEN_DOMCTL_CDF_hvm_guest;
119 if ( (ret = xc_domain_create(self->xc_handle, ssidref,
120 handle, flags, &dom)) < 0 )
121 return pyxc_error_to_exception();
123 return PyInt_FromLong(dom);
125 out_exception:
126 errno = EINVAL;
127 PyErr_SetFromErrno(xc_error_obj);
128 return NULL;
129 }
131 static PyObject *pyxc_domain_max_vcpus(XcObject *self, PyObject *args)
132 {
133 uint32_t dom, max;
135 if (!PyArg_ParseTuple(args, "ii", &dom, &max))
136 return NULL;
138 if (xc_domain_max_vcpus(self->xc_handle, dom, max) != 0)
139 return pyxc_error_to_exception();
141 Py_INCREF(zero);
142 return zero;
143 }
145 static PyObject *pyxc_domain_pause(XcObject *self, PyObject *args)
146 {
147 return dom_op(self, args, xc_domain_pause);
148 }
150 static PyObject *pyxc_domain_unpause(XcObject *self, PyObject *args)
151 {
152 return dom_op(self, args, xc_domain_unpause);
153 }
155 static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
156 {
157 return dom_op(self, args, xc_domain_destroy);
158 }
161 static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
162 PyObject *args,
163 PyObject *kwds)
164 {
165 uint32_t dom;
166 int vcpu = 0, i;
167 uint64_t cpumap = ~0ULL;
168 PyObject *cpulist = NULL;
170 static char *kwd_list[] = { "domid", "vcpu", "cpumap", NULL };
172 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|iO", kwd_list,
173 &dom, &vcpu, &cpulist) )
174 return NULL;
176 if ( (cpulist != NULL) && PyList_Check(cpulist) )
177 {
178 cpumap = 0ULL;
179 for ( i = 0; i < PyList_Size(cpulist); i++ )
180 cpumap |= (uint64_t)1 << PyInt_AsLong(PyList_GetItem(cpulist, i));
181 }
183 if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap) != 0 )
184 return pyxc_error_to_exception();
186 Py_INCREF(zero);
187 return zero;
188 }
190 static PyObject *pyxc_domain_setcpuweight(XcObject *self,
191 PyObject *args,
192 PyObject *kwds)
193 {
194 uint32_t dom;
195 float cpuweight = 1;
197 static char *kwd_list[] = { "domid", "cpuweight", NULL };
199 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list,
200 &dom, &cpuweight) )
201 return NULL;
203 if ( xc_domain_setcpuweight(self->xc_handle, dom, cpuweight) != 0 )
204 return pyxc_error_to_exception();
206 Py_INCREF(zero);
207 return zero;
208 }
210 static PyObject *pyxc_domain_sethandle(XcObject *self, PyObject *args)
211 {
212 int i;
213 uint32_t dom;
214 PyObject *pyhandle;
215 xen_domain_handle_t handle;
217 if (!PyArg_ParseTuple(args, "iO", &dom, &pyhandle))
218 return NULL;
220 if ( !PyList_Check(pyhandle) ||
221 (PyList_Size(pyhandle) != sizeof(xen_domain_handle_t)) )
222 {
223 goto out_exception;
224 }
226 for ( i = 0; i < sizeof(xen_domain_handle_t); i++ )
227 {
228 PyObject *p = PyList_GetItem(pyhandle, i);
229 if ( !PyInt_Check(p) )
230 goto out_exception;
231 handle[i] = (uint8_t)PyInt_AsLong(p);
232 }
234 if (xc_domain_sethandle(self->xc_handle, dom, handle) < 0)
235 return pyxc_error_to_exception();
237 Py_INCREF(zero);
238 return zero;
240 out_exception:
241 PyErr_SetFromErrno(xc_error_obj);
242 return NULL;
243 }
246 static PyObject *pyxc_domain_getinfo(XcObject *self,
247 PyObject *args,
248 PyObject *kwds)
249 {
250 PyObject *list, *info_dict;
252 uint32_t first_dom = 0;
253 int max_doms = 1024, nr_doms, i, j;
254 xc_dominfo_t *info;
256 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
258 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
259 &first_dom, &max_doms) )
260 return NULL;
262 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
263 return PyErr_NoMemory();
265 nr_doms = xc_domain_getinfo(self->xc_handle, first_dom, max_doms, info);
267 if (nr_doms < 0)
268 {
269 free(info);
270 return pyxc_error_to_exception();
271 }
273 list = PyList_New(nr_doms);
274 for ( i = 0 ; i < nr_doms; i++ )
275 {
276 PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
277 for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
278 PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
279 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
280 ",s:l,s:L,s:l,s:i,s:i}",
281 "domid", info[i].domid,
282 "online_vcpus", info[i].nr_online_vcpus,
283 "max_vcpu_id", info[i].max_vcpu_id,
284 "hvm", info[i].hvm,
285 "dying", info[i].dying,
286 "crashed", info[i].crashed,
287 "shutdown", info[i].shutdown,
288 "paused", info[i].paused,
289 "blocked", info[i].blocked,
290 "running", info[i].running,
291 "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
292 "cpu_time", info[i].cpu_time,
293 "maxmem_kb", info[i].max_memkb,
294 "ssidref", info[i].ssidref,
295 "shutdown_reason", info[i].shutdown_reason);
296 PyDict_SetItemString(info_dict, "handle", pyhandle);
297 Py_DECREF(pyhandle);
298 PyList_SetItem(list, i, info_dict);
299 }
301 free(info);
303 return list;
304 }
306 static PyObject *pyxc_vcpu_getinfo(XcObject *self,
307 PyObject *args,
308 PyObject *kwds)
309 {
310 PyObject *info_dict, *cpulist;
312 uint32_t dom, vcpu = 0;
313 xc_vcpuinfo_t info;
314 int rc, i;
315 uint64_t cpumap;
317 static char *kwd_list[] = { "domid", "vcpu", NULL };
319 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
320 &dom, &vcpu) )
321 return NULL;
323 rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info);
324 if ( rc < 0 )
325 return pyxc_error_to_exception();
326 rc = xc_vcpu_getaffinity(self->xc_handle, dom, vcpu, &cpumap);
327 if ( rc < 0 )
328 return pyxc_error_to_exception();
330 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:L,s:i}",
331 "online", info.online,
332 "blocked", info.blocked,
333 "running", info.running,
334 "cpu_time", info.cpu_time,
335 "cpu", info.cpu);
337 cpulist = PyList_New(0);
338 for ( i = 0; cpumap != 0; i++ )
339 {
340 if ( cpumap & 1 )
341 PyList_Append(cpulist, PyInt_FromLong(i));
342 cpumap >>= 1;
343 }
344 PyDict_SetItemString(info_dict, "cpumap", cpulist);
345 Py_DECREF(cpulist);
346 return info_dict;
347 }
349 static PyObject *pyxc_linux_build(XcObject *self,
350 PyObject *args,
351 PyObject *kwds)
352 {
353 uint32_t dom;
354 char *image, *ramdisk = NULL, *cmdline = "", *features = NULL;
355 int flags = 0;
356 int store_evtchn, console_evtchn;
357 unsigned int mem_mb;
358 unsigned long store_mfn = 0;
359 unsigned long console_mfn = 0;
361 static char *kwd_list[] = { "domid", "store_evtchn", "memsize",
362 "console_evtchn", "image",
363 /* optional */
364 "ramdisk", "cmdline", "flags",
365 "features", NULL };
367 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssis", kwd_list,
368 &dom, &store_evtchn, &mem_mb,
369 &console_evtchn, &image,
370 /* optional */
371 &ramdisk, &cmdline, &flags,
372 &features) )
373 return NULL;
375 if ( xc_linux_build(self->xc_handle, dom, mem_mb, image,
376 ramdisk, cmdline, features, flags,
377 store_evtchn, &store_mfn,
378 console_evtchn, &console_mfn) != 0 ) {
379 return pyxc_error_to_exception();
380 }
381 return Py_BuildValue("{s:i,s:i}",
382 "store_mfn", store_mfn,
383 "console_mfn", console_mfn);
384 }
386 static PyObject *pyxc_hvm_build(XcObject *self,
387 PyObject *args,
388 PyObject *kwds)
389 {
390 uint32_t dom;
391 struct hvm_info_table *va_hvm;
392 uint8_t *va_map, sum;
393 char *image;
394 int i, store_evtchn, memsize, vcpus = 1, pae = 0, acpi = 0, apic = 1;
395 unsigned long store_mfn;
397 static char *kwd_list[] = { "domid", "store_evtchn",
398 "memsize", "image", "vcpus", "pae", "acpi",
399 "apic", NULL };
400 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|iiii", kwd_list,
401 &dom, &store_evtchn, &memsize,
402 &image, &vcpus, &pae, &acpi, &apic) )
403 return NULL;
405 if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
406 return pyxc_error_to_exception();
408 /* Set up the HVM info table. */
409 va_map = xc_map_foreign_range(self->xc_handle, dom, XC_PAGE_SIZE,
410 PROT_READ | PROT_WRITE,
411 HVM_INFO_PFN);
412 if ( va_map == NULL )
413 return PyErr_SetFromErrno(xc_error_obj);
414 va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
415 memset(va_hvm, 0, sizeof(*va_hvm));
416 strncpy(va_hvm->signature, "HVM INFO", 8);
417 va_hvm->length = sizeof(struct hvm_info_table);
418 va_hvm->acpi_enabled = acpi;
419 va_hvm->apic_mode = apic;
420 va_hvm->nr_vcpus = vcpus;
421 for ( i = 0, sum = 0; i < va_hvm->length; i++ )
422 sum += ((uint8_t *)va_hvm)[i];
423 va_hvm->checksum = -sum;
424 munmap(va_map, XC_PAGE_SIZE);
426 xc_get_hvm_param(self->xc_handle, dom, HVM_PARAM_STORE_PFN, &store_mfn);
427 xc_set_hvm_param(self->xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
428 xc_set_hvm_param(self->xc_handle, dom, HVM_PARAM_STORE_EVTCHN,
429 store_evtchn);
431 return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
432 }
434 static PyObject *pyxc_evtchn_alloc_unbound(XcObject *self,
435 PyObject *args,
436 PyObject *kwds)
437 {
438 uint32_t dom, remote_dom;
439 int port;
441 static char *kwd_list[] = { "domid", "remote_dom", NULL };
443 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
444 &dom, &remote_dom) )
445 return NULL;
447 if ( (port = xc_evtchn_alloc_unbound(self->xc_handle, dom, remote_dom)) < 0 )
448 return pyxc_error_to_exception();
450 return PyInt_FromLong(port);
451 }
453 static PyObject *pyxc_physdev_pci_access_modify(XcObject *self,
454 PyObject *args,
455 PyObject *kwds)
456 {
457 uint32_t dom;
458 int bus, dev, func, enable, ret;
460 static char *kwd_list[] = { "domid", "bus", "dev", "func", "enable", NULL };
462 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
463 &dom, &bus, &dev, &func, &enable) )
464 return NULL;
466 ret = xc_physdev_pci_access_modify(
467 self->xc_handle, dom, bus, dev, func, enable);
468 if ( ret != 0 )
469 return pyxc_error_to_exception();
471 Py_INCREF(zero);
472 return zero;
473 }
475 static PyObject *pyxc_readconsolering(XcObject *self,
476 PyObject *args,
477 PyObject *kwds)
478 {
479 unsigned int clear = 0;
480 char _str[32768], *str = _str;
481 unsigned int count = 32768;
482 int ret;
484 static char *kwd_list[] = { "clear", NULL };
486 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
487 return NULL;
489 ret = xc_readconsolering(self->xc_handle, &str, &count, clear);
490 if ( ret < 0 )
491 return pyxc_error_to_exception();
493 return PyString_FromStringAndSize(str, count);
494 }
497 static unsigned long pages_to_kib(unsigned long pages)
498 {
499 return pages * (XC_PAGE_SIZE / 1024);
500 }
503 static PyObject *pyxc_pages_to_kib(XcObject *self, PyObject *args)
504 {
505 unsigned long pages;
507 if (!PyArg_ParseTuple(args, "l", &pages))
508 return NULL;
510 return PyLong_FromUnsignedLong(pages_to_kib(pages));
511 }
514 static PyObject *pyxc_physinfo(XcObject *self)
515 {
516 xc_physinfo_t info;
517 char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
518 int i;
520 if ( xc_physinfo(self->xc_handle, &info) != 0 )
521 return pyxc_error_to_exception();
523 *q=0;
524 for(i=0;i<sizeof(info.hw_cap)/4;i++)
525 {
526 p+=sprintf(p,"%08x:",info.hw_cap[i]);
527 if(info.hw_cap[i])
528 q=p;
529 }
530 if(q>cpu_cap)
531 *(q-1)=0;
533 return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
534 "threads_per_core", info.threads_per_core,
535 "cores_per_socket", info.cores_per_socket,
536 "sockets_per_node", info.sockets_per_node,
537 "nr_nodes", info.nr_nodes,
538 "total_memory", pages_to_kib(info.total_pages),
539 "free_memory", pages_to_kib(info.free_pages),
540 "scrub_memory", pages_to_kib(info.scrub_pages),
541 "cpu_khz", info.cpu_khz,
542 "hw_caps", cpu_cap);
543 }
545 static PyObject *pyxc_xeninfo(XcObject *self)
546 {
547 xen_extraversion_t xen_extra;
548 xen_compile_info_t xen_cc;
549 xen_changeset_info_t xen_chgset;
550 xen_capabilities_info_t xen_caps;
551 xen_platform_parameters_t p_parms;
552 long xen_version;
553 long xen_pagesize;
554 char str[128];
556 xen_version = xc_version(self->xc_handle, XENVER_version, NULL);
558 if ( xc_version(self->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
559 return pyxc_error_to_exception();
561 if ( xc_version(self->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
562 return pyxc_error_to_exception();
564 if ( xc_version(self->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
565 return pyxc_error_to_exception();
567 if ( xc_version(self->xc_handle, XENVER_capabilities, &xen_caps) != 0 )
568 return pyxc_error_to_exception();
570 if ( xc_version(self->xc_handle, XENVER_platform_parameters, &p_parms) != 0 )
571 return pyxc_error_to_exception();
573 sprintf(str, "virt_start=0x%lx", p_parms.virt_start);
575 xen_pagesize = xc_version(self->xc_handle, XENVER_pagesize, NULL);
576 if (xen_pagesize < 0 )
577 return pyxc_error_to_exception();
579 return Py_BuildValue("{s:i,s:i,s:s,s:s,s:i,s:s,s:s,s:s,s:s,s:s,s:s}",
580 "xen_major", xen_version >> 16,
581 "xen_minor", (xen_version & 0xffff),
582 "xen_extra", xen_extra,
583 "xen_caps", xen_caps,
584 "xen_pagesize", xen_pagesize,
585 "platform_params", str,
586 "xen_changeset", xen_chgset,
587 "cc_compiler", xen_cc.compiler,
588 "cc_compile_by", xen_cc.compile_by,
589 "cc_compile_domain", xen_cc.compile_domain,
590 "cc_compile_date", xen_cc.compile_date);
591 }
594 static PyObject *pyxc_sedf_domain_set(XcObject *self,
595 PyObject *args,
596 PyObject *kwds)
597 {
598 uint32_t domid;
599 uint64_t period, slice, latency;
600 uint16_t extratime, weight;
601 static char *kwd_list[] = { "domid", "period", "slice",
602 "latency", "extratime", "weight",NULL };
604 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list,
605 &domid, &period, &slice,
606 &latency, &extratime, &weight) )
607 return NULL;
608 if ( xc_sedf_domain_set(self->xc_handle, domid, period,
609 slice, latency, extratime,weight) != 0 )
610 return pyxc_error_to_exception();
612 Py_INCREF(zero);
613 return zero;
614 }
616 static PyObject *pyxc_sedf_domain_get(XcObject *self, PyObject *args)
617 {
618 uint32_t domid;
619 uint64_t period, slice,latency;
620 uint16_t weight, extratime;
622 if(!PyArg_ParseTuple(args, "i", &domid))
623 return NULL;
625 if (xc_sedf_domain_get(self->xc_handle, domid, &period,
626 &slice,&latency,&extratime,&weight))
627 return pyxc_error_to_exception();
629 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i,s:i}",
630 "domid", domid,
631 "period", period,
632 "slice", slice,
633 "latency", latency,
634 "extratime", extratime,
635 "weight", weight);
636 }
638 static PyObject *pyxc_shadow_control(PyObject *self,
639 PyObject *args,
640 PyObject *kwds)
641 {
642 XcObject *xc = (XcObject *)self;
644 uint32_t dom;
645 int op=0;
647 static char *kwd_list[] = { "dom", "op", NULL };
649 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
650 &dom, &op) )
651 return NULL;
653 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL, 0, NULL)
654 < 0 )
655 return pyxc_error_to_exception();
657 Py_INCREF(zero);
658 return zero;
659 }
661 static PyObject *pyxc_shadow_mem_control(PyObject *self,
662 PyObject *args,
663 PyObject *kwds)
664 {
665 XcObject *xc = (XcObject *)self;
666 int op;
667 uint32_t dom;
668 int mbarg = -1;
669 unsigned long mb;
671 static char *kwd_list[] = { "dom", "mb", NULL };
673 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
674 &dom, &mbarg) )
675 return NULL;
677 if ( mbarg < 0 )
678 op = XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION;
679 else
680 {
681 mb = mbarg;
682 op = XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION;
683 }
684 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, &mb, 0, NULL) < 0 )
685 return pyxc_error_to_exception();
687 mbarg = mb;
688 return Py_BuildValue("i", mbarg);
689 }
691 static PyObject *pyxc_sched_id_get(XcObject *self) {
693 int sched_id;
694 if (xc_sched_id(self->xc_handle, &sched_id) != 0)
695 return PyErr_SetFromErrno(xc_error_obj);
697 return Py_BuildValue("i", sched_id);
698 }
700 static PyObject *pyxc_sched_credit_domain_set(XcObject *self,
701 PyObject *args,
702 PyObject *kwds)
703 {
704 uint32_t domid;
705 uint16_t weight;
706 uint16_t cap;
707 static char *kwd_list[] = { "domid", "weight", "cap", NULL };
708 static char kwd_type[] = "I|HH";
709 struct xen_domctl_sched_credit sdom;
711 weight = 0;
712 cap = (uint16_t)~0U;
713 if( !PyArg_ParseTupleAndKeywords(args, kwds, kwd_type, kwd_list,
714 &domid, &weight, &cap) )
715 return NULL;
717 sdom.weight = weight;
718 sdom.cap = cap;
720 if ( xc_sched_credit_domain_set(self->xc_handle, domid, &sdom) != 0 )
721 return pyxc_error_to_exception();
723 Py_INCREF(zero);
724 return zero;
725 }
727 static PyObject *pyxc_sched_credit_domain_get(XcObject *self, PyObject *args)
728 {
729 uint32_t domid;
730 struct xen_domctl_sched_credit sdom;
732 if( !PyArg_ParseTuple(args, "I", &domid) )
733 return NULL;
735 if ( xc_sched_credit_domain_get(self->xc_handle, domid, &sdom) != 0 )
736 return pyxc_error_to_exception();
738 return Py_BuildValue("{s:H,s:H}",
739 "weight", sdom.weight,
740 "cap", sdom.cap);
741 }
743 static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args)
744 {
745 uint32_t dom;
746 unsigned int maxmem_kb;
748 if (!PyArg_ParseTuple(args, "ii", &dom, &maxmem_kb))
749 return NULL;
751 if (xc_domain_setmaxmem(self->xc_handle, dom, maxmem_kb) != 0)
752 return pyxc_error_to_exception();
754 Py_INCREF(zero);
755 return zero;
756 }
758 static PyObject *pyxc_domain_memory_increase_reservation(XcObject *self,
759 PyObject *args,
760 PyObject *kwds)
761 {
762 uint32_t dom;
763 unsigned long mem_kb;
764 unsigned int extent_order = 0 , address_bits = 0;
765 unsigned long nr_extents;
767 static char *kwd_list[] = { "domid", "mem_kb", "extent_order", "address_bits", NULL };
769 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list,
770 &dom, &mem_kb, &extent_order, &address_bits) )
771 return NULL;
773 /* round down to nearest power of 2. Assume callers using extent_order>0
774 know what they are doing */
775 nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order;
776 if ( xc_domain_memory_increase_reservation(self->xc_handle, dom,
777 nr_extents, extent_order,
778 address_bits, NULL) )
779 return pyxc_error_to_exception();
781 Py_INCREF(zero);
782 return zero;
783 }
785 static PyObject *pyxc_domain_ioport_permission(XcObject *self,
786 PyObject *args,
787 PyObject *kwds)
788 {
789 uint32_t dom;
790 int first_port, nr_ports, allow_access, ret;
792 static char *kwd_list[] = { "domid", "first_port", "nr_ports", "allow_access", NULL };
794 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiii", kwd_list,
795 &dom, &first_port, &nr_ports, &allow_access) )
796 return NULL;
798 ret = xc_domain_ioport_permission(
799 self->xc_handle, dom, first_port, nr_ports, allow_access);
800 if ( ret != 0 )
801 return pyxc_error_to_exception();
803 Py_INCREF(zero);
804 return zero;
805 }
807 static PyObject *pyxc_domain_irq_permission(PyObject *self,
808 PyObject *args,
809 PyObject *kwds)
810 {
811 XcObject *xc = (XcObject *)self;
812 uint32_t dom;
813 int pirq, allow_access, ret;
815 static char *kwd_list[] = { "domid", "pirq", "allow_access", NULL };
817 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list,
818 &dom, &pirq, &allow_access) )
819 return NULL;
821 ret = xc_domain_irq_permission(
822 xc->xc_handle, dom, pirq, allow_access);
823 if ( ret != 0 )
824 return pyxc_error_to_exception();
826 Py_INCREF(zero);
827 return zero;
828 }
830 static PyObject *pyxc_domain_iomem_permission(PyObject *self,
831 PyObject *args,
832 PyObject *kwds)
833 {
834 XcObject *xc = (XcObject *)self;
835 uint32_t dom;
836 unsigned long first_pfn, nr_pfns, allow_access, ret;
838 static char *kwd_list[] = { "domid", "first_pfn", "nr_pfns", "allow_access", NULL };
840 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list,
841 &dom, &first_pfn, &nr_pfns, &allow_access) )
842 return NULL;
844 ret = xc_domain_iomem_permission(
845 xc->xc_handle, dom, first_pfn, nr_pfns, allow_access);
846 if ( ret != 0 )
847 return pyxc_error_to_exception();
849 Py_INCREF(zero);
850 return zero;
851 }
853 static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args)
854 {
855 uint32_t dom;
856 int32_t time_offset_seconds;
857 time_t calendar_time;
858 struct tm local_time;
859 struct tm utc_time;
861 if (!PyArg_ParseTuple(args, "i", &dom))
862 return NULL;
864 calendar_time = time(NULL);
865 localtime_r(&calendar_time, &local_time);
866 gmtime_r(&calendar_time, &utc_time);
867 /* set up to get calendar time based on utc_time, with local dst setting */
868 utc_time.tm_isdst = local_time.tm_isdst;
869 time_offset_seconds = (int32_t)difftime(calendar_time, mktime(&utc_time));
871 if (xc_domain_set_time_offset(self->xc_handle, dom, time_offset_seconds) != 0)
872 return NULL;
874 Py_INCREF(zero);
875 return zero;
876 }
878 static PyObject *dom_op(XcObject *self, PyObject *args,
879 int (*fn)(int, uint32_t))
880 {
881 uint32_t dom;
883 if (!PyArg_ParseTuple(args, "i", &dom))
884 return NULL;
886 if (fn(self->xc_handle, dom) != 0)
887 return pyxc_error_to_exception();
889 Py_INCREF(zero);
890 return zero;
891 }
894 static PyMethodDef pyxc_methods[] = {
895 { "handle",
896 (PyCFunction)pyxc_handle,
897 METH_NOARGS, "\n"
898 "Query the xc control interface file descriptor.\n\n"
899 "Returns: [int] file descriptor\n" },
901 { "domain_create",
902 (PyCFunction)pyxc_domain_create,
903 METH_VARARGS | METH_KEYWORDS, "\n"
904 "Create a new domain.\n"
905 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
906 "Returns: [int] new domain identifier; -1 on error.\n" },
908 { "domain_max_vcpus",
909 (PyCFunction)pyxc_domain_max_vcpus,
910 METH_VARARGS, "\n"
911 "Set the maximum number of VCPUs a domain may create.\n"
912 " dom [int, 0]: Domain identifier to use.\n"
913 " max [int, 0]: New maximum number of VCPUs in domain.\n"
914 "Returns: [int] 0 on success; -1 on error.\n" },
916 { "domain_dumpcore",
917 (PyCFunction)pyxc_domain_dumpcore,
918 METH_VARARGS, "\n"
919 "Dump core of a domain.\n"
920 " dom [int]: Identifier of domain to dump core of.\n"
921 " corefile [string]: Name of corefile to be created.\n\n"
922 "Returns: [int] 0 on success; -1 on error.\n" },
924 { "domain_pause",
925 (PyCFunction)pyxc_domain_pause,
926 METH_VARARGS, "\n"
927 "Temporarily pause execution of a domain.\n"
928 " dom [int]: Identifier of domain to be paused.\n\n"
929 "Returns: [int] 0 on success; -1 on error.\n" },
931 { "domain_unpause",
932 (PyCFunction)pyxc_domain_unpause,
933 METH_VARARGS, "\n"
934 "(Re)start execution of a domain.\n"
935 " dom [int]: Identifier of domain to be unpaused.\n\n"
936 "Returns: [int] 0 on success; -1 on error.\n" },
938 { "domain_destroy",
939 (PyCFunction)pyxc_domain_destroy,
940 METH_VARARGS, "\n"
941 "Destroy a domain.\n"
942 " dom [int]: Identifier of domain to be destroyed.\n\n"
943 "Returns: [int] 0 on success; -1 on error.\n" },
945 { "vcpu_setaffinity",
946 (PyCFunction)pyxc_vcpu_setaffinity,
947 METH_VARARGS | METH_KEYWORDS, "\n"
948 "Pin a VCPU to a specified set CPUs.\n"
949 " dom [int]: Identifier of domain to which VCPU belongs.\n"
950 " vcpu [int, 0]: VCPU being pinned.\n"
951 " cpumap [list, []]: list of usable CPUs.\n\n"
952 "Returns: [int] 0 on success; -1 on error.\n" },
954 { "domain_setcpuweight",
955 (PyCFunction)pyxc_domain_setcpuweight,
956 METH_VARARGS | METH_KEYWORDS, "\n"
957 "Set cpuweight scheduler parameter for domain.\n"
958 " dom [int]: Identifier of domain to be changed.\n"
959 " cpuweight [float, 1]: VCPU being pinned.\n"
960 "Returns: [int] 0 on success; -1 on error.\n" },
962 { "domain_sethandle",
963 (PyCFunction)pyxc_domain_sethandle,
964 METH_VARARGS, "\n"
965 "Set domain's opaque handle.\n"
966 " dom [int]: Identifier of domain.\n"
967 " handle [list of 16 ints]: New opaque handle.\n"
968 "Returns: [int] 0 on success; -1 on error.\n" },
970 { "domain_getinfo",
971 (PyCFunction)pyxc_domain_getinfo,
972 METH_VARARGS | METH_KEYWORDS, "\n"
973 "Get information regarding a set of domains, in increasing id order.\n"
974 " first_dom [int, 0]: First domain to retrieve info about.\n"
975 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
976 " about.\n\n"
977 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
978 " parameter then there was an error, or the end of the\n"
979 " domain-id space was reached.\n"
980 " dom [int]: Identifier of domain to which this info pertains\n"
981 " cpu [int]: CPU to which this domain is bound\n"
982 " vcpus [int]: Number of Virtual CPUS in this domain\n"
983 " dying [int]: Bool - is the domain dying?\n"
984 " crashed [int]: Bool - has the domain crashed?\n"
985 " shutdown [int]: Bool - has the domain shut itself down?\n"
986 " paused [int]: Bool - is the domain paused by control software?\n"
987 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
988 " running [int]: Bool - is the domain currently running?\n"
989 " mem_kb [int]: Memory reservation, in kilobytes\n"
990 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
991 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
992 " shutdown_reason [int]: Numeric code from guest OS, explaining "
993 "reason why it shut itself down.\n" },
995 { "vcpu_getinfo",
996 (PyCFunction)pyxc_vcpu_getinfo,
997 METH_VARARGS | METH_KEYWORDS, "\n"
998 "Get information regarding a VCPU.\n"
999 " dom [int]: Domain to retrieve info about.\n"
1000 " vcpu [int, 0]: VCPU to retrieve info about.\n\n"
1001 "Returns: [dict]\n"
1002 " online [int]: Bool - Is this VCPU currently online?\n"
1003 " blocked [int]: Bool - Is this VCPU blocked waiting for an event?\n"
1004 " running [int]: Bool - Is this VCPU currently running on a CPU?\n"
1005 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
1006 " cpumap [int]: Bitmap of CPUs this VCPU can run on\n"
1007 " cpu [int]: CPU that this VCPU is currently bound to\n" },
1009 { "linux_build",
1010 (PyCFunction)pyxc_linux_build,
1011 METH_VARARGS | METH_KEYWORDS, "\n"
1012 "Build a new Linux guest OS.\n"
1013 " dom [int]: Identifier of domain to build into.\n"
1014 " image [str]: Name of kernel image file. May be gzipped.\n"
1015 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1016 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1017 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
1018 "Returns: [int] 0 on success; -1 on error.\n" },
1020 { "hvm_build",
1021 (PyCFunction)pyxc_hvm_build,
1022 METH_VARARGS | METH_KEYWORDS, "\n"
1023 "Build a new HVM guest OS.\n"
1024 " dom [int]: Identifier of domain to build into.\n"
1025 " image [str]: Name of HVM loader image file.\n"
1026 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
1027 "Returns: [int] 0 on success; -1 on error.\n" },
1029 { "sched_id_get",
1030 (PyCFunction)pyxc_sched_id_get,
1031 METH_NOARGS, "\n"
1032 "Get the current scheduler type in use.\n"
1033 "Returns: [int] sched_id.\n" },
1035 { "sedf_domain_set",
1036 (PyCFunction)pyxc_sedf_domain_set,
1037 METH_KEYWORDS, "\n"
1038 "Set the scheduling parameters for a domain when running with Atropos.\n"
1039 " dom [int]: domain to set\n"
1040 " period [long]: domain's scheduling period\n"
1041 " slice [long]: domain's slice per period\n"
1042 " latency [long]: domain's wakeup latency hint\n"
1043 " extratime [int]: domain aware of extratime?\n"
1044 "Returns: [int] 0 on success; -1 on error.\n" },
1046 { "sedf_domain_get",
1047 (PyCFunction)pyxc_sedf_domain_get,
1048 METH_VARARGS, "\n"
1049 "Get the current scheduling parameters for a domain when running with\n"
1050 "the Atropos scheduler."
1051 " dom [int]: domain to query\n"
1052 "Returns: [dict]\n"
1053 " domain [int]: domain ID\n"
1054 " period [long]: scheduler period\n"
1055 " slice [long]: CPU reservation per period\n"
1056 " latency [long]: domain's wakeup latency hint\n"
1057 " extratime [int]: domain aware of extratime?\n"},
1059 { "sched_credit_domain_set",
1060 (PyCFunction)pyxc_sched_credit_domain_set,
1061 METH_KEYWORDS, "\n"
1062 "Set the scheduling parameters for a domain when running with the\n"
1063 "SMP credit scheduler.\n"
1064 " domid [int]: domain id to set\n"
1065 " weight [short]: domain's scheduling weight\n"
1066 "Returns: [int] 0 on success; -1 on error.\n" },
1068 { "sched_credit_domain_get",
1069 (PyCFunction)pyxc_sched_credit_domain_get,
1070 METH_VARARGS, "\n"
1071 "Get the scheduling parameters for a domain when running with the\n"
1072 "SMP credit scheduler.\n"
1073 " domid [int]: domain id to get\n"
1074 "Returns: [dict]\n"
1075 " weight [short]: domain's scheduling weight\n"},
1077 { "evtchn_alloc_unbound",
1078 (PyCFunction)pyxc_evtchn_alloc_unbound,
1079 METH_VARARGS | METH_KEYWORDS, "\n"
1080 "Allocate an unbound port that will await a remote connection.\n"
1081 " dom [int]: Domain whose port space to allocate from.\n"
1082 " remote_dom [int]: Remote domain to accept connections from.\n\n"
1083 "Returns: [int] Unbound event-channel port.\n" },
1085 { "physdev_pci_access_modify",
1086 (PyCFunction)pyxc_physdev_pci_access_modify,
1087 METH_VARARGS | METH_KEYWORDS, "\n"
1088 "Allow a domain access to a PCI device\n"
1089 " dom [int]: Identifier of domain to be allowed access.\n"
1090 " bus [int]: PCI bus\n"
1091 " dev [int]: PCI slot\n"
1092 " func [int]: PCI function\n"
1093 " enable [int]: Non-zero means enable access; else disable access\n\n"
1094 "Returns: [int] 0 on success; -1 on error.\n" },
1096 { "readconsolering",
1097 (PyCFunction)pyxc_readconsolering,
1098 METH_VARARGS | METH_KEYWORDS, "\n"
1099 "Read Xen's console ring.\n"
1100 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1101 "Returns: [str] string is empty on failure.\n" },
1103 { "physinfo",
1104 (PyCFunction)pyxc_physinfo,
1105 METH_NOARGS, "\n"
1106 "Get information about the physical host machine\n"
1107 "Returns [dict]: information about the hardware"
1108 " [None]: on failure.\n" },
1110 { "xeninfo",
1111 (PyCFunction)pyxc_xeninfo,
1112 METH_NOARGS, "\n"
1113 "Get information about the Xen host\n"
1114 "Returns [dict]: information about Xen"
1115 " [None]: on failure.\n" },
1117 { "shadow_control",
1118 (PyCFunction)pyxc_shadow_control,
1119 METH_VARARGS | METH_KEYWORDS, "\n"
1120 "Set parameter for shadow pagetable interface\n"
1121 " dom [int]: Identifier of domain.\n"
1122 " op [int, 0]: operation\n\n"
1123 "Returns: [int] 0 on success; -1 on error.\n" },
1125 { "shadow_mem_control",
1126 (PyCFunction)pyxc_shadow_mem_control,
1127 METH_VARARGS | METH_KEYWORDS, "\n"
1128 "Set or read shadow pagetable memory use\n"
1129 " dom [int]: Identifier of domain.\n"
1130 " mb [int, -1]: MB of shadow memory this domain should have.\n\n"
1131 "Returns: [int] MB of shadow memory in use by this domain.\n" },
1133 { "domain_setmaxmem",
1134 (PyCFunction)pyxc_domain_setmaxmem,
1135 METH_VARARGS, "\n"
1136 "Set a domain's memory limit\n"
1137 " dom [int]: Identifier of domain.\n"
1138 " maxmem_kb [int]: .\n"
1139 "Returns: [int] 0 on success; -1 on error.\n" },
1141 { "domain_memory_increase_reservation",
1142 (PyCFunction)pyxc_domain_memory_increase_reservation,
1143 METH_VARARGS | METH_KEYWORDS, "\n"
1144 "Increase a domain's memory reservation\n"
1145 " dom [int]: Identifier of domain.\n"
1146 " mem_kb [long]: .\n"
1147 "Returns: [int] 0 on success; -1 on error.\n" },
1149 { "domain_ioport_permission",
1150 (PyCFunction)pyxc_domain_ioport_permission,
1151 METH_VARARGS | METH_KEYWORDS, "\n"
1152 "Allow a domain access to a range of IO ports\n"
1153 " dom [int]: Identifier of domain to be allowed access.\n"
1154 " first_port [int]: First IO port\n"
1155 " nr_ports [int]: Number of IO ports\n"
1156 " allow_access [int]: Non-zero means enable access; else disable access\n\n"
1157 "Returns: [int] 0 on success; -1 on error.\n" },
1159 { "domain_irq_permission",
1160 (PyCFunction)pyxc_domain_irq_permission,
1161 METH_VARARGS | METH_KEYWORDS, "\n"
1162 "Allow a domain access to a physical IRQ\n"
1163 " dom [int]: Identifier of domain to be allowed access.\n"
1164 " pirq [int]: The Physical IRQ\n"
1165 " allow_access [int]: Non-zero means enable access; else disable access\n\n"
1166 "Returns: [int] 0 on success; -1 on error.\n" },
1168 { "domain_iomem_permission",
1169 (PyCFunction)pyxc_domain_iomem_permission,
1170 METH_VARARGS | METH_KEYWORDS, "\n"
1171 "Allow a domain access to a range of IO memory pages\n"
1172 " dom [int]: Identifier of domain to be allowed access.\n"
1173 " first_pfn [long]: First page of I/O Memory\n"
1174 " nr_pfns [long]: Number of pages of I/O Memory (>0)\n"
1175 " allow_access [int]: Non-zero means enable access; else disable access\n\n"
1176 "Returns: [int] 0 on success; -1 on error.\n" },
1178 { "pages_to_kib",
1179 (PyCFunction)pyxc_pages_to_kib,
1180 METH_VARARGS, "\n"
1181 "Returns: [int]: The size in KiB of memory spanning the given number "
1182 "of pages.\n" },
1184 { "domain_set_time_offset",
1185 (PyCFunction)pyxc_domain_set_time_offset,
1186 METH_VARARGS, "\n"
1187 "Set a domain's time offset to Dom0's localtime\n"
1188 " dom [int]: Domain whose time offset is being set.\n"
1189 "Returns: [int] 0 on success; -1 on error.\n" },
1191 { NULL, NULL, 0, NULL }
1192 };
1195 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1197 return Py_FindMethod(pyxc_methods, obj, name);
1200 static PyObject *PyXc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1202 XcObject *self = (XcObject *)type->tp_alloc(type, 0);
1204 if (self == NULL)
1205 return NULL;
1207 self->xc_handle = -1;
1209 return (PyObject *)self;
1212 static int
1213 PyXc_init(XcObject *self, PyObject *args, PyObject *kwds)
1215 if ((self->xc_handle = xc_interface_open()) == -1) {
1216 pyxc_error_to_exception();
1217 return -1;
1220 return 0;
1223 static void PyXc_dealloc(XcObject *self)
1225 if (self->xc_handle != -1) {
1226 xc_interface_close(self->xc_handle);
1227 self->xc_handle = -1;
1230 self->ob_type->tp_free((PyObject *)self);
1233 static PyTypeObject PyXcType = {
1234 PyObject_HEAD_INIT(NULL)
1235 0,
1236 PKG "." CLS,
1237 sizeof(XcObject),
1238 0,
1239 (destructor)PyXc_dealloc, /* tp_dealloc */
1240 NULL, /* tp_print */
1241 PyXc_getattr, /* tp_getattr */
1242 NULL, /* tp_setattr */
1243 NULL, /* tp_compare */
1244 NULL, /* tp_repr */
1245 NULL, /* tp_as_number */
1246 NULL, /* tp_as_sequence */
1247 NULL, /* tp_as_mapping */
1248 NULL, /* tp_hash */
1249 NULL, /* tp_call */
1250 NULL, /* tp_str */
1251 NULL, /* tp_getattro */
1252 NULL, /* tp_setattro */
1253 NULL, /* tp_as_buffer */
1254 Py_TPFLAGS_DEFAULT, /* tp_flags */
1255 "Xen client connections", /* tp_doc */
1256 NULL, /* tp_traverse */
1257 NULL, /* tp_clear */
1258 NULL, /* tp_richcompare */
1259 0, /* tp_weaklistoffset */
1260 NULL, /* tp_iter */
1261 NULL, /* tp_iternext */
1262 pyxc_methods, /* tp_methods */
1263 NULL, /* tp_members */
1264 NULL, /* tp_getset */
1265 NULL, /* tp_base */
1266 NULL, /* tp_dict */
1267 NULL, /* tp_descr_get */
1268 NULL, /* tp_descr_set */
1269 0, /* tp_dictoffset */
1270 (initproc)PyXc_init, /* tp_init */
1271 NULL, /* tp_alloc */
1272 PyXc_new, /* tp_new */
1273 };
1275 static PyMethodDef xc_methods[] = { { NULL } };
1277 PyMODINIT_FUNC initxc(void)
1279 PyObject *m;
1281 if (PyType_Ready(&PyXcType) < 0)
1282 return;
1284 m = Py_InitModule(PKG, xc_methods);
1286 if (m == NULL)
1287 return;
1289 xc_error_obj = PyErr_NewException(PKG ".Error", PyExc_RuntimeError, NULL);
1290 zero = PyInt_FromLong(0);
1292 /* KAF: This ensures that we get debug output in a timely manner. */
1293 setbuf(stdout, NULL);
1294 setbuf(stderr, NULL);
1296 Py_INCREF(&PyXcType);
1297 PyModule_AddObject(m, CLS, (PyObject *)&PyXcType);
1299 Py_INCREF(xc_error_obj);
1300 PyModule_AddObject(m, "Error", xc_error_obj);
1302 /* Expose some libxc constants to Python */
1303 PyModule_AddIntConstant(m, "XEN_SCHEDULER_SEDF", XEN_SCHEDULER_SEDF);
1304 PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
1309 /*
1310 * Local variables:
1311 * c-indent-level: 4
1312 * c-basic-offset: 4
1313 * End:
1314 */