package main import ( "errors" "fmt" "io/ioutil" "net/http" "os" "strings" "libvirt.org/go/libvirtxml" "go.wit.com/lib/gui/shell" pb "go.wit.com/lib/protobuf/virtbuf" "go.wit.com/lib/virtigolib" "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) { log.Info("Got URL Path: ", r.URL.Path) route := cleanURL(r.URL.Path) msg, err := ioutil.ReadAll(r.Body) // Read the body as []byte if err != nil { fmt.Fprintln(w, "ReadAll() error =", err) return } log.Info("Got URL msg:", string(msg)) if route == "/" { fmt.Fprintln(w, "OK") return } // curl http://localhost:2520/dumpdomain?domain=foo.bar.com if route == "/dumpdomain" { domname := r.URL.Query().Get("domain") fmt.Fprint(w, "import domain:", domname) xmldoc, err := virshDumpXML(domname) domcfg := &libvirtxml.Domain{} fmt.Fprintln(w, "domcfg.Unmarshal()") fmt.Fprintln(w, "domcfg.Unmarshal()") fmt.Fprintln(w, "domcfg.Unmarshal()") log.Warn("domcfg.Unmarshal()") err = domcfg.Unmarshal(xmldoc) if err != nil { fmt.Fprintln(w, "domain.Unmarshal XML failed") fmt.Fprintln(w, "error =", err) return } d, err := virtigolib.TestLibvirtDomain(domcfg) if err != nil { fmt.Fprintln(w, "ImportXML failed for", domname, err) return } if d == nil { fmt.Fprintln(w, "ImportXML failed d == nil", err) return } fmt.Fprintln(w, "ImportXML worked for", domname) fmt.Fprintln(w, "should send the protobuf to virtigo here", domname) log.Warn("About to DumpDroplet()") d.DumpDroplet(w, r) fmt.Fprintln(w, "DUMP DOMAIN DONE OK FOR", domname) return } if route == "/vms" { s := pollHypervisor(me.hv) fmt.Fprint(w, s) return } // exit the virtigo daemon & have systemd restart it // this can happen & when it does, access to // to libvirtd will hang (aka: virsh list will hang) // One way to trigger this is to not properly close // domain sockets opened from go-qemu/hypervisor // it's a good idea in any case so leave it here if route == "/kill" { log.Warn("KILLED") fmt.Fprintln(w, "KILLED") os.Exit(-1) return } // curl http://localhost:2520/import?domain=foo.bar.com if route == "/import" { domname := r.URL.Query().Get("domain") // fmt.Fprint(w, "import domain:", domname) xmldoc, err := virshDumpXML(domname) if err != nil { fmt.Fprintln(w, err) return } fmt.Fprintln(w, xmldoc) return /* domcfg := &libvirtxml.Domain{} err = domcfg.Unmarshal(xmldoc) if err != nil { fmt.Fprintln(w, "domain.Unmarshal XML failed") fmt.Fprintln(w, "error =", err) return } // importDomain(w, r, domcfg) // importDomain(w http.ResponseWriter, r *http.Request, dom *libvirtxml.Domain) { xml, _, err := virtigolib.ImportXML(domcfg) if err != nil { fmt.Fprintln(w, "ImportXML failed for", domname, err) return } log.Warn("ImportXML worked for", domname) fmt.Fprintln(w, xml) // d.Current.FullXml = xmldoc */ return } if route == "/start" { log.Info("/start jcarr actually doing START", me.Hostname) fmt.Fprintln(w, "/start jcarr actually doing START", me.Hostname) start := r.URL.Query().Get("start") xml := "/tmp/" + start + ".xml" if shell.Unlink(xml) { fmt.Fprintln(w, "START FAILED", me.Hostname) fmt.Fprintln(w, "error =", "could not remove existing xml file", xml) fmt.Fprintln(w, "error =", "file still exists after unlink") return } // fmt.Fprintln(w, "HTTP:", r.Body) var d *pb.Droplet d = new(pb.Droplet) // msg, err := ioutil.ReadAll(r.Body) // Read the body as []byte fmt.Fprintln(w, "/start ReadAll() START") fmt.Fprintln(w, "msg =", string(msg)) fmt.Fprintln(w, "/start ReadAll() END") if err != nil { fmt.Fprintln(w, "START FAILED", me.Hostname) fmt.Fprintln(w, "error =", err) return } fmt.Fprintln(w, "START len(msg) =", len(msg)) err = d.UnmarshalJSON(msg) if d.Hostname == "" { fmt.Fprintln(w, "START hostname is blank", me.Hostname) log.Info("START hostname is blank") return } if err != nil { fmt.Fprintln(w, "START FAILED", me.Hostname) fmt.Fprintln(w, "error =", err) } if err := newStart(start, d); err != nil { fmt.Fprintln(w, "START FAILED", me.Hostname) fmt.Fprintln(w, "error =", err) return } cmd := []string{"virsh", "create", xml} log.Warn("cmd :", cmd) fmt.Fprintln(w, "Handling start droplet", cmd) r := shell.PathRun("/home/", cmd) output := strings.Join(r.Stdout, "\n") if r.Error == nil { fmt.Fprintln(w, "START OK", me.Hostname) fmt.Fprintln(w, output) } else { fmt.Fprintln(w, "START FAILED", me.Hostname) fmt.Fprintln(w, "error =", r.Error) fmt.Fprintln(w, "output =", r.Stdout) } return } if route == "/favicon.ico" { writeFile(w, "ipv6.png") return } log.Warn("BAD URL =", route) fmt.Fprintln(w, "BAD URL =", route) } 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) } } func virshDumpXML(name string) (string, error) { cmd := []string{"virsh", "dumpxml", "--security-info", name} log.Warn("Running:", cmd) r := shell.PathRun("/home/", cmd) output := strings.Join(r.Stdout, "\n") if r.Error != nil { result := fmt.Sprintln(cmd, "failed:", r.Error) log.Warn(result) return output, errors.New(result) } if r.Exit != 0 { result := fmt.Sprintln(cmd, "failed exit:", r.Exit) log.Warn(result) return output, errors.New(result) } log.Warn(cmd, "OK") return output, nil }