diff --git a/builtin/providers/vsphere/resource_vsphere_folder_test.go b/builtin/providers/vsphere/resource_vsphere_folder_test.go index c8dd9828a..4e65ca6d2 100644 --- a/builtin/providers/vsphere/resource_vsphere_folder_test.go +++ b/builtin/providers/vsphere/resource_vsphere_folder_test.go @@ -136,8 +136,8 @@ func testAccCheckVSphereFolderDestroy(s *terraform.State) error { return fmt.Errorf("error %s", err) } - _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["path"]) - if err == nil { + f, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["path"]) + if f != nil { return fmt.Errorf("Record still exists") } } diff --git a/builtin/providers/vsphere/resource_vsphere_virtual_machine.go b/builtin/providers/vsphere/resource_vsphere_virtual_machine.go index 0ae637911..724881a85 100644 --- a/builtin/providers/vsphere/resource_vsphere_virtual_machine.go +++ b/builtin/providers/vsphere/resource_vsphere_virtual_machine.go @@ -38,8 +38,9 @@ type networkInterface struct { } type hardDisk struct { - size int64 - iops int64 + size int64 + iops int64 + initType string } type virtualMachine struct { @@ -235,6 +236,21 @@ func resourceVSphereVirtualMachine() *schema.Resource { ForceNew: true, }, + "type" : &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "eager_zeroed", + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if value != "thin" && value != "eager_zeroed" { + errors = append(errors, fmt.Errorf( + "only 'thin' and 'eager_zeroed' are supported values for 'type'")) + } + return + }, + }, + "datastore": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -381,10 +397,14 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{ } else { return fmt.Errorf("Size argument is required.") } + } if v, ok := disk["iops"].(int); ok && v != 0 { disks[i].iops = int64(v) } + if v, ok := disk["type"].(string); ok && v != "" { + disks[i].initType = v + } } vm.hardDisks = disks log.Printf("[DEBUG] disk init: %v", disks) @@ -678,7 +698,7 @@ func buildNetworkDevice(f *find.Finder, label, adapterType string) (*types.Virtu } // buildVMRelocateSpec builds VirtualMachineRelocateSpec to set a place for a new VirtualMachine. -func buildVMRelocateSpec(rp *object.ResourcePool, ds *object.Datastore, vm *object.VirtualMachine) (types.VirtualMachineRelocateSpec, error) { +func buildVMRelocateSpec(rp *object.ResourcePool, ds *object.Datastore, vm *object.VirtualMachine, initType string) (types.VirtualMachineRelocateSpec, error) { var key int devices, err := vm.Device(context.TODO()) @@ -691,6 +711,7 @@ func buildVMRelocateSpec(rp *object.ResourcePool, ds *object.Datastore, vm *obje } } + isThin := initType == "thin" rpr := rp.Reference() dsr := ds.Reference() return types.VirtualMachineRelocateSpec{ @@ -701,8 +722,8 @@ func buildVMRelocateSpec(rp *object.ResourcePool, ds *object.Datastore, vm *obje Datastore: dsr, DiskBackingInfo: &types.VirtualDiskFlatVer2BackingInfo{ DiskMode: "persistent", - ThinProvisioned: types.NewBool(false), - EagerlyScrub: types.NewBool(true), + ThinProvisioned: types.NewBool(isThin), + EagerlyScrub: types.NewBool(!isThin), }, DiskId: key, }, @@ -1057,6 +1078,7 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error { object.NewFolder(c.Client, d), } sps := buildStoragePlacementSpecClone(c, dcFolders, template, resourcePool, sp) + datastore, err = findDatastore(c, sps) if err != nil { return err @@ -1068,10 +1090,11 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error { } log.Printf("[DEBUG] datastore: %#v", datastore) - relocateSpec, err := buildVMRelocateSpec(resourcePool, datastore, template) + relocateSpec, err := buildVMRelocateSpec(resourcePool, datastore, template, vm.hardDisks[0].initType) if err != nil { return err } + log.Printf("[DEBUG] relocate spec: %v", relocateSpec) // network @@ -1226,7 +1249,7 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error { log.Printf("[DEBUG]VM customization finished") for i := 1; i < len(vm.hardDisks); i++ { - err = addHardDisk(newVM, vm.hardDisks[i].size, vm.hardDisks[i].iops, "eager_zeroed") + err = addHardDisk(newVM, vm.hardDisks[i].size, vm.hardDisks[i].iops, vm.hardDisks[i].initType) if err != nil { return err } diff --git a/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go b/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go index 5d239ac5e..7f689fea3 100644 --- a/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go +++ b/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go @@ -75,6 +75,69 @@ func TestAccVSphereVirtualMachine_basic(t *testing.T) { }) } +func TestAccVSphereVirtualMachine_diskInitType(t *testing.T) { + var vm virtualMachine + var locationOpt string + var datastoreOpt string + + if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { + locationOpt += fmt.Sprintf(" datacenter = \"%s\"\n", v) + } + if v := os.Getenv("VSPHERE_CLUSTER"); v != "" { + locationOpt += fmt.Sprintf(" cluster = \"%s\"\n", v) + } + if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" { + locationOpt += fmt.Sprintf(" resource_pool = \"%s\"\n", v) + } + if v := os.Getenv("VSPHERE_DATASTORE"); v != "" { + datastoreOpt = fmt.Sprintf(" datastore = \"%s\"\n", v) + } + template := os.Getenv("VSPHERE_TEMPLATE") + gateway := os.Getenv("VSPHERE_NETWORK_GATEWAY") + label := os.Getenv("VSPHERE_NETWORK_LABEL") + ip_address := os.Getenv("VSPHERE_NETWORK_IP_ADDRESS") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: fmt.Sprintf( + testAccCheckVSphereVirtualMachineConfig_initType, + locationOpt, + gateway, + label, + ip_address, + datastoreOpt, + template, + ), + Check: resource.ComposeTestCheckFunc( + testAccCheckVSphereVirtualMachineExists("vsphere_virtual_machine.thin", &vm), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "name", "terraform-test"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "vcpu", "2"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "memory", "4096"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "disk.#", "2"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "disk.0.template", template), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "disk.0.type", "thin"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "disk.1.type", "eager_zeroed"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "network_interface.#", "1"), + resource.TestCheckResourceAttr( + "vsphere_virtual_machine.thin", "network_interface.0.label", label), + ), + }, + }, + }) +} + func TestAccVSphereVirtualMachine_dhcp(t *testing.T) { var vm virtualMachine var locationOpt string @@ -357,9 +420,9 @@ func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error { } } - _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) + v, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) - if err == nil { + if v != nil { return fmt.Errorf("Record still exists") } } @@ -525,6 +588,30 @@ resource "vsphere_virtual_machine" "foo" { } } ` +const testAccCheckVSphereVirtualMachineConfig_initType = ` +resource "vsphere_virtual_machine" "thin" { + name = "terraform-test" +%s + vcpu = 2 + memory = 4096 + gateway = "%s" + network_interface { + label = "%s" + ipv4_address = "%s" + ipv4_prefix_length = 24 + } + disk { +%s + template = "%s" + iops = 500 + type = "thin" + } + disk { + size = 1 + iops = 500 + } +} +` const testAccCheckVSphereVirtualMachineConfig_dhcp = ` resource "vsphere_virtual_machine" "bar" { name = "terraform-test" 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 008a0aed9..9812a0aed 100644 --- a/website/source/docs/providers/vsphere/r/virtual_machine.html.markdown +++ b/website/source/docs/providers/vsphere/r/virtual_machine.html.markdown @@ -68,6 +68,7 @@ The `disk` block supports: * `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. +* `type` - (Optional) 'eager_zeroed' (the default), or 'thin' are supported options. ## Attributes Reference