From 68ac4bceafcefe17e5ad25f87df1d6dd40e974fe Mon Sep 17 00:00:00 2001 From: Takaaki Furukawa Date: Tue, 24 Nov 2015 09:53:11 +0900 Subject: [PATCH] provider/vsphere: Change ip_address parameter to ipv4_address and ipv6_address for ipv6 support --- .../resource_vsphere_virtual_machine.go | 111 +++++++++++++----- .../resource_vsphere_virtual_machine_test.go | 4 +- .../vsphere/r/virtual_machine.html.markdown | 34 ++++-- 3 files changed, 106 insertions(+), 43 deletions(-) diff --git a/builtin/providers/vsphere/resource_vsphere_virtual_machine.go b/builtin/providers/vsphere/resource_vsphere_virtual_machine.go index 98a523488..9c4db401f 100644 --- a/builtin/providers/vsphere/resource_vsphere_virtual_machine.go +++ b/builtin/providers/vsphere/resource_vsphere_virtual_machine.go @@ -28,11 +28,13 @@ var DefaultDNSServers = []string{ } type networkInterface struct { - deviceName string - label string - ipAddress string - subnetMask string - adapterType string // TODO: Make "adapter_type" argument + deviceName string + label string + ipv4Address string + ipv4PrefixLength int + ipv6Address string + ipv6PrefixLength int + adapterType string // TODO: Make "adapter_type" argument } type hardDisk struct { @@ -148,15 +150,40 @@ func resourceVSphereVirtualMachine() *schema.Resource { }, "ip_address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Deprecated: "Please use ipv4_address", + }, + + "subnet_mask": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Deprecated: "Please use ipv4_prefix_length", + }, + + "ipv4_address": &schema.Schema{ Type: schema.TypeString, Optional: true, Computed: true, + }, + + "ipv4_prefix_length": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + + // TODO: Imprement ipv6 parameters to be optional + "ipv6_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, ForceNew: true, }, - "subnet_mask": &schema.Schema{ - Type: schema.TypeString, - Optional: true, + "ipv6_prefix_length": &schema.Schema{ + Type: schema.TypeInt, Computed: true, ForceNew: true, }, @@ -267,10 +294,23 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{ network := v.(map[string]interface{}) networks[i].label = network["label"].(string) if v, ok := network["ip_address"].(string); ok && v != "" { - networks[i].ipAddress = v + networks[i].ipv4Address = v } if v, ok := network["subnet_mask"].(string); ok && v != "" { - networks[i].subnetMask = v + ip := net.ParseIP(v).To4() + if ip != nil { + mask := net.IPv4Mask(ip[0], ip[1], ip[2], ip[3]) + pl, _ := mask.Size() + networks[i].ipv4PrefixLength = pl + } else { + return fmt.Errorf("subnet_mask parameter is invalid.") + } + } + if v, ok := network["ipv4_address"].(string); ok && v != "" { + networks[i].ipv4Address = v + } + if v, ok := network["ipv4_prefix_length"].(int); ok && v != 0 { + networks[i].ipv4PrefixLength = v } } vm.networkInterfaces = networks @@ -321,7 +361,7 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{ } } - if _, ok := d.GetOk("network_interface.0.ip_address"); !ok { + if _, ok := d.GetOk("network_interface.0.ipv4_address"); !ok { if v, ok := d.GetOk("boot_delay"); ok { stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, @@ -377,15 +417,22 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] %#v", v.Network) networkInterface := make(map[string]interface{}) networkInterface["label"] = v.Network - if len(v.IpAddress) > 0 { - log.Printf("[DEBUG] %#v", v.IpAddress[0]) - networkInterface["ip_address"] = v.IpAddress[0] - - m := net.CIDRMask(v.IpConfig.IpAddress[0].PrefixLength, 32) - subnetMask := net.IPv4(m[0], m[1], m[2], m[3]) - networkInterface["subnet_mask"] = subnetMask.String() - log.Printf("[DEBUG] %#v", subnetMask.String()) + for _, ip := range v.IpConfig.IpAddress { + p := net.ParseIP(ip.IpAddress) + if p.To4() != nil { + log.Printf("[DEBUG] %#v", p.String()) + log.Printf("[DEBUG] %#v", ip.PrefixLength) + networkInterface["ipv4_address"] = p.String() + networkInterface["ipv4_prefix_length"] = ip.PrefixLength + } else if p.To16() != nil { + log.Printf("[DEBUG] %#v", p.String()) + log.Printf("[DEBUG] %#v", ip.PrefixLength) + networkInterface["ipv6_address"] = p.String() + networkInterface["ipv6_prefix_length"] = ip.PrefixLength + } + log.Printf("[DEBUG] networkInterface: %#v", networkInterface) } + log.Printf("[DEBUG] networkInterface: %#v", networkInterface) networkInterfaces = append(networkInterfaces, networkInterface) } } @@ -420,14 +467,6 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{}) d.Set("cpu", mvm.Summary.Config.NumCpu) d.Set("datastore", rootDatastore) - // Initialize the connection info - if len(networkInterfaces) > 0 { - d.SetConnInfo(map[string]string{ - "type": "ssh", - "host": networkInterfaces[0]["ip_address"].(string), - }) - } - return nil } @@ -967,23 +1006,31 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error { } networkDevices = append(networkDevices, nd) + // TODO: IPv6 support var ipSetting types.CustomizationIPSettings - if network.ipAddress == "" { + if network.ipv4Address == "" { ipSetting = types.CustomizationIPSettings{ Ip: &types.CustomizationDhcpIpGenerator{}, } } else { + if network.ipv4PrefixLength == 0 { + return fmt.Errorf("Error: ipv4_prefix_length argument is empty.") + } + m := net.CIDRMask(network.ipv4PrefixLength, 32) + sm := net.IPv4(m[0], m[1], m[2], m[3]) + subnetMask := sm.String() log.Printf("[DEBUG] gateway: %v", vm.gateway) - log.Printf("[DEBUG] ip address: %v", network.ipAddress) - log.Printf("[DEBUG] subnet mask: %v", network.subnetMask) + log.Printf("[DEBUG] ipv4 address: %v", network.ipv4Address) + log.Printf("[DEBUG] ipv4 prefix length: %v", network.ipv4PrefixLength) + log.Printf("[DEBUG] ipv4 subnet mask: %v", subnetMask) ipSetting = types.CustomizationIPSettings{ Gateway: []string{ vm.gateway, }, Ip: &types.CustomizationFixedIp{ - IpAddress: network.ipAddress, + IpAddress: network.ipv4Address, }, - SubnetMask: network.subnetMask, + SubnetMask: subnetMask, } } diff --git a/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go b/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go index 66d6ea44f..102db6993 100644 --- a/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go +++ b/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go @@ -198,8 +198,8 @@ resource "vsphere_virtual_machine" "foo" { gateway = "%s" network_interface { label = "%s" - ip_address = "%s" - subnet_mask = "255.255.255.0" + ipv4_address = "%s" + ipv4_prefix_length = 24 } disk { %s diff --git a/website/source/docs/providers/vsphere/r/virtual_machine.html.markdown b/website/source/docs/providers/vsphere/r/virtual_machine.html.markdown index 19421aaa9..4c704bf17 100644 --- a/website/source/docs/providers/vsphere/r/virtual_machine.html.markdown +++ b/website/source/docs/providers/vsphere/r/virtual_machine.html.markdown @@ -49,21 +49,37 @@ The following arguments are supported: * `disk` - (Required) Configures virtual disks; see [Disks](#disks) below for details * `boot_delay` - (Optional) Time in seconds to wait for machine network to be ready. - -## Network Interfaces - -Network interfaces support the following attributes: +The `network_interface` block supports: * `label` - (Required) Label to assign to this network interface -* `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. -* `subnet_mask` - (Optional) Subnet mask to use when statically assigning an IP. +* `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. +* `ipv4_prefix_length` - (Optional) prefix length to use when statically assigning an IP. - -## Disks +The following arguments are maintained for backwards compatibility and may be +removed in a future version: -Disks support the following attributes: +* `ip_address` - __Deprecated, please use `ipv4_address` instead_. +* `subnet_mask` - __Deprecated, please use `ipv4_prefix_length` instead_. + + +The `disk` block supports: * `template` - (Required if size not provided) Template for this disk. * `datastore` - (Optional) Datastore for this disk * `size` - (Required if template not provided) Size of this disk (in GB). * `iops` - (Optional) Number of virtual iops to allocate for this disk. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The instance ID. +* `name` - See Argument Reference above. +* `vcpu` - See Argument Reference above. +* `memory` - See Argument Reference above. +* `datacenter` - See Argument Reference above. +* `network_interface/label` - See Argument Reference above. +* `network_interface/ipv4_address` - See Argument Reference above. +* `network_interface/ipv4_prefix_length` - See Argument Reference above. +* `network_interface/ipv6_address` - Assigned static IPv6 address. +* `network_interface/ipv6_prefix_length` - Prefix length of assigned static IPv6 address.