2019-02-01 07:28:17 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import "log"
|
2019-05-24 02:04:37 -05:00
|
|
|
import "fmt"
|
2019-05-06 20:57:59 -05:00
|
|
|
import "os"
|
2019-05-06 19:42:59 -05:00
|
|
|
import "time"
|
2019-05-23 13:33:30 -05:00
|
|
|
import "os/user"
|
2019-05-23 18:38:51 -05:00
|
|
|
import "runtime"
|
|
|
|
import "runtime/debug"
|
2019-02-01 07:28:17 -06:00
|
|
|
|
|
|
|
import "github.com/gookit/config"
|
2019-05-23 11:47:48 -05:00
|
|
|
import "github.com/gobuffalo/packr"
|
2019-02-01 07:28:17 -06:00
|
|
|
|
2019-05-24 03:17:37 -05:00
|
|
|
// will try to get this hosts FQDN
|
|
|
|
import "github.com/Showmax/go-fqdn"
|
|
|
|
|
2019-05-23 21:36:20 -05:00
|
|
|
// import "github.com/golang/protobuf/proto"
|
|
|
|
import pb "git.wit.com/wit/witProtobuf"
|
|
|
|
|
2019-05-13 01:02:10 -05:00
|
|
|
import "git.wit.com/wit/gui"
|
2019-05-08 15:09:44 -05:00
|
|
|
|
2019-05-23 02:11:49 -05:00
|
|
|
var GITCOMMIT string // this is passed in as an ldflag
|
|
|
|
var GOVERSION string // this is passed in as an ldflag
|
2019-05-24 02:21:15 -05:00
|
|
|
var BUILDTIME string // this is passed in as an ldflag
|
2019-05-23 02:11:49 -05:00
|
|
|
|
2019-05-07 07:02:39 -05:00
|
|
|
// import "github.com/davecgh/go-spew/spew"
|
2019-02-01 07:28:17 -06:00
|
|
|
|
|
|
|
// reminder to use this for JSON
|
|
|
|
// https://github.com/tidwall/gjson
|
|
|
|
// value := gjson.Get(json, "name.last")
|
|
|
|
// println(value.String())
|
|
|
|
// value := gjson.Get(json, friends.#[last=="Murphy"].first)
|
|
|
|
|
|
|
|
// use mergo to merge structs
|
|
|
|
// import "github.com/imdario/mergo"
|
|
|
|
// mergo.Merge(&dest, src)
|
|
|
|
|
|
|
|
// always sorted slice (new project)
|
|
|
|
// https://github.com/yaa110/sslice
|
|
|
|
|
2019-05-12 08:18:06 -05:00
|
|
|
// several smart slice functions (new project. April 2019)
|
|
|
|
// https://github.com/elliotchance/pie
|
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
func onExit(err error) {
|
2019-05-12 01:21:57 -05:00
|
|
|
log.Println("Sleep for 1 second")
|
|
|
|
time.Sleep(1 * 1000 * 1000 * 1000)
|
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
filename := config.String("configfile")
|
2019-05-23 15:14:57 -05:00
|
|
|
if (filename == "") {
|
|
|
|
log.Println("NOT SAVING CONFIG FILE")
|
|
|
|
} else {
|
|
|
|
log.Println("SAVING CONFIG FILE AS:", filename)
|
|
|
|
f, err := os.Create(filename + ".yaml")
|
|
|
|
if err == nil {
|
|
|
|
config.DumpTo(f, "yaml")
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err = os.Create(filename)
|
|
|
|
if err == nil {
|
|
|
|
config.DumpTo(f, "json")
|
|
|
|
}
|
2019-05-12 01:21:57 -05:00
|
|
|
}
|
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
if (err != nil) {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2019-05-12 01:21:57 -05:00
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2019-05-24 13:32:26 -05:00
|
|
|
var packrBox packr.Box
|
|
|
|
|
2019-05-10 03:21:32 -05:00
|
|
|
func main() {
|
2019-05-23 11:47:48 -05:00
|
|
|
// This puts all the files in that directory in the binary
|
|
|
|
// This directory includes the default config file if there is not already one
|
2019-05-24 13:32:26 -05:00
|
|
|
packrBox = packr.NewBox("./resources")
|
|
|
|
defaultConfig, _ := packrBox.FindString("cloud.json")
|
2019-05-23 11:47:48 -05:00
|
|
|
|
|
|
|
// This will parse the command line and config file
|
|
|
|
parseConfig(defaultConfig)
|
2019-05-08 17:29:06 -05:00
|
|
|
|
2019-05-10 03:21:32 -05:00
|
|
|
// only test the socket code if no GUI
|
|
|
|
if (config.String("nogui") == "true") {
|
2019-05-12 20:36:31 -05:00
|
|
|
log.Println("Need to re-implement this")
|
2019-05-23 13:33:30 -05:00
|
|
|
onExit(nil)
|
2019-05-10 03:21:32 -05:00
|
|
|
}
|
2019-05-08 16:03:10 -05:00
|
|
|
|
2019-05-11 09:53:32 -05:00
|
|
|
initChannel()
|
|
|
|
go processEvents()
|
|
|
|
|
2019-05-12 08:18:06 -05:00
|
|
|
go gorillaDial("v000185.testing.com.customers.wprod.wit.com:9000")
|
2019-05-23 00:33:16 -05:00
|
|
|
go watchGUI()
|
2019-05-07 16:54:08 -05:00
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
user, err := user.Current()
|
|
|
|
if err != nil {
|
|
|
|
onExit(err)
|
|
|
|
}
|
|
|
|
|
2019-05-23 02:11:49 -05:00
|
|
|
gui.Data.Width = config.Int("width")
|
|
|
|
gui.Data.Height = config.Int("height")
|
2019-05-24 00:47:26 -05:00
|
|
|
|
|
|
|
// TODO: figure out the hostname the right way
|
2019-05-24 03:17:37 -05:00
|
|
|
hostname := fqdn.Get()
|
|
|
|
log.Println("fqdn.Get() = ", hostname)
|
|
|
|
gui.Data.Hostname = hostname
|
2019-05-24 00:47:26 -05:00
|
|
|
gui.Data.IPv6 = "2604:bbc0:3:3:0:10:0:1004"
|
|
|
|
|
2019-05-24 15:43:22 -05:00
|
|
|
gui.Data.Version = "v0.7"
|
2019-05-23 02:11:49 -05:00
|
|
|
gui.Data.GitCommit = GITCOMMIT
|
|
|
|
gui.Data.GoVersion = GOVERSION
|
2019-05-24 02:21:15 -05:00
|
|
|
gui.Data.Buildtime = BUILDTIME
|
2019-05-24 15:43:22 -05:00
|
|
|
gui.Data.MouseClick = mainButtonClick
|
2019-05-23 13:33:30 -05:00
|
|
|
gui.Data.HomeDir = user.HomeDir
|
2019-05-24 11:04:36 -05:00
|
|
|
|
|
|
|
// Set output debugging level
|
2019-05-23 15:14:57 -05:00
|
|
|
gui.Data.Debug = config.Bool("debugging")
|
2019-05-24 11:04:36 -05:00
|
|
|
gui.Data.DebugTable = config.Bool("debugtable")
|
2019-05-23 15:14:57 -05:00
|
|
|
log.Println("gui.Data.Debug = ", gui.Data.Debug)
|
2019-05-24 11:04:36 -05:00
|
|
|
log.Println("gui.Data.DebugTable = ", gui.Data.DebugTable)
|
2019-05-23 13:33:30 -05:00
|
|
|
|
|
|
|
// Current User
|
|
|
|
log.Println("Hi " + user.Name + " (id: " + user.Uid + ")")
|
|
|
|
log.Println("Username: " + user.Username)
|
|
|
|
log.Println("Home Dir: " + user.HomeDir)
|
|
|
|
|
|
|
|
// Get "Real" User under sudo.
|
|
|
|
// More Info: https://stackoverflow.com/q/29733575/402585
|
|
|
|
log.Println("Real User: " + os.Getenv("SUDO_USER"))
|
2019-05-23 00:33:16 -05:00
|
|
|
|
2019-05-10 03:21:32 -05:00
|
|
|
// make this the main loop in an attempt to figure out the crashes
|
|
|
|
// do not change this until the GUI is stable
|
2019-05-23 00:33:16 -05:00
|
|
|
gui.GoMainWindow()
|
|
|
|
}
|
2019-05-10 03:21:32 -05:00
|
|
|
|
2019-05-24 15:43:22 -05:00
|
|
|
func mainButtonClick(b *gui.ButtonMap) {
|
|
|
|
log.Println("mainButtonClick() b =", b)
|
2019-05-09 08:52:51 -05:00
|
|
|
|
2019-05-23 15:45:11 -05:00
|
|
|
if (b == nil) {
|
2019-05-24 15:43:22 -05:00
|
|
|
log.Println("main() BACK IN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?")
|
|
|
|
log.Println("main() BACK IN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?")
|
|
|
|
log.Println("main() BACK IN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?")
|
2019-05-23 15:45:11 -05:00
|
|
|
} else {
|
2019-05-24 15:43:22 -05:00
|
|
|
log.Println("main() BACK IN CONTROL PANEL CODE (button b.Name =", b.Name, ")")
|
2019-05-23 15:45:11 -05:00
|
|
|
log.Println("\tb.Name", b.Name)
|
|
|
|
log.Println("\tb.Note", b.Note)
|
2019-05-23 19:43:41 -05:00
|
|
|
log.Println("\tb.AccNick", b.AccNick)
|
2019-05-23 15:45:11 -05:00
|
|
|
if (b.Note == "BACK") {
|
|
|
|
gui.Data.State = "splash"
|
2019-05-23 13:33:30 -05:00
|
|
|
}
|
2019-05-23 15:45:11 -05:00
|
|
|
if (b.Note == "QUIT") {
|
|
|
|
onExit(nil)
|
|
|
|
}
|
2019-05-24 15:43:22 -05:00
|
|
|
if (b.Note == "CREATE") {
|
|
|
|
log.Println("TRY TO ADD A NEW VIRTUAL MACHINE")
|
|
|
|
log.Println("\tTRIGGER CREATE VM")
|
|
|
|
gui.Data.State = "CREATE"
|
|
|
|
// gui.Data.AccNick = b.AccNick
|
|
|
|
}
|
2019-05-24 13:32:26 -05:00
|
|
|
if (b.Note == "CONFIG") {
|
|
|
|
log.Println("TRY TO LOAD DEFAULT CONFIG")
|
|
|
|
defaultConfig, _ := packrBox.FindString("test.json")
|
|
|
|
config.LoadData(defaultConfig)
|
|
|
|
log.Println("defaultConfig =", defaultConfig)
|
|
|
|
for account, _ := range config.StringMap("accounts") {
|
|
|
|
log.Println("gui.State = splash BUT THERE IS AN ACCOUNT = ", account)
|
|
|
|
log.Println("gui.State = splash BUT THERE IS AN ACCOUNT = ", account)
|
|
|
|
log.Println("SETTING gui.State =", gui.Data.State)
|
|
|
|
}
|
|
|
|
gui.Data.State = "done"
|
|
|
|
}
|
2019-05-23 18:38:51 -05:00
|
|
|
if (b.Note == "DEBUG") {
|
|
|
|
log.Println("debug.PrintStack() (SHOULD BE JUST THIS goroutine)")
|
|
|
|
debug.PrintStack()
|
|
|
|
|
|
|
|
log.Println("ATTEMPT FULL STACK DUMP")
|
|
|
|
buf := make([]byte, 1<<16)
|
|
|
|
runtime.Stack(buf, true)
|
|
|
|
log.Printf("%s", buf)
|
|
|
|
log.Println("FINISHED FULL STACK DUMP")
|
|
|
|
}
|
2019-05-23 15:45:11 -05:00
|
|
|
if (b.Note == "ADD") {
|
|
|
|
log.Println("\tSHOULD ADD ACCOUNT HERE")
|
|
|
|
if (gui.Data.AccNick != "") {
|
|
|
|
log.Println("\tADDING ACCOUNT HERE")
|
|
|
|
log.Println("\tADDING ACCOUNT HERE")
|
|
|
|
log.Println("\tADDING ACCOUNT HERE")
|
|
|
|
log.Println("\tData.AccNick = ", gui.Data.AccNick)
|
|
|
|
log.Println("\tData.AccUser = ", gui.Data.AccUser)
|
|
|
|
log.Println("\tData.AccPass = ", gui.Data.AccPass)
|
|
|
|
config.Set("accounts." + gui.Data.AccNick + ".username", gui.Data.AccUser)
|
|
|
|
config.Set("accounts." + gui.Data.AccNick + ".password", gui.Data.AccPass)
|
|
|
|
config.Set("accounts." + gui.Data.AccNick + ".hostname", "v000185.testing.com.customers.wprod.wit.com")
|
|
|
|
}
|
|
|
|
}
|
2019-05-24 00:47:26 -05:00
|
|
|
if (b.Note == "LOGIN") {
|
|
|
|
log.Println("\tTRIGGER LOGIN ACCOUNT")
|
|
|
|
gui.Data.State = "SEND LOGIN"
|
|
|
|
gui.Data.AccNick = b.AccNick
|
|
|
|
count := 0
|
|
|
|
for {
|
|
|
|
log.Println("Sleep() in buttonClick() gui.Data.State =", gui.Data.State)
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
if (gui.Data.State == "NEW PROTOBUF") {
|
|
|
|
if (currentMessage == nil) {
|
|
|
|
gui.SocketError()
|
|
|
|
gui.Data.State = "done"
|
|
|
|
} else {
|
2019-05-24 02:04:37 -05:00
|
|
|
log.Println("LOGIN currentMessage =", currentMessage)
|
|
|
|
if (currentMessage.Type == pb.Event_OK) {
|
|
|
|
log.Println("LOGIN WAS OK!")
|
|
|
|
log.Println("LOGIN WAS OK!")
|
|
|
|
log.Println("LOGIN WAS OK!")
|
2019-05-24 02:21:15 -05:00
|
|
|
msg := "On account " + gui.Data.AccNick + "\n"
|
|
|
|
gui.ErrorWindow("Login OK", msg)
|
2019-05-24 02:04:37 -05:00
|
|
|
}
|
|
|
|
if (currentMessage.Type == pb.Event_FAIL) {
|
|
|
|
log.Println("LOGIN FAILED")
|
|
|
|
log.Println("LOGIN FAILED")
|
|
|
|
log.Println("LOGIN FAILED")
|
|
|
|
msg := "On account " + gui.Data.AccNick + "\n"
|
|
|
|
msg += "pb.Comment = " + currentMessage.Comment + "\n"
|
|
|
|
msg += "pb.Id = " + fmt.Sprintf("%d", currentMessage.Id) + "\n"
|
|
|
|
msg += "pb.Email = " + currentMessage.Email + "\n"
|
|
|
|
msg += "pb.Username = " + currentMessage.Username + "\n"
|
|
|
|
gui.ErrorWindow("Login Failed", msg)
|
2019-05-24 00:47:26 -05:00
|
|
|
}
|
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
count += 1
|
|
|
|
if (count > 10) {
|
|
|
|
log.Println("ERROR: waited too long for a resposne")
|
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-23 18:38:51 -05:00
|
|
|
if (b.Note == "SHOW") {
|
|
|
|
log.Println("\tTRIGGER DISPLAY ACCOUNT")
|
2019-05-23 21:36:20 -05:00
|
|
|
gui.Data.State = "SEND WEBSOCKET"
|
2019-05-23 19:43:41 -05:00
|
|
|
gui.Data.AccNick = b.AccNick
|
2019-05-23 21:36:20 -05:00
|
|
|
count := 0
|
2019-05-23 18:38:51 -05:00
|
|
|
for {
|
|
|
|
log.Println("Sleep() in buttonClick() gui.Data.State =", gui.Data.State)
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
if (gui.Data.State == "NEW PROTOBUF") {
|
|
|
|
if (currentMessage == nil) {
|
|
|
|
gui.SocketError()
|
2019-05-23 19:43:41 -05:00
|
|
|
gui.Data.State = "done"
|
2019-05-23 18:38:51 -05:00
|
|
|
} else {
|
|
|
|
count := countVMS(currentMessage)
|
|
|
|
log.Println("SHOW VMS currentMessage =", currentMessage)
|
|
|
|
log.Println("SHOW VMS count =", count)
|
|
|
|
if (count != 0) {
|
2019-05-23 19:43:41 -05:00
|
|
|
name := "Virtual Machines (" + b.AccNick + ")"
|
|
|
|
mh := gui.AddVmsTab(name, count)
|
2019-05-23 18:38:51 -05:00
|
|
|
ReadReceivedData(currentMessage, mh)
|
|
|
|
}
|
|
|
|
currentMessage = nil
|
2019-05-23 19:43:41 -05:00
|
|
|
gui.Data.State = "done"
|
2019-05-23 18:38:51 -05:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2019-05-23 21:36:20 -05:00
|
|
|
count += 1
|
|
|
|
if (count > 10) {
|
|
|
|
log.Println("ERROR: waited too long for a resposne")
|
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
return
|
|
|
|
}
|
2019-05-23 18:38:51 -05:00
|
|
|
}
|
|
|
|
}
|
2019-05-23 00:33:16 -05:00
|
|
|
}
|
|
|
|
if (gui.Data.State == "splash") {
|
|
|
|
gui.ShowAccountQuestionTab()
|
|
|
|
gui.Data.State = "account1"
|
|
|
|
return
|
|
|
|
} else if (gui.Data.State == "account1") {
|
|
|
|
gui.ShowAccountTab()
|
|
|
|
gui.Data.State = "main"
|
|
|
|
} else if (gui.Data.State == "main") {
|
|
|
|
gui.ShowMainTab()
|
|
|
|
gui.Data.State = "done"
|
2019-05-23 15:45:11 -05:00
|
|
|
} else if (gui.Data.State == "QUIT") {
|
|
|
|
onExit(nil)
|
2019-05-23 00:33:16 -05:00
|
|
|
}
|
|
|
|
}
|
2019-05-09 08:52:51 -05:00
|
|
|
|
2019-05-24 00:47:26 -05:00
|
|
|
// this watches the GUI primarily to process protobuf's
|
2019-05-23 00:33:16 -05:00
|
|
|
func watchGUI() {
|
2019-05-23 15:27:05 -05:00
|
|
|
count := 0
|
2019-05-23 00:33:16 -05:00
|
|
|
|
|
|
|
for {
|
2019-05-23 15:27:05 -05:00
|
|
|
if (count > 10) {
|
|
|
|
log.Println("Sleep() in watchGUI() gui.Data.State =", gui.Data.State)
|
|
|
|
count = 0
|
|
|
|
}
|
|
|
|
count += 1
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
2019-05-23 00:33:16 -05:00
|
|
|
|
2019-05-23 21:36:20 -05:00
|
|
|
if (gui.Data.State == "SEND WEBSOCKET") {
|
2019-05-23 18:38:51 -05:00
|
|
|
log.Println("\tTRIGGERING WEBSOCKET HERE on AccNick =", gui.Data.AccNick)
|
|
|
|
log.Println("\tTRIGGERING WEBSOCKET HERE on AccNick =", gui.Data.AccNick)
|
|
|
|
log.Println("\tTRIGGERING WEBSOCKET HERE on AccNick =", gui.Data.AccNick)
|
2019-05-23 21:36:20 -05:00
|
|
|
|
|
|
|
event := pb.MakeGetEvent()
|
|
|
|
event.Token = config.String("accounts." + gui.Data.AccNick + ".token")
|
|
|
|
log.Println("\tTRIGGERING WEBSOCKET HERE with event.Token =", event.Token)
|
|
|
|
|
2019-05-23 21:44:10 -05:00
|
|
|
gorillaSendProtobuf(event)
|
|
|
|
gui.Data.State = "READ PROTOBUF"
|
2019-05-23 18:38:51 -05:00
|
|
|
}
|
2019-05-24 00:47:26 -05:00
|
|
|
if (gui.Data.State == "SEND LOGIN") {
|
|
|
|
log.Println("\tTRIGGERING LOGIN HERE on AccNick =", gui.Data.AccNick)
|
|
|
|
log.Println("\tTRIGGERING LOGIN HERE on AccNick =", gui.Data.AccNick)
|
|
|
|
log.Println("\tTRIGGERING LOGIN HERE on AccNick =", gui.Data.AccNick)
|
|
|
|
|
|
|
|
event := pb.MakeLoginEvent()
|
|
|
|
event.Username = config.String("accounts." + gui.Data.AccNick + ".username")
|
|
|
|
event.Password = config.String("accounts." + gui.Data.AccNick + ".password")
|
|
|
|
event.Token = config.String("accounts." + gui.Data.AccNick + ".token")
|
|
|
|
log.Println("\tTRIGGERING LOGIN HERE with event.Token =", event.Token)
|
|
|
|
|
|
|
|
gorillaSendProtobuf(event)
|
|
|
|
gui.Data.State = "READ PROTOBUF"
|
|
|
|
}
|
2019-05-24 15:43:22 -05:00
|
|
|
if (gui.Data.State == "CREATE") {
|
|
|
|
log.Println("\tTRIGGERING CREATE HERE")
|
|
|
|
|
|
|
|
event := pb.MakeAddVmEvent()
|
|
|
|
//event.Username = config.String("accounts." + gui.Data.AccNick + ".username")
|
|
|
|
//event.Password = config.String("accounts." + gui.Data.AccNick + ".password")
|
|
|
|
event.Token = config.String("accounts." + gui.Data.AccNick + ".token")
|
|
|
|
log.Println("\tTRIGGERING LOGIN HERE with event.Token =", event.Token)
|
|
|
|
|
|
|
|
gorillaSendProtobuf(event)
|
|
|
|
gui.Data.State = "READ PROTOBUF"
|
|
|
|
}
|
2019-05-23 00:33:16 -05:00
|
|
|
if (gui.Data.State == "kill") {
|
|
|
|
log.Println("gui.State = kill")
|
|
|
|
log.Println("gui.State = kill")
|
|
|
|
log.Println("gui.State = kill")
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
2019-05-23 15:27:05 -05:00
|
|
|
if (gui.Data.State == "splash") {
|
|
|
|
for account, _ := range config.StringMap("accounts") {
|
|
|
|
log.Println("gui.State = splash BUT THERE IS AN ACCOUNT = ", account)
|
|
|
|
log.Println("gui.State = splash BUT THERE IS AN ACCOUNT = ", account)
|
|
|
|
log.Println("SETTING gui.State = main")
|
|
|
|
gui.Data.State = "main";
|
|
|
|
}
|
|
|
|
}
|
2019-05-07 16:54:08 -05:00
|
|
|
}
|
2019-05-07 07:02:39 -05:00
|
|
|
}
|