virtigo/importDomain.go

138 lines
3.5 KiB
Go

package main
import (
"errors"
"fmt"
"net/http"
"time"
pb "go.wit.com/lib/protobuf/virtbuf"
"go.wit.com/lib/virtigolib"
"go.wit.com/log"
"libvirt.org/go/libvirtxml"
)
// attempts to create a new virtual machine
func importDomain(w http.ResponseWriter, r *http.Request) (string, error) {
name := r.URL.Query().Get("domainName")
if name == "" {
result := "importDomain() failed. name is blank " + r.URL.Path
log.Warn(result)
fmt.Fprintln(w, result)
return "", errors.New(result)
}
log.Warn("importDomain() START name is", name)
fmt.Fprintln(w, "importDomain() START name is", name)
d := me.cluster.FindDropletByName(name)
if d == nil {
result := "libvirt domain " + name + " could not be found on any hypervisor"
log.Info(result)
fmt.Fprintln(w, result)
return result, errors.New(result)
}
start := d.SprintHeader()
if d.LocalOnly == "" {
result := start + " LocalOnly is blank. THIS SHOULD NEVER HAPPEN."
log.Log(WARN, result)
fmt.Fprintln(w, result)
return result, errors.New(result)
}
if d.Current.State != pb.DropletState_OFF {
result := "error: libvirt domain " + name + " is not off"
log.Info(result)
fmt.Fprintln(w, result)
return result, errors.New(result)
}
h := findHypervisorByName(d.Current.Hypervisor)
if h == nil {
result := "unknown hypervisor = " + d.Current.Hypervisor
log.Log(WARN, result)
fmt.Fprintln(w, result)
return result, errors.New(result)
}
// attempt to get the domain record from virtigo
xml, err := postImportDomain(h.pb.Hostname, name)
if err != nil {
log.Log(WARN, err)
fmt.Fprintln(w, err)
return "", err
}
domcfg := &libvirtxml.Domain{}
err = domcfg.Unmarshal(string(xml))
if err != nil {
log.Info("Marshal failed", name, err)
log.Warn(string(xml))
fmt.Fprintln(w, string(xml))
return "", err
}
// func ImportXML(domcfg *libvirtxml.Domain) (*pb.Droplet, []*pb.Event, error) {
d, alle, err := virtigolib.ImportXML(domcfg)
if err != nil {
fmt.Fprintln(w, "ImportXML failed with", name, err)
return "", err
}
if d == nil {
fmt.Fprintln(w, "ImportXML d == nil for", name, err)
return "", err
}
for _, e := range alle {
me.cluster.AddEvent(e)
}
result := fmt.Sprintln("marshal worked", domcfg.Name, domcfg.UUID)
log.Log(WARN, result)
fmt.Fprintln(w, result)
return result, nil
}
// this must be bool in string because accumulated output is sometimes
// written to STDOUT, sometimes to http
func (h *HyperT) importDomain(d *pb.Droplet) (bool, string) {
ready, result := me.cluster.DropletReady(d)
if !ready {
return false, result
}
url := "http://" + h.pb.Hostname + ":2520/import?domain=" + d.Hostname
var msg string
var data []byte
msg = d.FormatJSON()
data = []byte(msg) // Convert the string to []byte
req, err := httpPost(url, data)
if err != nil {
return false, fmt.Sprintln("error:", err)
}
log.Info("http post url:", url)
log.Info("http post data:", msg)
result = "EVENT import droplet url: " + url + "\n"
result += "EVENT import droplet response: " + string(req)
// increment the counter for a start attempt working
d.Current.StartAttempts += 1
// mark the cluster as unstable so droplet starts can be throttled
me.unstable = time.Now()
return true, result
}
func postImportDomain(hypervisor string, domain string) ([]byte, error) {
url := "http://" + hypervisor + ":2520/import?domain=" + domain
var msg string
var data []byte
msg = "import " + domain
data = []byte(msg) // Convert the string to []byte
req, err := httpPost(url, data)
if err != nil {
return nil, err
}
return req, nil
}