diff --git a/builder/xenserver/common/client.go b/builder/xenserver/common/client.go index 1450271..03348b3 100644 --- a/builder/xenserver/common/client.go +++ b/builder/xenserver/common/client.go @@ -8,356 +8,9 @@ import ( "net" "strconv" - xmlrpc "github.com/amfranz/go-xmlrpc-client" xenapi "github.com/terra-farm/go-xen-api-client" ) -type XenAPIClient struct { - Session interface{} - Host string - Url string - Username string - Password string - RPC *xmlrpc.Client -} - -type APIResult struct { - Status string - Value interface{} - ErrorDescription string -} - -type XenAPIObject struct { - Ref string - Client *XenAPIClient -} - -type Host XenAPIObject -type VM XenAPIObject -type SR XenAPIObject -type VDI XenAPIObject -type Network XenAPIObject -type VBD XenAPIObject -type VIF XenAPIObject -type PIF XenAPIObject -type Pool XenAPIObject -type Task XenAPIObject - -type VDIType int - -const ( - _ VDIType = iota - Disk - CD - Floppy -) - -type TaskStatusType int - -const ( - _ TaskStatusType = iota - Pending - Success - Failure - Cancelling - Cancelled -) - -func (c *XenAPIClient) RPCCall(result interface{}, method string, params []interface{}) (err error) { - fmt.Println(params) - p := xmlrpc.Params{Params: params} - err = c.RPC.Call(method, p, result) - return err -} - -func (client *XenAPIClient) Login() (err error) { - //Do loging call - result := xmlrpc.Struct{} - - params := make([]interface{}, 2) - params[0] = client.Username - params[1] = client.Password - - err = client.RPCCall(&result, "session.login_with_password", params) - client.Session = result["Value"] - return err -} - -func (client *XenAPIClient) APICall(result *APIResult, method string, params ...interface{}) (err error) { - if client.Session == nil { - fmt.Println("Error: no session") - return fmt.Errorf("No session. Unable to make call") - } - - //Make a params slice which will include the session - p := make([]interface{}, len(params)+1) - p[0] = client.Session - - if params != nil { - for idx, element := range params { - p[idx+1] = element - } - } - - res := xmlrpc.Struct{} - - err = client.RPCCall(&res, method, p) - - if err != nil { - return err - } - - result.Status = res["Status"].(string) - - if result.Status != "Success" { - fmt.Println("Encountered an API error: ", result.Status) - fmt.Println(res["ErrorDescription"]) - return fmt.Errorf("API Error: %s", res["ErrorDescription"]) - } else { - result.Value = res["Value"] - } - return -} - -func (client *XenAPIClient) GetHosts() (hosts []*Host, err error) { - hosts = make([]*Host, 0) - result := APIResult{} - _ = client.APICall(&result, "host.get_all") - for _, elem := range result.Value.([]interface{}) { - host := new(Host) - host.Ref = elem.(string) - host.Client = client - hosts = append(hosts, host) - } - return -} - -func (client *XenAPIClient) GetPools() (pools []*Pool, err error) { - pools = make([]*Pool, 0) - result := APIResult{} - err = client.APICall(&result, "pool.get_all") - if err != nil { - return pools, err - } - - for _, elem := range result.Value.([]interface{}) { - pool := new(Pool) - pool.Ref = elem.(string) - pool.Client = client - pools = append(pools, pool) - } - - return pools, nil -} - -func (client *XenAPIClient) GetDefaultSR() (sr *SR, err error) { - pools, err := client.GetPools() - - if err != nil { - return nil, err - } - - pool_rec, err := pools[0].GetRecord() - - if err != nil { - return nil, err - } - - if pool_rec["default_SR"] == "" { - return nil, errors.New("No default_SR specified for the pool.") - } - - sr = new(SR) - sr.Ref = pool_rec["default_SR"].(string) - sr.Client = client - - return sr, nil -} - -func (client *XenAPIClient) GetVMByUuid(vm_uuid string) (vm *VM, err error) { - vm = new(VM) - result := APIResult{} - err = client.APICall(&result, "VM.get_by_uuid", vm_uuid) - if err != nil { - return nil, err - } - vm.Ref = result.Value.(string) - vm.Client = client - return -} - -func (client *XenAPIClient) GetVMByNameLabel(name_label string) (vms []*VM, err error) { - vms = make([]*VM, 0) - result := APIResult{} - err = client.APICall(&result, "VM.get_by_name_label", name_label) - if err != nil { - return vms, err - } - - for _, elem := range result.Value.([]interface{}) { - vm := new(VM) - vm.Ref = elem.(string) - vm.Client = client - vms = append(vms, vm) - } - - return vms, nil -} - -func (client *XenAPIClient) GetNetworkByUuid(network_uuid string) (network *Network, err error) { - network = new(Network) - result := APIResult{} - err = client.APICall(&result, "network.get_by_uuid", network_uuid) - if err != nil { - return nil, err - } - network.Ref = result.Value.(string) - network.Client = client - return -} - -func (client *XenAPIClient) GetNetworkByNameLabel(name_label string) (networks []*Network, err error) { - networks = make([]*Network, 0) - result := APIResult{} - err = client.APICall(&result, "network.get_by_name_label", name_label) - if err != nil { - return networks, err - } - - for _, elem := range result.Value.([]interface{}) { - network := new(Network) - network.Ref = elem.(string) - network.Client = client - networks = append(networks, network) - } - - return networks, nil -} - -func (client *XenAPIClient) GetVdiByNameLabel(name_label string) (vdis []*VDI, err error) { - vdis = make([]*VDI, 0) - result := APIResult{} - err = client.APICall(&result, "VDI.get_by_name_label", name_label) - if err != nil { - return vdis, err - } - - for _, elem := range result.Value.([]interface{}) { - vdi := new(VDI) - vdi.Ref = elem.(string) - vdi.Client = client - vdis = append(vdis, vdi) - } - - return vdis, nil -} - -func (client *XenAPIClient) GetVdiByUuid(vdi_uuid string) (vdi *VDI, err error) { - vdi = new(VDI) - result := APIResult{} - err = client.APICall(&result, "VDI.get_by_uuid", vdi_uuid) - if err != nil { - return nil, err - } - vdi.Ref = result.Value.(string) - vdi.Client = client - return -} - -func (client *XenAPIClient) GetPIFs() (pifs []*PIF, err error) { - pifs = make([]*PIF, 0) - result := APIResult{} - err = client.APICall(&result, "PIF.get_all") - if err != nil { - return pifs, err - } - for _, elem := range result.Value.([]interface{}) { - pif := new(PIF) - pif.Ref = elem.(string) - pif.Client = client - pifs = append(pifs, pif) - } - - return pifs, nil -} - -// Host associated functions - -func (self *Host) GetSoftwareVersion() (versions map[string]interface{}, err error) { - versions = make(map[string]interface{}) - - result := APIResult{} - err = self.Client.APICall(&result, "host.get_software_version", self.Ref) - if err != nil { - return nil, err - } - - for k, v := range result.Value.(xmlrpc.Struct) { - versions[k] = v.(string) - } - return -} - -func (self *Host) CallPlugin(plugin, function string, args map[string]string) (res string, err error) { - - args_rec := make(xmlrpc.Struct) - for key, value := range args { - args_rec[key] = value - } - - result := APIResult{} - err = self.Client.APICall(&result, "host.call_plugin", self.Ref, plugin, function, args_rec) - if err != nil { - return "", err - } - - // The plugin should return a string value - res = result.Value.(string) - return -} - -// VM associated functions - -func (self *VM) Clone(label string) (new_instance *VM, err error) { - new_instance = new(VM) - - result := APIResult{} - err = self.Client.APICall(&result, "VM.clone", self.Ref, label) - if err != nil { - return nil, err - } - new_instance.Ref = result.Value.(string) - new_instance.Client = self.Client - return -} - -func (self *VM) Destroy() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.destroy", self.Ref) - if err != nil { - return err - } - return -} - -func (self *VM) Start(paused, force bool) (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.start", self.Ref, paused, force) - if err != nil { - return err - } - return -} - -func (self *VM) CleanShutdown() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.clean_shutdown", self.Ref) - if err != nil { - return err - } - return -} - func Unpause(c *Connection, vmRef xenapi.VMRef) (err error) { err = c.client.VM.Unpause(c.session, vmRef) if err != nil { @@ -366,83 +19,6 @@ func Unpause(c *Connection, vmRef xenapi.VMRef) (err error) { return } -func (self *VM) SetHVMBoot(policy, bootOrder string) (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.set_HVM_boot_policy", self.Ref, policy) - if err != nil { - return err - } - result = APIResult{} - params := make(xmlrpc.Struct) - params["order"] = bootOrder - err = self.Client.APICall(&result, "VM.set_HVM_boot_params", self.Ref, params) - if err != nil { - return err - } - return -} - -func (self *VM) SetPVBootloader(pv_bootloader, pv_args string) (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.set_PV_bootloader", self.Ref, pv_bootloader) - if err != nil { - return err - } - result = APIResult{} - err = self.Client.APICall(&result, "VM.set_PV_bootloader_args", self.Ref, pv_args) - if err != nil { - return err - } - return -} - -func (self *VM) GetDomainId() (domid string, err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.get_domid", self.Ref) - if err != nil { - return "", err - } - domid = result.Value.(string) - return domid, nil -} - -func (self *VM) GetPowerState() (state string, err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.get_power_state", self.Ref) - if err != nil { - return "", err - } - state = result.Value.(string) - return state, nil -} - -func (self *VM) GetUuid() (uuid string, err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.get_uuid", self.Ref) - if err != nil { - return "", err - } - uuid = result.Value.(string) - return uuid, nil -} - -func (self *VM) GetVBDs() (vbds []VBD, err error) { - vbds = make([]VBD, 0) - result := APIResult{} - err = self.Client.APICall(&result, "VM.get_VBDs", self.Ref) - if err != nil { - return vbds, err - } - for _, elem := range result.Value.([]interface{}) { - vbd := VBD{} - vbd.Ref = elem.(string) - vbd.Client = self.Client - vbds = append(vbds, vbd) - } - - return vbds, nil -} - func GetDisks(c *Connection, vmRef xenapi.VMRef) (vdis []xenapi.VDIRef, err error) { // Return just data disks (non-isos) vdis = make([]xenapi.VDIRef, 0) @@ -469,44 +45,6 @@ func GetDisks(c *Connection, vmRef xenapi.VMRef) (vdis []xenapi.VDIRef, err erro return vdis, nil } -func (self *VM) GetGuestMetricsRef() (ref string, err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.get_guest_metrics", self.Ref) - if err != nil { - return "", nil - } - ref = result.Value.(string) - return ref, err -} - -func (self *VM) GetGuestMetrics() (metrics map[string]interface{}, err error) { - metrics_ref, err := self.GetGuestMetricsRef() - if err != nil { - return nil, err - } - if metrics_ref == "OpaqueRef:NULL" { - return nil, nil - } - - result := APIResult{} - err = self.Client.APICall(&result, "VM_guest_metrics.get_record", metrics_ref) - if err != nil { - return nil, err - } - return result.Value.(xmlrpc.Struct), nil -} - -func (self *VM) SetStaticMemoryRange(min, max uint) (err error) { - result := APIResult{} - strMin := fmt.Sprintf("%d", min) - strMax := fmt.Sprintf("%d", max) - err = self.Client.APICall(&result, "VM.set_memory_limits", self.Ref, strMin, strMax, strMin, strMax) - if err != nil { - return err - } - return -} - func ConnectVdi(c *Connection, vmRef xenapi.VMRef, vdiRef xenapi.VDIRef, vbdType xenapi.VbdType) (err error) { var mode xenapi.VbdMode @@ -595,21 +133,6 @@ func DisconnectVdi(c *Connection, vmRef xenapi.VMRef, vdi xenapi.VDIRef) error { return fmt.Errorf("Could not find VBD for VDI '%s'", vdi) } -func (self *VM) SetPlatform(params map[string]string) (err error) { - result := APIResult{} - platform_rec := make(xmlrpc.Struct) - for key, value := range params { - platform_rec[key] = value - } - - err = self.Client.APICall(&result, "VM.set_platform", self.Ref, platform_rec) - - if err != nil { - return err - } - return -} - func ConnectNetwork(c *Connection, networkRef xenapi.NetworkRef, vmRef xenapi.VMRef, device string) (*xenapi.VIFRef, error) { vif, err := c.client.VIF.Create(c.session, xenapi.VIFRecord{ Network: networkRef, @@ -626,194 +149,7 @@ func ConnectNetwork(c *Connection, networkRef xenapi.NetworkRef, vmRef xenapi.VM return &vif, nil } -// Setters - -func (self *VM) SetIsATemplate(is_a_template bool) (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VM.set_is_a_template", self.Ref, is_a_template) - if err != nil { - return err - } - return -} - -// SR associated functions - -func (self *SR) CreateVdi(name_label string, size int64) (vdi *VDI, err error) { - vdi = new(VDI) - - vdi_rec := make(xmlrpc.Struct) - vdi_rec["name_label"] = name_label - vdi_rec["SR"] = self.Ref - vdi_rec["virtual_size"] = fmt.Sprintf("%d", size) - vdi_rec["type"] = "user" - vdi_rec["sharable"] = false - vdi_rec["read_only"] = false - - oc := make(xmlrpc.Struct) - oc["temp"] = "temp" - vdi_rec["other_config"] = oc - - result := APIResult{} - err = self.Client.APICall(&result, "VDI.create", vdi_rec) - if err != nil { - return nil, err - } - - vdi.Ref = result.Value.(string) - vdi.Client = self.Client - - return -} - -// Network associated functions - -func (self *Network) GetAssignedIPs() (ip_map map[string]string, err error) { - ip_map = make(map[string]string, 0) - result := APIResult{} - err = self.Client.APICall(&result, "network.get_assigned_ips", self.Ref) - if err != nil { - return ip_map, err - } - for k, v := range result.Value.(xmlrpc.Struct) { - ip_map[k] = v.(string) - } - return ip_map, nil -} - -// PIF associated functions - -func (self *PIF) GetRecord() (record map[string]interface{}, err error) { - record = make(map[string]interface{}) - result := APIResult{} - err = self.Client.APICall(&result, "PIF.get_record", self.Ref) - if err != nil { - return record, err - } - for k, v := range result.Value.(xmlrpc.Struct) { - record[k] = v - } - return record, nil -} - -// Pool associated functions - -func (self *Pool) GetRecord() (record map[string]interface{}, err error) { - record = make(map[string]interface{}) - result := APIResult{} - err = self.Client.APICall(&result, "pool.get_record", self.Ref) - if err != nil { - return record, err - } - for k, v := range result.Value.(xmlrpc.Struct) { - record[k] = v - } - return record, nil -} - -// VBD associated functions -func (self *VBD) GetRecord() (record map[string]interface{}, err error) { - record = make(map[string]interface{}) - result := APIResult{} - err = self.Client.APICall(&result, "VBD.get_record", self.Ref) - if err != nil { - return record, err - } - for k, v := range result.Value.(xmlrpc.Struct) { - record[k] = v - } - return record, nil -} - -func (self *VBD) GetVDI() (vdi *VDI, err error) { - vbd_rec, err := self.GetRecord() - if err != nil { - return nil, err - } - - vdi = new(VDI) - vdi.Ref = vbd_rec["VDI"].(string) - vdi.Client = self.Client - - return vdi, nil -} - -func (self *VBD) Eject() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VBD.eject", self.Ref) - if err != nil { - return err - } - return nil -} - -func (self *VBD) Unplug() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VBD.unplug", self.Ref) - if err != nil { - return err - } - return nil -} - -func (self *VBD) Destroy() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VBD.destroy", self.Ref) - if err != nil { - return err - } - return nil -} - -// VIF associated functions - -func (self *VIF) Destroy() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VIF.destroy", self.Ref) - if err != nil { - return err - } - return nil -} - // VDI associated functions - -func (self *VDI) GetUuid() (vdi_uuid string, err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VDI.get_uuid", self.Ref) - if err != nil { - return "", err - } - vdi_uuid = result.Value.(string) - return vdi_uuid, nil -} - -func (self *VDI) GetVBDs() (vbds []VBD, err error) { - vbds = make([]VBD, 0) - result := APIResult{} - err = self.Client.APICall(&result, "VDI.get_VBDs", self.Ref) - if err != nil { - return vbds, err - } - for _, elem := range result.Value.([]interface{}) { - vbd := VBD{} - vbd.Ref = elem.(string) - vbd.Client = self.Client - vbds = append(vbds, vbd) - } - - return vbds, nil -} - -func (self *VDI) Destroy() (err error) { - result := APIResult{} - err = self.Client.APICall(&result, "VDI.destroy", self.Ref) - if err != nil { - return err - } - return -} - // Expose a VDI using the Transfer VM // (Legacy VHD export) @@ -910,36 +246,6 @@ func Unexpose(c *Connection, vdiRef xenapi.VDIRef) (err error) { return nil } -// Task associated functions - -// func (self *Task) GetResult() (object *XenAPIObject, err error) { -// result := APIResult{} -// err = self.Client.APICall(&result, "task.get_result", self.Ref) -// if err != nil { -// return -// } -// switch ref := result.Value.(type) { -// case string: -// // @fixme: xapi currently sends us an xmlrpc-encoded string via xmlrpc. -// // This seems to be a bug in xapi. Remove this workaround when it's fixed -// re := regexp.MustCompile("^([^<]*).*$") -// match := re.FindStringSubmatch(ref) -// if match == nil { -// object = nil -// } else { -// object = &XenAPIObject{ -// Ref: match[1], -// Client: self.Client, -// } -// } -// case nil: -// object = nil -// default: -// err = fmt.Errorf("task.get_result: unknown value type %T (expected string or nil)", ref) -// } -// return -// } - // Client Initiator type Connection struct { client *xenapi.Client