cloud-control-panel/main.go

358 lines
11 KiB
Go

package main
import "log"
import "fmt"
import "os"
import "time"
import "os/user"
import "runtime"
import "runtime/debug"
import "github.com/gookit/config"
import "github.com/gobuffalo/packr"
// will try to get this hosts FQDN
import "github.com/Showmax/go-fqdn"
// import "github.com/golang/protobuf/proto"
import pb "git.wit.com/wit/witProtobuf"
import "git.wit.com/wit/gui"
var GITCOMMIT string // this is passed in as an ldflag
var GOVERSION string // this is passed in as an ldflag
var BUILDTIME string // this is passed in as an ldflag
// import "github.com/davecgh/go-spew/spew"
// 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
// several smart slice functions (new project. April 2019)
// https://github.com/elliotchance/pie
func onExit(err error) {
log.Println("Sleep for 1 second")
time.Sleep(1 * 1000 * 1000 * 1000)
filename := config.String("configfile")
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")
}
}
if (err != nil) {
panic(err)
}
os.Exit(0)
}
var packrBox packr.Box
func main() {
// This puts all the files in that directory in the binary
// This directory includes the default config file if there is not already one
packrBox = packr.NewBox("./resources")
defaultConfig, _ := packrBox.FindString("cloud.json")
// This will parse the command line and config file
parseConfig(defaultConfig)
// only test the socket code if no GUI
if (config.String("nogui") == "true") {
log.Println("Need to re-implement this")
onExit(nil)
}
initChannel()
go processEvents()
go gorillaDial("v000185.testing.com.customers.wprod.wit.com:9000")
go watchGUI()
user, err := user.Current()
if err != nil {
onExit(err)
}
gui.Data.Width = config.Int("width")
gui.Data.Height = config.Int("height")
// TODO: figure out the hostname the right way
hostname := fqdn.Get()
log.Println("fqdn.Get() = ", hostname)
gui.Data.Hostname = hostname
gui.Data.IPv6 = "2604:bbc0:3:3:0:10:0:1004"
gui.Data.Version = "v0.7"
gui.Data.GitCommit = GITCOMMIT
gui.Data.GoVersion = GOVERSION
gui.Data.Buildtime = BUILDTIME
gui.Data.MouseClick = mainButtonClick
gui.Data.HomeDir = user.HomeDir
// Set output debugging level
gui.Data.Debug = config.Bool("debugging")
gui.Data.DebugTable = config.Bool("debugtable")
log.Println("gui.Data.Debug = ", gui.Data.Debug)
log.Println("gui.Data.DebugTable = ", gui.Data.DebugTable)
// 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"))
// make this the main loop in an attempt to figure out the crashes
// do not change this until the GUI is stable
gui.GoMainWindow()
}
func mainButtonClick(b *gui.ButtonMap) {
log.Println("mainButtonClick() b =", b)
if (b == nil) {
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?")
} else {
log.Println("main() BACK IN CONTROL PANEL CODE (button b.Name =", b.Name, ")")
log.Println("\tb.Name", b.Name)
log.Println("\tb.Note", b.Note)
log.Println("\tb.AccNick", b.AccNick)
if (b.Note == "BACK") {
gui.Data.State = "splash"
}
if (b.Note == "QUIT") {
onExit(nil)
}
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
}
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"
}
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")
}
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")
}
}
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 {
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!")
msg := "On account " + gui.Data.AccNick + "\n"
gui.ErrorWindow("Login OK", msg)
}
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)
}
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
}
}
}
if (b.Note == "SHOW") {
log.Println("\tTRIGGER DISPLAY ACCOUNT")
gui.Data.State = "SEND WEBSOCKET"
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 {
count := countVMS(currentMessage)
log.Println("SHOW VMS currentMessage =", currentMessage)
log.Println("SHOW VMS count =", count)
if (count != 0) {
name := "Virtual Machines (" + b.AccNick + ")"
mh := gui.AddVmsTab(name, count)
ReadReceivedData(currentMessage, mh)
}
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
}
}
}
}
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"
} else if (gui.Data.State == "QUIT") {
onExit(nil)
}
}
// this watches the GUI primarily to process protobuf's
func watchGUI() {
count := 0
for {
if (count > 10) {
log.Println("Sleep() in watchGUI() gui.Data.State =", gui.Data.State)
count = 0
}
count += 1
time.Sleep(200 * time.Millisecond)
if (gui.Data.State == "SEND WEBSOCKET") {
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)
event := pb.MakeGetEvent()
event.Token = config.String("accounts." + gui.Data.AccNick + ".token")
log.Println("\tTRIGGERING WEBSOCKET HERE with event.Token =", event.Token)
gorillaSendProtobuf(event)
gui.Data.State = "READ PROTOBUF"
}
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"
}
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"
}
if (gui.Data.State == "kill") {
log.Println("gui.State = kill")
log.Println("gui.State = kill")
log.Println("gui.State = kill")
os.Exit(0)
}
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";
}
}
}
}