Pulling out the client library and importing it from upstream: xenserver/go-xenserver-client.
Signed-off-by: Rob Dobson <rob.dobson@citrix.com>
This commit is contained in:
parent
4b8ec79cad
commit
7f52133218
@ -1,947 +0,0 @@
|
|||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/nilshell/xmlrpc"
|
|
||||||
"log"
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
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 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 := new(xmlrpc.Params)
|
|
||||||
p.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() (err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
_ = client.APICall(&result, "host.get_all")
|
|
||||||
hosts := result.Value
|
|
||||||
fmt.Println(hosts)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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) GetSRByNameLabel(name_label string) (srs []*SR, err error) {
|
|
||||||
srs = make([]*SR, 0)
|
|
||||||
result := APIResult{}
|
|
||||||
err = client.APICall(&result, "SR.get_by_name_label", name_label)
|
|
||||||
if err != nil {
|
|
||||||
return srs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, elem := range result.Value.([]interface{}) {
|
|
||||||
sr := new(SR)
|
|
||||||
sr.Ref = elem.(string)
|
|
||||||
sr.Client = client
|
|
||||||
srs = append(srs, sr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return srs, 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) GetSRByUuid(sr_uuid string) (sr *SR, err error) {
|
|
||||||
sr = new(SR)
|
|
||||||
result := APIResult{}
|
|
||||||
err = client.APICall(&result, "SR.get_by_uuid", sr_uuid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sr.Ref = result.Value.(string)
|
|
||||||
sr.Client = client
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *XenAPIClient) CreateTask() (task *Task, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = client.APICall(&result, "task.create", "packer-task", "Packer task")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
task = new(Task)
|
|
||||||
task.Ref = result.Value.(string)
|
|
||||||
task.Client = client
|
|
||||||
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 (self *VM) HardShutdown() (err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VM.hard_shutdown", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *VM) Unpause() (err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VM.unpause", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
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 (self *VM) GetVIFs() (vifs []VIF, err error) {
|
|
||||||
vifs = make([]VIF, 0)
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VM.get_VIFs", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return vifs, err
|
|
||||||
}
|
|
||||||
for _, elem := range result.Value.([]interface{}) {
|
|
||||||
vif := VIF{}
|
|
||||||
vif.Ref = elem.(string)
|
|
||||||
vif.Client = self.Client
|
|
||||||
vifs = append(vifs, vif)
|
|
||||||
}
|
|
||||||
|
|
||||||
return vifs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *VM) GetDisks() (vdis []*VDI, err error) {
|
|
||||||
// Return just data disks (non-isos)
|
|
||||||
vdis = make([]*VDI, 0)
|
|
||||||
vbds, err := self.GetVBDs()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, vbd := range vbds {
|
|
||||||
rec, err := vbd.GetRecord()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if rec["type"] == "Disk" {
|
|
||||||
|
|
||||||
vdi, err := vbd.GetVDI()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vdis = append(vdis, vdi)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 (self *VM) ConnectVdi(vdi *VDI, vdiType VDIType) (err error) {
|
|
||||||
|
|
||||||
// 1. Create a VBD
|
|
||||||
|
|
||||||
vbd_rec := make(xmlrpc.Struct)
|
|
||||||
vbd_rec["VM"] = self.Ref
|
|
||||||
vbd_rec["VDI"] = vdi.Ref
|
|
||||||
vbd_rec["userdevice"] = "autodetect"
|
|
||||||
vbd_rec["empty"] = false
|
|
||||||
vbd_rec["other_config"] = make(xmlrpc.Struct)
|
|
||||||
vbd_rec["qos_algorithm_type"] = ""
|
|
||||||
vbd_rec["qos_algorithm_params"] = make(xmlrpc.Struct)
|
|
||||||
|
|
||||||
switch vdiType {
|
|
||||||
case CD:
|
|
||||||
vbd_rec["mode"] = "RO"
|
|
||||||
vbd_rec["bootable"] = true
|
|
||||||
vbd_rec["unpluggable"] = false
|
|
||||||
vbd_rec["type"] = "CD"
|
|
||||||
case Disk:
|
|
||||||
vbd_rec["mode"] = "RW"
|
|
||||||
vbd_rec["bootable"] = false
|
|
||||||
vbd_rec["unpluggable"] = false
|
|
||||||
vbd_rec["type"] = "Disk"
|
|
||||||
case Floppy:
|
|
||||||
vbd_rec["mode"] = "RW"
|
|
||||||
vbd_rec["bootable"] = false
|
|
||||||
vbd_rec["unpluggable"] = true
|
|
||||||
vbd_rec["type"] = "Floppy"
|
|
||||||
}
|
|
||||||
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VBD.create", vbd_rec)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vbd_ref := result.Value.(string)
|
|
||||||
fmt.Println("VBD Ref:", vbd_ref)
|
|
||||||
|
|
||||||
result = APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VBD.get_uuid", vbd_ref)
|
|
||||||
|
|
||||||
fmt.Println("VBD UUID: ", result.Value.(string))
|
|
||||||
/*
|
|
||||||
// 2. Plug VBD (Non need - the VM hasn't booted.
|
|
||||||
// @todo - check VM state
|
|
||||||
result = APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VBD.plug", vbd_ref)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *VM) DisconnectVdi(vdi *VDI) error {
|
|
||||||
vbds, err := self.GetVBDs()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Unable to get VM VBDs: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, vbd := range vbds {
|
|
||||||
rec, err := vbd.GetRecord()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not get record for VBD '%s': %s", vbd.Ref, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if recVdi, ok := rec["VDI"].(string); ok {
|
|
||||||
if recVdi == vdi.Ref {
|
|
||||||
_ = vbd.Unplug()
|
|
||||||
err = vbd.Destroy()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not destroy VBD '%s': %s", vbd.Ref, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("Could not find VDI record in VBD '%s'", vbd.Ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("Could not find VBD for VDI '%s'", vdi.Ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (self *VM) ConnectNetwork(network *Network, device string) (vif *VIF, err error) {
|
|
||||||
// Create the VIF
|
|
||||||
|
|
||||||
vif_rec := make(xmlrpc.Struct)
|
|
||||||
vif_rec["network"] = network.Ref
|
|
||||||
vif_rec["VM"] = self.Ref
|
|
||||||
vif_rec["MAC"] = ""
|
|
||||||
vif_rec["device"] = device
|
|
||||||
vif_rec["MTU"] = "1504"
|
|
||||||
vif_rec["other_config"] = make(xmlrpc.Struct)
|
|
||||||
vif_rec["qos_algorithm_type"] = ""
|
|
||||||
vif_rec["qos_algorithm_params"] = make(xmlrpc.Struct)
|
|
||||||
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VIF.create", vif_rec)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vif = new(VIF)
|
|
||||||
vif.Ref = result.Value.(string)
|
|
||||||
vif.Client = self.Client
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Task associated functions
|
|
||||||
|
|
||||||
func (self *Task) GetStatus() (status TaskStatusType, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.get_status", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rawStatus := result.Value.(string)
|
|
||||||
switch rawStatus {
|
|
||||||
case "pending":
|
|
||||||
status = Pending
|
|
||||||
case "success":
|
|
||||||
status = Success
|
|
||||||
case "failure":
|
|
||||||
status = Failure
|
|
||||||
case "cancelling":
|
|
||||||
status = Cancelling
|
|
||||||
case "cancelled":
|
|
||||||
status = Cancelled
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("Task.get_status: Unknown status '%s'", rawStatus))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Task) GetProgress() (progress float64, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.get_progress", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
progress = result.Value.(float64)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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("^<value><array><data><value>([^<]*)</value>.*</data></array></value>$")
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Task) GetErrorInfo() (errorInfo []string, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.get_error_info", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errorInfo = make([]string, 0)
|
|
||||||
for _, infoRaw := range result.Value.([]interface{}) {
|
|
||||||
errorInfo = append(errorInfo, fmt.Sprintf("%v", infoRaw))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Task) Destroy() (err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.destroy", self.Ref)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client Initiator
|
|
||||||
|
|
||||||
func NewXenAPIClient(host, username, password string) (client XenAPIClient) {
|
|
||||||
client.Host = host
|
|
||||||
client.Url = "http://" + host
|
|
||||||
client.Username = username
|
|
||||||
client.Password = password
|
|
||||||
client.RPC, _ = xmlrpc.NewClient(client.Url, nil)
|
|
||||||
return
|
|
||||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
commonssh "github.com/mitchellh/packer/common/ssh"
|
commonssh "github.com/mitchellh/packer/common/ssh"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommonConfig struct {
|
type CommonConfig struct {
|
||||||
@ -244,7 +245,7 @@ func (c CommonConfig) ShouldKeepVM(state multistep.StateBag) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config CommonConfig) GetSR(client XenAPIClient) (*SR, error) {
|
func (config CommonConfig) GetSR(client xsclient.XenAPIClient) (*xsclient.SR, error) {
|
||||||
if config.SrName == "" {
|
if config.SrName == "" {
|
||||||
// Find the default SR
|
// Find the default SR
|
||||||
return client.GetDefaultSR()
|
return client.GetDefaultSR()
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -23,9 +24,9 @@ func appendQuery(urlstring, k, v string) (string, error) {
|
|||||||
return u.String(), err
|
return u.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (result *XenAPIObject, err error) {
|
func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (result *xsclient.XenAPIObject, err error) {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
task, err := client.CreateTask()
|
task, err := client.CreateTask()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -79,7 +80,7 @@ func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (resul
|
|||||||
return false, fmt.Errorf("Failed to get task status: %s", err.Error())
|
return false, fmt.Errorf("Failed to get task status: %s", err.Error())
|
||||||
}
|
}
|
||||||
switch status {
|
switch status {
|
||||||
case Pending:
|
case xsclient.Pending:
|
||||||
progress, err := task.GetProgress()
|
progress, err := task.GetProgress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("Failed to get progress: %s", err.Error())
|
return false, fmt.Errorf("Failed to get progress: %s", err.Error())
|
||||||
@ -89,15 +90,15 @@ func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (resul
|
|||||||
log.Printf("Upload %.0f%% complete", progress*100)
|
log.Printf("Upload %.0f%% complete", progress*100)
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
case Success:
|
case xsclient.Success:
|
||||||
return true, nil
|
return true, nil
|
||||||
case Failure:
|
case xsclient.Failure:
|
||||||
errorInfo, err := task.GetErrorInfo()
|
errorInfo, err := task.GetErrorInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorInfo = []string{fmt.Sprintf("furthermore, failed to get error info: %s", err.Error())}
|
errorInfo = []string{fmt.Sprintf("furthermore, failed to get error info: %s", err.Error())}
|
||||||
}
|
}
|
||||||
return false, fmt.Errorf("Task failed: %s", errorInfo)
|
return false, fmt.Errorf("Task failed: %s", errorInfo)
|
||||||
case Cancelling, Cancelled:
|
case xsclient.Cancelling, xsclient.Cancelled:
|
||||||
return false, fmt.Errorf("Task cancelled")
|
return false, fmt.Errorf("Task cancelled")
|
||||||
default:
|
default:
|
||||||
return false, fmt.Errorf("Unknown task status %v", status)
|
return false, fmt.Errorf("Unknown task status %v", status)
|
||||||
|
@ -4,19 +4,20 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepAttachVdi struct {
|
type StepAttachVdi struct {
|
||||||
VdiUuidKey string
|
VdiUuidKey string
|
||||||
VdiType VDIType
|
VdiType xsclient.VDIType
|
||||||
|
|
||||||
vdi *VDI
|
vdi *xsclient.VDI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
var vdiUuid string
|
var vdiUuid string
|
||||||
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
||||||
@ -53,7 +54,7 @@ func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
func (self *StepAttachVdi) Cleanup(state multistep.StateBag) {
|
func (self *StepAttachVdi) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
if config.ShouldKeepVM(state) {
|
if config.ShouldKeepVM(state) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepBootWait struct{}
|
type StepBootWait struct{}
|
||||||
|
|
||||||
func (self *StepBootWait) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepBootWait) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ type StepDetachVdi struct {
|
|||||||
|
|
||||||
func (self *StepDetachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepDetachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
var vdiUuid string
|
var vdiUuid string
|
||||||
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -44,7 +45,7 @@ func downloadFile(url, filename string) (err error) {
|
|||||||
func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
instance_uuid := state.Get("instance_uuid").(string)
|
instance_uuid := state.Get("instance_uuid").(string)
|
||||||
suffix := ".vhd"
|
suffix := ".vhd"
|
||||||
extrauri := "&format=vhd"
|
extrauri := "&format=vhd"
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepFindVdi struct {
|
type StepFindVdi struct {
|
||||||
@ -14,7 +15,7 @@ type StepFindVdi struct {
|
|||||||
|
|
||||||
func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
vdis, err := client.GetVdiByNameLabel(self.VdiName)
|
vdis, err := client.GetVdiByNameLabel(self.VdiName)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ type StepShutdown struct{}
|
|||||||
func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
instance_uuid := state.Get("instance_uuid").(string)
|
instance_uuid := state.Get("instance_uuid").(string)
|
||||||
|
|
||||||
instance, err := client.GetVMByUuid(instance_uuid)
|
instance, err := client.GetVMByUuid(instance_uuid)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -22,7 +23,7 @@ type StepStartOnHIMN struct{}
|
|||||||
func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
ui.Say("Step: Start VM on the Host Internal Mangement Network")
|
ui.Say("Step: Start VM on the Host Internal Mangement Network")
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ type StepStartVmPaused struct{}
|
|||||||
|
|
||||||
func (self *StepStartVmPaused) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepStartVmPaused) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Step: Start VM Paused")
|
ui.Say("Step: Start VM Paused")
|
||||||
@ -48,7 +49,7 @@ func (self *StepStartVmPaused) Run(state multistep.StateBag) multistep.StepActio
|
|||||||
|
|
||||||
func (self *StepStartVmPaused) Cleanup(state multistep.StateBag) {
|
func (self *StepStartVmPaused) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
if config.ShouldKeepVM(state) {
|
if config.ShouldKeepVM(state) {
|
||||||
return
|
return
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
@ -18,7 +19,7 @@ type StepUploadVdi struct {
|
|||||||
func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
imagePath := self.ImagePathFunc()
|
imagePath := self.ImagePathFunc()
|
||||||
if imagePath == "" {
|
if imagePath == "" {
|
||||||
@ -80,7 +81,7 @@ func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
|
func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
if config.ShouldKeepVM(state) {
|
if config.ShouldKeepVM(state) {
|
||||||
return
|
return
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/nilshell/xmlrpc"
|
"github.com/nilshell/xmlrpc"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepWaitForIP struct {
|
type StepWaitForIP struct {
|
||||||
@ -16,7 +17,7 @@ type StepWaitForIP struct {
|
|||||||
|
|
||||||
func (self *StepWaitForIP) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepWaitForIP) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
|
|
||||||
ui.Say("Step: Wait for VM's IP to become known to us.")
|
ui.Say("Step: Wait for VM's IP to become known to us.")
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
@ -167,7 +168,7 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
|
|
||||||
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||||
//Setup XAPI client
|
//Setup XAPI client
|
||||||
client := xscommon.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
client := xsclient.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
||||||
|
|
||||||
err := client.Login()
|
err := client.Login()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -231,15 +232,15 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
|||||||
new(stepCreateInstance),
|
new(stepCreateInstance),
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "floppy_vdi_uuid",
|
VdiUuidKey: "floppy_vdi_uuid",
|
||||||
VdiType: xscommon.Floppy,
|
VdiType: xsclient.Floppy,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "iso_vdi_uuid",
|
VdiUuidKey: "iso_vdi_uuid",
|
||||||
VdiType: xscommon.CD,
|
VdiType: xsclient.CD,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "tools_vdi_uuid",
|
VdiUuidKey: "tools_vdi_uuid",
|
||||||
VdiType: xscommon.CD,
|
VdiType: xsclient.CD,
|
||||||
},
|
},
|
||||||
new(xscommon.StepStartVmPaused),
|
new(xscommon.StepStartVmPaused),
|
||||||
new(xscommon.StepGetVNCPort),
|
new(xscommon.StepGetVNCPort),
|
||||||
|
@ -5,17 +5,17 @@ import (
|
|||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepCreateInstance struct {
|
type stepCreateInstance struct {
|
||||||
instance *xscommon.VM
|
instance *xsclient.VM
|
||||||
vdi *xscommon.VDI
|
vdi *xsclient.VDI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(xscommon.XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
config := state.Get("config").(config)
|
config := state.Get("config").(config)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
}
|
}
|
||||||
self.vdi = vdi
|
self.vdi = vdi
|
||||||
|
|
||||||
err = instance.ConnectVdi(vdi, xscommon.Disk)
|
err = instance.ConnectVdi(vdi, xsclient.Disk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to connect packer disk VDI: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to connect packer disk VDI: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -85,11 +85,11 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
|
|
||||||
// Connect Network
|
// Connect Network
|
||||||
|
|
||||||
var network *xscommon.Network
|
var network *xsclient.Network
|
||||||
|
|
||||||
if config.NetworkName == "" {
|
if config.NetworkName == "" {
|
||||||
// No network has be specified. Use the management interface
|
// No network has be specified. Use the management interface
|
||||||
network = new(xscommon.Network)
|
network = new(xsclient.Network)
|
||||||
network.Ref = ""
|
network.Ref = ""
|
||||||
network.Client = &client
|
network.Client = &client
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
@ -94,7 +95,7 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
|
|
||||||
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||||
//Setup XAPI client
|
//Setup XAPI client
|
||||||
client := xscommon.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
client := xsclient.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
||||||
|
|
||||||
err := client.Login()
|
err := client.Login()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -142,11 +143,11 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
|||||||
new(stepImportInstance),
|
new(stepImportInstance),
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "floppy_vdi_uuid",
|
VdiUuidKey: "floppy_vdi_uuid",
|
||||||
VdiType: xscommon.Floppy,
|
VdiType: xsclient.Floppy,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "tools_vdi_uuid",
|
VdiUuidKey: "tools_vdi_uuid",
|
||||||
VdiType: xscommon.CD,
|
VdiType: xsclient.CD,
|
||||||
},
|
},
|
||||||
new(xscommon.StepStartVmPaused),
|
new(xscommon.StepStartVmPaused),
|
||||||
new(xscommon.StepGetVNCPort),
|
new(xscommon.StepGetVNCPort),
|
||||||
@ -163,7 +164,7 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
|||||||
},
|
},
|
||||||
&xscommon.StepWaitForIP{
|
&xscommon.StepWaitForIP{
|
||||||
Chan: httpReqChan,
|
Chan: httpReqChan,
|
||||||
Timeout: 300 * time.Minute /*self.config.InstallTimeout*/, // @todo change this
|
Timeout: 300 * time.Minute, /*self.config.InstallTimeout*/ // @todo change this
|
||||||
},
|
},
|
||||||
&xscommon.StepForwardPortOverSSH{
|
&xscommon.StepForwardPortOverSSH{
|
||||||
RemotePort: xscommon.InstanceSSHPort,
|
RemotePort: xscommon.InstanceSSHPort,
|
||||||
|
@ -7,16 +7,17 @@ import (
|
|||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
||||||
|
xsclient "github.com/xenserver/go-xenserver-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepImportInstance struct {
|
type stepImportInstance struct {
|
||||||
instance *xscommon.VM
|
instance *xsclient.VM
|
||||||
vdi *xscommon.VDI
|
vdi *xsclient.VDI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *stepImportInstance) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *stepImportInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(xscommon.XenAPIClient)
|
client := state.Get("client").(xsclient.XenAPIClient)
|
||||||
config := state.Get("config").(config)
|
config := state.Get("config").(config)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ func (self *stepImportInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
instance := xscommon.VM(*result)
|
instance := xsclient.VM(*result)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
err = instance.SetStaticMemoryRange(config.VMMemory*1024*1024, config.VMMemory*1024*1024)
|
err = instance.SetStaticMemoryRange(config.VMMemory*1024*1024, config.VMMemory*1024*1024)
|
||||||
|
Loading…
Reference in New Issue
Block a user