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