[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH]: add libxl python binding
Changes since last time: - split auto-generated code in to c and h files - un-break the build system - fix ocaml binding due to libxl API change - lot's of tidy-ups too numerous to mention Please consider and apply :) -----8<--------------------------------------------------------------- Introduce python binding for libxl. The binding is not yet complete but list_domains, domid_to_name, domain_shutdown and domain_destroy methods are implemented and tested. These functions provide examples of the two basic patterns that all future methods should follow. About 5,000 lines of boilerplate is automatically generated to wrap and export all relevant libxl structure definitions. There are a few places where such code cannot be fully auto-generated and special hooks are declared and stubbed where, for example, conversion between libxl_file_reference and a python file object is required. There are minor changes to libxltypes.py and the libxl.idl file and the new rules are documented. I have also removed the use of a nasty union in libxl_device_pci structure which was making the binding more complicated than necessary and for no good reason (exporting random bits of low level ABI that libxl would rather hide anyway). Finally there is a corresponding (untested) change to the ocaml binding to fix a compile error and maintain previous API in ocaml. Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> -- tools/python/genwrap.py | 346 +++++++++++++++++++++++++++++++ tools/python/xen/lowlevel/xl/xl.c | 397 ++++++++++++++++++++++++++++++++++++ tools/libxl/idl.txt | 7 tools/libxl/libxl.idl | 28 -- tools/libxl/libxl_pci.c | 13 - tools/libxl/libxltypes.py | 27 +- tools/ocaml/libs/xl/xl_stubs.c | 10 tools/python/Makefile | 6 tools/python/setup.py | 19 + 9 files changed, 823 insertions(+), 30 deletions(-) -- diff -r b19856f6dd76 tools/libxl/idl.txt --- a/tools/libxl/idl.txt Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/libxl/idl.txt Thu Sep 09 12:06:50 2010 +0100 @@ -13,7 +13,8 @@ contain the initial namespace element (e how to specify a namespace. The Type.typename contains the C name of the type _including_ the -namespace element. +namespace element while Type.rawname is always set to the 'base' name +of the type. The libxltypes.Type base class has several other properties which apply to all types. The properties are set by passing a named @@ -48,6 +49,10 @@ Type.autogenerate_destructor: (default: Indicates if the above named Type.destructor_fn should be autogenerated. +Type.internal (default: False): + Indicates that type is not suitable for export, for example, via accessors + in auto-generated language bindings. + Other simple type-Classes ------------------------- diff -r b19856f6dd76 tools/libxl/libxl.idl --- a/tools/libxl/libxl.idl Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/libxl/libxl.idl Thu Sep 09 12:06:50 2010 +0100 @@ -6,11 +6,11 @@ libxl_ctx = Builtin("ctx") libxl_uuid = Builtin("uuid") libxl_mac = Builtin("mac") -libxl_qemu_machine_type = Builtin("qemu_machine_type") -libxl_console_consback = Builtin("console_consback") -libxl_console_constype = Builtin("console_constype") -libxl_disk_phystype = Builtin("disk_phystype") -libxl_nic_type = Builtin("nic_type") +libxl_qemu_machine_type = Number("qemu_machine_type", namespace="libxl_") +libxl_console_consback = Number("console_consback", namespace="libxl_") +libxl_console_constype = Number("console_constype", namespace="libxl_") +libxl_disk_phystype = Number("disk_phystype", namespace="libxl_") +libxl_nic_type = Number("nic_type", namespace="libxl_") libxl_string_list = Builtin("string_list", destructor_fn="libxl_string_list_destroy", passby=PASS_BY_REFERENCE) libxl_key_value_list = Builtin("key_value_list", destructor_fn="libxl_key_value_list_destroy", passby=PASS_BY_REFERENCE) @@ -85,7 +85,7 @@ libxl_file_reference = Struct("file_refe mapped is true then the actual file may already be unlinked."""), ("mapped", integer), ("data", void), - ("size", size_t)], autogenerate_destructor=False) + ("size", size_t)], autogenerate_destructor=False, internal=True) libxl_domain_build_info = Struct("domain_build_info",[ ("max_vcpus", integer), @@ -240,17 +240,11 @@ libxl_device_net2 = Struct("device_net2" ]) libxl_device_pci = Struct("device_pci", [ - (None, Union(None, [("value", unsigned_integer), - (None, Struct(None,[("reserved1", BitField(unsigned_integer, 2)), - ("reg", BitField(unsigned_integer, 6)), - ("func", BitField(unsigned_integer, 3)), - ("dev", BitField(unsigned_integer, 5)), - ("bus", BitField(unsigned_integer, 8)), - ("reserved2", BitField(unsigned_integer, 7)), - ("enable", BitField(unsigned_integer, 1)), - ])), - ]) - ), + ("reg", uint8), + ("func", uint8), + ("dev", uint8), + ("bus", uint8), + ("enable", bool), ("domain", unsigned_integer), ("vdevfn", unsigned_integer), ("vfunc_mask", unsigned_integer), diff -r b19856f6dd76 tools/libxl/libxl_pci.c --- a/tools/libxl/libxl_pci.c Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/libxl/libxl_pci.c Thu Sep 09 12:06:50 2010 +0100 @@ -41,6 +41,15 @@ #define PCI_BDF_SHORT "%02x:%02x.%01x" #define PCI_BDF_VDEVFN "%04x:%02x:%02x.%01x@%02x" +static unsigned int pcidev_value(libxl_device_pci *pcidev) +{ + return ((pcidev->reg & 0x3f) << 24) | + ((pcidev->func & 0x7) << 21) | + ((pcidev->dev & 0x1f) << 16) | + ((pcidev->bus & 0xff) << 8) | + ((pcidev->enable) ? 1 : 0); +} + static int pcidev_init(libxl_device_pci *pcidev, unsigned int domain, unsigned int bus, unsigned int dev, unsigned int func, unsigned int vdevfn) @@ -699,7 +708,7 @@ static int do_pci_add(libxl__gc *gc, uin } out: if (!libxl_is_stubdom(ctx, domid, NULL)) { - rc = xc_assign_device(ctx->xch, domid, pcidev->value); + rc = xc_assign_device(ctx->xch, domid, pcidev_value(pcidev)); if (rc < 0 && (hvm || errno != ENOSYS)) { LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_assign_device failed"); return ERROR_FAIL; @@ -915,7 +924,7 @@ out: } if (!libxl_is_stubdom(ctx, domid, NULL)) { - rc = xc_deassign_device(ctx->xch, domid, pcidev->value); + rc = xc_deassign_device(ctx->xch, domid, pcidev_value(pcidev)); if (rc < 0 && (hvm || errno != ENOSYS)) LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_deassign_device failed"); } diff -r b19856f6dd76 tools/libxl/libxltypes.py --- a/tools/libxl/libxltypes.py Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/libxl/libxltypes.py Thu Sep 09 12:06:50 2010 +0100 @@ -14,10 +14,13 @@ class Type(object): if typename is None: # Anonymous type self.typename = None + self.rawname = None elif self.namespace is None: # e.g. system provided types self.typename = typename + self.rawname = typename else: self.typename = self.namespace + typename + self.rawname = typename if self.typename is not None: self.destructor_fn = kwargs.setdefault('destructor_fn', self.typename + "_destroy") @@ -26,17 +29,27 @@ class Type(object): self.autogenerate_destructor = kwargs.setdefault('autogenerate_destructor', True) + self.internal = kwargs.setdefault('internal', False) + class Builtin(Type): """Builtin type""" def __init__(self, typename, **kwargs): kwargs.setdefault('destructor_fn', None) Type.__init__(self, typename, **kwargs) -class UInt(Type): +class Number(Builtin): + def __init__(self, ctype, **kwargs): + kwargs.setdefault('namespace', None) + kwargs.setdefault('destructor_fn', None) + kwargs.setdefault('signed', False) + self.signed = kwargs['signed'] + Builtin.__init__(self, ctype, **kwargs) + +class UInt(Number): def __init__(self, w, **kwargs): kwargs.setdefault('namespace', None) kwargs.setdefault('destructor_fn', None) - Type.__init__(self, "uint%d_t" % w, **kwargs) + Number.__init__(self, "uint%d_t" % w, **kwargs) self.width = w @@ -128,12 +141,12 @@ class Reference(Type): void = Builtin("void *", namespace = None) bool = Builtin("bool", namespace = None) -size_t = Builtin("size_t", namespace = None) +size_t = Number("size_t", namespace = None) -integer = Builtin("int", namespace = None) -unsigned_integer = Builtin("unsigned int", namespace = None) -unsigned = Builtin("unsigned int", namespace = None) -unsigned_long = Builtin("unsigned long", namespace = None) +integer = Number("int", namespace = None, signed = True) +unsigned_integer = Number("unsigned int", namespace = None) +unsigned = Number("unsigned int", namespace = None) +unsigned_long = Number("unsigned long", namespace = None) uint8 = UInt(8) uint16 = UInt(16) diff -r b19856f6dd76 tools/ocaml/libs/xl/xl_stubs.c --- a/tools/ocaml/libs/xl/xl_stubs.c Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/ocaml/libs/xl/xl_stubs.c Thu Sep 09 12:06:50 2010 +0100 @@ -269,9 +269,17 @@ static int device_vfb_val(caml_gc *gc, l static int device_pci_val(caml_gc *gc, libxl_device_pci *c_val, value v) { + unsigned int bitmask; CAMLparam1(v); - c_val->value = Int_val(Field(v, 0)); + /* FIXME: propagate API change to ocaml */ + bitmask = Int_val(Field(v, 0)); + c_val->reg = (bitmask & (0x3f << 24)) >> 24; + c_val->func = (bitmask & (0x7 << 21)) >> 21; + c_val->dev = (bitmask & (0x1f << 16)) >> 16; + c_val->bus = (bitmask & (0xff << 8)) >> 8; + c_val->enable = bitmask & 1; + c_val->domain = Int_val(Field(v, 1)); c_val->vdevfn = Int_val(Field(v, 2)); c_val->msitranslate = Bool_val(Field(v, 3)); diff -r b19856f6dd76 tools/python/Makefile --- a/tools/python/Makefile Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/python/Makefile Thu Sep 09 12:06:50 2010 +0100 @@ -20,6 +20,10 @@ genpath-target = $(call buildmakevars2fi .PHONY: build buildpy buildpy: genpath + PYTHONPATH=$(XEN_ROOT)/tools/libxl $(PYTHON) genwrap.py \ + $(XEN_ROOT)/tools/libxl/libxl.idl \ + xen/lowlevel/xl/_pyxl_types.h \ + xen/lowlevel/xl/_pyxl_types.c CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build build: buildpy refresh-pot refresh-po $(CATALOGS) @@ -85,6 +89,8 @@ test: clean: rm -f $(XENPATH) rm -rf build *.pyc *.pyo *.o *.a *~ $(CATALOGS) xen/util/auxbin.pyc + rm -f xen/lowlevel/xl/_pyxl_types.h + rm -f xen/lowlevel/xl/_pyxl_types.c rm -f $(DEPS) -include $(DEPS) diff -r b19856f6dd76 tools/python/genwrap.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/genwrap.py Thu Sep 09 12:06:50 2010 +0100 @@ -0,0 +1,346 @@ +#!/usr/bin/python + +import sys,os + +import libxltypes + +def py_type(ty): + if ty == libxltypes.bool or isinstance(ty, libxltypes.BitField) and ty.width == 1: + return "Bool" + if isinstance(ty, libxltypes.Number): + if ty.signed: + return "Int" + else: + return "Uint" + if ty == libxltypes.string: + return "String" + return None + +def py_wrapstruct(ty): + l = [] + l.append("typedef struct {") + l.append(" PyObject_HEAD;") + l.append(" %s obj;"%ty.typename); + l.append("}Py_%s;"%ty.rawname) + l.append("") + return "\n".join(l) + "\n" + +def fsanitize(name): + "Sanitise a function name given a C type" + ret = '_'.join(name.split()) + return ret.replace('*', 'ptr') + +def py_decls(ty): + l = [] + l.append("_hidden PyObject *Py%s_New(void);\n"%ty.rawname) + for f in ty.fields: + if py_type(f.type) is not None: + continue + l.append("_hidden PyObject *attrib__%s_get(%s *%s);"%(\ + fsanitize(f.type.typename), f.type.typename, f.name)) + l.append("_hidden int attrib__%s_set(PyObject *v, %s *%s);"%(\ + fsanitize(f.type.typename), f.type.typename, f.name)) + return '\n'.join(l) + "\n" + +def py_attrib_get(ty, f): + t = py_type(f.type) + l = [] + l.append("static PyObject *py_%s_%s_get(Py_%s *self, void *priv)"%(ty.rawname, f.name, ty.rawname)) + l.append("{") + if t == "Bool": + l.append(" return (self->obj.%s) ? Py_True : Py_False;"%f.name) + elif t == "Int": + l.append(" return genwrap__ll_get(self->obj.%s);"%f.name) + elif t == "Uint": + l.append(" return genwrap__ull_get(self->obj.%s);"%f.name) + elif t == "String": + l.append(" return genwrap__string_get(&self->obj.%s);"%f.name) + else: + tn = f.type.typename + l.append(" return attrib__%s_get((%s *)&self->obj.%s);"%(fsanitize(tn), tn, f.name)) + l.append("}") + return '\n'.join(l) + "\n\n" + +def py_attrib_set(ty, f): + t = py_type(f.type) + l = [] + l.append("static int py_%s_%s_set(Py_%s *self, PyObject *v, void *priv)"%(ty.rawname, f.name, ty.rawname)) + l.append("{") + if t == "Bool": + l.append(" self->obj.%s = (NULL == v || Py_None == v || Py_False == v) ? 0 : 1;"%f.name) + l.append(" return 0;") + elif t == "Uint" or t == "Int": + l.append(" %slong long tmp;"%(t == "Uint" and "unsigned " or "")) + l.append(" int ret;") + if t == "Uint": + l.append(" ret = genwrap__ull_set(v, &tmp, (%s)~0);"%f.type.typename) + else: + l.append(" ret = genwrap__ll_set(v, &tmp, (%s)~0);"%f.type.typename) + l.append(" if ( ret >= 0 )") + l.append(" self->obj.%s = tmp;"%f.name) + l.append(" return ret;") + elif t == "String": + l.append(" return genwrap__string_set(v, &self->obj.%s);"%f.name) + else: + tn = f.type.typename + l.append(" return attrib__%s_set(v, (%s *)&self->obj.%s);"%(fsanitize(tn), tn, f.name)) + l.append("}") + return '\n'.join(l) + "\n\n" + +def py_object_def(ty): + l = [] + if ty.destructor_fn is not None: + dtor = " %s(&self->obj);\n"%ty.destructor_fn + else: + dtor = "" + + funcs="""static void Py%s_dealloc(Py_%s *self) +{ +%s self->ob_type->tp_free((PyObject *)self); +} + +static int Py%s_init(Py_%s *self, PyObject *args, PyObject *kwds) +{ + memset(&self->obj, 0, sizeof(self->obj)); + return 0; +} + +static PyObject *Py%s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Py_%s *self = (Py_%s *)type->tp_alloc(type, 0); + if (self == NULL) + return NULL; + memset(&self->obj, 0, sizeof(self->obj)); + return (PyObject *)self; +} + +"""%((ty.rawname, ty.rawname, dtor) + tuple(ty.rawname for x in range(5))) + + l.append("static PyGetSetDef Py%s_getset[] = {"%ty.rawname) + for f in ty.fields: + l.append(" { .name = \"%s\", "%f.name) + l.append(" .get = (getter)py_%s_%s_get, "%(ty.rawname, f.name)) + l.append(" .set = (setter)py_%s_%s_set },"%(ty.rawname, f.name)) + l.append(" { .name = NULL }") + l.append("};") + struct=""" +static PyTypeObject Py%s_Type= { + PyObject_HEAD_INIT(NULL) + 0, + PKG ".%s", + sizeof(Py_%s), + 0, + (destructor)Py%s_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + NULL, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "%s", /* tp_doc */ + NULL, /* tp_traverse */ + NULL, /* tp_clear */ + NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + NULL, /* tp_methods */ + NULL, /* tp_members */ + Py%s_getset, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Py%s_init, /* tp_init */ + NULL, /* tp_alloc */ + Py%s_new, /* tp_new */ +}; + +PyObject *Py%s_New(void) +{ + return Py%s_new(&Py%s_Type, NULL, NULL); +} +"""%tuple(ty.rawname for x in range(11)) + return funcs + '\n'.join(l) + "\n" + struct + +def py_initfuncs(types): + l = [] + l.append("void genwrap__init(PyObject *m)") + l.append("{") + for ty in types: + l.append(" if (PyType_Ready(&Py%s_Type) >= 0) {"%ty.rawname) + l.append(" Py_INCREF(&Py%s_Type);"%ty.rawname) + l.append(" PyModule_AddObject(m, \"%s\", (PyObject *)&Py%s_Type);"%(ty.rawname, ty.rawname)) + l.append(" }") + l.append("}") + return '\n'.join(l) + "\n\n" + +def tree_frob(types): + ret = filter(lambda x:not x.internal, types) + for ty in ret: + ty.fields = filter(lambda f:f.name is not None and f.type.typename is not None, ty.fields) + return ret + +if __name__ == '__main__': + if len(sys.argv) < 4: + print >>sys.stderr, "Usage: genwrap.py <idl> <decls> <defns>" + sys.exit(1) + + idl = sys.argv[1] + (_,types) = libxltypes.parse(idl) + + types = tree_frob(types) + + decls = sys.argv[2] + f = open(decls, "w") + f.write("""#ifndef __PYXL_TYPES_H +#define __PYXL_TYPES_H + +/* + * DO NOT EDIT. + * + * This file is autogenerated by + * "%s" + */ + +#define PKG "xen.lowlevel.xl" + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define _hidden __attribute__((visibility("hidden"))) +#define _protected __attribute__((visibility("protected"))) +#else +#define _hidden +#define _protected +#endif + +/* Initialise all types */ +_hidden void genwrap__init(PyObject *m); + +/* Auto-generated get/set functions for simple data-types */ +_hidden int genwrap__string_set(PyObject *v, char **str); +_hidden PyObject *genwrap__string_get(char **str); +_hidden PyObject *genwrap__ull_get(unsigned long long val); +_hidden int genwrap__ull_set(PyObject *v, unsigned long long *val, unsigned long long mask); +_hidden PyObject *genwrap__ll_get(long long val); +_hidden int genwrap__ll_set(PyObject *v, long long *val, long long mask); + +""" % " ".join(sys.argv)) + for ty in types: + f.write("/* Internal APU for %s wrapper */\n"%ty.typename) + f.write(py_wrapstruct(ty)) + f.write(py_decls(ty)) + f.write("\n") + f.write("""#endif /* __PYXL_TYPES_H */\n""") + f.close() + + defns = sys.argv[3] + f = open(defns, "w") + f.write("""/* + * DO NOT EDIT. + * + * This file is autogenerated by + * "%s" + */ + +#include <Python.h> +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include "libxl.h" /* gah */ +#include "%s" + +int genwrap__string_set(PyObject *v, char **str) +{ + char *tmp; + if ( NULL == v ) { + free(*str); + *str = NULL; + return 0; + } + tmp = strdup(PyString_AsString(v)); + if ( NULL == tmp ) { + PyErr_SetString(PyExc_MemoryError, "Allocating device_net2.bridge attribute"); + return -1; + } + free(*str); + *str = tmp; + return 0; +} + +PyObject *genwrap__string_get(char **str) +{ + if ( NULL == *str ) + return Py_None; + return PyString_FromString(*str); +} + +PyObject *genwrap__ull_get(unsigned long long val) +{ + return PyLong_FromUnsignedLongLong(val); +} + +int genwrap__ull_set(PyObject *v, unsigned long long *val, unsigned long long mask) +{ + unsigned long long tmp; + if ( NULL == v ) { + *val = 0; + return 0; + } + if ( PyLong_Check(v) ) { + tmp = PyLong_AsUnsignedLongLong(v); + }else{ + tmp = (unsigned long long)PyInt_AsLong(v); + } + if ( tmp & ~mask ) { + PyErr_SetString(PyExc_ValueError, "Integer overflow"); + return -1; + } + *val = tmp; + return 0; +} + +PyObject *genwrap__ll_get(long long val) +{ + return PyLong_FromLongLong(val); +} + +int genwrap__ll_set(PyObject *v, long long *val, long long mask) +{ + long long tmp; + if ( NULL == v ) { + *val = 0; + return 0; + } + if ( PyLong_Check(v) ) { + tmp = PyLong_AsLongLong(v); + }else{ + tmp = (long long)PyInt_AsLong(v); + } + if ( tmp & ~mask ) { + PyErr_SetString(PyExc_ValueError, "Integer overflow"); + return -1; + } + *val = tmp; + return 0; +} + +""" % tuple((" ".join(sys.argv),) + (os.path.split(decls)[-1:]),)) + for ty in types: + f.write("/* Attribute get/set functions for %s */\n"%ty.typename) + for a in ty.fields: + f.write(py_attrib_get(ty,a)) + f.write(py_attrib_set(ty,a)) + f.write(py_object_def(ty)) + f.write(py_initfuncs(types)) + f.close() diff -r b19856f6dd76 tools/python/setup.py --- a/tools/python/setup.py Thu Sep 09 09:24:24 2010 +0100 +++ b/tools/python/setup.py Thu Sep 09 12:06:50 2010 +0100 @@ -9,14 +9,23 @@ extra_compile_args = [ "-fno-strict-ali include_dirs = [ XEN_ROOT + "/tools/libxc", XEN_ROOT + "/tools/xenstore", XEN_ROOT + "/tools/include", + XEN_ROOT + "/tools/libxl", ] library_dirs = [ XEN_ROOT + "/tools/libxc", XEN_ROOT + "/tools/xenstore", + XEN_ROOT + "/tools/libxl", + XEN_ROOT + "/tools/blktap2/control", ] libraries = [ "xenctrl", "xenguest", "xenstore" ] +plat = os.uname()[0] +if plat == 'Linux': + uuid_libs = ["uuid"] +else: + uuid_libs = [] + xc = Extension("xc", extra_compile_args = extra_compile_args, include_dirs = include_dirs + [ "xen/lowlevel/xc" ], @@ -83,8 +92,14 @@ netlink = Extension("netlink", sources = [ "xen/lowlevel/netlink/netlink.c", "xen/lowlevel/netlink/libnetlink.c"]) -modules = [ xc, xs, ptsname, acm, flask ] -plat = os.uname()[0] +xl = Extension("xl", + extra_compile_args = extra_compile_args, + include_dirs = include_dirs + [ "xen/lowlevel/xl" ], + library_dirs = library_dirs, + libraries = libraries + ["xenlight", "blktapctl" ] + uuid_libs, + sources = [ "xen/lowlevel/xl/xl.c", "xen/lowlevel/xl/_pyxl_types.c" ]) + +modules = [ xc, xs, ptsname, acm, flask, xl ] if plat == 'SunOS': modules.extend([ scf, process ]) if plat == 'Linux': diff -r b19856f6dd76 tools/python/xen/lowlevel/xl/xl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/lowlevel/xl/xl.c Thu Sep 09 12:06:50 2010 +0100 @@ -0,0 +1,397 @@ +/****************************************************************************** + * xl.c + * + * Copyright (c) 2010 Citrix Ltd. + * Author: Gianni Tedesco + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2.1 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <Python.h> +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <getopt.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <arpa/inet.h> +#include <xenctrl.h> +#include <ctype.h> +#include <inttypes.h> + + +#include <libxl.h> +#include <libxl_utils.h> + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* Needed for Python versions earlier than 2.3. */ +#ifndef PyMODINIT_FUNC +#define PyMODINIT_FUNC DL_EXPORT(void) +#endif + +#define CLS "ctx" + +static PyObject *xl_error_obj; + +static int fixed_bytearray_set(PyObject *v, uint8_t *ptr, size_t len) +{ + char *tmp; + size_t sz; + + if ( NULL == v ) { + memset(ptr, 0, len); + return 0; + } + if ( PyByteArray_Check(v) ) { + sz = PyByteArray_Size(v); + tmp = PyByteArray_AsString(v); + }else{ + Py_ssize_t ssz; + if ( PyString_AsStringAndSize(v, &tmp, &ssz) ) + return -1; + if ( ssz < 0 ) + tmp = NULL; + sz = ssz; + } + if ( NULL == tmp ) { + memset(ptr, 0, len); + return 0; + } + if ( sz != len ) { + PyErr_SetString(PyExc_TypeError, + (sz < len) ? "Byffer underflow" : "Buffer overflow"); + return -1; + } + + memcpy(ptr, tmp, sz); + return 0; +} + +static PyObject *fixed_bytearray_get(const uint8_t *ptr, size_t len) +{ + return PyByteArray_FromStringAndSize((const char *)ptr, len); +} + +#include "_pyxl_types.h" + +int attrib__libxl_cpumap_set(PyObject *v, libxl_cpumap *pptr) +{ + return -1; +} + +int attrib__libxl_domain_build_state_ptr_set(PyObject *v, libxl_domain_build_state **pptr) +{ + return -1; +} + +int attrib__libxl_file_reference_set(PyObject *v, libxl_file_reference *pptr) +{ + return -1; +} + +int attrib__libxl_hwcap_set(PyObject *v, libxl_hwcap *pptr) +{ + return -1; +} + +int attrib__libxl_key_value_list_set(PyObject *v, libxl_key_value_list *pptr) +{ + return -1; +} + +int attrib__libxl_mac_set(PyObject *v, libxl_mac *pptr) +{ + return fixed_bytearray_set(v, *pptr, 6); +} + +int attrib__libxl_string_list_set(PyObject *v, libxl_string_list *pptr) +{ + return -1; +} + +int attrib__libxl_uuid_set(PyObject *v, libxl_uuid *pptr) +{ + return fixed_bytearray_set(v, libxl_uuid_bytearray(pptr), 16); +} + +int attrib__struct_in_addr_set(PyObject *v, struct in_addr *pptr) +{ + return -1; +} + +PyObject *attrib__libxl_cpumap_get(libxl_cpumap *pptr) +{ + return NULL; +} + +PyObject *attrib__libxl_domain_build_state_ptr_get(libxl_domain_build_state **pptr) +{ + return NULL; +} + +PyObject *attrib__libxl_file_reference_get(libxl_file_reference *pptr) +{ + return NULL; +} + +PyObject *attrib__libxl_hwcap_get(libxl_hwcap *pptr) +{ + return NULL; +} + +PyObject *attrib__libxl_key_value_list_get(libxl_key_value_list *pptr) +{ + return NULL; +} + +PyObject *attrib__libxl_mac_get(libxl_mac *pptr) +{ + return fixed_bytearray_get(*pptr, 6); +} + +PyObject *attrib__libxl_string_list_get(libxl_string_list *pptr) +{ + return NULL; +} + +PyObject *attrib__libxl_uuid_get(libxl_uuid *pptr) +{ + return fixed_bytearray_get(libxl_uuid_bytearray(pptr), 16); +} + +PyObject *attrib__struct_in_addr_get(struct in_addr *pptr) +{ + return NULL; +} + +typedef struct { + PyObject_HEAD; + libxl_ctx ctx; + xentoollog_logger_stdiostream *logger; + xentoollog_level minmsglevel; +} XlObject; + +static PyObject *pyxl_list_domains(XlObject *self) +{ + libxl_dominfo *cur, *info; + PyObject *list; + int nr_dom, i; + + info = libxl_list_domain(&self->ctx, &nr_dom); + if ( NULL == info ) + return PyList_New(0); + + list = PyList_New(nr_dom); + if ( NULL == list ) + goto err_mem; + + for(i = 0, cur = info; i < nr_dom; i++, cur++) { + Py_dominfo *di; + di = (Py_dominfo *)Pydominfo_New(); + if ( NULL == di ) + goto err_mem; + memcpy(&di->obj, cur, sizeof(di->obj)); + PyList_SetItem(list, i, (PyObject *)di); + } + + free(info); + return list; +err_mem: + Py_DECREF(list); + PyErr_SetString(PyExc_MemoryError, "Allocating domain list"); + return NULL; +} + +static PyObject *pyxl_domid_to_name(XlObject *self, PyObject *args) +{ + char *domname; + int domid; + PyObject *ret; + + if ( !PyArg_ParseTuple(args, "i", &domid) ) + return NULL; + + domname = libxl_domid_to_name(&self->ctx, domid); + ret = PyString_FromString(domname); + free(domname); + + return ret; +} + +static PyObject *pyxl_domain_shutdown(XlObject *self, PyObject *args) +{ + int domid, req = 0; + if ( !PyArg_ParseTuple(args, "i|i", &domid, &req) ) + return NULL; + if ( libxl_domain_shutdown(&self->ctx, domid, req) ) { + PyErr_SetString(xl_error_obj, "cannot shutdown domain"); + return NULL; + } + return Py_None; +} + +static PyObject *pyxl_domain_destroy(XlObject *self, PyObject *args) +{ + int domid, force = 1; + if ( !PyArg_ParseTuple(args, "i|i", &domid, &force) ) + return NULL; + if ( libxl_domain_destroy(&self->ctx, domid, force) ) { + PyErr_SetString(xl_error_obj, "cannot destroy domain"); + return NULL; + } + return Py_None; +} + +static PyMethodDef pyxl_methods[] = { + {"list_domains", (PyCFunction)pyxl_list_domains, METH_NOARGS, + "List domains"}, + {"domid_to_name", (PyCFunction)pyxl_domid_to_name, METH_VARARGS, + "Retrieve name from domain-id"}, + {"domain_shutdown", (PyCFunction)pyxl_domain_shutdown, METH_VARARGS, + "Shutdown a domain"}, + {"domain_destroy", (PyCFunction)pyxl_domain_destroy, METH_VARARGS, + "Destroy a domain"}, + { NULL, NULL, 0, NULL } +}; + +static PyObject *PyXl_getattr(PyObject *obj, char *name) +{ + return Py_FindMethod(pyxl_methods, obj, name); +} + +static PyObject *PyXl_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + XlObject *self = (XlObject *)type->tp_alloc(type, 0); + + if (self == NULL) + return NULL; + + memset(&self->ctx, 0, sizeof(self->ctx)); + self->logger = NULL; + self->minmsglevel = XTL_PROGRESS; + + return (PyObject *)self; +} + +static int +PyXl_init(XlObject *self, PyObject *args, PyObject *kwds) +{ + self->logger = xtl_createlogger_stdiostream(stderr, self->minmsglevel, 0); + if (!self->logger) { + PyErr_SetString(xl_error_obj, "cannot init xl logger"); + return -1; + } + + if ( libxl_ctx_init(&self->ctx, LIBXL_VERSION, + (xentoollog_logger*)self->logger) ) { + PyErr_SetString(xl_error_obj, "cannot init xl context"); + return -1; + } + + return 0; +} + +static void PyXl_dealloc(XlObject *self) +{ + libxl_ctx_free(&self->ctx); + if ( self->logger ) + xtl_logger_destroy((xentoollog_logger*)self->logger); + + self->ob_type->tp_free((PyObject *)self); +} + +static PyTypeObject PyXlType = { + PyObject_HEAD_INIT(NULL) + 0, + PKG "." CLS, + sizeof(XlObject), + 0, + (destructor)PyXl_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + PyXl_getattr, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + NULL, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "libxenlight connection", /* tp_doc */ + NULL, /* tp_traverse */ + NULL, /* tp_clear */ + NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + pyxl_methods, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)PyXl_init, /* tp_init */ + NULL, /* tp_alloc */ + PyXl_new, /* tp_new */ +}; + +static PyMethodDef xl_methods[] = { { NULL } }; + +PyMODINIT_FUNC initxl(void) +{ + PyObject *m; + + if (PyType_Ready(&PyXlType) < 0) + return; + + m = Py_InitModule(PKG, xl_methods); + + if (m == NULL) + return; + + xl_error_obj = PyErr_NewException(PKG ".Error", PyExc_RuntimeError, NULL); + + Py_INCREF(&PyXlType); + PyModule_AddObject(m, CLS, (PyObject *)&PyXlType); + + Py_INCREF(xl_error_obj); + PyModule_AddObject(m, "Error", xl_error_obj); + + genwrap__init(m); +} + + +/* + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * End: + */ _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |