171 lines
4.4 KiB
Go
171 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.wit.com/lib/gui/shell"
|
|
"go.wit.com/log"
|
|
)
|
|
|
|
// remove '?' part and trailing '/'
|
|
func cleanURL(url string) string {
|
|
url = "/" + strings.Trim(url, "/")
|
|
return url
|
|
}
|
|
|
|
func okHandler(w http.ResponseWriter, r *http.Request) {
|
|
var tmp string
|
|
tmp = cleanURL(r.URL.Path)
|
|
|
|
// list all the droplets
|
|
if tmp == "/droplets" {
|
|
log.Info("Handling URL:", tmp)
|
|
for _, d := range me.droplets {
|
|
dur := time.Since(d.lastpoll) // Calculate the elapsed time
|
|
fmt.Fprintln(w, d.Hostname, d.hname, shell.FormatDuration(dur))
|
|
}
|
|
return
|
|
}
|
|
|
|
// is the cluster running what it should?
|
|
if tmp == "/droplets" {
|
|
for _, d := range me.droplets {
|
|
if d.State != "ON" {
|
|
continue
|
|
}
|
|
dur := time.Since(d.lastpoll) // Calculate the elapsed time
|
|
if d.CurrentState != "ON" {
|
|
fmt.Fprintln(w, "BAD STATE ", d.Hostname, "State =", d.State, "CurrentState =", d.CurrentState, shell.FormatDuration(dur))
|
|
} else {
|
|
dur := time.Since(d.lastpoll) // Calculate the elapsed time
|
|
fmt.Fprintln(w, "GOOD STATE ON", d.Hostname, d.hname, shell.FormatDuration(dur))
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if tmp == "/favicon.ico" {
|
|
writeFile(w, "ipv6.png")
|
|
return
|
|
}
|
|
if tmp == "/uptime" {
|
|
b, s := clusterHealthy()
|
|
if b {
|
|
log.Info("Handling URL:", tmp, "cluster is ok", s)
|
|
fmt.Fprintln(w, s)
|
|
} else {
|
|
log.Info("Handling URL:", tmp, "cluster is not right yet", s)
|
|
fmt.Fprintln(w, s)
|
|
}
|
|
for _, h := range me.hypers {
|
|
url := "http://" + h.Hostname + ":2520/kill"
|
|
dur := time.Since(h.lastpoll) // Calculate the elapsed time
|
|
if dur > 90*time.Second {
|
|
h.RestartDaemon()
|
|
continue
|
|
}
|
|
if h.killcount != 0 {
|
|
log.Info("KILL count =", h.killcount, "FOR", h.Hostname, dur, "curl", url)
|
|
}
|
|
if h.killcount > 10 {
|
|
log.Info("KILL count is greater than 10 for host", h.Hostname, dur, "curl", url)
|
|
}
|
|
// l := shell.FormatDuration(dur)
|
|
// log.Warn("HOST =", h.Hostname, "Last poll =", l)
|
|
//if d.State != "ON" {
|
|
// continue
|
|
//}
|
|
// dur := time.Since(d.lastpoll) // Calculate the elapsed time
|
|
}
|
|
return
|
|
}
|
|
|
|
if tmp == "/start" {
|
|
start := r.URL.Query().Get("start")
|
|
log.Info("Handling URL:", tmp, "start droplet", start)
|
|
dur := time.Since(me.unstable) // how long has the cluster been stable?
|
|
|
|
fmt.Fprintln(w, "should start droplet here", start, shell.FormatDuration(dur))
|
|
if dur < 17*time.Second {
|
|
fmt.Fprintln(w, "grid is still to unstable")
|
|
return
|
|
}
|
|
d := findDroplet(start)
|
|
if d == nil {
|
|
fmt.Fprintln(w, "can't start unknown droplet", start)
|
|
return
|
|
}
|
|
|
|
// make the list of hypervisors that are active and can start new droplets
|
|
var pool []*HyperT
|
|
for _, h := range me.hypers {
|
|
fmt.Fprintln(w, "could start droplet on", start, "on", h.Hostname, h.Active)
|
|
if d.hyperPreferred == h.Hostname {
|
|
// the config file says this droplet should run on this hypervisor
|
|
h.Start(d)
|
|
return
|
|
}
|
|
if h.Active != true {
|
|
continue
|
|
}
|
|
pool = append(pool, h)
|
|
}
|
|
|
|
// left here as an example of how to actually do random numbers
|
|
// it's complete mathematical chaos. Randomness is simple when
|
|
// human interaction occurs -- which is exactly what happens most
|
|
// of the time. most random shit is bullshit. all you really need
|
|
// is exactly this to make sure the random functions work as they
|
|
// should. Probably, just use this everywhere in all cases. --jcarr
|
|
rand.Seed(time.Now().UnixNano())
|
|
a := 0
|
|
b := len(pool)
|
|
n := a + rand.Intn(b-a)
|
|
fmt.Fprintln(w, "pool has", len(pool), "members", "rand =", n)
|
|
h := pool[n]
|
|
h.Start(d)
|
|
return
|
|
}
|
|
|
|
log.Warn("BAD URL =", tmp)
|
|
fmt.Fprintln(w, "BAD ZOOT")
|
|
// badurl(w, r.URL.String())
|
|
// fmt.Fprintln(w, "BAD", tmp)
|
|
}
|
|
|
|
func writeFile(w http.ResponseWriter, filename string) {
|
|
// fmt.Fprintln(w, "GOT TEST?")
|
|
fullname := "resources/" + filename
|
|
pfile, err := resources.ReadFile(fullname)
|
|
if err != nil {
|
|
log.Println("ERROR:", err)
|
|
// w.Write(pfile)
|
|
return
|
|
}
|
|
|
|
var repohtml string
|
|
repohtml = string(pfile)
|
|
if filename == "goReference.svg" {
|
|
w.Header().Set("Content-Type", "image/svg+xml")
|
|
}
|
|
fmt.Fprintln(w, repohtml)
|
|
log.Println("writeFile() found internal file:", filename)
|
|
}
|
|
|
|
// starts and sits waiting for HTTP requests
|
|
func startHTTP() {
|
|
http.HandleFunc("/", okHandler)
|
|
|
|
p := fmt.Sprintf(":%d", argv.Port)
|
|
log.Println("Running on port", p)
|
|
|
|
err := http.ListenAndServe(p, nil)
|
|
if err != nil {
|
|
log.Println("Error starting server:", err)
|
|
}
|
|
}
|