diff --git a/lib/guest/domains.go b/lib/guest/domains.go index 9dad745..b624e22 100644 --- a/lib/guest/domains.go +++ b/lib/guest/domains.go @@ -3,6 +3,7 @@ package guest import ( "errors" + "log" "time" "libvirt.org/go/libvirt" @@ -104,14 +105,12 @@ func GetGuest(name string, conn *libvirt.Connect) (*VM, error) { // If the domain can't be found by name, exit early with an error if g.dom, err = conn.LookupDomainByName(name); err != nil { - return g, ErrVMNotFound + return g, err } if g.ID, err = g.dom.GetID(); err != nil { return g, err } - if g.BackupXML, err = g.dom.BackupGetXMLDesc(0); err != nil { - return g, err - } + if g.Autostart, err = g.dom.GetAutostart(); err != nil { return g, err } @@ -197,6 +196,11 @@ func GetGuest(name string, conn *libvirt.Connect) (*VM, error) { } } + // Not errors, but still log the warnings when this happens + if g.BackupXML, err = g.dom.BackupGetXMLDesc(0); err != nil { + log.Printf("WARNING: While loading backup information: %s", err) + } + go func() { defer close(g.closeErr) <-g.close @@ -216,6 +220,7 @@ func setNotSet(v string, s bool) string { // Close closes an open connection func (g *VM) Close() error { + log.Println("Closing VM", g.Name) close(g.close) return <-g.closeErr } diff --git a/lib/host/host.go b/lib/host/host.go index bc4dfbf..101234e 100644 --- a/lib/host/host.go +++ b/lib/host/host.go @@ -2,6 +2,7 @@ package host import ( "fmt" + "log" "git.staur.ca/stobbsm/clustvirt/lib/guest" "libvirt.org/go/libvirt" @@ -61,11 +62,11 @@ func (h *Host) GetGuestByName(name string) (*guest.VM, error) { return guest.GetGuest(name, h.conn) } return nil, err - } // Close triggers closing the host connection func (h *Host) Close() error { + log.Println("Closing Host", h.HostName) close(h.close) return <-h.closeErr } diff --git a/main.go b/main.go index 8f7de0f..55086d4 100644 --- a/main.go +++ b/main.go @@ -2,21 +2,22 @@ package main import ( "log" + + "git.staur.ca/stobbsm/clustvirt/lib/host" ) func main() { log.Println("Starting clustvirt, the libvirt cluster manager") - // Try connecting to libvirt - doms, err := GetDomsInCluster("earth.staur.ca", "mars.staur.ca", "venus.staur.ca") + venus, err := host.ConnectHost("venus.staur.ca") if err != nil { log.Fatal(err) } - log.Printf("Domains in cluster: %d", len(doms)) - // Example of xmlns uri found in libvirt xml definition: - // xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0" - for _, d := range doms { - log.Println(d.GetMetadata(0, "", 0)) - d.Free() + defer venus.Close() + lm, err := venus.GetGuestByName("logan-minecraft") + if err != nil { + log.Fatal(err) } + defer lm.Close() + log.Println(lm) } diff --git a/util/cleanup/cleanup.go b/util/cleanup/cleanup.go new file mode 100644 index 0000000..46684d0 --- /dev/null +++ b/util/cleanup/cleanup.go @@ -0,0 +1,55 @@ +// Package cleanup collects functions that should be run at the end of program operation +// to clean things up and shut things down properly. +// The default CleanItUp instance is initialized with a size 3 stack, just so it's initialized. +package cleanup + +// CleanItUp holds a stack of functions that take no arguments and return no +// values, in order to run the stack at a given point. +// Technically doesn't need to be used for cleanup, but that is it's purpose. +type CleanItUp struct { + stack []EmptyFunc +} + +// EmptyFunc is just what you think it is, a function with no arguments and no returns +type EmptyFunc func() + +var cleaner *CleanItUp + +func init() { + cleaner = &CleanItUp{ + stack: make([]EmptyFunc, 3), + } +} + +// Push onto the default (global) CleanItUp instance +func Push(f EmptyFunc) { + cleaner.Push(f) +} + +// Push adds a function to the end of the function stack +func (c *CleanItUp) Push(f EmptyFunc) { + c.stack = append(c.stack, f) +} + +// Stack onto the default (global) CleanItUp instance +func Stack(f EmptyFunc) { + cleaner.Stack(f) +} + +// Stack adds a function to the start of the function stack +// not very efficient, doesn't really need to be. +func (c *CleanItUp) Stack(f EmptyFunc) { + c.stack = append([]EmptyFunc{f}, c.stack...) +} + +// Clean using the default (global) CleanItUp instance +func Clean() { + cleaner.Clean() +} + +// Clean runs the stack in reverse order, using the defer keyword to make sure they all run +func (c *CleanItUp) Clean() { + for i := len(c.stack) - 1; i >= 0; i-- { + defer c.stack[i]() + } +}