xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ronald Rojas <ronladred@gmail.com>
To: xen-devel <xen-devel@lists.xen.org>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Wei Liu <wei.liu2@citrix.com>,
	George Dunlap <george.dunlap@citrix.com>,
	George Dunlap <dunlapg@umich.edu>
Cc: Ronald Rojas <ronladred@gmail.com>
Subject: [PATCH RFC 59/59] tools/xenlight: Create interface for xenlight info
Date: Wed, 28 Dec 2016 20:14:52 -0500	[thread overview]
Message-ID: <1482974092-15891-59-git-send-email-ronladred@gmail.com> (raw)
In-Reply-To: <1482974092-15891-1-git-send-email-ronladred@gmail.com>

Create interface to interact with libxl_verions_info
and libxl_physinfo. Also introduce proper error
handling.

Signed-off-by: Ronald Rojas <ronladred@gmail.com>
---
 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@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2016-12-29  1:14 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-29  1:13 [PATCH RFC 01/59] Initial controller framework Ronald Rojas
2016-12-29  1:13 ` [PATCH RFC 02/59] controller: Revamp communication structure Ronald Rojas
2016-12-29  1:13 ` [PATCH RFC 03/59] controller: Initial attempt to generalize process / vm creation Ronald Rojas
2016-12-29  1:13 ` [PATCH RFC 04/59] Controller: Move process worker into its own file Ronald Rojas
2016-12-29  1:13 ` [PATCH RFC 05/59] controller: Add WorkerParams argument to Init in Worker interface Ronald Rojas
2016-12-29  1:13 ` [PATCH RFC 06/59] Reorganize to enable "Dist" directory Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 07/59] controller: Introduce basic Xen functionality Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 08/59] controller: Exit after second SIGINT Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 09/59] controller: Refactor creation and stopping of workers into WorkerList methods Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 10/59] controller: First cut at BenchmarkParams Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 11/59] Refactor to move towards benchmark "plans" and data analysis Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 12/59] Basic 'report' functionality Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 13/59] Add GPL headers / COPYING file (v2 only) Ronald Rojas
2016-12-29 10:51   ` Wei Liu
2016-12-29  1:14 ` [PATCH RFC 14/59] benchmark: Store data in terms of worker sets and worker ids Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 15/59] controller: Move "running" code to a separate file Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 16/59] controller: Rename an element in BenchmarkRun to be more accurate Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 17/59] controller: Collect and display statistics on WorkerSets Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 18/59] controller: Add cpupool global config Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 19/59] Add basic libxl framework, get domain cpu_time Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 20/59] xenworker: Use libxl_domain_unpause rather than forking xl Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 21/59] Report utilization statistics Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 22/59] Use tsc for time rather than rumpkernel clock_gettime() Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 23/59] run: Don't collect results reported after command to stop guests is issued Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 24/59] report: Lots of changes Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 25/59] main: Change default workload to something a bit more extreme Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 26/59] Use kops rather than mops Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 27/59] report: Allow report verbosity to be specified Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 28/59] controller: Handle worker early death Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 29/59] report: Add basic html report Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 30/59] htmlreport: Include utilization scatterplots Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 31/59] Make a binary that can run reports on a system without libxl Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 32/59] controller: Allow specification of an input file Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 33/59] controller: Add verbosity argument and update README with new instructions Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 34/59] controller: Make a useful config file Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 35/59] libxl: Add ListCpupool Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 36/59] controller: Make 'dummy' at the level of 'run' rather than xenworker Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 37/59] libxl.go: Provide a single global context by default Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 38/59] controller: Allow multiple schedulers in the same benchmark file Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 39/59] libxl.go: Put common link flags in libxl.go Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 40/59] controller: Add / update GPL text Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 41/59] libxl.go: Link statically rather than dynamically Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 42/59] plan: Allow "templating" from other runs Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 43/59] libxl: Add bitmap support Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 44/59] libxl: Implement CpupoolCreate Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 45/59] libxl: Implement Destroy, Add/Remove operations Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 46/59] libxl: Reorganize bitmapGotoC Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 47/59] libxl: Reorganize code Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 48/59] libxl: Add Ctx.CheckOpen Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 49/59] libxl: Implement libxl_cpupool_info and Scheduler.FromString() Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 50/59] libxl: Fix Bitmap.Max(), make Test() / Clear() more robust Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 51/59] controller: Make and/or modify cpupools when possible Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 52/59] libxl: Implement Bitmap.String() Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 53/59] controller: Add WorkerConfig.SoftAffinity Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 54/59] controller/run: Add RunConfig.NumaDisable Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 55/59] plan: Make the matrix generation more programmatic Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 56/59] controller/plan: Add NumaDisable to SimpleMatrix Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 57/59] tools/blktap2: remove unused inclusion of sys/sysctl.l Ronald Rojas
2016-12-29  1:14 ` [PATCH RFC 58/59] remove irrelevant files from old repository Ronald Rojas
2016-12-29  1:14 ` Ronald Rojas [this message]
2016-12-29 10:34   ` [PATCH RFC 59/59] tools/xenlight: Create interface for xenlight info George Dunlap
2016-12-29 10:52     ` Wei Liu
2016-12-29 13:49       ` Ronald Rojas
2016-12-29 13:45   ` George Dunlap
2016-12-29 20:20     ` George Dunlap
2017-01-03 17:45     ` Ronald Rojas
2017-01-04 16:44       ` George Dunlap

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1482974092-15891-59-git-send-email-ronladred@gmail.com \
    --to=ronladred@gmail.com \
    --cc=dunlapg@umich.edu \
    --cc=george.dunlap@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).