summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README3
-rw-r--r--argv.go6
-rw-r--r--event.go9
-rw-r--r--http.go21
-rw-r--r--main.go30
-rw-r--r--poll.go57
-rw-r--r--structs.go39
-rw-r--r--watchdog.go64
8 files changed, 201 insertions, 28 deletions
diff --git a/README b/README
index c006767..4810076 100644
--- a/README
+++ b/README
@@ -16,8 +16,9 @@ Notes & Goals:
* Be super easy to use.
* Automatically map access to serial and graphical consoles
+* This is intended for managing Virtual Machines, not for containers
* This often uses the DO nomenclature 'droplets' instead of 'virtual machines' or 'domU'
-* When possible, use protobuf over the wire
+* When possible, use protobuf
* Let security be handled externally at the socket layer with other tools
* Put network, cpu, etc stats in external tools
* Automatic live migration to decommission nodes
diff --git a/argv.go b/argv.go
index 7221523..4bed667 100644
--- a/argv.go
+++ b/argv.go
@@ -9,9 +9,9 @@ package main
var argv args
type args struct {
- Hosts []string `arg:"--hosts" help:"hosts to connect to"`
- Uptime bool `arg:"--uptime" default:"true" help:"allow uptime checks for things like Kuma"`
- Port int `arg:"--port" default:"8080" help:"specify a different default port"`
+ Hosts []string `arg:"--hosts" help:"hosts to connect to"`
+ Uptime bool `arg:"--uptime" default:"true" help:"allow uptime checks for things like Kuma"`
+ Port int `arg:"--port" default:"8080" help:"specify a different default port"`
}
func (a args) Description() string {
diff --git a/event.go b/event.go
new file mode 100644
index 0000000..5a31eb1
--- /dev/null
+++ b/event.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+ "go.wit.com/log"
+)
+
+func (d *DropletT) Start() {
+ log.Info("a new virtual machine is running")
+}
diff --git a/http.go b/http.go
index 6c5e397..2188ed5 100644
--- a/http.go
+++ b/http.go
@@ -5,7 +5,6 @@ import (
"net/http"
"strings"
- "go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
@@ -30,24 +29,8 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
}
if tmp == "/vms" {
- for _, hostname := range argv.Hosts {
- url := "http://" + hostname + ":2520/vms"
- log.Info("wget url =", url)
- s := shell.Wget(url)
- if s == nil {
- continue;
- }
- var bytesSplice []byte
- bytesSplice = s.Bytes()
- // fmt.Fprintln(w, string(bytesSplice))
- for _, line := range strings.Split(string(bytesSplice), "\n") {
- if line == "" {
- continue
- }
- fmt.Fprintln(w, hostname, line)
- log.Info("LINE: =", hostname, line)
- }
- // log.Info("i, s =", hostname, i, s)
+ for _, d := range me.droplets {
+ fmt.Fprintln(w, d.Hostname, d.hname, d.lastpoll)
}
return
}
diff --git a/main.go b/main.go
index bf56a04..2ba5dda 100644
--- a/main.go
+++ b/main.go
@@ -3,9 +3,9 @@
package main
import (
- // "log"
"embed"
"os"
+ "time"
"go.wit.com/dev/alexflint/arg"
"go.wit.com/log"
@@ -19,15 +19,35 @@ var resources embed.FS
func main() {
pp := arg.MustParse(&argv)
- if ! argv.Uptime {
+ if !argv.Uptime {
pp.WriteHelp(os.Stdout)
os.Exit(0)
}
log.Info("connect to cluser here", argv.Hosts)
- for i, s := range argv.Hosts {
- log.Info("i, s =", i, s)
+ for _, s := range argv.Hosts {
+ me.names = append(me.names, s)
+
+ log.Info("Make a hypervisor struct for", s)
+ var h HyperT
+ h.Hostname = s
+ h.Autoscan = true
+ h.Delay = 3 * time.Second
+ h.Scan = func() {
+ log.Info("scanned farm03?")
+ h.pollHypervisor()
+ }
+ me.hypers = append(me.hypers, h)
+ }
+ go startHTTP()
+
+ log.Info("me.names =", me.names)
+ for _, h := range me.hypers {
+ log.Info("me hostname =", h.Hostname)
+ if h.Hostname == "farm03" {
+ log.Info("should start watchdog here for hostname =", h.Hostname)
+ h.NewWatchdog()
+ }
}
- startHTTP()
}
diff --git a/poll.go b/poll.go
new file mode 100644
index 0000000..b7daeb9
--- /dev/null
+++ b/poll.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "strings"
+ "time"
+
+ "go.wit.com/lib/gui/shell"
+ "go.wit.com/log"
+)
+
+func (h HyperT) pollHypervisor() {
+ url := "http://" + h.Hostname + ":2520/vms"
+ log.Info("wget url =", url)
+ s := shell.Wget(url)
+ if s == nil {
+ return
+ }
+ var bytesSplice []byte
+ bytesSplice = s.Bytes()
+ // fmt.Fprintln(w, string(bytesSplice))
+ for _, line := range strings.Split(string(bytesSplice), "\n") {
+ if line == "" {
+ continue
+ }
+ fields := strings.Fields(line)
+ if len(fields) < 2 {
+ continue
+ }
+ state := fields[0]
+ name := fields[1]
+ if state == "ON" {
+ log.Info("POLL", h.Hostname, "STATE:", state, "HOST:", name, "rest:", fields[2:])
+ var found = false
+ for _, d := range me.droplets {
+ if d.Hostname == name {
+ log.Info("ALREADY RECORDED", d.Hostname)
+ found = true
+ d.lastpoll = time.Now()
+ if d.hname != h.Hostname {
+ log.Info("DROPLET", d.Hostname, "MOVED FROM", d.hname, "TO", d.Hostname)
+ }
+
+ d.hname = h.Hostname
+ }
+ }
+ if found {
+ continue
+ }
+ var d DropletT
+ d.Hostname = name
+ d.hname = h.Hostname
+ me.droplets = append(me.droplets, d)
+ log.Info(name, "IS NEW. ADDED ON", h.Hostname)
+ }
+ }
+ // log.Info("i, s =", hostname, i, s)
+}
diff --git a/structs.go b/structs.go
new file mode 100644
index 0000000..7a0f0ee
--- /dev/null
+++ b/structs.go
@@ -0,0 +1,39 @@
+package main
+
+import "time"
+
+var me virtigoT
+
+// disable the GUI
+func (b *virtigoT) Disable() {
+ // b.mainbox.Disable()
+}
+
+// enable the GUI
+func (b *virtigoT) Enable() {
+ // b.mainbox.Enable()
+}
+
+// this app's variables
+type virtigoT struct {
+ names []string
+ hypers []HyperT
+ droplets []DropletT
+}
+
+// the stuff that is needed for a hypervisor
+type HyperT struct {
+ Hostname string // the hypervisor hostname
+ Scan func() // the function to run to scan the hypervisor
+ Autoscan bool // to scan or not to scan
+ Delay time.Duration // how often to poll the hypervisor
+ Dog *time.Ticker // the watchdog timer itself
+}
+
+// the stuff that is needed for a hypervisor
+type DropletT struct {
+ Hostname string // the name of the virtual machine. should be unique (probably enforce this forever)
+ hname string // the hypervisor it's currently running on
+ h *HyperT // the hypervisor it's currently running on
+ lastpoll time.Time // the last time the droplet was seen running
+}
diff --git a/watchdog.go b/watchdog.go
new file mode 100644
index 0000000..155c79d
--- /dev/null
+++ b/watchdog.go
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "go.wit.com/log"
+)
+
+// scan hypervisors every i seconds
+func (h *HyperT) NewWatchdog() {
+ var delay int = 99
+ var i int = delay
+ h.MyTicker(h.Delay, "new Watchdog() "+h.Hostname, func() {
+ i += 1
+ // check if the env var is set to autoscan
+ if os.Getenv("WATCHDOG_AUTO_SCAN") != "true" {
+ if i < delay {
+ i = delay
+ }
+ // print every 'delay' seconds
+ if i%delay == 0 {
+ log.Info("Not auto scanning", i, "WATCHDOG_AUTO_SCAN =", os.Getenv("WATCHDOG_AUTO_SCAN"))
+ }
+ return
+ }
+ if i < delay {
+ return
+ }
+ i = 0
+ })
+}
+
+// timeFunction takes a function as an argument and returns the execution time.
+func TimeFunction(f func()) time.Duration {
+ startTime := time.Now() // Record the start time
+ f() // Execute the function
+ return time.Since(startTime) // Calculate the elapsed time
+}
+
+func (h *HyperT) MyTicker(t time.Duration, name string, f func()) {
+ h.Dog = time.NewTicker(t)
+ defer h.Dog.Stop()
+ done := make(chan bool)
+ /*
+ // this example would exit/destroy the ticker in 10 seconds
+ go func() {
+ time.Sleep(10 * time.Second)
+ done <- true
+ }()
+ */
+ for {
+ select {
+ case <-done:
+ fmt.Println("Done!")
+ return
+ case t := <-h.Dog.C:
+ log.Info(name, "Current time: ", t)
+ h.Scan()
+ // f()
+ }
+ }
+}