mirror of
https://github.com/hashicorp/packer.git
synced 2026-05-28 04:35:38 -04:00
Support IP address settle down timeout
Sometimes it's possible that Windows VM starts with one address and then changes to another one. For successful communication we need latest one
This commit is contained in:
parent
f7151b4058
commit
1111c74696
6 changed files with 88 additions and 14 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_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.
|
||||
* `ssh_private_key_file`(string) - Path to the SSH private key file to access guest OS. Only specify `ssh_password` or `ssh_private_key_file`, but not both.
|
||||
|
|
|
|||
|
|
@ -55,7 +55,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
Config: &b.config.RunConfig,
|
||||
SetOrder: false,
|
||||
},
|
||||
&common.StepWaitForIp{},
|
||||
&common.StepWaitForIp{
|
||||
&b.config.WaitIpConfig,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: common.CommHost(b.config.Comm.SSHHost),
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type Config struct {
|
|||
common.ConfigParamsConfig `mapstructure:",squash"`
|
||||
|
||||
common.RunConfig `mapstructure:",squash"`
|
||||
common.WaitIpConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
common.ShutdownConfig `mapstructure:",squash"`
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
|||
errs = packer.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
|
||||
|
||||
errs = packer.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare()...)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,35 @@ import (
|
|||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StepWaitForIp struct{}
|
||||
type WaitIpConfig struct {
|
||||
SettleTimeout string `mapstructure:"ip_settle_timeout"`
|
||||
|
||||
settleTimeout time.Duration
|
||||
}
|
||||
|
||||
type StepWaitForIp struct {
|
||||
Config *WaitIpConfig
|
||||
}
|
||||
|
||||
func (c *WaitIpConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.SettleTimeout == "" {
|
||||
c.SettleTimeout = "5s"
|
||||
}
|
||||
|
||||
var err error
|
||||
c.settleTimeout, err = time.ParseDuration(c.SettleTimeout)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed parsing ip_settle_timeout: %s", err))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
|
@ -20,12 +45,7 @@ func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
ipChan := make(chan string)
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
ip, err := vm.WaitForIP(ctx)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
} else {
|
||||
ipChan <- ip
|
||||
}
|
||||
doGetIp(vm, ctx, s.Config, errChan, ipChan)
|
||||
}()
|
||||
|
||||
for {
|
||||
|
|
@ -47,4 +67,49 @@ 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) {
|
||||
var prevIp = ""
|
||||
var stopTime time.Time
|
||||
var interval time.Duration
|
||||
if c.settleTimeout.Seconds() >= 120 {
|
||||
interval = 30 * time.Second
|
||||
} else if c.settleTimeout.Seconds() >= 60 {
|
||||
interval = 15 * time.Second
|
||||
} else if c.settleTimeout.Seconds() >= 10 {
|
||||
interval = 5 * time.Second
|
||||
} else {
|
||||
interval = 1 * time.Second
|
||||
}
|
||||
loop:
|
||||
ip, err := vm.WaitForIP(ctx)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
if prevIp == "" || prevIp != ip {
|
||||
if prevIp == "" {
|
||||
log.Printf("VM IP aquired: %s", ip)
|
||||
} else {
|
||||
log.Printf("VM IP changed from %s to %s", prevIp, ip)
|
||||
}
|
||||
prevIp = ip
|
||||
stopTime = time.Now().Add(c.settleTimeout)
|
||||
goto loop
|
||||
} else {
|
||||
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
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-time.After(interval):
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *StepWaitForIp) Cleanup(state multistep.StateBag) {}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
Ctx: b.config.ctx,
|
||||
VMName: b.config.VMName,
|
||||
},
|
||||
&common.StepWaitForIp{},
|
||||
&common.StepWaitForIp{
|
||||
Config: &b.config.WaitIpConfig,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: common.CommHost(b.config.Comm.SSHHost),
|
||||
|
|
|
|||
|
|
@ -21,11 +21,12 @@ type Config struct {
|
|||
|
||||
packerCommon.ISOConfig `mapstructure:",squash"`
|
||||
|
||||
CDRomConfig `mapstructure:",squash"`
|
||||
FloppyConfig `mapstructure:",squash"`
|
||||
common.RunConfig `mapstructure:",squash"`
|
||||
BootConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
CDRomConfig `mapstructure:",squash"`
|
||||
FloppyConfig `mapstructure:",squash"`
|
||||
common.RunConfig `mapstructure:",squash"`
|
||||
BootConfig `mapstructure:",squash"`
|
||||
common.WaitIpConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
|
||||
common.ShutdownConfig `mapstructure:",squash"`
|
||||
|
||||
|
|
@ -67,6 +68,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
|||
|
||||
errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare()...)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue