diff --git a/argv.go b/argv.go index d032aea..f9b7862 100644 --- a/argv.go +++ b/argv.go @@ -15,6 +15,7 @@ type args struct { Droplet *DropletCmd `arg:"subcommand:droplet" help:"send events to a droplet"` Config string `arg:"env:VIRTIGO_HOME" help:"defaults to ~/.config/virtigo/"` Server string `arg:"env:VIRTIGO_SERVER" help:"what virtigo cluster to connect to"` + Daemon bool `arg:"--daemon" help:"run as a daemon"` Verbose bool `arg:"--verbose" help:"talk more"` Port int `arg:"--port" default:"8080" help:"allow droplet events via http"` Xml []string `arg:"--libvirt" help:"import qemu xml files: --libvirt /etc/libvirt/qemu/*.xml"` diff --git a/doDaemon.go b/doDaemon.go new file mode 100644 index 0000000..2a82b48 --- /dev/null +++ b/doDaemon.go @@ -0,0 +1,154 @@ +// Copyright 2024 WIT.COM Inc Licensed GPL 3.0 + +package main + +import ( + "fmt" + "time" + + "go.wit.com/lib/protobuf/virtpb" + "go.wit.com/lib/virtigolib" + "go.wit.com/log" +) + +func doDaemon() error { + // set defaults + me.unstable = time.Now() // initialize the grid as unstable + me.changed = false + me.hmap = make(map[*virtpb.Hypervisor]*HyperT) + + // how long a droplet can be missing until it's declared dead + me.unstableTimeout = 17 * time.Second + me.missingDropletTimeout = time.Minute // not sure the difference between these values + + // how often to poll the hypervisors + me.hyperPollDelay = 5 * time.Second + + // how long the cluster must be stable before new droplets can be started + me.clusterStableDuration = 37 * time.Second + + me.cluster = virtpb.InitCluster() + if err := me.cluster.ConfigLoad(); err != nil { + log.Info("config load error", err) + log.Info("") + log.Info("You have never run this before") + log.Info("init example cloud here") + log.Sleep(2) + return err + } + + loop := me.cluster.DropletsAll() // get the list of droplets + for loop.Scan() { + d := loop.Next() + if d == nil { + fmt.Println("d == nil") + return fmt.Errorf("d == nil") + } + fmt.Println("Droplet UUID:", d.Uuid) + if d.Current == nil { + d.Current = new(virtpb.Current) + } + d.SetState(virtpb.DropletState_OFF) + log.Info("droplet", d.Hostname) + } + hmm := "pihole.wit.com" + d := me.cluster.FindDropletByName(hmm) + if d == nil { + log.Info("did not find found droplet", hmm) + } else { + log.Info("found droplet", d.Hostname, d) + } + + var newEvents []*virtpb.Event + + // sanity check the cluster & droplets + if _, _, err := ValidateDroplets(); err != nil { + log.Info("todo: add flag to ignore. for now, fix problems in the config file.") + return err + } + newe, err := ValidateDiskFilenames() + if err != nil { + log.Info(err) + return err + } + // this is a new droplet. add it to the cluster + for _, e := range newe { + newEvents = append(newEvents, e) + } + ValidateUniqueFilenames() + + for _, filename := range argv.Xml { + domcfg, err := virtigolib.ReadXml(filename) + if err != nil { + // parsing the libvirt xml file failed + log.Info("error:", filename, err) + log.Info("readXml() error", filename) + log.Info("readXml() error", err) + log.Info("libvirt XML will have to be fixed by hand") + return err + } + // this is a new droplet. add it to the cluster + log.Info("Add XML Droplet here", domcfg.Name) + _, newe, err := virtigolib.AddDomainDroplet(me.cluster, domcfg) + if err != nil { + log.Info("addDomainDroplet() error", filename) + log.Info("addDomainDroplet() error", err) + log.Info("libvirt XML will have to be fixed by hand") + return err + } + for _, e := range newe { + newEvents = append(newEvents, e) + } + } + for i, e := range newEvents { + log.Info(i, "Event:", e.Droplet, e.FieldName, "orig:", e.OrigVal, "new:", e.NewVal) + me.changed = true + } + + if me.changed { + if err := me.cluster.ConfigSave(); err != nil { + log.Info("configsave error", err) + return err + } + log.Info("XML changes saved in protobuf config") + return nil + } + if len(argv.Xml) != 0 { + log.Info("No XML changes found") + return fmt.Errorf("No XML changes found") + } + + // initialize each hypervisor + for _, pbh := range me.cluster.H.Hypervisors { + // this is a new unknown droplet (not in the config file) + var h *HyperT + h = new(HyperT) + h.pb = pbh + h.lastDroplets = make(map[string]time.Time) + h.lastpoll = time.Now() + + me.hmap[pbh] = h + me.hypers = append(me.hypers, h) + log.Log(EVENT, "config new hypervisors", h.pb.Hostname) + } + + // start the watchdog polling for each hypervisor + for _, h := range me.hypers { + log.Info("starting polling on", h.pb.Hostname) + + // start a watchdog on each hypervisor + go h.NewWatchdog() + } + + var cloud *virtigolib.CloudManager + cloud = virtigolib.NewCloud() + found, _ := cloud.FindDropletByName("www.wit.com") + if found == nil { + log.Info("d == nil") + } else { + log.Info("d == ", found) + } + + startHTTP() + return nil +} diff --git a/doGui.go b/doGui.go index 13bba73..8a552b3 100644 --- a/doGui.go +++ b/doGui.go @@ -130,6 +130,10 @@ func drawWindow(win *gadgets.GenericWindow) { } func updateUptimeGui(uptime string) { + if me.status == nil { + // gui is not initialized + return + } me.status.SetLabel(uptime) datestamp := time.Now().Format("2006-01-02 15:04:03") diff --git a/http.go b/http.go index 861949b..452ff74 100644 --- a/http.go +++ b/http.go @@ -31,7 +31,7 @@ func okHandler(w http.ResponseWriter, r *http.Request) { } if route == "/uptime" { ok, s := uptimeCheck() - fmt.Fprint(w, s) + fmt.Fprintln(w, s) // log.Info(s) updateUptimeGui(s) if ok { diff --git a/main.go b/main.go index 0dc18f5..94242d8 100644 --- a/main.go +++ b/main.go @@ -4,17 +4,14 @@ package main import ( "embed" - "fmt" "net/url" "os" "path/filepath" - "time" "github.com/google/uuid" "go.wit.com/dev/alexflint/arg" "go.wit.com/gui" "go.wit.com/lib/protobuf/virtpb" - "go.wit.com/lib/virtigolib" "go.wit.com/log" ) @@ -101,143 +98,151 @@ func main() { me.admin.doAdminGui() okExit("admin close") } - os.Exit(-1) - // set defaults - me.unstable = time.Now() // initialize the grid as unstable - me.changed = false - me.hmap = make(map[*virtpb.Hypervisor]*HyperT) + /* + // set defaults + me.unstable = time.Now() // initialize the grid as unstable + me.changed = false + me.hmap = make(map[*virtpb.Hypervisor]*HyperT) - // how long a droplet can be missing until it's declared dead - me.unstableTimeout = 17 * time.Second - me.missingDropletTimeout = time.Minute // not sure the difference between these values + // how long a droplet can be missing until it's declared dead + me.unstableTimeout = 17 * time.Second + me.missingDropletTimeout = time.Minute // not sure the difference between these values - // how often to poll the hypervisors - me.hyperPollDelay = 5 * time.Second + // how often to poll the hypervisors + me.hyperPollDelay = 5 * time.Second - // how long the cluster must be stable before new droplets can be started - me.clusterStableDuration = 37 * time.Second + // how long the cluster must be stable before new droplets can be started + me.clusterStableDuration = 37 * time.Second - me.cluster = virtpb.InitCluster() - if err := me.cluster.ConfigLoad(); err != nil { - log.Info("config load error", err) - log.Info("") - log.Info("You have never run this before") - log.Info("init example cloud here") - log.Sleep(2) - os.Exit(-1) - } - - loop := me.cluster.DropletsAll() // get the list of droplets - for loop.Scan() { - d := loop.Next() - if d == nil { - fmt.Println("d == nil") + me.cluster = virtpb.InitCluster() + if err := me.cluster.ConfigLoad(); err != nil { + log.Info("config load error", err) + log.Info("") + log.Info("You have never run this before") + log.Info("init example cloud here") + log.Sleep(2) os.Exit(-1) } - fmt.Println("Droplet UUID:", d.Uuid) - if d.Current == nil { - d.Current = new(virtpb.Current) + + loop := me.cluster.DropletsAll() // get the list of droplets + for loop.Scan() { + d := loop.Next() + if d == nil { + fmt.Println("d == nil") + os.Exit(-1) + } + fmt.Println("Droplet UUID:", d.Uuid) + if d.Current == nil { + d.Current = new(virtpb.Current) + } + d.SetState(virtpb.DropletState_OFF) + log.Info("droplet", d.Hostname) + } + hmm := "pihole.wit.com" + d := me.cluster.FindDropletByName(hmm) + if d == nil { + log.Info("did not find found droplet", hmm) + } else { + log.Info("found droplet", d.Hostname, d) } - d.SetState(virtpb.DropletState_OFF) - log.Info("droplet", d.Hostname) - } - hmm := "pihole.wit.com" - d := me.cluster.FindDropletByName(hmm) - if d == nil { - log.Info("did not find found droplet", hmm) - } else { - log.Info("found droplet", d.Hostname, d) - } - var newEvents []*virtpb.Event + var newEvents []*virtpb.Event - // sanity check the cluster & droplets - if _, _, err := ValidateDroplets(); err != nil { - log.Info("todo: add flag to ignore. for now, fix problems in the config file.") - os.Exit(0) - } - newe, err := ValidateDiskFilenames() - if err != nil { - log.Info(err) - os.Exit(-1) - } - // this is a new droplet. add it to the cluster - for _, e := range newe { - newEvents = append(newEvents, e) - } - ValidateUniqueFilenames() - - for _, filename := range argv.Xml { - domcfg, err := virtigolib.ReadXml(filename) + // sanity check the cluster & droplets + if _, _, err := ValidateDroplets(); err != nil { + log.Info("todo: add flag to ignore. for now, fix problems in the config file.") + os.Exit(0) + } + newe, err := ValidateDiskFilenames() if err != nil { - // parsing the libvirt xml file failed - log.Info("error:", filename, err) - log.Info("readXml() error", filename) - log.Info("readXml() error", err) - log.Info("libvirt XML will have to be fixed by hand") + log.Info(err) os.Exit(-1) } // this is a new droplet. add it to the cluster - log.Info("Add XML Droplet here", domcfg.Name) - _, newe, err := virtigolib.AddDomainDroplet(me.cluster, domcfg) - if err != nil { - log.Info("addDomainDroplet() error", filename) - log.Info("addDomainDroplet() error", err) - log.Info("libvirt XML will have to be fixed by hand") - os.Exit(-1) - } for _, e := range newe { newEvents = append(newEvents, e) } - } - for i, e := range newEvents { - log.Info(i, "Event:", e.Droplet, e.FieldName, "orig:", e.OrigVal, "new:", e.NewVal) - me.changed = true - } + ValidateUniqueFilenames() - if me.changed { - if err := me.cluster.ConfigSave(); err != nil { - log.Info("configsave error", err) - os.Exit(-1) + for _, filename := range argv.Xml { + domcfg, err := virtigolib.ReadXml(filename) + if err != nil { + // parsing the libvirt xml file failed + log.Info("error:", filename, err) + log.Info("readXml() error", filename) + log.Info("readXml() error", err) + log.Info("libvirt XML will have to be fixed by hand") + os.Exit(-1) + } + // this is a new droplet. add it to the cluster + log.Info("Add XML Droplet here", domcfg.Name) + _, newe, err := virtigolib.AddDomainDroplet(me.cluster, domcfg) + if err != nil { + log.Info("addDomainDroplet() error", filename) + log.Info("addDomainDroplet() error", err) + log.Info("libvirt XML will have to be fixed by hand") + os.Exit(-1) + } + for _, e := range newe { + newEvents = append(newEvents, e) + } + } + for i, e := range newEvents { + log.Info(i, "Event:", e.Droplet, e.FieldName, "orig:", e.OrigVal, "new:", e.NewVal) + me.changed = true } - log.Info("XML changes saved in protobuf config") - os.Exit(0) - } - if len(argv.Xml) != 0 { - log.Info("No XML changes found") - os.Exit(0) - } - // initialize each hypervisor - for _, pbh := range me.cluster.H.Hypervisors { - // this is a new unknown droplet (not in the config file) - var h *HyperT - h = new(HyperT) - h.pb = pbh - h.lastDroplets = make(map[string]time.Time) - h.lastpoll = time.Now() + if me.changed { + if err := me.cluster.ConfigSave(); err != nil { + log.Info("configsave error", err) + os.Exit(-1) + } + log.Info("XML changes saved in protobuf config") + os.Exit(0) + } + if len(argv.Xml) != 0 { + log.Info("No XML changes found") + os.Exit(0) + } - me.hmap[pbh] = h - me.hypers = append(me.hypers, h) - log.Log(EVENT, "config new hypervisors", h.pb.Hostname) - } + // initialize each hypervisor + for _, pbh := range me.cluster.H.Hypervisors { + // this is a new unknown droplet (not in the config file) + var h *HyperT + h = new(HyperT) + h.pb = pbh + h.lastDroplets = make(map[string]time.Time) + h.lastpoll = time.Now() - // start the watchdog polling for each hypervisor - for _, h := range me.hypers { - log.Info("starting polling on", h.pb.Hostname) + me.hmap[pbh] = h + me.hypers = append(me.hypers, h) + log.Log(EVENT, "config new hypervisors", h.pb.Hostname) + } - // start a watchdog on each hypervisor - go h.NewWatchdog() - } + // start the watchdog polling for each hypervisor + for _, h := range me.hypers { + log.Info("starting polling on", h.pb.Hostname) - var cloud *virtigolib.CloudManager - cloud = virtigolib.NewCloud() - found, _ := cloud.FindDropletByName("www.wit.com") - if found == nil { - log.Info("d == nil") - } else { - log.Info("d == ", found) + // start a watchdog on each hypervisor + go h.NewWatchdog() + } + + var cloud *virtigolib.CloudManager + cloud = virtigolib.NewCloud() + found, _ := cloud.FindDropletByName("www.wit.com") + if found == nil { + log.Info("d == nil") + } else { + log.Info("d == ", found) + } + */ + + if argv.Daemon { + if err := doDaemon(); err != nil { + badExit(err) + } + okExit("") } // sit here