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 58/59] remove irrelevant files from old repository
Date: Wed, 28 Dec 2016 20:14:51 -0500	[thread overview]
Message-ID: <1482974092-15891-58-git-send-email-ronladred@gmail.com> (raw)
In-Reply-To: <1482974092-15891-1-git-send-email-ronladred@gmail.com>

Signed-off-by: Ronald Rojas <ronladred@gmail.com>
---
 Makefile                       |  31 --
 benchmark.go                   | 467 --------------------------
 htmlreport.go                  | 238 --------------
 libxl.go                       | 720 -----------------------------------------
 main.go                        | 146 ---------
 plan.go                        | 157 ---------
 processworker.go               |  98 ------
 run.go                         | 456 --------------------------
 stubs.go                       |  34 --
 tools/golang/xenlight/libxl.go | 720 +++++++++++++++++++++++++++++++++++++++++
 xenworker.go                   | 278 ----------------
 11 files changed, 720 insertions(+), 2625 deletions(-)
 delete mode 100644 Makefile
 delete mode 100644 benchmark.go
 delete mode 100644 htmlreport.go
 delete mode 100644 libxl.go
 delete mode 100644 main.go
 delete mode 100644 plan.go
 delete mode 100644 processworker.go
 delete mode 100644 run.go
 delete mode 100644 stubs.go
 create mode 100644 tools/golang/xenlight/libxl.go
 delete mode 100644 xenworker.go

diff --git a/Makefile b/Makefile
deleted file mode 100644
index 699cc53..0000000
--- a/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-BIN = schedbench
-BINALL = $(BIN)
-
-.PHONY: all
-all: $(BIN)
-
-
-
-CGO_CFLAGS = -I/build/hg/xen.git/dist/install/usr/local/include
-
-# FIXME
-XENLIB_PATH ?= /build/hg/xen.git/dist/install/usr/local/lib/
-CGO_LDFLAGS = -L$(XENLIB_PATH) -Wl,-rpath-link=$(XENLIB_PATH) 
-
-schedbench: main.go processworker.go xenworker.go benchmark.go run.go libxl.go htmlreport.go plan.go
-	CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CFLAGS="$(CGO_CFLAGS)" go build -ldflags '-linkmode external -extldflags "-static"' -o $@ $^
-
-# If we use a statically linked binary we don't need this; the same
-# binary can be used on any system.  Keep this version (without any
-# run support) support) around for now in case we want to go back to
-# it.
-schedbench-report: main.go benchmark.go stubs.go htmlreport.go plan.go
-	go build -o $@ $^
-
-.PHONY: clean
-clean:
-	rm -f $(BINALL)
-
-.PHONY: dist
-dist:
-	cp $(BIN) $(DISTDIR)
diff --git a/benchmark.go b/benchmark.go
deleted file mode 100644
index abe2dfb..0000000
--- a/benchmark.go
+++ /dev/null
@@ -1,467 +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
-
-import (
-	"fmt"
-	"os"
-	"io/ioutil"
-	"encoding/json"
-	"math"
-	"time"
-)
-
-type WorkerId struct {
-	Set int
-	Id int
-}
-
-func (wid WorkerId) String() (string) {
-	return fmt.Sprintf("%d:%d", wid.Set, wid.Id)
-}
-
-type WorkerReport struct {
-	Id WorkerId
-	Now int
-	Kops int
-	MaxDelta int
-	Cputime time.Duration
-}
-
-type WorkerParams struct {
-	Args []string
-}
-
-func (l *WorkerParams) SetkHZ(kHZ uint64) {
-	if l.Args[0] == "kHZ" {
-		l.Args[1] = fmt.Sprintf("%d", kHZ)
-	} else {
-		l.Args = append([]string{"kHZ", fmt.Sprintf("%d", kHZ)}, l.Args...)
-	}
-}
-
-type WorkerConfig struct {
-	Pool string
-	SoftAffinity string
-}
-
-// Propagate unset values from a higher level
-func (l *WorkerConfig) PropagateFrom(g WorkerConfig) {
-	if l.Pool == "" {
-		l.Pool = g.Pool
-	}
-}
-
-type WorkerSet struct {
-	Params WorkerParams
-	Config WorkerConfig
-	Count int
-}
-
-const (
-	USEC = 1000
-	MSEC = USEC * 1000
-	SEC = MSEC * 1000
-)
-
-func Throughput(lt int, lm int, t int, m int) (tput float64) {
-	time := float64(t - lt) / SEC
-	kops := m - lm
-	
-	tput = float64(kops) / time
-	return
-}
-
-func Utilization(lt int, lct time.Duration, t int, ct time.Duration) (util float64) {
-	util = float64(ct - lct) / float64(t - lt)
-	return
-}
-
-type MinMax struct {
-	Min float64
-	Max float64
-}
-
-func (mm *MinMax) Update(x float64) {
-	if x > mm.Max {
-		mm.Max = x
-	}
-	if x < mm.Min || mm.Min == 0 {
-		mm.Min = x
-	}
-}
-
-type WorkerSummary struct {
-	Raw []WorkerReport
-	MinMaxTput MinMax
-	MinMaxUtil MinMax
-	TotalTput int
-	TotalTime time.Duration
-	TotalCputime time.Duration
-	AvgTput float64
-	AvgUtil float64
-}
-
-type WorkerSetSummary struct {
-	Workers    []WorkerSummary
-	TotalTput     float64
-	AvgAvgTput    float64
-	MinMaxTput    MinMax
-	MinMaxAvgTput MinMax
-	AvgStdDevTput float64
-
-	TotalUtil     float64
-	MinMaxUtil    MinMax
-	MinMaxAvgUtil MinMax
-	AvgAvgUtil    float64
-	AvgStdDevUtil float64
-}
-
-type BenchmarkRunData struct {
-	Raw []WorkerReport       `json:",omitempty"`
-	Summary []WorkerSetSummary  `json:",omitempty"`
-}
-
-type RunConfig struct {
-	Scheduler string
-	Pool string
-	Cpus []int
-	NumaDisable *bool `json:",omitempty"`
-}
-
-// Propagate unset values from a higher level
-func (l *RunConfig) PropagateFrom(g RunConfig) {
-	if l.Pool == "" {
-		l.Pool = g.Pool
-	}
-	if l.Scheduler == "" {
-		l.Scheduler = g.Scheduler
-	}
-	if l.Cpus == nil {
-		l.Cpus = g.Cpus
-	}
-	if l.NumaDisable == nil {
-		l.NumaDisable = g.NumaDisable
-	}
-}
-
-type BenchmarkRun struct {
-	Label string
-	WorkerSets []WorkerSet
-	WorkerConfig
-	RunConfig
-	RuntimeSeconds int
-	Completed bool
-	Results BenchmarkRunData 
-}
-
-type BenchmarkPlan struct {
-	Input *PlanInput     `json:",omitempty"`
-	filename string      `json:",omitempty"`
-	WorkerType int       `json:",omitempty"`
-	// Global options for workers that will be over-ridden by Run
-	// and WorkerSet config options
-	WorkerConfig         `json:",omitempty"`
-	RunConfig RunConfig   `json:",omitempty"`
-	Runs []BenchmarkRun  `json:",omitempty"`
-}
-
-func (run *BenchmarkRun) checkSummary() (done bool, err error) {
-	if run.Results.Summary != nil {
-		done = true
-		return 
-	}
-	
-	return
-}
-
-func (run *BenchmarkRun) Process() (err error) {
-	done, err := run.checkSummary()
-	if done || err != nil {
-		return
-	}
-
-	run.Results.Summary = make([]WorkerSetSummary, len(run.WorkerSets))
-
-	type Data struct{
-		startTime int
-		startCputime time.Duration
-		lastTime int
-		lastKops int
-		lastCputime time.Duration
-	}
-	
-	data := make(map[WorkerId]*Data)
-
-	// FIXME: Filter out results which started before all have started
-	for i := range run.Results.Raw {
-		e := run.Results.Raw[i]
-
-		if e.Id.Set > len(run.Results.Summary) {
-			return fmt.Errorf("Internal error: e.Id.Set %d > len(Results.Summary) %d\n",
-				e.Id.Set, len(run.Results.Summary))
-		}
-		
-		if run.Results.Summary[e.Id.Set].Workers == nil {
-			run.Results.Summary[e.Id.Set].Workers = make([]WorkerSummary,
-				run.WorkerSets[e.Id.Set].Count)
-		}
-
-		ws := &run.Results.Summary[e.Id.Set]
-
-		if e.Id.Id > len(ws.Workers) {
-			return fmt.Errorf("Internal error: e.Id.Id %d > len(Results.Summary[].Workers) %d\n",
-				e.Id.Id, len(ws.Workers))
-		}
-
-		s := &ws.Workers[e.Id.Id]
-
-		s.Raw = append(s.Raw, e)
-		
-		d := data[e.Id]
-		if d == nil {
-			d = &Data{}
-			data[e.Id] = d
-		}
-			
-		if d.startTime == 0 {
-			d.startTime = e.Now
-			d.startCputime = e.Cputime
-		} else {
-			tput := Throughput(d.lastTime, d.lastKops, e.Now, e.Kops)
-			util := Utilization(d.lastTime, d.lastCputime, e.Now, e.Cputime)
-
-			s.MinMaxTput.Update(tput)
-			s.MinMaxUtil.Update(util)
-			ws.MinMaxTput.Update(tput)
-			ws.MinMaxUtil.Update(util)
-		}
-		d.lastTime = e.Now
-		d.lastKops = e.Kops
-		d.lastCputime = e.Cputime
-	}
-
-	for Id, d := range data {
-		ws := &run.Results.Summary[Id.Set]
-		s := &ws.Workers[Id.Id]
-
-		s.TotalTput = d.lastKops
-		s.TotalTime = time.Duration(d.lastTime - d.startTime)
-		s.TotalCputime = d.lastCputime - d.startCputime
-		
-		s.AvgTput = Throughput(d.startTime, 0, d.lastTime, d.lastKops)
-		s.AvgUtil = Utilization(d.startTime, d.startCputime, d.lastTime, d.lastCputime)
-
-		ws.MinMaxAvgTput.Update(s.AvgTput)
-		ws.MinMaxAvgUtil.Update(s.AvgUtil)
-	}
-
-	// Calculate the average-of-averages for each set
-	for set := range run.Results.Summary {
-		ws := &run.Results.Summary[set]
-		
-		var totalTput float64
-		var totalUtil float64
-		var count int
-		for id := range ws.Workers {
-			totalTput += ws.Workers[id].AvgTput
-			totalUtil += ws.Workers[id].AvgUtil
-			count++
-		}
-
-		// FIXME -- Is this legit?
-		ws.TotalTput = totalTput
-		ws.TotalUtil = totalUtil
-		ws.AvgAvgTput = totalTput / float64(count)
-		ws.AvgAvgUtil = totalUtil / float64(count)
-	}
-
-	// Then calculate the standard deviation
-	for set := range run.Results.Summary {
-		ws := &run.Results.Summary[set]
-		
-		var totalAvgTput float64
-		var totalAvgUtil float64
-		var count int
-		
-		for id := range ws.Workers {
-			d1 := ws.Workers[id].AvgTput - ws.AvgAvgTput
-			d2 := ws.Workers[id].AvgUtil - ws.AvgAvgUtil
-			totalAvgTput += d1 * d1
-			totalAvgUtil += d2 * d2
-			count++
-		}
-		v1 := totalAvgTput / float64(count)
-		v2 := totalAvgUtil / float64(count)
-		ws.AvgStdDevTput = math.Sqrt(v1)
-		ws.AvgStdDevUtil = math.Sqrt(v2)
-	}
-
-	return
-}
-
-func (run *BenchmarkRun) TextReport(level int) (err error) {
-	var done bool
-	done, err = run.checkSummary()
-	if err != nil {
-		return
-	}
-	if ! done {
-		err = fmt.Errorf("Run not yet processed")
-		return
-	}
-
-	fmt.Printf("== RUN %s ==\n", run.Label)
-
-	for set := range run.WorkerSets {
-		ws := &run.WorkerSets[set]
-		params := ""
-		for _, s := range ws.Params.Args {
-			params = fmt.Sprintf("%s %s", params, s)
-		}
-		fmt.Printf("Set %d: %s\n", set, params)
-	}
-
-	fmt.Printf("\n%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", "set", "ttotal", "tavgavg", "tstdev", "tavgmax", "tavgmin", "ttotmax", "ttotmin", "utotal", "uavgavg", "ustdev", "uavgmax", "uavgmin", "utotmax", "utotmin")
-	for set := range run.WorkerSets {
-		ws := &run.Results.Summary[set]
-		fmt.Printf("%8d %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f\n",
-			set,
-			ws.TotalTput, ws.AvgAvgTput, ws.AvgStdDevTput, ws.MinMaxAvgTput.Max,
-			ws.MinMaxAvgTput.Min, ws.MinMaxTput.Max, ws.MinMaxTput.Min,
-			ws.TotalUtil, ws.AvgAvgUtil, ws.AvgStdDevUtil, ws.MinMaxAvgUtil.Max,
-			ws.MinMaxAvgUtil.Min, ws.MinMaxUtil.Max, ws.MinMaxUtil.Min)
-	}
-
-	if level >= 1 {
- 		fmt.Printf("\n%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", "workerid", "toput", "time", "cpu", "tavg", "tmin", "tmax", "uavg", "umin", "umax")
-		for set := range run.Results.Summary {
-			for id := range run.Results.Summary[set].Workers {
-				s := run.Results.Summary[set].Workers[id]
-				fmt.Printf("%2d:%2d    %10d %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f\n",
-					set, id,
-					s.TotalTput, s.TotalTime.Seconds(), s.TotalCputime.Seconds(),
-					s.AvgTput, s.MinMaxTput.Min, s.MinMaxTput.Max,
-					s.AvgUtil, s.MinMaxUtil.Min, s.MinMaxUtil.Max)
-
-				if level >= 2 {
-					var le WorkerReport
-					for _, e := range s.Raw {
-						var dtime float64
-						var dCputime time.Duration
-						var dKops int
-						time := float64(e.Now) / SEC
-						if e.Now > le.Now {
-							dtime = float64(e.Now - le.Now) / SEC
-							dCputime = e.Cputime - le.Cputime
-							dKops = e.Kops - le.Kops
-
-						}
-						fmt.Printf ("   [%8.3f] (%8.3f) %8.3f (%8.3f) %8d (%8d) %12d\n",
-							time, dtime,
-							e.Cputime.Seconds(), dCputime.Seconds(),
-							e.Kops, dKops, e.MaxDelta)
-						le = e
-					}
-				}
-
-			}
-		}
-	}
-
-	fmt.Printf("\n\n")
-
-	return
-}
-
-func LoadBenchmark(filename string) (plan BenchmarkPlan, err error) {
-	plan.filename = filename
-	
-	var b []byte
-	b, err = ioutil.ReadFile(filename)
-	if err != nil {
-		return
-	}
-	
-	err = json.Unmarshal(b, &plan)
-	if err != nil {
-		return
-	}
-
-	return
-}
-
-func (plan *BenchmarkPlan) Save() (err error) {
-	if plan.filename == "" {
-		err = fmt.Errorf("Invalid filename")
-		return
-	}
-	
-	var b []byte
-	b, err = json.Marshal(*plan)
-	if err != nil {
-		return
-	}
-
-	backupFilename := fmt.Sprintf(".%s.tmp", plan.filename)
-	err = os.Rename(plan.filename, backupFilename)
-	if err != nil {
-		if os.IsNotExist(err) {
-			backupFilename = ""
-		} else {
-			return
-		}
-	}
-
-	err = ioutil.WriteFile(plan.filename, b, 0666)
-	if err != nil {
-		if backupFilename != "" {
-			os.Rename(backupFilename, plan.filename)
-		}
-		return
-	}
-
-	if backupFilename != "" {
-		os.Remove(backupFilename)
-	}
-	return
-}
-
-func (plan *BenchmarkPlan) TextReport(level int) (err error) {
-	for i := range plan.Runs {
-		r := &plan.Runs[i]
-		if ! r.Completed {
-			fmt.Printf("Test [%d] %s not run\n", i, r.Label)
-		}
-
-		err = r.Process()
-		if err != nil {
-			fmt.Printf("Error processing [%d] %s: %v\n", i, r.Label, err)
-			return
-		}
-
-		err = r.TextReport(level)
-		if err != nil {
-			return
-		}
-	}
-
-	return
-}
-
diff --git a/htmlreport.go b/htmlreport.go
deleted file mode 100644
index 545582d..0000000
--- a/htmlreport.go
+++ /dev/null
@@ -1,238 +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
-
-import (
-	"fmt"
-	"os"
-	"io"
-	"encoding/json"
-)
-
-type OptionAxis struct {
-	Title string `json:"title,omitempty"`
-	// Always include this one so that we can start graphs at 0
-	MinValue float64 `json:"minValue"`
-	MaxValue float64 `json:"maxValue,omitempty"`
-}
-
-type Options struct {
-	Title string     `json:"title,omitempty"`
-	HAxis OptionAxis `json:"hAxis"`
-	VAxis OptionAxis `json:"vAxis"`
-	Legend string    `json:"legend,omitempty"`
-}
-
-type Point struct {
-	x float64
-	y float64
-}
-
-type RunRaw struct {
-	Tag string
-	Title string
-	hTitle string
-	vTitle string
-	Points [][]Point
-}
-
-func (options *Options) OutputJavascript(w io.Writer, tag string) (err error) {
-	var optionsJson []byte
-	optionsJson, err = json.Marshal(options)
-	if err != nil {
-		return
-	}
-
-	fmt.Fprintf(w, "        var %sopt = ", tag)
-	fmt.Fprint(w, string(optionsJson))
-	fmt.Fprintln(w, ";")
-
-	return
-}
-
-func (p *Point) OutputJson(w io.Writer, id int, max int) (err error) {
-	fmt.Fprintf(w, "            [%f", p.x)
-	for i := 0; i < max; i++ {
-		if i == id {
-			fmt.Fprintf(w, ", %f", p.y)
-		} else {
-			fmt.Fprintf(w, ", null")
-		}
-	}
-	fmt.Fprint(w, "],\n")
-	return
-}
-
-func (d *RunRaw) OutputHTML(w io.Writer) (err error) {
-	fmt.Fprintf(w, "    <div class='scatterplot' id='scatterplot%s'></div>\n", d.Tag)
-	return
-}
-
-func (d *RunRaw) OutputJavascript(w io.Writer) (err error) {
-	var options Options
-
-	options.Title = d.Title
-	options.HAxis.Title = d.hTitle
-	options.VAxis.Title = d.vTitle
-
-	err = options.OutputJavascript(w, d.Tag)
-	if err != nil {
-		return
-	}
-
-	fmt.Printf("        var %sdata = new google.visualization.DataTable();\n", d.Tag)
-	fmt.Printf("        %sdata.addColumn('number', 'Time');\n", d.Tag)
-	for i := range d.Points {
-		fmt.Printf("        %sdata.addColumn('number', 'Worker %d');\n", d.Tag, i)
-	}
-	fmt.Printf("        %sdata.addRows([\n", d.Tag)
-
-	// Can't use json here because we need to be able to use 'null' for non-existent values
-	for i := range d.Points {
-		for j := range d.Points[i] {
-			err = d.Points[i][j].OutputJson(w, i, len(d.Points))
-			if err != nil {
-				return
-			}
-		}
-	}
-	fmt.Print("          ]);\n")
-	
-	fmt.Printf("        var %schart = new google.visualization.ScatterChart(document.getElementById('scatterplot%s'));\n", d.Tag, d.Tag);
-	fmt.Printf("        %schart.draw(%sdata, %sopt);\n\n", d.Tag, d.Tag, d.Tag)
-	
-	return
-}
-
-type HTMLReport struct {
-	Raw []RunRaw
-}
-
-
-func (rpt *HTMLReport) Output(w io.Writer) (err error) {
-	// Print start -> json charts
-	fmt.Fprint(w,
-		`<html>
-  <head>
-    <style>
-      .scatterplot {
-      margin:auto;
-      width: 100vw;
-      height: 60vw;
-      }
-
-      .empty {
-      margin: auto;
-      }
-    </style>
-    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
-    <script type="text/javascript">
-      google.charts.load('current', {'packages':['corechart']});
-      google.charts.setOnLoadCallback(drawCharts);
-      function drawCharts() {
-`);
-	// Print json chart code
-	for i := range rpt.Raw {
-		err = rpt.Raw[i].OutputJavascript(w)
-		if err != nil {
-			return
-		}
-	}
-	// Print json -> html
-	fmt.Fprint(w,
-		`      }
-    </script>
-  </head>
-  <body>
-`);
-	// Print html
-	for i := range rpt.Raw {
-		err = rpt.Raw[i].OutputHTML(w)
-		if err != nil {
-			return
-		}
-	}
-	// Print html -> end
-	fmt.Fprint(w,
-		`  </body>
-</html>
-`);
-	return
-}
-
-func (rpt *HTMLReport) AddRun(run *BenchmarkRun) (err error) {
-	var tPut RunRaw
-	var Util RunRaw
-
-	tPut.Title = fmt.Sprintf("Run %s Individual Throughput", run.Label)
-	tPut.hTitle = "Time (s)"
-	tPut.vTitle = "Throughput (kOps)"
-	Util.Title = fmt.Sprintf("Run %s Individual Utilization", run.Label)
-	Util.hTitle = "Time (s)"
-	Util.vTitle = "Utilization"
-	for set := range run.Results.Summary {
-		var idTput []Point
-		var idUtil []Point
-		for id := range run.Results.Summary[set].Workers {
-			var le WorkerReport
-			for _, e := range run.Results.Summary[set].Workers[id].Raw {
-				if e.Kops > 0 {
-					time := float64(e.Now) / SEC
-					tput := Throughput(e.Now, e.Kops, le.Now, le.Kops)
-					util := Utilization(e.Now, e.Cputime, le.Now, le.Cputime)
-					idTput = append(idTput, Point{x:time, y:tput})
-					idUtil = append(idUtil, Point{x:time, y:util})
-				}
-				le = e
-			}
-		}
-		tPut.Points = append(tPut.Points, idTput)
-		Util.Points = append(Util.Points, idUtil)
-	}
-	tPut.Tag = fmt.Sprintf("raw%d", len(rpt.Raw))
-	rpt.Raw = append(rpt.Raw, tPut)
-	Util.Tag = fmt.Sprintf("raw%d", len(rpt.Raw))
-	rpt.Raw = append(rpt.Raw, Util)
-	return
-}
-
-func (plan *BenchmarkPlan) HTMLReport() (err error) {
-	rpt := HTMLReport{}
-
-	for i := range plan.Runs {
-		r := &plan.Runs[i]
-		if ! r.Completed {
-			fmt.Printf("Test [%d] %s not run\n", i, r.Label)
-		}
-
-		err = r.Process()
-		if err != nil {
-			fmt.Printf("Error processing [%d] %s: %v\n", i, r.Label, err)
-			return
-		}
-
-		err = rpt.AddRun(r)
-		if err != nil {
-			return
-		}
-	}
-	err = rpt.Output(os.Stdout)
-
-	return
-}
diff --git a/libxl.go b/libxl.go
deleted file mode 100644
index aa5c01c..0000000
--- a/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/main.go b/main.go
deleted file mode 100644
index ead6ab0..0000000
--- a/main.go
+++ /dev/null
@@ -1,146 +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
-
-import (
-	"fmt"
-	"os"
-	"strconv"
-)
-
-func main() {
-	Args := os.Args
-
-	Args = Args[1:]
-	filename := "test.bench"
-	template := ""
-	verbosity := 0
-
-	for len(Args) > 0 {
-		switch(Args[0]) {
-		case "-f":
-			if len(Args) < 2 {
-				fmt.Println("Need arg for -f")
-				os.Exit(1)
-			}
-			filename = Args[1]
-			Args = Args[2:]
-		case "-t":
-			if len(Args) < 2 {
-				fmt.Println("Need arg for -t")
-				os.Exit(1)
-			}
-			template = Args[1]
-			Args = Args[2:]
-		case "-v":
-			if len(Args) < 2 {
-				fmt.Println("Need arg for -v")
-				os.Exit(1)
-			}
-			verbosity, _ = strconv.Atoi(Args[1])
-			Args = Args[2:]
-		case "plan":
-			// Load either the template benchmark or the filename
-			loadfile := filename
-			if template != "" {
-				loadfile = template
-			}
-			plan, err := LoadBenchmark(loadfile)
-			if err != nil {
-				fmt.Printf("Loading benchmark %s: %v\n",
-					loadfile, err)
-				os.Exit(1)
-			}
-
-			if template != "" {
-				plan.filename = filename
-				err = plan.ClearRuns()
-				if err != nil {
-					fmt.Printf("Clearing runs: %v\n",
-						err)
-					os.Exit(1)
-				}
-			}
-			
-			err = plan.ExpandInput()
-			if err != nil {
-				fmt.Printf("Expanding plan: %v\n", err)
-				os.Exit(1)
-			}
-
-			err = plan.Save()
-			if err != nil {
-				fmt.Printf("Saving plan %s: %v\n", filename, err)
-				os.Exit(1)
-			}
-			fmt.Printf("Created plan in %s\n", filename)
-			Args = Args[1:]
-		case "run":
-			plan, err := LoadBenchmark(filename)
-			if err != nil {
-				fmt.Println("Loading benchmark ", filename, " ", err)
-				os.Exit(1)
-			}
-			
-			err = plan.Run()
-			if err != nil {
-				fmt.Println("Running benchmark run:", err)
-				os.Exit(1)
-			}
-			Args = Args[1:]
-			
-		case "report":
-			Args = Args[1:]
-			plan, err := LoadBenchmark(filename)
-			if err != nil {
-				fmt.Println("Loading benchmark ", filename, " ", err)
-				os.Exit(1)
-			}
-			
-			err = plan.TextReport(verbosity)
-			if err != nil {
-				fmt.Println("Running benchmark run:", err)
-				os.Exit(1)
-			}
-		case "htmlreport":
-			plan, err := LoadBenchmark(filename)
-			if err != nil {
-				fmt.Println("Loading benchmark ", filename, " ", err)
-				os.Exit(1)
-			}
-			
-			err = plan.HTMLReport()
-			if err != nil {
-				fmt.Println("Running benchmark run:", err)
-				os.Exit(1)
-			}
-			Args = Args[1:]
-
-		case "xltest":
-			XlTest(Args)
-			Args = nil
-			
-		default:
-			fmt.Println("Unknown argument: ", Args[0])
-			os.Exit(1)
-		}
-	}
-}
-
diff --git a/plan.go b/plan.go
deleted file mode 100644
index b8e0c6b..0000000
--- a/plan.go
+++ /dev/null
@@ -1,157 +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
-
-import (
-	"fmt"
-)
-
-type PlanSimpleMatrix struct {
-	Schedulers []string
-	Workers []string
-	Count []int
-	NumaDisable []bool
-}
-
-type PlanInput struct {
-	WorkerPresets map[string]WorkerParams
-	SimpleMatrix *PlanSimpleMatrix
-}
-
-var WorkerPresets = map[string]WorkerParams{
-	"P001":WorkerParams{[]string{"burnwait", "70", "200000"}},
-}
-
-func (plan *BenchmarkPlan) ClearRuns() (err error) {
-	plan.Runs = nil
-
-	return
-}
-
-func (plan *BenchmarkPlan) ExpandInput() (err error) {
-	if plan.Runs != nil {
-		err = fmt.Errorf("Runs non-empty, not doing anything\n");
-		return
-	}
-
-	if plan.Input == nil {
-		err = fmt.Errorf("Input nil, nothing to do")
-		return
-	}
-	
-	if plan.Input.SimpleMatrix == nil {
-		err = fmt.Errorf("Input.SimpleMatrix nil, nothing to do\n");
-		return
-	}
-
-	for k := range plan.Input.WorkerPresets {
-		WorkerPresets[k] = plan.Input.WorkerPresets[k];
-	}
-
-	// Use named schedulers, or default to "" (which will use the
-	// current one)
-	var schedulers []string
-	if plan.Input.SimpleMatrix.Schedulers != nil {
-		schedulers = plan.Input.SimpleMatrix.Schedulers
-	} else {
-		schedulers = append(schedulers, "")
-	}
-
-	// Start by making a slice with baselines and each of the counts
-	var a, b []BenchmarkRun
-	
-	for _, wn := range plan.Input.SimpleMatrix.Workers {
-		wp := WorkerPresets[wn]
-		
-		if wp.Args == nil {
-			err = fmt.Errorf("Invalid worker preset: %s", wn)
-			return
-		}
-		
-		run := BenchmarkRun{
-			WorkerSets:[]WorkerSet{{Params:wp, Count:1}},
-			RuntimeSeconds:10,
-		}
-
-		run.Label = wn+" baseline"
-		a = append(a, run)
-	}
-
-
-	for _, c := range plan.Input.SimpleMatrix.Count {
-		run := BenchmarkRun{
-			RuntimeSeconds:10,
-		}
-		
-		for _, wn := range plan.Input.SimpleMatrix.Workers {
-			wp := WorkerPresets[wn]
-			
-			if run.Label != "" {
-				run.Label = run.Label+" + "
-			}
-			run.Label = fmt.Sprintf("%s%s %d", run.Label, wn, c)
-
-			ws := WorkerSet{Params:wp, Count:c}
-			run.WorkerSets = append(run.WorkerSets, ws)
-		}
-
-		a = append(a, run)
-	}
-
-	// ...then cross it by schedulers
-	if len(schedulers) > 0 {
-		for _, base := range a {
-			for _, s := range schedulers {
-				run := base
-				run.RunConfig.Scheduler = s
-				run.Label = run.Label+" "+s
-				b = append(b, run)
-			}
-		}
-		a = b
-		b = nil
-	}
-
-	// ...and NumaDisable
-	if len(plan.Input.SimpleMatrix.NumaDisable) > 0 {
-		for _, base := range a {
-			for _, d := range plan.Input.SimpleMatrix.NumaDisable {
-				run := base
-				// Need to make a copy of this so that
-				// we have a pointer to use as a tristate
-				run.RunConfig.NumaDisable = new(bool)
-				*run.RunConfig.NumaDisable = d
-				if d {
-					run.Label = run.Label+" NumaOff"
-				} else {
-					run.Label = run.Label+" NumaOn "
-				}
-				b = append(b, run)
-			}
-		}
-		a = b
-		b = nil
-	}
-
-	for i := range a {
-		fmt.Printf("%s\n", a[i].Label)
-	}
-	plan.Runs = a;
-	return
-}
diff --git a/processworker.go b/processworker.go
deleted file mode 100644
index 8c27f15..0000000
--- a/processworker.go
+++ /dev/null
@@ -1,98 +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
-
-import (
-	"fmt"
-	"os/exec"
-	"encoding/json"
-	"bufio"
-	"io"
-	
-)
-
-type ProcessWorker struct {
-	id WorkerId
-	c *exec.Cmd
-	stdout io.ReadCloser
-	jsonStarted bool
-	Log []string
-}
-
-func (w *ProcessWorker) SetId(i WorkerId) {
-	w.id = i
-}
-
-func (w *ProcessWorker) Init(p WorkerParams, g WorkerConfig) (err error) {
-	w.c = exec.Command("./worker-proc", p.Args...)
-
-	w.stdout, err = w.c.StdoutPipe()
-	if err != nil {
-		fmt.Print("Conneting to stdout: ", err)
-		return
-	}
-
-	return
-}
-
-func (w *ProcessWorker) Shutdown() {
-	w.c.Process.Kill()
-}
-
-func (w *ProcessWorker) DumpLog(f io.Writer) (err error) {
-	b := bufio.NewWriter(f)
-	defer b.Flush()
-	for _, line := range w.Log {
-		_, err = fmt.Println(b, line)
-		if err != nil {
-			return
-		}
-	}
-	return
-}
-
-func (w *ProcessWorker) Process(report chan WorkerReport, done chan WorkerId) {
-	w.c.Start()
-
-	scanner := bufio.NewScanner(w.stdout)
-
-	for scanner.Scan() {
-		s := scanner.Text()
-		
-		//fmt.Println("Got these bytes: ", s);
-		w.Log = append(w.Log, s)
-
-		if w.jsonStarted {
-			var r WorkerReport
-			json.Unmarshal([]byte(s), &r)
-			r.Id = w.id
-			report <- r
-		} else {
-			if s == "START JSON" {
-				//fmt.Println("Got token to start parsing json")
-				w.jsonStarted = true
-			}
-		}
-	}
-
-	done <- w.id
-
-	w.c.Wait()
-}
-
diff --git a/run.go b/run.go
deleted file mode 100644
index d1c5d95..0000000
--- a/run.go
+++ /dev/null
@@ -1,456 +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
-
-import (
-	"fmt"
-	"os"
-	"os/signal"
-	"time"
-	"regexp"
-	"strconv"
-	"bufio"
-	"io"
-)
-
-type WorkerState struct {
-	w Worker
-	LastReport WorkerReport
-}
-
-type Worker interface {
-	SetId(WorkerId)
-	Init(WorkerParams, WorkerConfig) error
-	Shutdown()
-	Process(chan WorkerReport, chan WorkerId)
-	DumpLog(io.Writer) error
-}
-
-func Report(ws *WorkerState, r WorkerReport) {
-	//fmt.Println(r)
-
-	lr := ws.LastReport
-
-	if (lr.Now > 0) {
-		time := float64(r.Now) / SEC
-		dtime := float64(r.Now - lr.Now) / SEC
-		kops := r.Kops - lr.Kops
-
-		tput := Throughput(lr.Now, lr.Kops, r.Now, r.Kops)
-
-		util := Utilization(lr.Now, lr.Cputime, r.Now, r.Cputime)
-		
-		fmt.Printf("%v %8.3f [%8.3f] cpu %8.3f [%8.3f] Kops: %8d [%8d] Tput: %4.2f Util: %4.2f\n",
-			r.Id, time, dtime, r.Cputime.Seconds(), r.Cputime.Seconds() - lr.Cputime.Seconds(),
-			r.Kops, kops, tput, util);
-	}
-
-	ws.LastReport = r
-}
-
-type WorkerList map[WorkerId]*WorkerState
-
-func (ws *WorkerList) Start(report chan WorkerReport, done chan WorkerId) (i int) {
-	i = 0
-	for j := range *ws {
-		go (*ws)[j].w.Process(report, done)
-		i++
-	}
-	return
-}
-
-func (ws *WorkerList) Stop() {
-	for i := range *ws {
-		(*ws)[i].w.Shutdown()
-	}
-}
-
-const (
-	WorkerProcess = iota
-	WorkerXen = iota
-)
-
-func NewWorkerList(WorkerSets []WorkerSet, workerType int) (wl WorkerList, err error) {
-	wl = WorkerList(make(map[WorkerId]*WorkerState))
-
-	for wsi := range WorkerSets {
-		for i := 0; i < WorkerSets[wsi].Count; i = i+1 {
-			Id := WorkerId{Set:wsi,Id:i}
-
-			ws := wl[Id]
-
-			if ws != nil {
-				panic("Duplicate worker for id!")
-			}
-			
-			ws = &WorkerState{}
-			
-			switch workerType {
-			case WorkerProcess:
-				ws.w = &ProcessWorker{}
-			case WorkerXen:
-				ws.w = &XenWorker{}
-			default:
-				err = fmt.Errorf("Unknown type: %d", workerType)
-				return
-			}
-			
-			ws.w.SetId(Id)
-		
-			ws.w.Init(WorkerSets[wsi].Params, WorkerSets[wsi].Config)
-
-			wl[Id] = ws
-		}
-	}
-	return
-}
-
-var CpukHZ uint64
-
-func getCpuHz() (err error) {
-	if CpukHZ == 0 {
-		var cpuinfo *os.File
-		cpuinfo, err = os.Open("/proc/cpuinfo")
-		if err != nil {
-			return
-		}
-		re := regexp.MustCompile("^cpu MHz\\s*: ([0-9.]+)$")
-		scanner := bufio.NewScanner(cpuinfo)
-		for scanner.Scan() {
-			s := scanner.Text()
-			m := re.FindStringSubmatch(s)
-			if m != nil {
-				var MHZ float64
-				MHZ, err = strconv.ParseFloat(m[1], 64)
-				if err != nil {
-					return
-				}
-				CpukHZ = uint64(MHZ*1000)
-				break
-			}
-		}
-		if CpukHZ == 0 {
-			err = fmt.Errorf("Couldn't find cpu MHz")
-			return
-		} else {
-			fmt.Println("CpukHZ: ", CpukHZ)
-			
-		}
-	}
-	return
-}
-
-// If the pool is specified, use that pool; otherwise assume pool 0.
-//
-// Unspecified schedulers match any pool; unspecifiend cpu lists match
-// any pool.
-//
-// If the pool exists and the scheduler and cpu lists match the pool,
-// carry on.  (This is running the VMs in a pre-configured pool.)
-//
-// If the pool exists and either the scheduler or the cpus don't match
-// the pool, and this is pool 0, skip.
-//
-// TODO: If the scheduler matches but the cpus don't, modify the pool
-// by adding or removing cpus.  (This can be done for Pool-0 as well.)
-//
-// If the pool is not Pool-0, and the scheduler doesn't match or the
-// pool doesn't exist, but there are no cpus, skip (because we don't
-// have enough information to create the pool).
-//
-// If the pool is not Pool-0, and either the scheduler or the cpus
-// don't match, and the cpus are specified, create the pool.
-func (run *BenchmarkRun) Prep() (ready bool, why string) {
-	var pool CpupoolInfo
-	poolPresent := false
-	
-	// Generate the requested cpumap
-	var Cpumap Bitmap
-	if run.RunConfig.Cpus != nil {
-		fmt.Print("Run.Prep: Cpus: ")
-		printed := false
-		for _, i := range run.RunConfig.Cpus {
-			if printed {
-				fmt.Printf(",%d", i)
-			} else {
-				printed = true
-				fmt.Printf("%d", i)
-			}				
-			Cpumap.Set(i)
-		}
-		fmt.Print("\n")
-		if Cpumap.IsEmpty() {
-			why = "Invalid (empty) cpumap"
-			return
-		}
-	}
-	
-
-	if run.RunConfig.Pool == "" {
-		fmt.Printf("Run.Prep: No pool set, using 0\n")
-		pool = Ctx.CpupoolInfo(0)
-		poolPresent = true
-	} else {
-		pool, poolPresent = Ctx.CpupoolFindByName(run.RunConfig.Pool)
-		if poolPresent {
-			fmt.Printf("Run.Prep: Pool %s found, Poolid %d\n",
-				run.RunConfig.Pool, pool.Poolid)
-		} else {
-			fmt.Printf("Run.Prep: Pool %s not found\n")
-		}
-	}
-
-	schedMatches := true
-	if run.RunConfig.Scheduler != "" &&
-		poolPresent &&
-		pool.Scheduler.String() != run.RunConfig.Scheduler {
-			schedMatches = false;
-	}
-
-	cpuMatches := true
-	if run.RunConfig.Cpus != nil {
-		if !poolPresent {
-			cpuMatches = false
-		} else {
-			for i := 0; i <= pool.Cpumap.Max(); i++ {
-				if pool.Cpumap.Test(i) != Cpumap.Test(i) {
-					fmt.Printf("Prep: cpu %d: pool %v, want %v, bailing\n",
-						i, pool.Cpumap.Test(i), Cpumap.Test(i))
-					cpuMatches = false
-					break
-				}
-			}
-		}
-	}
-		
-
-	// If we're using pool 0, and the scheduler or cpus don't
-	// match, bail; otherwise say we're ready.
-	if poolPresent && pool.Poolid == 0 {
-		if ! schedMatches {
-			why = "scheduler != "+run.RunConfig.Scheduler+", can't change"
-			return
-		}
-
-		// TODO: Actually, we can modify pool 0; leave this until we want it.
-		if ! cpuMatches {
-			why = "Cpumap mismatch"
-			return
-		}
-
-		fmt.Printf("Prep: Poolid 0, sched and cpumap matches\n")
-		ready = true
-		return
-	}
-
-	// OK, we got here it
-	if run.RunConfig.Cpus == nil {
-		// No construction information; is the cpupool ready without it?
-		if !poolPresent {
-			why = "Pool not present, no pool construction information"
-			return
-		} else if !schedMatches {
-			why = "scheduler != "+run.RunConfig.Scheduler+", no pool construction information"
-			return
-		}
-
-		// Scheduler matches, pool present, cpus not
-		// specified, just go with it
-		ready = true
-		return
-	}
-
-	// OK, we have all the information we need to create the pool we want.
-	Scheduler := SchedulerCredit
-	err := Scheduler.FromString(run.RunConfig.Scheduler)
-	if err != nil {
-		why = "Invalid scheduler: "+run.RunConfig.Scheduler
-		return
-	}
-
-	// Destroy the pool if it's present;
-	if poolPresent {
-		err := Ctx.CpupoolDestroy(pool.Poolid)
-		if err != nil {
-			fmt.Printf("Trying to destroy pool: %v\n", err)
-			why = "Couldn't destroy cpupool"
-			return
-		}
-	}
-
-	// Free the cpus we need;
-	err = Ctx.CpupoolMakeFree(Cpumap)
-	if err != nil {
-		why = "Couldn't free cpus"
-		return
-	}
-
-	// And create the pool.
-	err, _ = Ctx.CpupoolCreate("schedbench", Scheduler, Cpumap)
-	if err != nil {
-		why = "Couldn't create cpupool"
-		return
-	}
-
-	ready = true
-	return 
-}
-
-func (run *BenchmarkRun) GetCpumap() (Cpumap Bitmap) {
-	if run.RunConfig.Pool == "" {
-		fmt.Printf("Run.Prep: No pool set, using 0\n")
-		pool := Ctx.CpupoolInfo(0)
-		Cpumap = pool.Cpumap
-	} else {
-		pool, poolPresent := Ctx.CpupoolFindByName(run.RunConfig.Pool)
-		if poolPresent {
-			Cpumap = pool.Cpumap
-		} else {
-			panic("run.GetCpumap(): Pool "+run.RunConfig.Pool+" not found!")
-		}
-	}
-	return
-}
-
-func (run *BenchmarkRun) Run() (err error) {
-	for wsi := range run.WorkerSets {
-		conf := &run.WorkerSets[wsi].Config
-		
-		conf.PropagateFrom(run.WorkerConfig)
-		if conf.Pool == "" {
-			conf.Pool = run.RunConfig.Pool
-		}
-		run.WorkerSets[wsi].Params.SetkHZ(CpukHZ)
-		
-		if *run.RunConfig.NumaDisable {
-			if conf.SoftAffinity != "" {
-				err = fmt.Errorf("Cannot disable Numa if SoftAffinity is set!")
-				return
-			}
-			// Disable libxl NUMA by setting the soft
-			// affinity to the set of cpus in the cpupool
-		 	conf.SoftAffinity = run.GetCpumap().String()
-			fmt.Printf("Setting SoftAffinity to %s to disable NUMA placement\n",
-				conf.SoftAffinity)
-		}
-	}
-	
-	Workers, err := NewWorkerList(run.WorkerSets, WorkerXen)
-	if err != nil {
-		fmt.Println("Error creating workers: %v", err)
-		return
-
-	}
-	
-	report := make(chan WorkerReport)
-	done := make(chan WorkerId)
-	signals := make(chan os.Signal, 1)
-
-	signal.Notify(signals, os.Interrupt)
-	
-	i := Workers.Start(report, done)
-
-	// FIXME:
-	// 1. Make a zero timeout mean "never"
-	// 2. Make the signals / timeout thing a bit more rational; signal then timeout shouldn't hard kill
-	timeout := time.After(time.Duration(run.RuntimeSeconds) * time.Second);
-	stopped := false
-	for i > 0 {
-		select {
-		case r := <-report:
-			if ! stopped {
-				run.Results.Raw = append(run.Results.Raw, r)
-				Report(Workers[r.Id], r)
-			}
-		case did := <-done:
-			if ! stopped {
-				fmt.Println("WARNING: Worker", did, "left early, shutting down workers")
-				Workers.Stop()
-				stopped = true
-				err = fmt.Errorf("Worker %v exited early", did)
-				Workers[did].w.DumpLog(os.Stdout)
-			}
-			i--;
-			fmt.Printf("Worker %v exited; %d workers left\n", did, i);
-		case <-timeout:
-			if ! stopped {
-				Workers.Stop()
-				stopped = true
-				run.Completed = true
-			}
-		case <-signals:
-			if ! stopped {
-				fmt.Println("SIGINT receieved, shutting down workers")
-				Workers.Stop()
-				stopped = true
-				if run.RuntimeSeconds == 0 {
-					run.Completed = true
-				}
-				err = fmt.Errorf("Interrupted")
-			} else {
-				fmt.Println("SIGINT received after stop, exiting without cleaning up")
-				return
-			}
-		}
-	}
-	return
-}
-
-func (plan *BenchmarkPlan) Run() (err error) {
-
-	err = getCpuHz()
-	if err != nil {
-		return
-	}
-
-	if plan.WorkerType == WorkerXen {
-		err = Ctx.Open()
-		if err != nil {
-			return
-		}
-	}
-	
-	for i := range plan.Runs {
-		r := &plan.Runs[i];
-		if ! r.Completed { 
-			r.WorkerConfig.PropagateFrom(plan.WorkerConfig)
-			r.RunConfig.PropagateFrom(plan.RunConfig)
-			ready, why := r.Prep()
-			if ready {
-				fmt.Printf("Running test [%d] %s\n", i, r.Label)
-				err = r.Run()
-				if err != nil {
-					return
-				}
-			} else {
-				fmt.Printf("Test [%d]: %s skipped (%s)\n", i, r.Label, why)
-			}
-		}
-		if r.Completed {
-			fmt.Printf("Test [%d] %s completed\n", i, r.Label)
-			err = plan.Save()
-			if err != nil {
-				fmt.Println("Error saving: ", err)
-				return
-			}
-		}
-	}
-	return
-}
-
diff --git a/stubs.go b/stubs.go
deleted file mode 100644
index 78987ad..0000000
--- a/stubs.go
+++ /dev/null
@@ -1,34 +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
-
-import (
-	"fmt"
-)
-
-func (plan *BenchmarkPlan) Run() (err error) {
-	err = fmt.Errorf("Not implemented")
-
-	return
-}
-
-func XlTest(Args []string) {
-	return
-}
-
diff --git a/tools/golang/xenlight/libxl.go b/tools/golang/xenlight/libxl.go
new file mode 100644
index 0000000..aa5c01c
--- /dev/null
+++ b/tools/golang/xenlight/libxl.go
@@ -0,0 +1,720 @@
+/*
+ * 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/xenworker.go b/xenworker.go
deleted file mode 100644
index f2f316f..0000000
--- a/xenworker.go
+++ /dev/null
@@ -1,278 +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
-
-import (
-	"fmt"
-	"os"
-	"os/exec"
-	"encoding/json"
-	"bufio"
-	"io"
-)
-
-type XenWorker struct {
-	id WorkerId
-	Ctx Context
-	vmname string
-	domid int
-	consoleCmd *exec.Cmd
-	console io.ReadCloser
-	jsonStarted bool
-	Log []string
-}
-
-// We have to capitalize the element names so that the json class can
-// get access to it; so annotate the elements so they come out lower
-// case
-type RumpRunConfigBlk struct {
-	Source string     `json:"source"`
-	Path string       `json:"path"`
-	Fstype string     `json:"fstype"` 
-	Mountpoint string `json:"mountpoint"`
-}
-
-type RumpRunConfig struct {
-	Blk RumpRunConfigBlk `json:"blk"`
-	Cmdline string       `json:"cmdline"`
-	Hostname string      `json:"hostname"`
-}
-
-func (w *XenWorker) SetId(i WorkerId) {
-	w.id = i
-	w.vmname = fmt.Sprintf("worker-%v", i)
-	w.domid = -1 // INVALID DOMID
-}
-
-func (w *XenWorker) Init(p WorkerParams, g WorkerConfig) (err error) {
-	if err != nil {
-		return
-	}
-	
-	mock := false
-	
-	// Make xl config file
-	//  name=worker-$(id)
-
-	cfgName := os.TempDir()+"/schedbench-"+w.vmname+".cfg"
-
-	cfg, err := os.Create(cfgName)
-	//defer os.Remove(cfgName)
-
-	if err != nil {
-		fmt.Printf("Error creating configfile %s: %v\n", cfgName, err)
-		return
-	}
-
-	fmt.Fprintf(cfg, "name = '%s'\n", w.vmname)
-	fmt.Fprintf(cfg, "kernel = 'worker-xen.img'\n")
-	fmt.Fprintf(cfg, "memory = 32\n")
-	fmt.Fprintf(cfg, "vcpus = 1\n")
-	fmt.Fprintf(cfg, "on_crash = 'destroy'\n")
-	fmt.Fprintf(cfg, "tsc_mode = 'native'\n")
-
-	if g.Pool != "" {
-		fmt.Fprintf(cfg, "pool = '%s'\n", g.Pool)
-	}
-
-	if g.SoftAffinity != "" {
-		fmt.Fprintf(cfg, "cpus_soft = '%s'\n", g.SoftAffinity)
-	}
-
-	
-	// xl create -p [filename]
-	{
-		args := []string{"xl", "create", "-p", cfgName}
-		if mock {
-			args = append([]string{"echo"}, args...)
-		}
-		e := exec.Command(args[0], args[1:]...)
-		
-		e.Stdout = os.Stdout
-		e.Stderr = os.Stderr
-
-		err = e.Run()
-		if err != nil {
-			fmt.Printf("Error creating domain: %v\n", err)
-			return
-		}
-	}
-
-	// Get domid
-	{
-		var domidString []byte
-		var args []string
-		
-		if mock {
-			args = []string{"echo", "232"}
-		} else {
-			args = []string{"xl", "domid", w.vmname}
-		}
-		e := exec.Command(args[0], args[1:]...)
-
-		domidString, err = e.Output()
-		if err != nil {
-			fmt.Printf("Error getting domid: %v\n", err)
-			return
-		}
-
-		_, err = fmt.Sscanf(string(domidString), "%d\n", &w.domid)
-		if err != nil {
-			fmt.Printf("Error converting domid: %v\n", err)
-			return
-		}
-
-		//fmt.Printf(" %s domid %d\n", w.vmname, w.domid)
-	}
-	
-	// Set xenstore config
-	{
-		rcfg := RumpRunConfig{
-			Blk:RumpRunConfigBlk{Source:"dev",
-				Path:"virtual",
-				Fstype:"kernfs",
-				Mountpoint:"/kern"},
-			Hostname:w.vmname}
-		
-		rcfg.Cmdline = "worker-xen.img"
-		for _, a := range p.Args {
-			rcfg.Cmdline += fmt.Sprintf(" %s", a)
-		}
-
-		var rcfgBytes []byte
-	
-		rcfgBytes, err = json.Marshal(rcfg)
-		if err != nil {
-			fmt.Printf("Error marshalling rumprun json: %v\n", err)
-			return
-		}
-
-		//fmt.Printf("json:\n%s\n", string(rcfgBytes))
-		rcfgPath := fmt.Sprintf("/local/domain/%d/rumprun/cfg", w.domid)
-
-		//fmt.Printf("Writing to %s, json config %s\n", rcfgPath, rcfgBytes)
-		
-		args := []string{"xenstore-write", rcfgPath, string(rcfgBytes)}
-		if mock {
-			args = append([]string{"echo"}, args...)
-		}
-		e := exec.Command(args[0], args[1:]...)
-		
-		e.Stdout = os.Stdout
-		e.Stderr = os.Stderr
-
-		err = e.Run()
-		if err != nil {
-			fmt.Printf("Error writing json into xenstore: %v\n", err)
-			return
-		}
-	}
-	
-
-	// Run console command, attach to w.console
-	{
-		args := []string{"xl", "console", w.vmname}
-		if mock {
-			args = append([]string{"echo"}, args...)
-		}
-		w.consoleCmd = exec.Command(args[0], args[1:]...)
-
-		w.console, err = w.consoleCmd.StdoutPipe()
-		if err != nil {
-			fmt.Print("Conneting to stdout: ", err)
-			return
-		}
-
-		w.consoleCmd.Start()
-	}
-	
-	return
-}
-
-// FIXME: Return an error
-func (w *XenWorker) Shutdown() {
-	// xl destroy [vmname]
-	e := exec.Command("xl", "destroy", w.vmname)
-
-	e.Stdout = os.Stdout
-	e.Stderr = os.Stderr
-
-	err := e.Run()
-	if err != nil {
-		fmt.Printf("Error destroying domain: %v\n", err)
-		return
-	}
-}
-
-func (w *XenWorker) DumpLog(f io.Writer) (err error) {
-	b := bufio.NewWriter(f)
-	defer b.Flush()
-	for _, line := range w.Log {
-		_, err = fmt.Fprintln(b, line)
-		if err != nil {
-			return
-		}
-	}
-	return
-}
-
-
-
-// FIXME: Return an error
-func (w *XenWorker) Process(report chan WorkerReport, done chan WorkerId) {
-	// // xl unpause [vmname]
-	//err := xg.Ctx.DomainUnpause(Domid(w.domid))
-	err := Ctx.DomainUnpause(Domid(w.domid))
-	if err != nil {
-		fmt.Printf("Error unpausing domain: %v\n", err)
-		return
-	}
-
-	scanner := bufio.NewScanner(w.console)
-
-	for scanner.Scan() {
-		s := scanner.Text()
-
-		w.Log = append(w.Log, s)
-		
-		//fmt.Println("Got these bytes: ", s);
-
-		if w.jsonStarted {
-			var r WorkerReport
-			json.Unmarshal([]byte(s), &r)
-			r.Id = w.id
-			di, err := Ctx.DomainInfo(Domid(w.domid))
-			// Ignore errors for now
-			if err == nil {
-				r.Cputime = di.Cpu_time
-			}
-			report <- r
-		} else {
-			if s == "START JSON" {
-				//fmt.Println("Got token to start parsing json")
-				w.jsonStarted = true
-			}
-		}
-	}
-
-	done <- w.id
-
-	w.consoleCmd.Wait()
-}
-
-- 
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 ` Ronald Rojas [this message]
2016-12-29  1:14 ` [PATCH RFC 59/59] tools/xenlight: Create interface for xenlight info Ronald Rojas
2016-12-29 10:34   ` 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-58-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).