415 lines
9.7 KiB
Go
415 lines
9.7 KiB
Go
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
|
|
// Use of this source code is governed by the GPL 3.0
|
|
|
|
package main
|
|
|
|
// An app to submit patches for the 30 GO GUI repos
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"os/user"
|
|
"time"
|
|
|
|
"go.wit.com/gui"
|
|
"go.wit.com/lib/gadgets"
|
|
"go.wit.com/lib/protobuf/virtpb"
|
|
"go.wit.com/log"
|
|
)
|
|
|
|
// refresh the windows & tables the user has open
|
|
func (admin *adminT) refresh() {
|
|
if argv.Verbose {
|
|
log.Info("virtigo scan here")
|
|
}
|
|
|
|
if admin.url == nil {
|
|
log.Info("admin url == nil")
|
|
return
|
|
}
|
|
|
|
msg := []byte(`{"message": "Hello"}`)
|
|
|
|
// display the uptime
|
|
if data, err := postData(admin.url.String()+"/uptime", msg); err != nil {
|
|
log.Info("/uptime Error:", err)
|
|
} else {
|
|
log.Info("Response:", string(data))
|
|
admin.uptime.SetText(string(data))
|
|
}
|
|
|
|
// update the droplet list
|
|
if data, err := postData(admin.url.String()+"/DropletsPB", msg); err != nil {
|
|
log.Info("/DropletsPB Error:", err)
|
|
} else {
|
|
fmt.Println("DropletsPB Response len:", len(data))
|
|
admin.cluster.Droplets = new(virtpb.Droplets)
|
|
if err := admin.cluster.Droplets.Unmarshal(data); err != nil {
|
|
fmt.Println("droplets marshal failed", err)
|
|
return
|
|
}
|
|
fmt.Println("Droplet len=", admin.cluster.Droplets.Len())
|
|
}
|
|
|
|
// update the hypervisor list
|
|
if data, err := postData(admin.url.String()+"/HypervisorsPB", msg); err != nil {
|
|
log.Info("Error:", err)
|
|
} else {
|
|
fmt.Println("HypervisorsPB Response len:", len(data))
|
|
admin.cluster.Hypervisors = new(virtpb.Hypervisors)
|
|
if err := admin.cluster.Hypervisors.Unmarshal(data); err != nil {
|
|
fmt.Println("hypervisors marshal failed", err)
|
|
return
|
|
}
|
|
fmt.Println("Hypervisors len=", admin.cluster.Hypervisors.Len())
|
|
}
|
|
|
|
// update the events list
|
|
if data, err := postData(admin.url.String()+"/EventsPB", msg); err != nil {
|
|
log.Info("Error:", err)
|
|
} else {
|
|
fmt.Println("EventsPB Response len:", len(data))
|
|
admin.cluster.Events = new(virtpb.Events)
|
|
if err := admin.cluster.Events.Unmarshal(data); err != nil {
|
|
fmt.Println("events marshal failed", err)
|
|
return
|
|
}
|
|
fmt.Println("Events len=", admin.cluster.Events.Len())
|
|
}
|
|
}
|
|
|
|
var client *http.Client
|
|
|
|
func doLocalhostAdminGui() *adminT {
|
|
admin := new(adminT)
|
|
|
|
admin.uptime = me.gwin.Group.NewLabel("uptime")
|
|
|
|
grid := me.gwin.Group.RawGrid()
|
|
|
|
grid.NewButton("show hypervisors", func() {
|
|
if admin.cluster.Hypervisors == nil {
|
|
log.Info("hypervisors not initialized")
|
|
return
|
|
}
|
|
log.Info("Hypervisors len=", admin.cluster.Hypervisors.Len())
|
|
admin.hwin = newHypervisorsWindow()
|
|
admin.hwin.doStdHypervisors(admin.cluster.Hypervisors)
|
|
admin.hwin.win.Custom = func() {
|
|
log.Info("hiding table window")
|
|
}
|
|
})
|
|
|
|
grid.NewButton("droplets", func() {
|
|
if admin.cluster.Droplets == nil {
|
|
log.Info("droplets not initialized")
|
|
return
|
|
}
|
|
admin.dwin = newDropletsWindow(admin)
|
|
admin.dwin.win.Custom = func() {
|
|
log.Info("hiding droplet table window")
|
|
}
|
|
var found *virtpb.Droplets
|
|
found = virtpb.NewDroplets()
|
|
all := admin.cluster.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.cluster.Events == nil {
|
|
log.Info("events are not initialized")
|
|
return
|
|
}
|
|
log.Info("Events len=", admin.cluster.Events.Len())
|
|
admin.ewin = newEventsWindow()
|
|
admin.ewin.doStdEvents(admin.cluster.Events)
|
|
admin.ewin.win.Custom = func() {
|
|
log.Info("hiding table window")
|
|
}
|
|
})
|
|
|
|
grid.NextRow()
|
|
|
|
grid.NewButton("refresh", func() {
|
|
admin.refresh()
|
|
})
|
|
|
|
return admin
|
|
}
|
|
|
|
func doAdminGui() {
|
|
me.myGui = gui.New()
|
|
me.myGui.InitEmbed(resources)
|
|
me.myGui.Default()
|
|
|
|
// Initialize a persistent client with a custom Transport
|
|
client = &http.Client{
|
|
Transport: &http.Transport{
|
|
DisableKeepAlives: false, // Ensure Keep-Alive is enabled
|
|
},
|
|
Timeout: 10 * time.Second, // Set a reasonable timeout
|
|
}
|
|
|
|
me.gwin = gadgets.NewGenericWindow("Virtigo: (run your cluster)", "")
|
|
me.gwin.Custom = func() {
|
|
log.Warn("Main window close")
|
|
os.Exit(0)
|
|
}
|
|
|
|
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[0])
|
|
a.makeClusterGroup(c)
|
|
}
|
|
|
|
// sit here forever refreshing the GUI
|
|
for {
|
|
// admin.refresh()
|
|
log.Info("todo: refresh() protobufs here")
|
|
time.Sleep(90 * time.Second)
|
|
}
|
|
}
|
|
|
|
func (admin *adminT) doAdminGui() {
|
|
me.myGui = gui.New()
|
|
me.myGui.InitEmbed(resources)
|
|
me.myGui.Default()
|
|
|
|
// Initialize a persistent client with a custom Transport
|
|
client = &http.Client{
|
|
Transport: &http.Transport{
|
|
DisableKeepAlives: false, // Ensure Keep-Alive is enabled
|
|
},
|
|
Timeout: 10 * time.Second, // Set a reasonable timeout
|
|
}
|
|
|
|
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")
|
|
|
|
grid := win.Group.RawGrid()
|
|
|
|
grid.NewButton("show hypervisors", func() {
|
|
if admin.cluster.Hypervisors == nil {
|
|
log.Info("hypervisors not initialized")
|
|
return
|
|
}
|
|
log.Info("Hypervisors len=", admin.cluster.Hypervisors.Len())
|
|
admin.hwin = newHypervisorsWindow()
|
|
admin.hwin.doStdHypervisors(admin.cluster.Hypervisors)
|
|
admin.hwin.win.Custom = func() {
|
|
log.Info("hiding table window")
|
|
}
|
|
})
|
|
|
|
grid.NewButton("droplets", func() {
|
|
if admin.cluster.Droplets == nil {
|
|
log.Info("droplets not initialized")
|
|
return
|
|
}
|
|
admin.dwin = newDropletsWindow(admin)
|
|
admin.dwin.win.Custom = func() {
|
|
log.Info("hiding droplet table window")
|
|
}
|
|
var found *virtpb.Droplets
|
|
found = virtpb.NewDroplets()
|
|
all := admin.cluster.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.cluster.Events == nil {
|
|
log.Info("events are not initialized")
|
|
return
|
|
}
|
|
log.Info("Events len=", admin.cluster.Events.Len())
|
|
admin.ewin = newEventsWindow()
|
|
admin.ewin.doStdEvents(admin.cluster.Events)
|
|
admin.ewin.win.Custom = func() {
|
|
log.Info("hiding table window")
|
|
}
|
|
})
|
|
|
|
grid.NextRow()
|
|
|
|
grid.NewButton("refresh", func() {
|
|
admin.refresh()
|
|
})
|
|
|
|
grid.NewButton("test gui close", func() {
|
|
me.myGui.Close()
|
|
// 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[0])
|
|
a.makeClusterGroup(c)
|
|
}
|
|
|
|
// sit here forever refreshing the GUI
|
|
for {
|
|
admin.refresh()
|
|
time.Sleep(90 * time.Second)
|
|
}
|
|
}
|
|
|
|
func (admin *adminT) makeClusterGroup(c *virtpb.Cluster) {
|
|
var err error
|
|
admin.url, err = url.Parse(c.URL[0])
|
|
if err != nil {
|
|
badExit(err)
|
|
}
|
|
|
|
if admin.cluster == nil {
|
|
admin.cluster = new(virtpb.Cluster)
|
|
admin.cluster.Name = c.Name
|
|
admin.cluster.Uuid = c.Uuid
|
|
}
|
|
|
|
name := c.GetName()
|
|
if name == "" {
|
|
name = admin.url.Hostname()
|
|
}
|
|
|
|
group := me.gwin.Bottom.NewGroup(name)
|
|
admin.uptime = group.NewLabel("uptime")
|
|
|
|
grid := group.RawGrid()
|
|
|
|
grid.NewButton("show hypervisors", func() {
|
|
if admin.cluster.Hypervisors == nil {
|
|
log.Info("hypervisors not initialized")
|
|
return
|
|
}
|
|
log.Info("Hypervisors len=", admin.cluster.Hypervisors.Len())
|
|
admin.hwin = newHypervisorsWindow()
|
|
admin.hwin.doStdHypervisors(admin.cluster.Hypervisors)
|
|
admin.hwin.win.Custom = func() {
|
|
log.Info("hiding table window")
|
|
}
|
|
})
|
|
|
|
grid.NewButton("droplets", func() {
|
|
if admin.cluster.Droplets == nil {
|
|
log.Info("droplets not initialized")
|
|
return
|
|
}
|
|
admin.dwin = newDropletsWindow(admin)
|
|
admin.dwin.win.Custom = func() {
|
|
log.Info("hiding droplet table window")
|
|
}
|
|
var found *virtpb.Droplets
|
|
found = virtpb.NewDroplets()
|
|
all := admin.cluster.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.cluster.Events == nil {
|
|
log.Info("events are not initialized")
|
|
return
|
|
}
|
|
log.Info("Events len=", admin.cluster.Events.Len())
|
|
admin.ewin = newEventsWindow()
|
|
admin.ewin.doStdEvents(admin.cluster.Events)
|
|
admin.ewin.win.Custom = func() {
|
|
log.Info("hiding table window")
|
|
}
|
|
})
|
|
|
|
grid.NewButton("refresh", func() {
|
|
admin.refresh()
|
|
})
|
|
|
|
grid.NewButton("save cluster.pb", func() {
|
|
admin.cluster.ConfigSave()
|
|
})
|
|
}
|
|
|
|
func postData(url string, data []byte) ([]byte, error) {
|
|
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
|
|
usr, _ := user.Current()
|
|
req.Header.Set("author", usr.Username)
|
|
req.Header.Set("Connection", "keep-alive") // Ensure keep-alive is used
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read response: %w", err)
|
|
}
|
|
|
|
return body, nil
|
|
}
|
|
|
|
func (admin *adminT) postEvent(e *virtpb.Event) error {
|
|
var result *virtpb.Event
|
|
result = new(virtpb.Event)
|
|
|
|
msg, err := e.Marshal()
|
|
if err != nil {
|
|
log.Info("postEvent() marshal() failed", err, e)
|
|
return err
|
|
}
|
|
|
|
// update the droplet list
|
|
if data, err := postData(admin.url.String()+"/event", msg); err != nil {
|
|
log.Info("postEvent() /event Error:", err)
|
|
return err
|
|
} else {
|
|
if err := result.Unmarshal(data); err != nil {
|
|
log.Println("postEvent() result marshal failed", err, "len(dat) =", len(data))
|
|
log.Println("postEvent() data =", string(data))
|
|
return err
|
|
}
|
|
}
|
|
if result.Error != "" {
|
|
return fmt.Errorf(result.Error)
|
|
}
|
|
log.Printf("Event worked: %s\n", result.DropletUuid)
|
|
return nil
|
|
}
|