summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--argv.go26
-rw-r--r--doAdminGui.go106
-rw-r--r--doGui.go11
-rw-r--r--main.go34
-rw-r--r--structs.go8
-rw-r--r--windowDroplets.go2
6 files changed, 125 insertions, 62 deletions
diff --git a/argv.go b/argv.go
index 70adb00..b3cab5c 100644
--- a/argv.go
+++ b/argv.go
@@ -16,36 +16,16 @@ type args struct {
Port int `arg:"--port" default:"8080" help:"allow droplet events via http"`
Server string `arg:"env:VIRTIGO_SERVER" help:"what virtigo cluster to connect to"`
Xml []string `arg:"--libvirt" help:"import qemu xml files: --libvirt /etc/libvirt/qemu/*.xml"`
+ Admin bool `arg:"--admin" help:"enter admin mode"`
}
-// Daemon bool `arg:"--daemon" help:"run in daemon mode"`
-// IgnoreCpu bool `arg:"--xml-ignore-cpu" default:"true" help:"ignore non-standard libvirt xml cpus"`
-// IgnoreBr bool `arg:"--xml-ignore-net" default:"true" help:"ignore network bridge name changes"`
-// IgnDisk bool `arg:"--xml-ignore-disk" default:"false" help:"ignore duplicate disk names"`
-
-// Save bool `arg:"--save" default:"false" help:"save protobuf config after import"`
-// Start string `arg:"--start" help:"start a droplet"`
-// Uptime bool `arg:"--uptime" default:"true" help:"allow uptime checks for things like Kuma"`
-// Hosts []string `arg:"--hosts" help:"hosts to connect to"`
-
func (a args) Description() string {
return `
- virtigo will help control your cluster
+ virtigo: control your cluster
This maintains a master list of all your vm's (aka 'droplets')
in your homelab cloud. You can import libvirt xml files.
This app talks to your hypervisors via the virtigod daemon.
-
-At this time, this _only_ supports qcow2 images. If you need
-something else you'll have to add it in virtigolib.
-
-This runs a http server so you can control your virtual machines.
-For example to start a vm called 'www.wit.com' your cluster 'foo.bar.com':
-
- curl http://virtigo.foo.com/start?www.wit.com
-
-Use 'virtigoctl' to import xml files from libvirt and configure new
-hypervisors in your cluster.
`
}
@@ -56,7 +36,6 @@ func (args) Version() string {
var INFO *log.LogFlag
var POLL *log.LogFlag
var WARN *log.LogFlag
-var SPEW *log.LogFlag
var EVENT *log.LogFlag
func init() {
@@ -66,6 +45,5 @@ func init() {
INFO = log.NewFlag("INFO", false, full, short, "general virtigo")
POLL = log.NewFlag("POLL", false, full, short, "virtigo polling")
WARN = log.NewFlag("WARN", true, full, short, "bad things")
- SPEW = log.NewFlag("SPEW", true, full, short, "dump everything")
EVENT = log.NewFlag("EVENT", true, full, short, "hypeprvisor/droplet events")
}
diff --git a/doAdminGui.go b/doAdminGui.go
index e7cdf48..11d02f0 100644
--- a/doAdminGui.go
+++ b/doAdminGui.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
+ "net/url"
"os"
"os/user"
"time"
@@ -26,11 +27,15 @@ func (admin *adminT) refresh() {
log.Info("virtigo scan here")
}
- url := argv.Server
+ if admin.url == nil {
+ log.Info("admin url == nil")
+ return
+ }
+
msg := []byte(`{"message": "Hello"}`)
// display the uptime
- if data, err := postData(url+"/uptime", msg); err != nil {
+ if data, err := postData(admin.url.String()+"/uptime", msg); err != nil {
log.Info("/uptime Error:", err)
} else {
log.Info("Response:", string(data))
@@ -38,7 +43,7 @@ func (admin *adminT) refresh() {
}
// update the droplet list
- if data, err := postData(url+"/DropletsPB", msg); err != nil {
+ if data, err := postData(admin.url.String()+"/DropletsPB", msg); err != nil {
log.Info("/DropletsPB Error:", err)
} else {
fmt.Println("DropletsPB Response len:", len(data))
@@ -51,7 +56,7 @@ func (admin *adminT) refresh() {
}
// update the hypervisor list
- if data, err := postData(url+"/HypervisorsPB", msg); err != nil {
+ if data, err := postData(admin.url.String()+"/HypervisorsPB", msg); err != nil {
log.Info("Error:", err)
} else {
fmt.Println("HypervisorsPB Response len:", len(data))
@@ -64,7 +69,7 @@ func (admin *adminT) refresh() {
}
// update the events list
- if data, err := postData(url+"/EventsPB", msg); err != nil {
+ if data, err := postData(admin.url.String()+"/EventsPB", msg); err != nil {
log.Info("Error:", err)
} else {
fmt.Println("EventsPB Response len:", len(data))
@@ -92,11 +97,12 @@ func (admin *adminT) doAdminGui() {
Timeout: 10 * time.Second, // Set a reasonable timeout
}
- win := gadgets.NewGenericWindow("Virtigo: (run your cluster)", "virtigo stuff")
+ win := gadgets.NewGenericWindow("Virtigo: (run your cluster)", "localhost")
win.Custom = func() {
log.Warn("Main window close")
os.Exit(0)
}
+ me.gwin = win
admin.uptime = win.Group.NewLabel("uptime")
@@ -161,6 +167,14 @@ func (admin *adminT) doAdminGui() {
// okExit("admin close")
})
+ me.cmap = make(map[*virtpb.Cluster]*adminT)
+ for c := range me.clusters.IterAll() {
+ a := new(adminT)
+ me.cmap[c] = a
+ log.Info("found in the config file", c.URL)
+ a.makeClusterGroup(c)
+ }
+
// sit here forever refreshing the GUI
for {
admin.refresh()
@@ -168,6 +182,67 @@ func (admin *adminT) doAdminGui() {
}
}
+func (admin *adminT) makeClusterGroup(c *virtpb.Cluster) {
+ var err error
+ admin.url, err = url.Parse(c.URL)
+ if err != nil {
+ badExit(err)
+ }
+
+ group := me.gwin.Bottom.NewGroup(admin.url.Hostname())
+ admin.uptime = group.NewLabel("uptime")
+
+ grid := group.RawGrid()
+
+ grid.NewButton("show hypervisors", func() {
+ if admin.hypervisors == nil {
+ log.Info("hypervisors not initialized")
+ return
+ }
+ log.Info("Hypervisors len=", admin.hypervisors.Len())
+ admin.hwin = newHypervisorsWindow()
+ admin.hwin.doStdHypervisors(admin.hypervisors)
+ admin.hwin.win.Custom = func() {
+ log.Info("hiding table window")
+ }
+ })
+
+ grid.NewButton("droplets", func() {
+ if admin.droplets == nil {
+ log.Info("droplets not initialized")
+ return
+ }
+ admin.dwin = newDropletsWindow()
+ admin.dwin.win.Custom = func() {
+ log.Info("hiding droplet table window")
+ }
+ var found *virtpb.Droplets
+ found = virtpb.NewDroplets()
+ all := admin.droplets.All()
+ for all.Scan() {
+ vm := all.Next()
+ if vm.Current.State != virtpb.DropletState_ON {
+ continue
+ }
+ found.Append(vm)
+ }
+ admin.dwin.doActiveDroplets(found)
+ })
+
+ grid.NewButton("events", func() {
+ if admin.events == nil {
+ log.Info("events are not initialized")
+ return
+ }
+ log.Info("Events len=", admin.events.Len())
+ admin.ewin = newEventsWindow()
+ admin.ewin.doStdEvents(admin.events)
+ admin.ewin.win.Custom = func() {
+ log.Info("hiding table window")
+ }
+ })
+}
+
func postData(url string, data []byte) ([]byte, error) {
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data))
if err != nil {
@@ -191,22 +266,3 @@ func postData(url string, data []byte) ([]byte, error) {
return body, nil
}
-
-/*
-func main() {
- url := "http://example.com/endpoint"
- data := []byte(`{"message": "Hello"}`)
-
- ticker := time.NewTicker(1 * time.Minute)
- defer ticker.Stop()
-
- for range ticker.C {
- response, err := postData(url, data)
- if err != nil {
- fmt.Println("Error:", err)
- } else {
- fmt.Println("Response:", string(response))
- }
- }
-}
-*/
diff --git a/doGui.go b/doGui.go
index 3e6b2ba..13bba73 100644
--- a/doGui.go
+++ b/doGui.go
@@ -45,17 +45,6 @@ func doGui() {
func drawWindow(win *gadgets.GenericWindow) {
grid := win.Group.RawGrid()
- /*
- var hyperWin *gadgets.GenericWindow
- grid.NewButton("hypervisors", func() {
- if hyperWin != nil {
- hyperWin.Toggle()
- return
- }
- hyperWin = makeHypervisorsWindow(me.cluster.H)
- })
- */
-
var newHyperWin *stdHypervisorTableWin
grid.NewButton("show hypervisors", func() {
if newHyperWin != nil {
diff --git a/main.go b/main.go
index e34750b..b6403fc 100644
--- a/main.go
+++ b/main.go
@@ -5,10 +5,12 @@ 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"
@@ -37,11 +39,43 @@ func main() {
os.Setenv("VIRTIGO_HOME", fullpath)
}
+ me.clusters = virtpb.NewClusters()
+
+ if argv.Admin {
+ err := me.clusters.ConfigLoad()
+ if err != nil {
+ badExit(err)
+ }
+
+ me.admin = new(adminT)
+ me.admin.doAdminGui()
+ okExit("admin close")
+ }
+
if argv.Server != "" {
+ log.Info("start admin interface")
me.admin = new(adminT)
+ var err error
+ me.admin.url, err = url.Parse(argv.Server)
+ if err != nil {
+ badExit(err)
+ }
+ err = me.clusters.ConfigLoad()
+ if err != nil {
+ clusters := virtpb.NewClusters()
+ c := new(virtpb.Cluster)
+ c.Uuid = uuid.New().String()
+ c.URL = argv.Server
+ clusters.Append(c)
+ virtpb.ConfigWriteTEXT(clusters, "cluster.text")
+
+ badExit(err)
+ }
+
me.admin.doAdminGui()
okExit("admin close")
}
+ os.Exit(-1)
// set defaults
me.unstable = time.Now() // initialize the grid as unstable
diff --git a/structs.go b/structs.go
index e5cb9c0..c7010f9 100644
--- a/structs.go
+++ b/structs.go
@@ -1,9 +1,11 @@
package main
import (
+ "net/url"
"time"
"go.wit.com/gui"
+ "go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/virtpb"
)
@@ -21,7 +23,7 @@ func (b *virtigoT) Enable() {
// this app's variables
type virtigoT struct {
- cluster *virtpb.Cluster // basic cluster settings
+ cluster *virtpb.OldCluster // basic cluster settings
myGui *gui.Node // the gui toolkit handle
e *virtpb.Events // virt protobuf events
hmap map[*virtpb.Hypervisor]*HyperT // map to the local struct
@@ -37,6 +39,9 @@ type virtigoT struct {
status *gui.Node // the cluster status
lastuptime *gui.Node // the last time uptime was checked by Kuma
admin *adminT // the admin struct
+ clusters *virtpb.Clusters // clusters protobuf
+ cmap map[*virtpb.Cluster]*adminT // map to local GUI objects and the protobuf
+ gwin *gadgets.GenericWindow // main window
}
type adminT struct {
@@ -48,6 +53,7 @@ type adminT struct {
dwin *stdDropletTableWin // the droplet window
hwin *stdHypervisorTableWin // the hypervisor window
ewin *stdEventTableWin // the events window
+ url *url.URL // URL for the cloud
}
// the stuff that is needed for a hypervisor
diff --git a/windowDroplets.go b/windowDroplets.go
index 09c2d18..2c7aa81 100644
--- a/windowDroplets.go
+++ b/windowDroplets.go
@@ -161,7 +161,7 @@ func (dw *stdDropletTableWin) doInactiveDroplets(pb *virtpb.Droplets) {
return d.Current.Hypervisor
})
*/
- vp := t.AddButtonFunc("Configure Hostname", func(p *virtpb.Droplet) string {
+ vp := t.AddButtonFunc("Verify Config", func(p *virtpb.Droplet) string {
return p.Hostname
})
vp.Custom = func(d *virtpb.Droplet) {