Skip to content

Commit 231f0cb

Browse files
committed
Merge pull request hashicorp#4035 from rakutentech/fix-ipv6-bug
provider/vsphere: Change ip_address parameter for ipv6 support
2 parents 21aa9dd + 68ac4bc commit 231f0cb

3 files changed

Lines changed: 106 additions & 43 deletions

File tree

builtin/providers/vsphere/resource_vsphere_virtual_machine.go

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ var DefaultDNSServers = []string{
2828
}
2929

3030
type networkInterface struct {
31-
deviceName string
32-
label string
33-
ipAddress string
34-
subnetMask string
35-
adapterType string // TODO: Make "adapter_type" argument
31+
deviceName string
32+
label string
33+
ipv4Address string
34+
ipv4PrefixLength int
35+
ipv6Address string
36+
ipv6PrefixLength int
37+
adapterType string // TODO: Make "adapter_type" argument
3638
}
3739

3840
type hardDisk struct {
@@ -174,16 +176,41 @@ func resourceVSphereVirtualMachine() *schema.Resource {
174176
},
175177

176178
"ip_address": &schema.Schema{
179+
Type: schema.TypeString,
180+
Optional: true,
181+
Computed: true,
182+
Deprecated: "Please use ipv4_address",
183+
},
184+
185+
"subnet_mask": &schema.Schema{
186+
Type: schema.TypeString,
187+
Optional: true,
188+
Computed: true,
189+
Deprecated: "Please use ipv4_prefix_length",
190+
},
191+
192+
"ipv4_address": &schema.Schema{
177193
Type: schema.TypeString,
178194
Optional: true,
179195
Computed: true,
180-
ForceNew: true,
181196
},
182197

183-
"subnet_mask": &schema.Schema{
184-
Type: schema.TypeString,
198+
"ipv4_prefix_length": &schema.Schema{
199+
Type: schema.TypeInt,
185200
Optional: true,
186201
Computed: true,
202+
},
203+
204+
// TODO: Imprement ipv6 parameters to be optional
205+
"ipv6_address": &schema.Schema{
206+
Type: schema.TypeString,
207+
Computed: true,
208+
ForceNew: true,
209+
},
210+
211+
"ipv6_prefix_length": &schema.Schema{
212+
Type: schema.TypeInt,
213+
Computed: true,
187214
ForceNew: true,
188215
},
189216

@@ -308,10 +335,23 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
308335
network := v.(map[string]interface{})
309336
networks[i].label = network["label"].(string)
310337
if v, ok := network["ip_address"].(string); ok && v != "" {
311-
networks[i].ipAddress = v
338+
networks[i].ipv4Address = v
312339
}
313340
if v, ok := network["subnet_mask"].(string); ok && v != "" {
314-
networks[i].subnetMask = v
341+
ip := net.ParseIP(v).To4()
342+
if ip != nil {
343+
mask := net.IPv4Mask(ip[0], ip[1], ip[2], ip[3])
344+
pl, _ := mask.Size()
345+
networks[i].ipv4PrefixLength = pl
346+
} else {
347+
return fmt.Errorf("subnet_mask parameter is invalid.")
348+
}
349+
}
350+
if v, ok := network["ipv4_address"].(string); ok && v != "" {
351+
networks[i].ipv4Address = v
352+
}
353+
if v, ok := network["ipv4_prefix_length"].(int); ok && v != 0 {
354+
networks[i].ipv4PrefixLength = v
315355
}
316356
}
317357
vm.networkInterfaces = networks
@@ -362,7 +402,7 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
362402
}
363403
}
364404

365-
if _, ok := d.GetOk("network_interface.0.ip_address"); !ok {
405+
if _, ok := d.GetOk("network_interface.0.ipv4_address"); !ok {
366406
if v, ok := d.GetOk("boot_delay"); ok {
367407
stateConf := &resource.StateChangeConf{
368408
Pending: []string{"pending"},
@@ -419,15 +459,22 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{})
419459
log.Printf("[DEBUG] %#v", v.Network)
420460
networkInterface := make(map[string]interface{})
421461
networkInterface["label"] = v.Network
422-
if len(v.IpAddress) > 0 {
423-
log.Printf("[DEBUG] %#v", v.IpAddress[0])
424-
networkInterface["ip_address"] = v.IpAddress[0]
425-
426-
m := net.CIDRMask(v.IpConfig.IpAddress[0].PrefixLength, 32)
427-
subnetMask := net.IPv4(m[0], m[1], m[2], m[3])
428-
networkInterface["subnet_mask"] = subnetMask.String()
429-
log.Printf("[DEBUG] %#v", subnetMask.String())
462+
for _, ip := range v.IpConfig.IpAddress {
463+
p := net.ParseIP(ip.IpAddress)
464+
if p.To4() != nil {
465+
log.Printf("[DEBUG] %#v", p.String())
466+
log.Printf("[DEBUG] %#v", ip.PrefixLength)
467+
networkInterface["ipv4_address"] = p.String()
468+
networkInterface["ipv4_prefix_length"] = ip.PrefixLength
469+
} else if p.To16() != nil {
470+
log.Printf("[DEBUG] %#v", p.String())
471+
log.Printf("[DEBUG] %#v", ip.PrefixLength)
472+
networkInterface["ipv6_address"] = p.String()
473+
networkInterface["ipv6_prefix_length"] = ip.PrefixLength
474+
}
475+
log.Printf("[DEBUG] networkInterface: %#v", networkInterface)
430476
}
477+
log.Printf("[DEBUG] networkInterface: %#v", networkInterface)
431478
networkInterfaces = append(networkInterfaces, networkInterface)
432479
}
433480
}
@@ -462,14 +509,6 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{})
462509
d.Set("cpu", mvm.Summary.Config.NumCpu)
463510
d.Set("datastore", rootDatastore)
464511

465-
// Initialize the connection info
466-
if len(networkInterfaces) > 0 {
467-
d.SetConnInfo(map[string]string{
468-
"type": "ssh",
469-
"host": networkInterfaces[0]["ip_address"].(string),
470-
})
471-
}
472-
473512
return nil
474513
}
475514

@@ -1046,23 +1085,31 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
10461085
}
10471086
networkDevices = append(networkDevices, nd)
10481087

1088+
// TODO: IPv6 support
10491089
var ipSetting types.CustomizationIPSettings
1050-
if network.ipAddress == "" {
1090+
if network.ipv4Address == "" {
10511091
ipSetting = types.CustomizationIPSettings{
10521092
Ip: &types.CustomizationDhcpIpGenerator{},
10531093
}
10541094
} else {
1095+
if network.ipv4PrefixLength == 0 {
1096+
return fmt.Errorf("Error: ipv4_prefix_length argument is empty.")
1097+
}
1098+
m := net.CIDRMask(network.ipv4PrefixLength, 32)
1099+
sm := net.IPv4(m[0], m[1], m[2], m[3])
1100+
subnetMask := sm.String()
10551101
log.Printf("[DEBUG] gateway: %v", vm.gateway)
1056-
log.Printf("[DEBUG] ip address: %v", network.ipAddress)
1057-
log.Printf("[DEBUG] subnet mask: %v", network.subnetMask)
1102+
log.Printf("[DEBUG] ipv4 address: %v", network.ipv4Address)
1103+
log.Printf("[DEBUG] ipv4 prefix length: %v", network.ipv4PrefixLength)
1104+
log.Printf("[DEBUG] ipv4 subnet mask: %v", subnetMask)
10581105
ipSetting = types.CustomizationIPSettings{
10591106
Gateway: []string{
10601107
vm.gateway,
10611108
},
10621109
Ip: &types.CustomizationFixedIp{
1063-
IpAddress: network.ipAddress,
1110+
IpAddress: network.ipv4Address,
10641111
},
1065-
SubnetMask: network.subnetMask,
1112+
SubnetMask: subnetMask,
10661113
}
10671114
}
10681115

builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,8 +511,8 @@ resource "vsphere_virtual_machine" "foo" {
511511
gateway = "%s"
512512
network_interface {
513513
label = "%s"
514-
ip_address = "%s"
515-
subnet_mask = "255.255.255.0"
514+
ipv4_address = "%s"
515+
ipv4_prefix_length = 24
516516
}
517517
disk {
518518
%s

website/source/docs/providers/vsphere/r/virtual_machine.html.markdown

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,37 @@ The following arguments are supported:
4949
* `boot_delay` - (Optional) Time in seconds to wait for machine network to be ready.
5050
* `custom_configuration_parameters` - (Optional) Map of values that is set as virtual machine custom configurations.
5151

52-
<a id="network-interfaces"></a>
53-
## Network Interfaces
54-
55-
Network interfaces support the following attributes:
52+
The `network_interface` block supports:
5653

5754
* `label` - (Required) Label to assign to this network interface
58-
* `ip_address` - (Optional) Static IP to assign to this network interface. Interface will use DHCP if this is left blank. Currently only IPv4 IP addresses are supported.
59-
* `subnet_mask` - (Optional) Subnet mask to use when statically assigning an IP.
55+
* `ipv4_address` - (Optional) Static IP to assign to this network interface. Interface will use DHCP if this is left blank. Currently only IPv4 IP addresses are supported.
56+
* `ipv4_prefix_length` - (Optional) prefix length to use when statically assigning an IP.
57+
58+
The following arguments are maintained for backwards compatibility and may be
59+
removed in a future version:
60+
61+
* `ip_address` - __Deprecated, please use `ipv4_address` instead_.
62+
* `subnet_mask` - __Deprecated, please use `ipv4_prefix_length` instead_.
6063

61-
<a id="disks"></a>
62-
## Disks
6364

64-
Disks support the following attributes:
65+
The `disk` block supports:
6566

6667
* `template` - (Required if size not provided) Template for this disk.
6768
* `datastore` - (Optional) Datastore for this disk
6869
* `size` - (Required if template not provided) Size of this disk (in GB).
6970
* `iops` - (Optional) Number of virtual iops to allocate for this disk.
71+
72+
## Attributes Reference
73+
74+
The following attributes are exported:
75+
76+
* `id` - The instance ID.
77+
* `name` - See Argument Reference above.
78+
* `vcpu` - See Argument Reference above.
79+
* `memory` - See Argument Reference above.
80+
* `datacenter` - See Argument Reference above.
81+
* `network_interface/label` - See Argument Reference above.
82+
* `network_interface/ipv4_address` - See Argument Reference above.
83+
* `network_interface/ipv4_prefix_length` - See Argument Reference above.
84+
* `network_interface/ipv6_address` - Assigned static IPv6 address.
85+
* `network_interface/ipv6_prefix_length` - Prefix length of assigned static IPv6 address.

0 commit comments

Comments
 (0)