mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-09 08:42:33 -04:00
Don't wait for IP till heat death of the universe
Introduced 'ip_wait_timeout' parameter with '5m' (five minutes) default value.
This commit is contained in:
parent
9b254b2f53
commit
a9ffa1559e
2 changed files with 33 additions and 12 deletions
|
|
@ -109,6 +109,7 @@ See complete Ubuntu, Windows, and macOS templates in the [examples folder](https
|
|||
### Provision
|
||||
|
||||
* `communicator` - `ssh` (default), `winrm`, or `none` (create/clone, customize hardware, but do not boot).
|
||||
* `ip_wait_timeout`(string) - Amount of time to wait for VM's IP, similar to 'ssh_timeout'. Defaults to 5m (5 minutes). See the Go Lang [ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation for full details.
|
||||
* `ip_settle_timeout`(string) - Amount of time to wait for VM's IP to settle down, sometimes VM may report incorrect IP initially, then its recommended to set that parameter to apx. 2 minutes. Examples 45s and 10m. Defaults to 5s(5 seconds). See the Go Lang [ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation for full details.
|
||||
* `ssh_username`(string) - Username in guest OS.
|
||||
* `ssh_password`(string) - Password to access guest OS. Only specify `ssh_password` or `ssh_private_key_file`, but not both.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ import (
|
|||
)
|
||||
|
||||
type WaitIpConfig struct {
|
||||
WaitTimeout time.Duration `mapstructure:"ip_wait_timeout"`
|
||||
SettleTimeout time.Duration `mapstructure:"ip_settle_timeout"`
|
||||
|
||||
// WaitTimeout is a total timeout, so even if VM changes IP frequently and it doesn't settle down we will end waiting.
|
||||
}
|
||||
|
||||
type StepWaitForIp struct {
|
||||
|
|
@ -24,6 +27,10 @@ func (c *WaitIpConfig) Prepare() []error {
|
|||
if c.SettleTimeout == 0 {
|
||||
c.SettleTimeout = 5 * time.Second
|
||||
}
|
||||
if c.WaitTimeout == 0 {
|
||||
// Same default value as default timeout for 'ssh_timeout' in StepConnect
|
||||
c.SettleTimeout = 5 * time.Minute
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
|
@ -32,22 +39,37 @@ func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
|
||||
ui.Say("Waiting for IP...")
|
||||
var ip string
|
||||
var err error
|
||||
|
||||
sub, cancel := context.WithCancel(ctx)
|
||||
waitDone := make(chan bool, 1)
|
||||
|
||||
ipChan := make(chan string)
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
doGetIp(vm, ctx, s.Config, errChan, ipChan)
|
||||
ui.Say("Waiting for IP...")
|
||||
ip, err = doGetIp(vm, sub, s.Config)
|
||||
waitDone <- true
|
||||
}()
|
||||
|
||||
log.Printf("[INFO] Waiting for IP, up to total timeout: %s, settle timeout: %s", s.Config.WaitTimeout, s.Config.SettleTimeout)
|
||||
timeout := time.After(s.Config.WaitTimeout)
|
||||
for {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
case <-timeout:
|
||||
err := fmt.Errorf("Timeout waiting for IP.")
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
cancel()
|
||||
return multistep.ActionHalt
|
||||
case <-ctx.Done():
|
||||
cancel()
|
||||
log.Println("[WARN] Interrupt detected, quitting waiting for IP.")
|
||||
return multistep.ActionHalt
|
||||
case ip := <-ipChan:
|
||||
case <-waitDone:
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("ip", ip)
|
||||
ui.Say(fmt.Sprintf("IP address: %v", ip))
|
||||
return multistep.ActionContinue
|
||||
|
|
@ -59,7 +81,7 @@ func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
}
|
||||
}
|
||||
|
||||
func doGetIp(vm *driver.VirtualMachine, ctx context.Context, c *WaitIpConfig, errChan chan error, ipChan chan string) {
|
||||
func doGetIp(vm *driver.VirtualMachine, ctx context.Context, c *WaitIpConfig) (string, error) {
|
||||
var prevIp = ""
|
||||
var stopTime time.Time
|
||||
var interval time.Duration
|
||||
|
|
@ -75,8 +97,7 @@ func doGetIp(vm *driver.VirtualMachine, ctx context.Context, c *WaitIpConfig, er
|
|||
loop:
|
||||
ip, err := vm.WaitForIP(ctx)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
return "", err
|
||||
}
|
||||
if prevIp == "" || prevIp != ip {
|
||||
if prevIp == "" {
|
||||
|
|
@ -91,12 +112,11 @@ loop:
|
|||
log.Printf("VM IP is still the same: %s", prevIp)
|
||||
if time.Now().After(stopTime) {
|
||||
log.Printf("VM IP seems stable enough: %s", ip)
|
||||
ipChan <- ip
|
||||
return
|
||||
return ip, nil
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
return "", fmt.Errorf("IP wait cancelled")
|
||||
case <-time.After(interval):
|
||||
goto loop
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue