Try getting IP if reported by PV drivers

This commit is contained in:
Cheng Sun 2015-01-05 16:35:00 +00:00
parent 176c4ad7a3
commit 6ef9b70500
4 changed files with 89 additions and 53 deletions

View File

@ -491,21 +491,20 @@ func (self *VM) GetGuestMetricsRef() (ref string, err error) {
} }
func (self *VM) GetGuestMetrics() (metrics map[string]interface{}, err error) { func (self *VM) GetGuestMetrics() (metrics map[string]interface{}, err error) {
metrics = make(map[string]interface{})
metrics_ref, err := self.GetGuestMetricsRef() metrics_ref, err := self.GetGuestMetricsRef()
if err != nil { if err != nil {
return metrics, err return nil, err
}
if metrics_ref == "OpaqueRef:NULL" {
return nil, nil
} }
result := APIResult{} result := APIResult{}
err = self.Client.APICall(&result, "VM_guest_metrics.get_record", metrics_ref) err = self.Client.APICall(&result, "VM_guest_metrics.get_record", metrics_ref)
if err != nil { if err != nil {
return metrics, nil return nil, err
} }
for k, v := range result.Value.(xmlrpc.Struct) { return result.Value.(xmlrpc.Struct), nil
metrics[k] = v
}
return metrics, nil
} }
func (self *VM) SetStaticMemoryRange(min, max uint) (err error) { func (self *VM) SetStaticMemoryRange(min, max uint) (err error) {

View File

@ -1,45 +0,0 @@
package common
import (
"fmt"
"time"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
type StepWaitForHTTPRequest struct {
Chan <-chan string
Timeout time.Duration
}
func (self *StepWaitForHTTPRequest) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
ui.Say("Step: Wait for install to complete.")
timeout := time.After(self.Timeout)
var ip string
select {
case ip = <-self.Chan:
case <-timeout:
ui.Error("Timed out. Giving up waiting for installation to complete.")
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Got IP address '%s'", ip))
state.Put("instance_ssh_address", ip)
return multistep.ActionContinue
}
func (self *StepWaitForHTTPRequest) Cleanup(state multistep.StateBag) {}
func InstanceSSHIP(state multistep.StateBag) (string, error) {
ip := state.Get("instance_ssh_address").(string)
return ip, nil
}
func InstanceSSHPort(state multistep.StateBag) (uint, error) {
return 22, nil
}

View File

@ -0,0 +1,82 @@
package common
import (
"fmt"
"time"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/nilshell/xmlrpc"
)
type StepWaitForIP struct {
Chan <-chan string
Timeout time.Duration
}
func (self *StepWaitForIP) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
client := state.Get("client").(XenAPIClient)
ui.Say("Step: Wait for VM's IP to become known to us.")
uuid := state.Get("instance_uuid").(string)
instance, err := client.GetVMByUuid(uuid)
if err != nil {
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
return multistep.ActionHalt
}
var ip string
err = InterruptibleWait{
Timeout: self.Timeout,
PredicateInterval: 5 * time.Second,
Predicate: func() (result bool, err error) {
// first check if we got any HTTP requests
select {
case ip = <-self.Chan:
ui.Message(fmt.Sprintf("Got IP '%s' from HTTP request", ip))
return true, nil
default:
}
// failing that, look for PV IP
metrics, err := instance.GetGuestMetrics()
if err != nil {
return false, err
}
if metrics != nil {
networks := metrics["networks"].(xmlrpc.Struct)
if ipRaw, ok := networks["0/ip"]; ok {
if ip = ipRaw.(string); ip != "" {
ui.Message(fmt.Sprintf("Got IP '%s' from XenServer tools", ip))
return true, nil
}
}
}
return false, nil
},
}.Wait(state)
if err != nil {
ui.Error(fmt.Sprintf("Could not get IP address of VM: %s", err.Error()))
// @todo: give advice on what went wrong (no HTTP server? no PV drivers?)
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Got IP address '%s'", ip))
state.Put("instance_ssh_address", ip)
return multistep.ActionContinue
}
func (self *StepWaitForIP) Cleanup(state multistep.StateBag) {}
func InstanceSSHIP(state multistep.StateBag) (string, error) {
ip := state.Get("instance_ssh_address").(string)
return ip, nil
}
func InstanceSSHPort(state multistep.StateBag) (uint, error) {
return 22, nil
}

View File

@ -254,7 +254,7 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
&xscommon.StepTypeBootCommand{ &xscommon.StepTypeBootCommand{
Tpl: self.config.tpl, Tpl: self.config.tpl,
}, },
&xscommon.StepWaitForHTTPRequest{ &xscommon.StepWaitForIP{
Chan: httpReqChan, Chan: httpReqChan,
Timeout: self.config.InstallTimeout, // @todo change this Timeout: self.config.InstallTimeout, // @todo change this
}, },