[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.