[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 59/59] tools/xenlight: Create interface for xenlight info
Create interface to interact with libxl_verions_info and libxl_physinfo. Also introduce proper error handling. Signed-off-by: Ronald Rojas <ronladred@xxxxxxxxx> --- tools/golang/xenlight/libxl.go | 720 -------------------------- tools/golang/xenlight/xenlight.go | 1000 +++++++++++++++++++++++++++++++++++++ 2 files changed, 1000 insertions(+), 720 deletions(-) delete mode 100644 tools/golang/xenlight/libxl.go create mode 100644 tools/golang/xenlight/xenlight.go diff --git a/tools/golang/xenlight/libxl.go b/tools/golang/xenlight/libxl.go deleted file mode 100644 index aa5c01c..0000000 --- a/tools/golang/xenlight/libxl.go +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright (C) 2016 George W. Dunlap, Citrix Systems UK Ltd - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of the - * License only. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -package main - -/* -#cgo LDFLAGS: -lxenlight -lyajl_s -lxengnttab -lxenstore -lxenguest -lxentoollog -lxenevtchn -lxenctrl -lblktapctl -lxenforeignmemory -lxencall -lz -luuid -lutil -#include <stdlib.h> -#include <libxl.h> -*/ -import "C" - -/* - * Other flags that may be needed at some point: - * -lnl-route-3 -lnl-3 - * - * To get back to simple dynamic linking: -#cgo LDFLAGS: -lxenlight -lyajl -*/ - -import ( - "unsafe" - "fmt" - "time" -) - -/* - * Types: Builtins - */ - -type Domid uint32 - -type MemKB uint64 - -// typedef struct { -// uint32_t size; /* number of bytes in map */ -// uint8_t *map; -// } libxl_bitmap; - -// Implement the Go bitmap type such that the underlying data can -// easily be copied in and out. NB that we still have to do copies -// both directions, because cgo runtime restrictions forbid passing to -// a C function a pointer to a Go-allocated structure which contains a -// pointer. -type Bitmap struct { - bitmap []C.uint8_t -} - -type Context struct { - ctx *C.libxl_ctx -} - -type Uuid C.libxl_uuid - -/* - * Types: IDL - * - * FIXME: Generate these automatically from the IDL - */ -type Dominfo struct { - Uuid Uuid - Domid Domid - Running bool - Blocked bool - Paused bool - Shutdown bool - Dying bool - Never_stop bool - - Shutdown_reason int32 // FIXME shutdown_reason enumeration - Outstanding_memkb MemKB - Current_memkb MemKB - Shared_memkb MemKB - Paged_memkb MemKB - Max_memkb MemKB - Cpu_time time.Duration - Vcpu_max_id uint32 - Vcpu_online uint32 - Cpupool uint32 - Domain_type int32 //FIXME libxl_domain_type enumeration - -} - -// # Consistent with values defined in domctl.h -// # Except unknown which we have made up -// libxl_scheduler = Enumeration("scheduler", [ -// (0, "unknown"), -// (4, "sedf"), -// (5, "credit"), -// (6, "credit2"), -// (7, "arinc653"), -// (8, "rtds"), -// ]) -type Scheduler int -var ( - SchedulerUnknown Scheduler = C.LIBXL_SCHEDULER_UNKNOWN - SchedulerSedf Scheduler = C.LIBXL_SCHEDULER_SEDF - SchedulerCredit Scheduler = C.LIBXL_SCHEDULER_CREDIT - SchedulerCredit2 Scheduler = C.LIBXL_SCHEDULER_CREDIT2 - SchedulerArinc653 Scheduler = C.LIBXL_SCHEDULER_ARINC653 - SchedulerRTDS Scheduler = C.LIBXL_SCHEDULER_RTDS -) - -// libxl_cpupoolinfo = Struct("cpupoolinfo", [ -// ("poolid", uint32), -// ("pool_name", string), -// ("sched", libxl_scheduler), -// ("n_dom", uint32), -// ("cpumap", libxl_bitmap) -// ], dir=DIR_OUT) - -type CpupoolInfo struct { - Poolid uint32 - PoolName string - Scheduler Scheduler - DomainCount int - Cpumap Bitmap -} - -/* - * Context - */ -var Ctx Context - -func (Ctx *Context) IsOpen() bool { - return Ctx.ctx != nil -} - -func (Ctx *Context) Open() (err error) { - if Ctx.ctx != nil { - return - } - - ret := C.libxl_ctx_alloc(unsafe.Pointer(&Ctx.ctx), C.LIBXL_VERSION, 0, nil) - - if ret != 0 { - err = fmt.Errorf("Allocating libxl context: %d", ret) - } - return -} - -func (Ctx *Context) Close() (err error) { - ret := C.libxl_ctx_free(unsafe.Pointer(Ctx.ctx)) - Ctx.ctx = nil - - if ret != 0 { - err = fmt.Errorf("Freeing libxl context: %d", ret) - } - return -} - -func (Ctx *Context) CheckOpen() (err error) { - if Ctx.ctx == nil { - err = fmt.Errorf("Context not opened") - } - return -} - -func (Ctx *Context) DomainInfo(Id Domid) (di *Dominfo, err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - var cdi C.libxl_dominfo - - ret := C.libxl_domain_info(Ctx.ctx, unsafe.Pointer(&cdi), C.uint32_t(Id)) - - // FIXME: IsDomainNotPresentError - if ret != 0 { - err = fmt.Errorf("libxl_domain_info failed: %d", ret) - return - } - - // We could consider having this boilerplate generated by the - // idl, in a function like this: - // - // di = translateCdomaininfoToGoDomaininfo(cdi) - di = &Dominfo{} - di.Uuid = Uuid(cdi.uuid) - di.Domid = Domid(cdi.domid) - di.Running = bool(cdi.running) - di.Blocked = bool(cdi.blocked) - di.Paused = bool(cdi.paused) - di.Shutdown = bool(cdi.shutdown) - di.Dying = bool(cdi.dying) - di.Never_stop = bool(cdi.never_stop) - di.Shutdown_reason = int32(cdi.shutdown_reason) - di.Outstanding_memkb = MemKB(cdi.outstanding_memkb) - di.Current_memkb = MemKB(cdi.current_memkb) - di.Shared_memkb = MemKB(cdi.shared_memkb) - di.Paged_memkb = MemKB(cdi.paged_memkb) - di.Max_memkb = MemKB(cdi.max_memkb) - di.Cpu_time = time.Duration(cdi.cpu_time) - di.Vcpu_max_id = uint32(cdi.vcpu_max_id) - di.Vcpu_online = uint32(cdi.vcpu_online) - di.Cpupool = uint32(cdi.cpupool) - di.Domain_type = int32(cdi.domain_type) - - return -} - -func (Ctx *Context) DomainUnpause(Id Domid) (err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - ret := C.libxl_domain_unpause(Ctx.ctx, C.uint32_t(Id)) - - if ret != 0 { - err = fmt.Errorf("libxl_domain_unpause failed: %d", ret) - } - return -} - -/* - * Bitmap operations - */ - -// Return a Go bitmap which is a copy of the referred C bitmap. -func bitmapCToGo(cbm C.libxl_bitmap) (gbm Bitmap) { - // Alloc a Go slice for the bytes - size := int(cbm.size) - gbm.bitmap = make([]C.uint8_t, size) - - // Make a slice pointing to the C array - mapslice := (*[1 << 30]C.uint8_t)(unsafe.Pointer(cbm._map))[:size:size] - - // And copy the C array into the Go array - copy(gbm.bitmap, mapslice) - - return -} - -// Must be C.libxl_bitmap_dispose'd of afterwards -func bitmapGotoC(gbm Bitmap) (cbm C.libxl_bitmap) { - C.libxl_bitmap_init(&cbm) - - size := len(gbm.bitmap) - cbm._map = (*C.uint8_t)(C.malloc(C.size_t(size))) - cbm.size = C.uint32_t(size) - if cbm._map == nil { - panic("C.calloc failed!") - } - - // Make a slice pointing to the C array - mapslice := (*[1 << 30]C.uint8_t)(unsafe.Pointer(cbm._map))[:size:size] - - // And copy the Go array into the C array - copy(mapslice, gbm.bitmap) - - return -} - -func (bm *Bitmap) Test(bit int) (bool) { - ubit := uint(bit) - if (bit > bm.Max() || bm.bitmap == nil) { - return false - } - - return (bm.bitmap[bit / 8] & (1 << (ubit & 7))) != 0 -} - -func (bm *Bitmap) Set(bit int) { - ibit := bit / 8; - if (ibit + 1 > len(bm.bitmap)) { - bm.bitmap = append(bm.bitmap, make([]C.uint8_t, ibit+1-len(bm.bitmap))...) - } - - bm.bitmap[ibit] |= 1 << (uint(bit) & 7) -} - -func (bm *Bitmap) SetRange(start int, end int) { - for i := start; i <= end; i++ { - bm.Set(i) - } -} - -func (bm *Bitmap) Clear(bit int) { - ubit := uint(bit) - if (bit > bm.Max() || bm.bitmap == nil) { - return - } - - bm.bitmap[bit / 8] &= ^(1 << (ubit & 7)) -} - -func (bm *Bitmap) ClearRange(start int, end int) { - for i := start; i <= end; i++ { - bm.Clear(i) - } -} - -func (bm *Bitmap) Max() (int) { - return len(bm.bitmap) * 8 - 1 -} - -func (bm *Bitmap) IsEmpty() (bool) { - for i:=0; i<len(bm.bitmap); i++ { - if bm.bitmap[i] != 0 { - return false - } - } - return true -} - -func (a Bitmap) And(b Bitmap) (c Bitmap) { - var max, min int - if len(a.bitmap) > len(b.bitmap) { - max = len(a.bitmap) - min = len(b.bitmap) - } else { - max = len(b.bitmap) - min = len(a.bitmap) - } - c.bitmap = make([]C.uint8_t, max) - - for i := 0; i < min; i++ { - c.bitmap[i] = a.bitmap[i] & b.bitmap[i] - } - return -} - -func (bm Bitmap) String() (s string) { - lastOnline := false - crange := false - printed := false - var i int - /// --x-xxxxx-x -> 2,4-8,10 - /// --x-xxxxxxx -> 2,4-10 - for i = 0; i <= bm.Max(); i++ { - if bm.Test(i) { - if !lastOnline { - // Switching offline -> online, print this cpu - if printed { - s += "," - } - s += fmt.Sprintf("%d", i) - printed = true - } else if !crange { - // last was online, but we're not in a range; print - - crange = true - s += "-" - } else { - // last was online, we're in a range, nothing else to do - } - lastOnline = true - } else { - if lastOnline { - // Switching online->offline; do we need to end a range? - if crange { - s += fmt.Sprintf("%d", i-1) - } - } - lastOnline = false - crange = false - } - } - if lastOnline { - // Switching online->offline; do we need to end a range? - if crange { - s += fmt.Sprintf("%d", i-1) - } - } - - return -} - -// const char *libxl_scheduler_to_string(libxl_scheduler p); -func (s Scheduler) String() (string) { - cs := C.libxl_scheduler_to_string(C.libxl_scheduler(s)) - // No need to free const return value - - return C.GoString(cs) -} - -// int libxl_scheduler_from_string(const char *s, libxl_scheduler *e); -func (s *Scheduler) FromString(gstr string) (err error) { - cstr := C.CString(gstr) - defer C.free(unsafe.Pointer(cstr)) - - var cs C.libxl_scheduler - ret := C.libxl_scheduler_from_string(cstr, &cs) - if ret != 0 { - err = fmt.Errorf("libxl_scheduler_from_string: %d\n", ret) - return - } - - *s = Scheduler(cs) - return -} - -func translateCpupoolInfoCToGo(cci C.libxl_cpupoolinfo) (gci CpupoolInfo) { - gci.Poolid = uint32(cci.poolid) - gci.PoolName = C.GoString(cci.pool_name) - gci.Scheduler = Scheduler(cci.sched) - gci.DomainCount = int(cci.n_dom) - gci.Cpumap = bitmapCToGo(cci.cpumap) - - return -} - -func SchedulerFromString(name string) (s Scheduler, err error) { - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - - var cs C.libxl_scheduler - - ret := C.libxl_scheduler_from_string(cname, &cs) - if ret != 0 { - err = fmt.Errorf("libxl_scheduler_from_string failed: %d", ret) - return - } - - s = Scheduler(cs) - - return -} - -// libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx*, int *nb_pool_out); -// void libxl_cpupoolinfo_list_free(libxl_cpupoolinfo *list, int nb_pool); -func (Ctx *Context) ListCpupool() (list []CpupoolInfo) { - err := Ctx.CheckOpen() - if err != nil { - return - } - - var nbPool C.int - - c_cpupool_list := C.libxl_list_cpupool(Ctx.ctx, &nbPool) - - defer C.libxl_cpupoolinfo_list_free(c_cpupool_list, nbPool) - - if int(nbPool) == 0 { - return - } - - // Magic - cpupoolListSlice := (*[1 << 30]C.libxl_cpupoolinfo)(unsafe.Pointer(c_cpupool_list))[:nbPool:nbPool] - - for i := range cpupoolListSlice { - info := translateCpupoolInfoCToGo(cpupoolListSlice[i]) - - list = append(list, info) - } - - return -} - -// int libxl_cpupool_info(libxl_ctx *ctx, libxl_cpupoolinfo *info, uint32_t poolid); -func (Ctx *Context) CpupoolInfo(Poolid uint32) (pool CpupoolInfo) { - err := Ctx.CheckOpen() - if err != nil { - return - } - - var c_cpupool C.libxl_cpupoolinfo - - ret := C.libxl_cpupool_info(Ctx.ctx, &c_cpupool, C.uint32_t(Poolid)) - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_info failed: %d", ret) - return - } - defer C.libxl_cpupoolinfo_dispose(&c_cpupool) - - pool = translateCpupoolInfoCToGo(c_cpupool) - - return -} - - - -// int libxl_cpupool_create(libxl_ctx *ctx, const char *name, -// libxl_scheduler sched, -// libxl_bitmap cpumap, libxl_uuid *uuid, -// uint32_t *poolid); -// FIXME: uuid -// FIXME: Setting poolid -func (Ctx *Context) CpupoolCreate(Name string, Scheduler Scheduler, Cpumap Bitmap) (err error, Poolid uint32) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - poolid := C.uint32_t(0) - name := C.CString(Name) - defer C.free(unsafe.Pointer(name)) - - // For now, just do what xl does, and make a new uuid every time we create the pool - var uuid C.libxl_uuid - C.libxl_uuid_generate(&uuid) - - cbm := bitmapGotoC(Cpumap) - defer C.libxl_bitmap_dispose(&cbm) - - ret := C.libxl_cpupool_create(Ctx.ctx, name, C.libxl_scheduler(Scheduler), - cbm, &uuid, &poolid) - // FIXME: Proper error - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_create failed: %d", ret) - return - } - - Poolid = uint32(poolid) - - return -} - -// int libxl_cpupool_destroy(libxl_ctx *ctx, uint32_t poolid); -func (Ctx *Context) CpupoolDestroy(Poolid uint32) (err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - ret := C.libxl_cpupool_destroy(Ctx.ctx, C.uint32_t(Poolid)) - // FIXME: Proper error - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_destroy failed: %d", ret) - return - } - - return -} - -// int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu); -func (Ctx *Context) CpupoolCpuadd(Poolid uint32, Cpu int) (err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - ret := C.libxl_cpupool_cpuadd(Ctx.ctx, C.uint32_t(Poolid), C.int(Cpu)) - // FIXME: Proper error - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_cpuadd failed: %d", ret) - return - } - - return -} - -// int libxl_cpupool_cpuadd_cpumap(libxl_ctx *ctx, uint32_t poolid, -// const libxl_bitmap *cpumap); -func (Ctx *Context) CpupoolCpuaddCpumap(Poolid uint32, Cpumap Bitmap) (err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - cbm := bitmapGotoC(Cpumap) - defer C.libxl_bitmap_dispose(&cbm) - - ret := C.libxl_cpupool_cpuadd_cpumap(Ctx.ctx, C.uint32_t(Poolid), &cbm) - // FIXME: Proper error - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_cpuadd_cpumap failed: %d", ret) - return - } - - return -} - -// int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu); -func (Ctx *Context) CpupoolCpuremove(Poolid uint32, Cpu int) (err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - ret := C.libxl_cpupool_cpuremove(Ctx.ctx, C.uint32_t(Poolid), C.int(Cpu)) - // FIXME: Proper error - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_cpuremove failed: %d", ret) - return - } - - return -} - -// int libxl_cpupool_cpuremove_cpumap(libxl_ctx *ctx, uint32_t poolid, -// const libxl_bitmap *cpumap); -func (Ctx *Context) CpupoolCpuremoveCpumap(Poolid uint32, Cpumap Bitmap) (err error) { - err = Ctx.CheckOpen() - if err != nil { - return - } - - cbm := bitmapGotoC(Cpumap) - defer C.libxl_bitmap_dispose(&cbm) - - ret := C.libxl_cpupool_cpuremove_cpumap(Ctx.ctx, C.uint32_t(Poolid), &cbm) - // FIXME: Proper error - if ret != 0 { - err = fmt.Errorf("libxl_cpupool_cpuremove_cpumap failed: %d", ret) - return - } - - return -} - -// int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid); -// int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus); -// int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus); -// int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid); - -// -// Utility functions -// -func (Ctx *Context) CpupoolFindByName(name string) (info CpupoolInfo, found bool) { - plist := Ctx.ListCpupool() - - for i := range plist { - if plist[i].PoolName == name { - found = true - info = plist[i] - return - } - } - return -} - -func (Ctx *Context) CpupoolMakeFree(Cpumap Bitmap) (err error) { - plist := Ctx.ListCpupool() - - for i := range plist { - var Intersection Bitmap - Intersection = Cpumap.And(plist[i].Cpumap) - if ! Intersection.IsEmpty() { - err = Ctx.CpupoolCpuremoveCpumap(plist[i].Poolid, Intersection) - if err != nil { - return - } - } - } - return -} - -func XlTest(Args []string) { - var Cpumap Bitmap - - Cpumap.Set(2) - Cpumap.SetRange(4, 8) - Cpumap.Set(10) - - fmt.Printf("Cpumap: %v\n", Cpumap) - - Cpumap.Set(9) - - fmt.Printf("Cpumap: %v\n", Cpumap) - - var Ctx Context - - err := Ctx.Open() - if err != nil { - fmt.Printf("Opening context: %v\n", err) - return - } - - pool, found := Ctx.CpupoolFindByName("schedbench") - - if found { - fmt.Printf("Found schedbench, destroying\n") - - err = Ctx.CpupoolDestroy(pool.Poolid) - if err != nil { - fmt.Printf("Couldn't destroy pool: %v\n", err) - return - } - - fmt.Printf("Returning cpus to pool 0 for fun\n") - err = Ctx.CpupoolCpuaddCpumap(0, pool.Cpumap) - if err != nil { - fmt.Printf("Couldn't add cpus to domain 0: %v\n", err) - return - } - } - - Cpumap = Bitmap{} - - Cpumap.SetRange(12, 15) - - fmt.Printf("Freeing cpus\n") - err = Ctx.CpupoolMakeFree(Cpumap) - if err != nil { - fmt.Printf("Couldn't free cpus: %v\n", err) - return - } - - - fmt.Printf("Creating new pool\n") - - err, Poolid := Ctx.CpupoolCreate("schedbench", SchedulerCredit, Cpumap) - if err != nil { - fmt.Printf("Error creating cpupool: %v\n", err) - } else { - fmt.Printf("Pool id: %d\n", Poolid) - } - - pool = Ctx.CpupoolInfo(0) - fmt.Printf("Cpupool 0 info: %v\n", pool) - - Ctx.Close() -} diff --git a/tools/golang/xenlight/xenlight.go b/tools/golang/xenlight/xenlight.go new file mode 100644 index 0000000..b0eb6f8 --- /dev/null +++ b/tools/golang/xenlight/xenlight.go @@ -0,0 +1,1000 @@ +/* + * Copyright (C) 2016 George W. Dunlap, Citrix Systems UK Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the + * License only. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +package xenlight + +/* +#cgo LDFLAGS: -lxenlight -lyajl +#include <stdlib.h> +#include <libxl.h> +*/ +import "C" + +/* + * Other flags that may be needed at some point: + * -lnl-route-3 -lnl-3 +#cgo LDFLAGS: -lxenlight -lyajl_s -lxengnttab -lxenstore -lxenguest -lxentoollog -lxenevtchn -lxenctrl -lblktapctl -lxenforeignmemory -lxencall -lz -luuid -lutil + * + * To get back to simple dynamic linking: +*/ + +import ( + "fmt" + "time" + "unsafe" +) + +/* + * Errors + */ +const ( + ErrorNonspecific = int(C.ERROR_NONSPECIFIC) + ErrorVersion = int(C.ERROR_VERSION) + ErrorFail = int(C.ERROR_FAIL) + ErrorNi = int(C.ERROR_NI) + ErrorNomem = int(C.ERROR_NOMEM) + ErrorInval = int(C.ERROR_INVAL) + ErrorBadfail = int(C.ERROR_BADFAIL) + ErrorGuestTimedout = int(C.ERROR_GUEST_TIMEDOUT) + ErrorTimedout = int(C.ERROR_TIMEDOUT) + ErrorNoparavirt = int(C.ERROR_NOPARAVIRT) + ErrorNotReady = int(C.ERROR_NOT_READY) + ErrorOseventRegFail = int(C.ERROR_OSEVENT_REG_FAIL) + ErrorBufferfull = int(C.ERROR_BUFFERFULL) + ErrorUnknownChild = int(C.ERROR_UNKNOWN_CHILD) + ErrorLockFail = int(C.ERROR_LOCK_FAIL) + ErrorJsonConfigEmpty = int(C.ERROR_JSON_CONFIG_EMPTY) + ErrorDeviceExists = int(C.ERROR_DEVICE_EXISTS) + ErrorCheckpointDevopsDoesNotMatch = int(C.ERROR_CHECKPOINT_DEVOPS_DOES_NOT_MATCH) + ErrorCheckpointDeviceNotSupported = int(C.ERROR_CHECKPOINT_DEVICE_NOT_SUPPORTED) + ErrorVnumaConfigInvalid = int(C.ERROR_VNUMA_CONFIG_INVALID) + ErrorDomainNotfound = int(C.ERROR_DOMAIN_NOTFOUND) + ErrorAborted = int(C.ERROR_ABORTED) + ErrorNotfound = int(C.ERROR_NOTFOUND) + ErrorDomainDestroyed = int(C.ERROR_DOMAIN_DESTROYED) + ErrorFeatureRemoved = int(C.ERROR_FEATURE_REMOVED) +) + +/* + * Types: Builtins + */ + +type Domid uint32 + +type MemKB uint64 + +type Hwcap struct { + Hwcap []C.uint32_t +} + +// typedef struct { +// uint32_t size; /* number of bytes in map */ +// uint8_t *map; +// } libxl_bitmap; + +// Implement the Go bitmap type such that the underlying data can +// easily be copied in and out. NB that we still have to do copies +// both directions, because cgo runtime restrictions forbid passing to +// a C function a pointer to a Go-allocated structure which contains a +// pointer. +type Bitmap struct { + bitmap []C.uint8_t +} + +type Context struct { + ctx *C.libxl_ctx +} + +type Uuid C.libxl_uuid + +/* + * Types: IDL + * + * FIXME: Generate these automatically from the IDL + */ +type Dominfo struct { + Uuid Uuid + Domid Domid + Running bool + Blocked bool + Paused bool + Shutdown bool + Dying bool + Never_stop bool + + Shutdown_reason int32 // FIXME shutdown_reason enumeration + Outstanding_memkb MemKB + Current_memkb MemKB + Shared_memkb MemKB + Paged_memkb MemKB + Max_memkb MemKB + Cpu_time time.Duration + Vcpu_max_id uint32 + Vcpu_online uint32 + Cpupool uint32 + Domain_type int32 //FIXME libxl_domain_type enumeration + +} + +type Physinfo struct { + Threads_per_core uint32 + Cores_per_socket uint32 + + Max_cpu_id uint32 + Nr_cpus uint32 + Cpu_khz uint32 + + Total_pages uint64 + Free_pages uint64 + Scrub_pages uint64 + Outstanding_pages uint64 + Sharing_freed_pages uint64 + Sharing_used_frames uint64 + + Nr_nodes uint32 + Hw_cap Hwcap + + Cap_hvm bool + Cap_hvm_directio bool +} + +type VersionInfo struct { + Xen_version_major int + Xen_version_minor int + Xen_version_extra string + Compiler string + Compile_by string + Compile_domain string + Compile_date string + Capabilities string + Changeset string + Virt_start uint64 + Pagesize int + Commandline string + Build_id string +} + +// # Consistent with values defined in domctl.h +// # Except unknown which we have made up +// libxl_scheduler = Enumeration("scheduler", [ +// (0, "unknown"), +// (4, "sedf"), +// (5, "credit"), +// (6, "credit2"), +// (7, "arinc653"), +// (8, "rtds"), +// ]) +type Scheduler int + +var ( + SchedulerUnknown Scheduler = C.LIBXL_SCHEDULER_UNKNOWN + SchedulerSedf Scheduler = C.LIBXL_SCHEDULER_SEDF + SchedulerCredit Scheduler = C.LIBXL_SCHEDULER_CREDIT + SchedulerCredit2 Scheduler = C.LIBXL_SCHEDULER_CREDIT2 + SchedulerArinc653 Scheduler = C.LIBXL_SCHEDULER_ARINC653 + SchedulerRTDS Scheduler = C.LIBXL_SCHEDULER_RTDS +) + +// libxl_cpupoolinfo = Struct("cpupoolinfo", [ +// ("poolid", uint32), +// ("pool_name", string), +// ("sched", libxl_scheduler), +// ("n_dom", uint32), +// ("cpumap", libxl_bitmap) +// ], dir=DIR_OUT) + +type CpupoolInfo struct { + Poolid uint32 + PoolName string + Scheduler Scheduler + DomainCount int + Cpumap Bitmap +} + +/* + * Context + */ +var Ctx Context + +func (Ctx *Context) IsOpen() bool { + return Ctx.ctx != nil +} + +func (Ctx *Context) Open() (err error) { + if Ctx.ctx != nil { + return + } + + ret := C.libxl_ctx_alloc(unsafe.Pointer(&Ctx.ctx), C.LIBXL_VERSION, 0, nil) + + if ret != 0 { + //FIXME: proper error + err = createError("Allocating libxl context: ", ret) + } + return +} + +func (Ctx *Context) Close() (err error) { + ret := C.libxl_ctx_free(unsafe.Pointer(Ctx.ctx)) + Ctx.ctx = nil + + if ret != 0 { + //FIXME: proper error + err = createError("Freeing libxl context: ", ret) + } + return +} + +func (Ctx *Context) CheckOpen() (err error) { + if Ctx.ctx == nil { + err = fmt.Errorf("Context not opened") + } + return +} + +func (Ctx *Context) DomainInfo(Id Domid) (di *Dominfo, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + var cdi C.libxl_dominfo + + ret := C.libxl_domain_info(Ctx.ctx, unsafe.Pointer(&cdi), C.uint32_t(Id)) + + // FIXME: proper error + if ret != 0 { + err = createError("libxl_domain_info failed: ", ret) + return + } + + // We could consider having this boilerplate generated by the + // idl, in a function like this: + // + // di = translateCdomaininfoToGoDomaininfo(cdi) + di = &Dominfo{} + di.Uuid = Uuid(cdi.uuid) + di.Domid = Domid(cdi.domid) + di.Running = bool(cdi.running) + di.Blocked = bool(cdi.blocked) + di.Paused = bool(cdi.paused) + di.Shutdown = bool(cdi.shutdown) + di.Dying = bool(cdi.dying) + di.Never_stop = bool(cdi.never_stop) + di.Shutdown_reason = int32(cdi.shutdown_reason) + di.Outstanding_memkb = MemKB(cdi.outstanding_memkb) + di.Current_memkb = MemKB(cdi.current_memkb) + di.Shared_memkb = MemKB(cdi.shared_memkb) + di.Paged_memkb = MemKB(cdi.paged_memkb) + di.Max_memkb = MemKB(cdi.max_memkb) + di.Cpu_time = time.Duration(cdi.cpu_time) + di.Vcpu_max_id = uint32(cdi.vcpu_max_id) + di.Vcpu_online = uint32(cdi.vcpu_online) + di.Cpupool = uint32(cdi.cpupool) + di.Domain_type = int32(cdi.domain_type) + + return +} + +func (Ctx *Context) DomainUnpause(Id Domid) (err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + ret := C.libxl_domain_unpause(Ctx.ctx, C.uint32_t(Id)) + + if ret != 0 { + //FIXME: proper error + err = createError("libxl_domain_unpause failed: ", ret) + } + return +} + +/* + * Bitmap operations + */ + +// Return a Go bitmap which is a copy of the referred C bitmap. +func bitmapCToGo(cbm C.libxl_bitmap) (gbm Bitmap) { + // Alloc a Go slice for the bytes + size := int(cbm.size) + gbm.bitmap = make([]C.uint8_t, size) + + // Make a slice pointing to the C array + mapslice := (*[1 << 30]C.uint8_t)(unsafe.Pointer(cbm._map))[:size:size] + + // And copy the C array into the Go array + copy(gbm.bitmap, mapslice) + + return +} + +// Must be C.libxl_bitmap_dispose'd of afterwards +func bitmapGotoC(gbm Bitmap) (cbm C.libxl_bitmap) { + C.libxl_bitmap_init(&cbm) + + size := len(gbm.bitmap) + cbm._map = (*C.uint8_t)(C.malloc(C.size_t(size))) + cbm.size = C.uint32_t(size) + if cbm._map == nil { + panic("C.calloc failed!") + } + + // Make a slice pointing to the C array + mapslice := (*[1 << 30]C.uint8_t)(unsafe.Pointer(cbm._map))[:size:size] + + // And copy the Go array into the C array + copy(mapslice, gbm.bitmap) + + return +} + +func (bm *Bitmap) Test(bit int) bool { + ubit := uint(bit) + if bit > bm.Max() || bm.bitmap == nil { + return false + } + + return (bm.bitmap[bit/8] & (1 << (ubit & 7))) != 0 +} + +func (bm *Bitmap) Set(bit int) { + ibit := bit / 8 + if ibit+1 > len(bm.bitmap) { + bm.bitmap = append(bm.bitmap, make([]C.uint8_t, ibit+1-len(bm.bitmap))...) + } + + bm.bitmap[ibit] |= 1 << (uint(bit) & 7) +} + +func (bm *Bitmap) SetRange(start int, end int) { + for i := start; i <= end; i++ { + bm.Set(i) + } +} + +func (bm *Bitmap) Clear(bit int) { + ubit := uint(bit) + if bit > bm.Max() || bm.bitmap == nil { + return + } + + bm.bitmap[bit/8] &= ^(1 << (ubit & 7)) +} + +func (bm *Bitmap) ClearRange(start int, end int) { + for i := start; i <= end; i++ { + bm.Clear(i) + } +} + +func (bm *Bitmap) Max() int { + return len(bm.bitmap)*8 - 1 +} + +func (bm *Bitmap) IsEmpty() bool { + for i := 0; i < len(bm.bitmap); i++ { + if bm.bitmap[i] != 0 { + return false + } + } + return true +} + +func (a Bitmap) And(b Bitmap) (c Bitmap) { + var max, min int + if len(a.bitmap) > len(b.bitmap) { + max = len(a.bitmap) + min = len(b.bitmap) + } else { + max = len(b.bitmap) + min = len(a.bitmap) + } + c.bitmap = make([]C.uint8_t, max) + + for i := 0; i < min; i++ { + c.bitmap[i] = a.bitmap[i] & b.bitmap[i] + } + return +} + +func (bm Bitmap) String() (s string) { + lastOnline := false + crange := false + printed := false + var i int + /// --x-xxxxx-x -> 2,4-8,10 + /// --x-xxxxxxx -> 2,4-10 + for i = 0; i <= bm.Max(); i++ { + if bm.Test(i) { + if !lastOnline { + // Switching offline -> online, print this cpu + if printed { + s += "," + } + s += fmt.Sprintf("%d", i) + printed = true + } else if !crange { + // last was online, but we're not in a range; print - + crange = true + s += "-" + } else { + // last was online, we're in a range, nothing else to do + } + lastOnline = true + } else { + if lastOnline { + // Switching online->offline; do we need to end a range? + if crange { + s += fmt.Sprintf("%d", i-1) + } + } + lastOnline = false + crange = false + } + } + if lastOnline { + // Switching online->offline; do we need to end a range? + if crange { + s += fmt.Sprintf("%d", i-1) + } + } + + return +} + +// const char *libxl_scheduler_to_string(libxl_scheduler p); +func (s Scheduler) String() string { + cs := C.libxl_scheduler_to_string(C.libxl_scheduler(s)) + // No need to free const return value + + return C.GoString(cs) +} + +// int libxl_scheduler_from_string(const char *s, libxl_scheduler *e); +func (s *Scheduler) FromString(gstr string) (err error) { + cstr := C.CString(gstr) + defer C.free(unsafe.Pointer(cstr)) + + var cs C.libxl_scheduler + ret := C.libxl_scheduler_from_string(cstr, &cs) + if ret != 0 { + //FIXME: proper error + err = createError("libxl_scheduler_from_string: ", ret) + return + } + + *s = Scheduler(cs) + return +} + +func translateCpupoolInfoCToGo(cci C.libxl_cpupoolinfo) (gci CpupoolInfo) { + gci.Poolid = uint32(cci.poolid) + gci.PoolName = C.GoString(cci.pool_name) + gci.Scheduler = Scheduler(cci.sched) + gci.DomainCount = int(cci.n_dom) + gci.Cpumap = bitmapCToGo(cci.cpumap) + + return +} + +func SchedulerFromString(name string) (s Scheduler, err error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + var cs C.libxl_scheduler + + ret := C.libxl_scheduler_from_string(cname, &cs) + if ret != 0 { + //FIXME: proper error + err = createError("libxl_scheduler_from_string failed: ", ret) + return + } + + s = Scheduler(cs) + + return +} + +// libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx*, int *nb_pool_out); +// void libxl_cpupoolinfo_list_free(libxl_cpupoolinfo *list, int nb_pool); +func (Ctx *Context) ListCpupool() (list []CpupoolInfo) { + err := Ctx.CheckOpen() + if err != nil { + return + } + + var nbPool C.int + + c_cpupool_list := C.libxl_list_cpupool(Ctx.ctx, &nbPool) + + defer C.libxl_cpupoolinfo_list_free(c_cpupool_list, nbPool) + + if int(nbPool) == 0 { + return + } + + // Magic + cpupoolListSlice := (*[1 << 30]C.libxl_cpupoolinfo)(unsafe.Pointer(c_cpupool_list))[:nbPool:nbPool] + + for i := range cpupoolListSlice { + info := translateCpupoolInfoCToGo(cpupoolListSlice[i]) + + list = append(list, info) + } + + return +} + +// int libxl_cpupool_info(libxl_ctx *ctx, libxl_cpupoolinfo *info, uint32_t poolid); +func (Ctx *Context) CpupoolInfo(Poolid uint32) (pool CpupoolInfo) { + err := Ctx.CheckOpen() + if err != nil { + return + } + + var c_cpupool C.libxl_cpupoolinfo + + ret := C.libxl_cpupool_info(Ctx.ctx, &c_cpupool, C.uint32_t(Poolid)) + //FIXME: proper error + if ret != 0 { + err = createError("libxl_cpupool_info failed: ", ret) + return + } + defer C.libxl_cpupoolinfo_dispose(&c_cpupool) + + pool = translateCpupoolInfoCToGo(c_cpupool) + + return +} + +// int libxl_cpupool_create(libxl_ctx *ctx, const char *name, +// libxl_scheduler sched, +// libxl_bitmap cpumap, libxl_uuid *uuid, +// uint32_t *poolid); +// FIXME: uuid +// FIXME: Setting poolid +func (Ctx *Context) CpupoolCreate(Name string, Scheduler Scheduler, Cpumap Bitmap) (err error, Poolid uint32) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + poolid := C.uint32_t(0) + name := C.CString(Name) + defer C.free(unsafe.Pointer(name)) + + // For now, just do what xl does, and make a new uuid every time we create the pool + var uuid C.libxl_uuid + C.libxl_uuid_generate(&uuid) + + cbm := bitmapGotoC(Cpumap) + defer C.libxl_bitmap_dispose(&cbm) + + ret := C.libxl_cpupool_create(Ctx.ctx, name, C.libxl_scheduler(Scheduler), + cbm, &uuid, &poolid) + // FIXME: Proper error + if ret != 0 { + err = createError("libxl_cpupool_create failed: ", ret) + return + } + + Poolid = uint32(poolid) + + return +} + +// int libxl_cpupool_destroy(libxl_ctx *ctx, uint32_t poolid); +func (Ctx *Context) CpupoolDestroy(Poolid uint32) (err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + ret := C.libxl_cpupool_destroy(Ctx.ctx, C.uint32_t(Poolid)) + // FIXME: Proper error + if ret != 0 { + err = createError("libxl_cpupool_destroy failed: ", ret) + return + } + + return +} + +// int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu); +func (Ctx *Context) CpupoolCpuadd(Poolid uint32, Cpu int) (err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + ret := C.libxl_cpupool_cpuadd(Ctx.ctx, C.uint32_t(Poolid), C.int(Cpu)) + // FIXME: Proper error + if ret != 0 { + err = createError("libxl_cpupool_cpuadd failed: ", ret) + return + } + + return +} + +// int libxl_cpupool_cpuadd_cpumap(libxl_ctx *ctx, uint32_t poolid, +// const libxl_bitmap *cpumap); +func (Ctx *Context) CpupoolCpuaddCpumap(Poolid uint32, Cpumap Bitmap) (err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + cbm := bitmapGotoC(Cpumap) + defer C.libxl_bitmap_dispose(&cbm) + + ret := C.libxl_cpupool_cpuadd_cpumap(Ctx.ctx, C.uint32_t(Poolid), &cbm) + // FIXME: Proper error + if ret != 0 { + err = createError("libxl_cpupool_cpuadd_cpumap failed: ", ret) + return + } + + return +} + +// int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu); +func (Ctx *Context) CpupoolCpuremove(Poolid uint32, Cpu int) (err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + ret := C.libxl_cpupool_cpuremove(Ctx.ctx, C.uint32_t(Poolid), C.int(Cpu)) + // FIXME: Proper error + if ret != 0 { + err = createError("libxl_cpupool_cpuremove failed: ", ret) + return + } + + return +} + +// int libxl_cpupool_cpuremove_cpumap(libxl_ctx *ctx, uint32_t poolid, +// const libxl_bitmap *cpumap); +func (Ctx *Context) CpupoolCpuremoveCpumap(Poolid uint32, Cpumap Bitmap) (err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + cbm := bitmapGotoC(Cpumap) + defer C.libxl_bitmap_dispose(&cbm) + + ret := C.libxl_cpupool_cpuremove_cpumap(Ctx.ctx, C.uint32_t(Poolid), &cbm) + // FIXME: Proper error + if ret != 0 { + err = createError("libxl_cpupool_cpuremove_cpumap failed: ", ret) + return + } + + return +} + +// int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid); +// int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus); +// int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus); +// int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid); + +// +// Utility functions +// +func (Ctx *Context) CpupoolFindByName(name string) (info CpupoolInfo, found bool) { + plist := Ctx.ListCpupool() + + for i := range plist { + if plist[i].PoolName == name { + found = true + info = plist[i] + return + } + } + return +} + +func (Ctx *Context) CpupoolMakeFree(Cpumap Bitmap) (err error) { + plist := Ctx.ListCpupool() + + for i := range plist { + var Intersection Bitmap + Intersection = Cpumap.And(plist[i].Cpumap) + if !Intersection.IsEmpty() { + err = Ctx.CpupoolCpuremoveCpumap(plist[i].Poolid, Intersection) + if err != nil { + return + } + } + } + return +} + +func XlTest(Args []string) { + var Cpumap Bitmap + + Cpumap.Set(2) + Cpumap.SetRange(4, 8) + Cpumap.Set(10) + + fmt.Printf("Cpumap: %v\n", Cpumap) + + Cpumap.Set(9) + + fmt.Printf("Cpumap: %v\n", Cpumap) + + var Ctx Context + + err := Ctx.Open() + if err != nil { + fmt.Printf("Opening context: %v\n", err) + return + } + + pool, found := Ctx.CpupoolFindByName("schedbench") + + if found { + fmt.Printf("Found schedbench, destroying\n") + + err = Ctx.CpupoolDestroy(pool.Poolid) + if err != nil { + fmt.Printf("Couldn't destroy pool: %v\n", err) + return + } + + fmt.Printf("Returning cpus to pool 0 for fun\n") + err = Ctx.CpupoolCpuaddCpumap(0, pool.Cpumap) + if err != nil { + fmt.Printf("Couldn't add cpus to domain 0: %v\n", err) + return + } + } + + Cpumap = Bitmap{} + + Cpumap.SetRange(12, 15) + + fmt.Printf("Freeing cpus\n") + err = Ctx.CpupoolMakeFree(Cpumap) + if err != nil { + fmt.Printf("Couldn't free cpus: %v\n", err) + return + } + + fmt.Printf("Creating new pool\n") + + err, Poolid := Ctx.CpupoolCreate("schedbench", SchedulerCredit, Cpumap) + if err != nil { + fmt.Printf("Error creating cpupool: %v\n", err) + } else { + fmt.Printf("Pool id: %d\n", Poolid) + } + + pool = Ctx.CpupoolInfo(0) + fmt.Printf("Cpupool 0 info: %v\n", pool) + + Ctx.Close() +} + +//int libxl_get_max_cpus(libxl_ctx *ctx); +func (Ctx *Context) GetMaxCpus() (maxCpus int, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + ret := C.libxl_get_max_cpus(Ctx.ctx) + //FIXME: proper error + if ret < 0 { + err = createError("libxl_get_max_cpus failed: ", ret) + return + } + maxCpus = int(ret) + return +} + +//int libxl_get_online_cpus(libxl_ctx *ctx); +func (Ctx *Context) GetOnlineCpus() (onCpus int, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + ret := C.libxl_get_online_cpus(Ctx.ctx) + //FIXME: proper error + if ret < 0 { + err = createError("libxl_get_online_cpus failed: ", ret) + return + } + onCpus = int(ret) + return +} + +//int libxl_get_max_nodes(libxl_ctx *ctx); +func (Ctx *Context) GetMaxNodes() (maxNodes int, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + ret := C.libxl_get_max_nodes(Ctx.ctx) + //FIXME: proper error + if ret < 0 { + err = createError("libxl_get_max_nodes failed: ", ret) + return + } + maxNodes = int(ret) + return +} + +//int libxl_get_free_memory(libxl_ctx *ctx, uint64_t *memkb); +func (Ctx *Context) GetFreeMemory() (memkb uint64, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + var cmem C.uint64_t + ret := C.libxl_get_free_memory(Ctx.ctx, &cmem) + + if ret < 0 { + err = createError("libxl_get_free_memory failed: ", ret) + return + } + + memkb = uint64(ret) + return + +} + +//int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo) +func (Ctx *Context) GetPhysinfo() (physinfo *Physinfo, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + var cphys C.libxl_physinfo + + ret := C.libxl_get_physinfo(Ctx.ctx, &cphys) + + //FIXME: proper error + if ret < 0 { + err = createError("libxl_get_physinfo failed: ", ret) + return + } + physinfo = &Physinfo{} + physinfo.Threads_per_core = uint32(cphys.threads_per_core) + physinfo.Cores_per_socket = uint32(cphys.cores_per_socket) + physinfo.Max_cpu_id = uint32(cphys.max_cpu_id) + physinfo.Nr_cpus = uint32(cphys.nr_cpus) + physinfo.Cpu_khz = uint32(cphys.cpu_khz) + physinfo.Total_pages = uint64(cphys.total_pages) + physinfo.Free_pages = uint64(cphys.free_pages) + physinfo.Scrub_pages = uint64(cphys.scrub_pages) + physinfo.Outstanding_pages = uint64(cphys.scrub_pages) + physinfo.Sharing_freed_pages = uint64(cphys.sharing_freed_pages) + physinfo.Sharing_used_frames = uint64(cphys.sharing_used_frames) + physinfo.Nr_nodes = uint32(cphys.nr_nodes) + physinfo.Hw_cap = hwcapCToGo(cphys.hw_cap) + physinfo.Cap_hvm = bool(cphys.cap_hvm) + physinfo.Cap_hvm_directio = bool(cphys.cap_hvm_directio) + + return +} + +//const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx); +func (Ctx *Context) GetVersionInfo() (info *VersionInfo, err error) { + err = Ctx.CheckOpen() + if err != nil { + return + } + + var cinfo *C.libxl_version_info + + cinfo = C.libxl_get_version_info(Ctx.ctx) + + info = &VersionInfo{} + info.Xen_version_major = int(cinfo.xen_version_major) + info.Xen_version_minor = int(cinfo.xen_version_minor) + info.Xen_version_extra = C.GoString(cinfo.xen_version_extra) + info.Compiler = C.GoString(cinfo.compiler) + info.Compile_by = C.GoString(cinfo.compile_by) + info.Compile_domain = C.GoString(cinfo.compile_domain) + info.Compile_date = C.GoString(cinfo.compile_date) + info.Capabilities = C.GoString(cinfo.capabilities) + info.Changeset = C.GoString(cinfo.changeset) + info.Virt_start = uint64(cinfo.virt_start) + info.Pagesize = int(cinfo.pagesize) + + return +} +func hwcapCToGo(chwcap C.libxl_hwcap) (ghwcap Hwcap) { + // Alloc a Go slice for the bytes + size := 8 + ghwcap.Hwcap = make([]C.uint32_t, size) + + // Make a slice pointing to the C array + mapslice := (*[1 << 30]C.uint32_t)(unsafe.Pointer(&chwcap[0]))[:size:size] + + // And copy the C array into the Go array + copy(ghwcap.Hwcap, mapslice) + + return +} + +func createError(method string, cerrNum C.int) (err error) { + method += " %s" + errNum := int(cerrNum) + switch errNum { + case ErrorNonspecific: + err = fmt.Errorf(method, "ERROR_NONSPECIFIC") + case ErrorVersion: + err = fmt.Errorf(method, "ERROR_VERSION") + case ErrorFail: + err = fmt.Errorf(method, "ERROR_FAIL") + case ErrorNi: + err = fmt.Errorf(method, "ERROR_NI") + case ErrorNomem: + err = fmt.Errorf(method, "ERROR_NOMEM") + case ErrorInval: + err = fmt.Errorf(method, "ERROR_INVAL") + case ErrorBadfail: + err = fmt.Errorf(method, "ERROR_BADFAIL") + case ErrorGuestTimedout: + err = fmt.Errorf(method, "ERROR_GUEST_TIMEDOUT") + case ErrorNoparavirt: + err = fmt.Errorf(method, "ERROR_NOPARAVIRT") + case ErrorNotReady: + err = fmt.Errorf(method, "ERROR_NOT_READY") + case ErrorOseventRegFail: + err = fmt.Errorf(method, "ERROR_OSEVENT_REG_FAIL") + case ErrorBufferfull: + err = fmt.Errorf(method, "ERROR_BUFFERFULL") + case ErrorUnknownChild: + err = fmt.Errorf(method, "ERROR_UNKNOWN_CHILD") + case ErrorLockFail: + err = fmt.Errorf(method, "ERROR_LOCK_FAIL") + case ErrorJsonConfigEmpty: + err = fmt.Errorf(method, "ERROR_JSON_CONFIG_EMPTY") + case ErrorDeviceExists: + err = fmt.Errorf(method, "ERROR_DEVICE_EXISTS") + case ErrorCheckpointDevopsDoesNotMatch: + err = fmt.Errorf(method, "ERROR_CHECKPOINT_DEVOPS_DOES_NOT_MATCH") + case ErrorCheckpointDeviceNotSupported: + err = fmt.Errorf(method, "ERROR_CHECKPOINT_DEVICE_NOT_SUPPORTED") + case ErrorVnumaConfigInvalid: + err = fmt.Errorf(method, "ERROR_VNUMA_CONFIG_INVALID") + case ErrorDomainNotfound: + err = fmt.Errorf(method, "ERROR_DOMAIN_NOTFOUND") + case ErrorAborted: + err = fmt.Errorf(method, "ERROR_ABORTED") + case ErrorNotfound: + err = fmt.Errorf(method, "ERROR_NOTFOUND") + case ErrorDomainDestroyed: + err = fmt.Errorf(method, "ERROR_DOMAIN_DESTROYED") + case ErrorFeatureRemoved: + err = fmt.Errorf(method, "ERROR_FEATURE_REMOVED") + default: + err = fmt.Errorf(method, "error not found") + } + return + +} -- 2.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |