Merge pull request #9358 from jhawk28/bug_9349

(vsphere-iso) add the ability to check if the IP is within the an IP range
This commit is contained in:
Megan Marsh 2020-06-05 12:18:51 -07:00 committed by GitHub
commit 7fcd702b45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 6 deletions

View File

@ -51,6 +51,7 @@ type FlatConfig struct {
BootOrder *string `mapstructure:"boot_order" cty:"boot_order" hcl:"boot_order"`
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
WaitAddress *string `mapstructure:"ip_wait_address" cty:"ip_wait_address" hcl:"ip_wait_address"`
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
@ -154,6 +155,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false},
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
"ip_wait_address": &hcldec.AttrSpec{Name: "ip_wait_address", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},

View File

@ -7,6 +7,7 @@ import (
"context"
"fmt"
"log"
"net"
"time"
"github.com/hashicorp/packer/builder/vsphere/driver"
@ -16,7 +17,7 @@ import (
type WaitIpConfig struct {
// Amount of time to wait for VM's IP, similar to 'ssh_timeout'.
// Defaults to 30m (30 minutes). See the Goang
// Defaults to 30m (30 minutes). See the Golang
// [ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation
// for full details.
WaitTimeout time.Duration `mapstructure:"ip_wait_timeout"`
@ -27,6 +28,14 @@ type WaitIpConfig struct {
// [ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation
// for full details.
SettleTimeout time.Duration `mapstructure:"ip_settle_timeout"`
// Set this to a CIDR address to cause the service to wait for an address that is contained in
// this network range. Defaults to "0.0.0.0/0" for any ipv4 address. Examples include:
//
// * empty string ("") - remove all filters
// * "0:0:0:0:0:0:0:0/0" - allow only ipv6 addresses
// * "192.168.1.0/24 - only allow ipv4 addresses from 192.168.1.1 to 192.168.1.254
WaitAddress *string `mapstructure:"ip_wait_address"`
ipnet *net.IPNet
// WaitTimeout is a total timeout, so even if VM changes IP frequently and it doesn't settle down we will end waiting.
}
@ -44,6 +53,18 @@ func (c *WaitIpConfig) Prepare() []error {
if c.WaitTimeout == 0 {
c.WaitTimeout = 30 * time.Minute
}
if c.WaitAddress == nil {
addr := "0.0.0.0/0"
c.WaitAddress = &addr
}
if *c.WaitAddress != "" {
var err error
_, c.ipnet, err = net.ParseCIDR(*c.WaitAddress)
if err != nil {
errs = append(errs, fmt.Errorf("unable to parse \"ip_wait_address\": %w", err))
}
}
return errs
}
@ -111,7 +132,7 @@ func doGetIp(vm *driver.VirtualMachine, ctx context.Context, c *WaitIpConfig) (s
interval = 1 * time.Second
}
loop:
ip, err := vm.WaitForIP(ctx)
ip, err := vm.WaitForIP(ctx, c.ipnet)
if err != nil {
return "", err
}

View File

@ -11,6 +11,7 @@ import (
type FlatWaitIpConfig struct {
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
WaitAddress *string `mapstructure:"ip_wait_address" cty:"ip_wait_address" hcl:"ip_wait_address"`
}
// FlatMapstructure returns a new FlatWaitIpConfig.
@ -27,6 +28,7 @@ func (*FlatWaitIpConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
"ip_wait_address": &hcldec.AttrSpec{Name: "ip_wait_address", Type: cty.String, Required: false},
}
return s
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log"
"net"
"strings"
"time"
@ -491,8 +492,38 @@ func (vm *VirtualMachine) PowerOn() error {
return err
}
func (vm *VirtualMachine) WaitForIP(ctx context.Context) (string, error) {
return vm.vm.WaitForIP(ctx)
func (vm *VirtualMachine) WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error) {
var ip string
p := property.DefaultCollector(vm.vm.Client())
err := property.Wait(ctx, p, vm.vm.Reference(), []string{"guest.ipAddress"}, func(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Name != "guest.ipAddress" {
continue
}
if c.Op != types.PropertyChangeOpAssign {
continue
}
if c.Val == nil {
continue
}
ip = c.Val.(string)
if ipNet != nil && !ipNet.Contains(net.ParseIP(ip)) {
// ip address is not in range
return false
}
return true
}
return false
})
if err != nil {
return "", err
}
return ip, nil
}
func (vm *VirtualMachine) PowerOff() error {

View File

@ -235,7 +235,7 @@ func startAndStopCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
stopper := startVM(t, vm, config.Name)
defer stopper()
switch ip, err := vm.WaitForIP(context.TODO()); {
switch ip, err := vm.WaitForIP(context.TODO(), nil); {
case err != nil:
t.Errorf("Cannot obtain IP address from created vm '%v': %v", config.Name, err)
case net.ParseIP(ip) == nil:

View File

@ -72,6 +72,7 @@ type FlatConfig struct {
HTTPIP *string `mapstructure:"http_ip" cty:"http_ip" hcl:"http_ip"`
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
WaitAddress *string `mapstructure:"ip_wait_address" cty:"ip_wait_address" hcl:"ip_wait_address"`
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
@ -196,6 +197,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"http_ip": &hcldec.AttrSpec{Name: "http_ip", Type: cty.String, Required: false},
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
"ip_wait_address": &hcldec.AttrSpec{Name: "ip_wait_address", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},

View File

@ -1,7 +1,7 @@
<!-- Code generated from the comments of the WaitIpConfig struct in builder/vsphere/common/step_wait_for_ip.go; DO NOT EDIT MANUALLY -->
- `ip_wait_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for VM's IP, similar to 'ssh_timeout'.
Defaults to 30m (30 minutes). See the Goang
Defaults to 30m (30 minutes). See the Golang
[ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation
for full details.
@ -11,4 +11,11 @@
5s(5 seconds). See the Golang
[ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation
for full details.
- `ip_wait_address` (\*string) - Set this to a CIDR address to cause the service to wait for an address that is contained in
this network range. Defaults to "0.0.0.0/0" for any ipv4 address. Examples include:
* empty string ("") - remove all filters
* "0:0:0:0:0:0:0:0/0" - allow only ipv6 addresses
* "192.168.1.0/24 - only allow ipv4 addresses from 192.168.1.1 to 192.168.1.254