github.com/gabrielperezs/terraform@v0.7.0-rc2.0.20160715084931-f7da2612946f/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go (about)

     1  package vsphere
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"regexp"
     8  	"testing"
     9  
    10  	"path/filepath"
    11  
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/terraform"
    14  	"github.com/vmware/govmomi"
    15  	"github.com/vmware/govmomi/find"
    16  	"github.com/vmware/govmomi/object"
    17  	"github.com/vmware/govmomi/property"
    18  	"github.com/vmware/govmomi/vim25/mo"
    19  	"github.com/vmware/govmomi/vim25/types"
    20  	"golang.org/x/net/context"
    21  )
    22  
    23  ///////
    24  // Various ENV vars are used to setup these tests. Look for `os.Getenv`
    25  ///////
    26  
    27  // Base setup function to check that a template, and nic information is set
    28  // TODO needs some TLC - determine exactly how we want to do this
    29  func testBasicPreCheck(t *testing.T) {
    30  
    31  	testAccPreCheck(t)
    32  
    33  	if v := os.Getenv("VSPHERE_TEMPLATE"); v == "" {
    34  		t.Fatal("env variable VSPHERE_TEMPLATE must be set for acceptance tests")
    35  	}
    36  
    37  	if v := os.Getenv("VSPHERE_IPV4_GATEWAY"); v == "" {
    38  		t.Fatal("env variable VSPHERE_IPV4_GATEWAY must be set for acceptance tests")
    39  	}
    40  
    41  	if v := os.Getenv("VSPHERE_IPV4_ADDRESS"); v == "" {
    42  		t.Fatal("env variable VSPHERE_IPV4_ADDRESS must be set for acceptance tests")
    43  	}
    44  
    45  	if v := os.Getenv("VSPHERE_NETWORK_LABEL"); v == "" {
    46  		t.Fatal("env variable VSPHERE_NETWORK_LABEL must be set for acceptance tests")
    47  	}
    48  }
    49  
    50  ////
    51  // Collects optional env vars used in the tests
    52  ////
    53  func setupBaseVars() (string, string) {
    54  	var locationOpt string
    55  	var datastoreOpt string
    56  
    57  	if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
    58  		locationOpt += fmt.Sprintf("    datacenter = \"%s\"\n", v)
    59  	}
    60  	if v := os.Getenv("VSPHERE_CLUSTER"); v != "" {
    61  		locationOpt += fmt.Sprintf("    cluster = \"%s\"\n", v)
    62  	}
    63  	if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" {
    64  		locationOpt += fmt.Sprintf("    resource_pool = \"%s\"\n", v)
    65  	}
    66  	if v := os.Getenv("VSPHERE_DATASTORE"); v != "" {
    67  		datastoreOpt = fmt.Sprintf("        datastore = \"%s\"\n", v)
    68  	}
    69  
    70  	return locationOpt, datastoreOpt
    71  }
    72  
    73  ////
    74  // Structs and funcs used with DHCP data template
    75  ////
    76  type TestDHCPBodyData struct {
    77  	template     string
    78  	locationOpt  string
    79  	datastoreOpt string
    80  	label        string
    81  }
    82  
    83  func (body TestDHCPBodyData) parseDHCPTemplateConfigWithTemplate(template string) string {
    84  	return fmt.Sprintf(
    85  		template,
    86  		body.locationOpt,
    87  		body.label,
    88  		body.datastoreOpt,
    89  		body.template,
    90  	)
    91  
    92  }
    93  
    94  const testAccCheckVSphereTemplate_dhcp = `
    95  %s
    96    vcpu = 2
    97    memory = 1024
    98    network_interface {
    99      label = "%s"
   100    }
   101    disk {
   102  %s
   103      template = "%s"
   104    }
   105  }
   106  `
   107  
   108  // replaces data in the above template
   109  func (body TestDHCPBodyData) parseDHCPTemplateConfig() string {
   110  	return fmt.Sprintf(
   111  		testAccCheckVSphereTemplate_dhcp,
   112  		body.locationOpt,
   113  		body.label,
   114  		body.datastoreOpt,
   115  		body.template,
   116  	)
   117  }
   118  
   119  func (body TestDHCPBodyData) testSprintfDHCPTemplateBodySecondArgDynamic(template string, arg string) string {
   120  	return fmt.Sprintf(
   121  		template,
   122  		body.locationOpt,
   123  		arg,
   124  		body.label,
   125  		body.datastoreOpt,
   126  		body.template,
   127  	)
   128  }
   129  
   130  // returns variables that are used in DHCP tests
   131  func setupTemplateFuncDHCPData() TestDHCPBodyData {
   132  
   133  	locationOpt, datastoreOpt := setupBaseVars()
   134  	data := TestDHCPBodyData{
   135  		template:     os.Getenv("VSPHERE_TEMPLATE"),
   136  		label:        os.Getenv("VSPHERE_NETWORK_LABEL_DHCP"),
   137  		locationOpt:  locationOpt,
   138  		datastoreOpt: datastoreOpt,
   139  	}
   140  	// log.Printf("[DEBUG] basic vars= %v", data)
   141  	return data
   142  
   143  }
   144  
   145  ////
   146  // Structs and funcs used with static ip data templates
   147  ////
   148  type TemplateBasicBodyVars struct {
   149  	locationOpt   string
   150  	label         string
   151  	ipv4IpAddress string
   152  	ipv4Prefix    string
   153  	ipv4Gateway   string
   154  	datastoreOpt  string
   155  	template      string
   156  }
   157  
   158  // Takes a base template that has seven "%s" values in it, used by most fixed ip
   159  // tests
   160  func (body TemplateBasicBodyVars) testSprintfTemplateBody(template string) string {
   161  
   162  	return fmt.Sprintf(
   163  		template,
   164  		body.locationOpt,
   165  		body.label,
   166  		body.ipv4IpAddress,
   167  		body.ipv4Prefix,
   168  		body.ipv4Gateway,
   169  		body.datastoreOpt,
   170  		body.template,
   171  	)
   172  }
   173  
   174  // setups variables used by fixed ip tests
   175  func setupTemplateBasicBodyVars() TemplateBasicBodyVars {
   176  
   177  	locationOpt, datastoreOpt := setupBaseVars()
   178  	prefix := os.Getenv("VSPHERE_IPV4_PREFIX")
   179  	if prefix == "" {
   180  		prefix = "24"
   181  	}
   182  	data := TemplateBasicBodyVars{
   183  		template:      os.Getenv("VSPHERE_TEMPLATE"),
   184  		ipv4Gateway:   os.Getenv("VSPHERE_IPV4_GATEWAY"),
   185  		label:         os.Getenv("VSPHERE_NETWORK_LABEL"),
   186  		ipv4IpAddress: os.Getenv("VSPHERE_IPV4_ADDRESS"),
   187  		ipv4Prefix:    prefix,
   188  		locationOpt:   locationOpt,
   189  		datastoreOpt:  datastoreOpt,
   190  	}
   191  	// log.Printf("[DEBUG] basic vars= %v", data)
   192  	return data
   193  }
   194  
   195  ////
   196  // Basic data to create series of testing functions
   197  ////
   198  type TestFuncData struct {
   199  	vm         virtualMachine
   200  	label      string
   201  	vmName     string
   202  	vmResource string
   203  	numDisks   string
   204  	numCPU     string
   205  	mem        string
   206  }
   207  
   208  // returns TestCheckFunc's that are used in many of our tests
   209  // mem defaults to 1024
   210  // cpu defaults to 2
   211  // disks defatuls to 1
   212  // vmResource defaults to "terraform-test"
   213  // vmName defaults to "vsphere_virtual_machine.foo
   214  func (test TestFuncData) testCheckFuncBasic() (
   215  	resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc,
   216  	resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc) {
   217  	// log.Printf("[DEBUG] data= %v", test)
   218  	mem := test.mem
   219  	if mem == "" {
   220  		mem = "1024"
   221  	}
   222  	cpu := test.numCPU
   223  	if cpu == "" {
   224  		cpu = "2"
   225  	}
   226  	disks := test.numDisks
   227  	if disks == "" {
   228  		disks = "1"
   229  	}
   230  	res := test.vmResource
   231  	if res == "" {
   232  		res = "terraform-test"
   233  	}
   234  	vmName := test.vmName
   235  	if vmName == "" {
   236  		vmName = "vsphere_virtual_machine.foo"
   237  	}
   238  	return testAccCheckVSphereVirtualMachineExists(vmName, &test.vm),
   239  		resource.TestCheckResourceAttr(vmName, "name", res),
   240  		resource.TestCheckResourceAttr(vmName, "vcpu", cpu),
   241  		resource.TestMatchResourceAttr(vmName, "uuid", regexp.MustCompile("[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}")),
   242  		resource.TestCheckResourceAttr(vmName, "memory", mem),
   243  		resource.TestCheckResourceAttr(vmName, "disk.#", disks),
   244  		resource.TestCheckResourceAttr(vmName, "network_interface.#", "1"),
   245  		resource.TestCheckResourceAttr(vmName, "network_interface.0.label", test.label)
   246  }
   247  
   248  const testAccCheckVSphereVirtualMachineConfig_really_basic = `
   249  resource "vsphere_virtual_machine" "foo" {
   250      name = "terraform-test"
   251  ` + testAccTemplateBasicBodyWithEnd
   252  
   253  // WARNING this is one of the base templates.  You change this and you will
   254  // be impacting multiple tests
   255  const testAccTemplateBasicBody = `
   256  %s
   257      vcpu = 2
   258      memory = 1024
   259      network_interface {
   260          label = "%s"
   261          ipv4_address = "%s"
   262          ipv4_prefix_length = %s
   263          ipv4_gateway = "%s"
   264      }
   265       disk {
   266  %s
   267          template = "%s"
   268          iops = 500
   269      }
   270  `
   271  const testAccTemplateBasicBodyWithEnd = testAccTemplateBasicBody + `
   272  }`
   273  
   274  func TestAccVSphereVirtualMachine_basic(t *testing.T) {
   275  	var vm virtualMachine
   276  	basic_vars := setupTemplateBasicBodyVars()
   277  	config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic)
   278  
   279  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic)
   280  	log.Printf("[DEBUG] template config= %s", config)
   281  
   282  	resource.Test(t, resource.TestCase{
   283  		PreCheck:     func() { testBasicPreCheck(t) },
   284  		Providers:    testAccProviders,
   285  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   286  		Steps: []resource.TestStep{
   287  			resource.TestStep{
   288  				Config: config,
   289  				Check: resource.ComposeTestCheckFunc(
   290  					TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic(),
   291  				),
   292  			},
   293  		},
   294  	})
   295  }
   296  
   297  const testAccCheckVSphereVirtualMachineConfig_debug = `
   298  provider "vsphere" {
   299    client_debug = true
   300  }
   301  
   302  ` + testAccCheckVSphereVirtualMachineConfig_really_basic
   303  
   304  func TestAccVSphereVirtualMachine_client_debug(t *testing.T) {
   305  	var vm virtualMachine
   306  	basic_vars := setupTemplateBasicBodyVars()
   307  	config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_debug)
   308  
   309  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_debug)
   310  	log.Printf("[DEBUG] template config= %s", config)
   311  
   312  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   313  		TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic()
   314  
   315  	resource.Test(t, resource.TestCase{
   316  		PreCheck:     func() { testBasicPreCheck(t) },
   317  		Providers:    testAccProviders,
   318  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   319  		Steps: []resource.TestStep{
   320  			resource.TestStep{
   321  				Config: config,
   322  				Check: resource.ComposeTestCheckFunc(
   323  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   324  					testAccCheckDebugExists(),
   325  				),
   326  			},
   327  		},
   328  	})
   329  }
   330  
   331  const testAccCheckVSphereVirtualMachineConfig_initType = `
   332  resource "vsphere_virtual_machine" "thin" {
   333      name = "terraform-test"
   334  ` + testAccTemplateBasicBody + `
   335      disk {
   336          size = 1
   337          iops = 500
   338  	controller_type = "scsi"
   339  	name = "one"
   340      }
   341      disk {
   342          size = 1
   343  	controller_type = "ide"
   344  	type = "eager_zeroed"
   345  	name = "two"
   346      }
   347  }
   348  `
   349  
   350  func TestAccVSphereVirtualMachine_diskInitType(t *testing.T) {
   351  	var vm virtualMachine
   352  	basic_vars := setupTemplateBasicBodyVars()
   353  	config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_initType)
   354  
   355  	vmName := "vsphere_virtual_machine.thin"
   356  
   357  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   358  		TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "3"}.testCheckFuncBasic()
   359  
   360  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_initType)
   361  	log.Printf("[DEBUG] template config= %s", config)
   362  
   363  	resource.Test(t, resource.TestCase{
   364  		PreCheck:     func() { testAccPreCheck(t) },
   365  		Providers:    testAccProviders,
   366  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   367  		Steps: []resource.TestStep{
   368  			resource.TestStep{
   369  				Config: config,
   370  				Check: resource.ComposeTestCheckFunc(
   371  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   372  					// FIXME dynmically calculate the hashes
   373  					resource.TestCheckResourceAttr(vmName, "disk.294918912.type", "eager_zeroed"),
   374  					resource.TestCheckResourceAttr(vmName, "disk.294918912.controller_type", "ide"),
   375  					resource.TestCheckResourceAttr(vmName, "disk.1380467090.controller_type", "scsi"),
   376  				),
   377  			},
   378  		},
   379  	})
   380  }
   381  
   382  const testAccCheckVSphereVirtualMachineConfig_dhcp = `
   383  resource "vsphere_virtual_machine" "bar" {
   384      name = "terraform-test"
   385  `
   386  
   387  func TestAccVSphereVirtualMachine_dhcp(t *testing.T) {
   388  	var vm virtualMachine
   389  	data := setupTemplateFuncDHCPData()
   390  	config := testAccCheckVSphereVirtualMachineConfig_dhcp + data.parseDHCPTemplateConfigWithTemplate(testAccCheckVSphereTemplate_dhcp)
   391  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_dhcp+testAccCheckVSphereTemplate_dhcp)
   392  	log.Printf("[DEBUG] config= %s", config)
   393  
   394  	resource.Test(t, resource.TestCase{
   395  		PreCheck:     func() { testAccPreCheck(t) },
   396  		Providers:    testAccProviders,
   397  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   398  		Steps: []resource.TestStep{
   399  			resource.TestStep{
   400  				Config: config,
   401  				Check: resource.ComposeTestCheckFunc(
   402  					TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(),
   403  				),
   404  			},
   405  		},
   406  	})
   407  }
   408  
   409  const testAccCheckVSphereVirtualMachineConfig_custom_configs = `
   410  resource "vsphere_virtual_machine" "car" {
   411      name = "terraform-test-custom"
   412      custom_configuration_parameters {
   413        "foo" = "bar"
   414        "car" = "ferrari"
   415        "num" = 42
   416      }
   417  	enable_disk_uuid = true
   418  `
   419  
   420  func TestAccVSphereVirtualMachine_custom_configs(t *testing.T) {
   421  
   422  	var vm virtualMachine
   423  	data := setupTemplateFuncDHCPData()
   424  	config := testAccCheckVSphereVirtualMachineConfig_custom_configs + data.parseDHCPTemplateConfigWithTemplate(testAccCheckVSphereTemplate_dhcp)
   425  	vmName := "vsphere_virtual_machine.car"
   426  	res := "terraform-test-custom"
   427  
   428  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   429  		TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: res}.testCheckFuncBasic()
   430  
   431  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_custom_configs+testAccCheckVSphereTemplate_dhcp)
   432  	log.Printf("[DEBUG] config= %s", config)
   433  
   434  	resource.Test(t, resource.TestCase{
   435  		PreCheck:     func() { testAccPreCheck(t) },
   436  		Providers:    testAccProviders,
   437  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   438  		Steps: []resource.TestStep{
   439  			resource.TestStep{
   440  				Config: config,
   441  				Check: resource.ComposeTestCheckFunc(
   442  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   443  					testAccCheckVSphereVirtualMachineExistsHasCustomConfig(vmName, &vm),
   444  					resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.foo", "bar"),
   445  					resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.car", "ferrari"),
   446  					resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.num", "42"),
   447  					resource.TestCheckResourceAttr(vmName, "enable_disk_uuid", "true"),
   448  				),
   449  			},
   450  		},
   451  	})
   452  }
   453  
   454  const testAccCheckVSphereVirtualMachineConfig_createInFolder = `
   455  resource "vsphere_virtual_machine" "folder" {
   456      name = "terraform-test-folder"
   457      folder = "%s"
   458  `
   459  
   460  func TestAccVSphereVirtualMachine_createInExistingFolder(t *testing.T) {
   461  	var vm virtualMachine
   462  	datacenter := os.Getenv("VSPHERE_DATACENTER")
   463  
   464  	folder := "tf_test_cpureateInExistingFolder"
   465  
   466  	data := setupTemplateFuncDHCPData()
   467  	config := fmt.Sprintf(testAccCheckVSphereVirtualMachineConfig_createInFolder,
   468  		folder,
   469  	) + data.parseDHCPTemplateConfig()
   470  
   471  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_createInFolder)
   472  	log.Printf("[DEBUG] template config= %s", config)
   473  
   474  	resource.Test(t, resource.TestCase{
   475  		PreCheck:  func() { testAccPreCheck(t) },
   476  		Providers: testAccProviders,
   477  		CheckDestroy: resource.ComposeTestCheckFunc(
   478  			testAccCheckVSphereVirtualMachineDestroy,
   479  			removeVSphereFolder(datacenter, folder, ""),
   480  		),
   481  		Steps: []resource.TestStep{
   482  			resource.TestStep{
   483  				PreConfig: func() { createVSphereFolder(datacenter, folder) },
   484  				Config:    config,
   485  				Check: resource.ComposeTestCheckFunc(
   486  					TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.folder", vmResource: "terraform-test-folder"}.testCheckFuncBasic(),
   487  				),
   488  			},
   489  		},
   490  	})
   491  }
   492  
   493  const testAccCheckVSphereVirtualMachineConfig_createWithFolder = `
   494  resource "vsphere_folder" "with_folder" {
   495  	path = "%s"
   496  %s
   497  }
   498  resource "vsphere_virtual_machine" "with_folder" {
   499      name = "terraform-test-with-folder"
   500      folder = "${vsphere_folder.with_folder.path}"
   501  `
   502  
   503  func TestAccVSphereVirtualMachine_createWithFolder(t *testing.T) {
   504  	var vm virtualMachine
   505  	var folderLocationOpt string
   506  	var f folder
   507  
   508  	if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
   509  		folderLocationOpt = fmt.Sprintf("    datacenter = \"%s\"\n", v)
   510  	}
   511  
   512  	folder := "tf_test_cpureateWithFolder"
   513  
   514  	data := setupTemplateFuncDHCPData()
   515  	vmName := "vsphere_virtual_machine.with_folder"
   516  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   517  		TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: "terraform-test-with-folder"}.testCheckFuncBasic()
   518  
   519  	config := fmt.Sprintf(testAccCheckVSphereVirtualMachineConfig_createWithFolder,
   520  		folder,
   521  		folderLocationOpt,
   522  	) + data.parseDHCPTemplateConfig()
   523  
   524  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_createWithFolder+testAccCheckVSphereTemplate_dhcp)
   525  	log.Printf("[DEBUG] template config= %s", config)
   526  
   527  	resource.Test(t, resource.TestCase{
   528  		PreCheck:  func() { testAccPreCheck(t) },
   529  		Providers: testAccProviders,
   530  		CheckDestroy: resource.ComposeTestCheckFunc(
   531  			testAccCheckVSphereVirtualMachineDestroy,
   532  			testAccCheckVSphereFolderDestroy,
   533  		),
   534  		Steps: []resource.TestStep{
   535  			resource.TestStep{
   536  				Config: config,
   537  				Check: resource.ComposeTestCheckFunc(
   538  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   539  					testAccCheckVSphereFolderExists(vmName, &f),
   540  					resource.TestCheckResourceAttr(vmName, "folder", folder),
   541  				),
   542  			},
   543  		},
   544  	})
   545  }
   546  
   547  const testAccCheckVsphereVirtualMachineConfig_cdrom = `
   548  resource "vsphere_virtual_machine" "with_cdrom" {
   549      name = "terraform-test-with-cdrom"
   550      cdrom {
   551          datastore = "%s"
   552          path = "%s"
   553      }
   554  `
   555  
   556  func TestAccVSphereVirtualMachine_createWithCdrom(t *testing.T) {
   557  	var vm virtualMachine
   558  
   559  	// FIXME check that these exist
   560  	cdromDatastore := os.Getenv("VSPHERE_CDROM_DATASTORE")
   561  	cdromPath := os.Getenv("VSPHERE_CDROM_PATH")
   562  	vmName := "vsphere_virtual_machine.with_cdrom"
   563  
   564  	data := setupTemplateFuncDHCPData()
   565  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   566  		TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: "terraform-test-with-cdrom"}.testCheckFuncBasic()
   567  
   568  	config := fmt.Sprintf(
   569  		testAccCheckVsphereVirtualMachineConfig_cdrom,
   570  		cdromDatastore,
   571  		cdromPath,
   572  	) + data.parseDHCPTemplateConfig()
   573  
   574  	log.Printf("[DEBUG] template= %s", testAccCheckVsphereVirtualMachineConfig_cdrom)
   575  	log.Printf("[DEBUG] template config= %s", config)
   576  
   577  	resource.Test(t, resource.TestCase{
   578  		PreCheck:     func() { testAccPreCheck(t) },
   579  		Providers:    testAccProviders,
   580  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   581  		Steps: []resource.TestStep{
   582  			resource.TestStep{
   583  				Config: config,
   584  				Check: resource.ComposeTestCheckFunc(
   585  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   586  					//resource.TestCheckResourceAttr(
   587  					//	"vsphere_virtual_machine.with_cdrom", "disk.4088143748.template", template),
   588  					resource.TestCheckResourceAttr(vmName, "cdrom.#", "1"),
   589  					resource.TestCheckResourceAttr(vmName, "cdrom.0.datastore", cdromDatastore),
   590  					resource.TestCheckResourceAttr(vmName, "cdrom.0.path", cdromPath),
   591  				),
   592  			},
   593  		},
   594  	})
   595  }
   596  
   597  const testAccCheckVSphereVirtualMachineConfig_withExistingVmdk = `
   598  resource "vsphere_virtual_machine" "with_existing_vmdk" {
   599      name = "terraform-test-with-existing-vmdk"
   600  %s
   601      vcpu = 2
   602      memory = 1024
   603      network_interface {
   604          label = "%s"
   605      }
   606      disk {
   607  %s
   608          vmdk = "%s"
   609  	bootable = true
   610      }
   611  }
   612  `
   613  
   614  func TestAccVSphereVirtualMachine_createWithExistingVmdk(t *testing.T) {
   615  	var vm virtualMachine
   616  	vmdk_path := os.Getenv("VSPHERE_VMDK_PATH")
   617  
   618  	data := setupTemplateFuncDHCPData()
   619  	config := fmt.Sprintf(
   620  		testAccCheckVSphereVirtualMachineConfig_withExistingVmdk,
   621  		data.locationOpt,
   622  		data.label,
   623  		data.datastoreOpt,
   624  		vmdk_path,
   625  	)
   626  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_withExistingVmdk)
   627  	log.Printf("[DEBUG] template config= %s", config)
   628  
   629  	resource.Test(t, resource.TestCase{
   630  		PreCheck:     func() { testAccPreCheck(t) },
   631  		Providers:    testAccProviders,
   632  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   633  		Steps: []resource.TestStep{
   634  			resource.TestStep{
   635  				Config: config,
   636  				Check: resource.ComposeTestCheckFunc(
   637  					TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.with_existing_vmdk",
   638  						vmResource: "terraform-test-with-existing-vmdk"}.testCheckFuncBasic(),
   639  					//resource.TestCheckResourceAttr(
   640  					//	"vsphere_virtual_machine.with_existing_vmdk", "disk.2393891804.vmdk", vmdk_path),
   641  					//resource.TestCheckResourceAttr(
   642  					//	"vsphere_virtual_machine.with_existing_vmdk", "disk.2393891804.bootable", "true"),
   643  				),
   644  			},
   645  		},
   646  	})
   647  }
   648  
   649  const testAccCheckVSphereVirtualMachineConfig_updateMemory = `
   650  resource "vsphere_virtual_machine" "bar" {
   651      name = "terraform-test"
   652  %s
   653      vcpu = 2
   654      memory = %s
   655      network_interface {
   656          label = "%s"
   657      }
   658      disk {
   659  %s
   660        template = "%s"
   661      }
   662  }
   663  `
   664  
   665  func TestAccVSphereVirtualMachine_updateMemory(t *testing.T) {
   666  	var vm virtualMachine
   667  	data := setupTemplateFuncDHCPData()
   668  
   669  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_updateMemory)
   670  
   671  	config := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateMemory, "1024")
   672  	log.Printf("[DEBUG] template config= %s", config)
   673  
   674  	configUpdate := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateMemory, "2048")
   675  	log.Printf("[DEBUG] template configUpdate= %s", configUpdate)
   676  
   677  	resource.Test(t, resource.TestCase{
   678  		PreCheck:     func() { testAccPreCheck(t) },
   679  		Providers:    testAccProviders,
   680  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   681  		Steps: []resource.TestStep{
   682  			resource.TestStep{
   683  				Config: config,
   684  				Check: resource.ComposeTestCheckFunc(
   685  					TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(),
   686  				),
   687  			},
   688  			resource.TestStep{
   689  				Config: configUpdate,
   690  				Check: resource.ComposeTestCheckFunc(
   691  					TestFuncData{vm: vm, label: data.label, mem: "2048", vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(),
   692  				),
   693  			},
   694  		},
   695  	})
   696  }
   697  
   698  const testAccCheckVSphereVirtualMachineConfig_updateVcpu = `
   699  resource "vsphere_virtual_machine" "bar" {
   700      name = "terraform-test"
   701  %s
   702      vcpu = %s
   703      memory = 1024
   704      network_interface {
   705          label = "%s"
   706      }
   707      disk {
   708  %s
   709          template = "%s"
   710      }
   711  }
   712  `
   713  
   714  func TestAccVSphereVirtualMachine_updateVcpu(t *testing.T) {
   715  	var vm virtualMachine
   716  	data := setupTemplateFuncDHCPData()
   717  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_updateVcpu)
   718  
   719  	config := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateVcpu, "2")
   720  	log.Printf("[DEBUG] template config= %s", config)
   721  
   722  	configUpdate := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateVcpu, "4")
   723  	log.Printf("[DEBUG] template configUpdate= %s", configUpdate)
   724  
   725  	resource.Test(t, resource.TestCase{
   726  		PreCheck:     func() { testAccPreCheck(t) },
   727  		Providers:    testAccProviders,
   728  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   729  		Steps: []resource.TestStep{
   730  			resource.TestStep{
   731  				Config: config,
   732  				Check: resource.ComposeTestCheckFunc(
   733  					TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(),
   734  				),
   735  			},
   736  			resource.TestStep{
   737  				Config: configUpdate,
   738  				Check: resource.ComposeTestCheckFunc(
   739  					TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar", numCPU: "4"}.testCheckFuncBasic(),
   740  				),
   741  			},
   742  		},
   743  	})
   744  }
   745  
   746  const testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6 = `
   747  resource "vsphere_virtual_machine" "ipv4ipv6" {
   748      name = "terraform-test-ipv4-ipv6"
   749  %s
   750      vcpu = 2
   751      memory = 1024
   752      network_interface {
   753          label = "%s"
   754          ipv4_address = "%s"
   755          ipv4_prefix_length = %s
   756          ipv4_gateway = "%s"
   757          ipv6_address = "%s"
   758          ipv6_prefix_length = 64
   759          ipv6_gateway = "%s"
   760      }
   761      disk {
   762  %s
   763          template = "%s"
   764          iops = 500
   765      }
   766      disk {
   767          size = 1
   768          iops = 500
   769  	name = "one"
   770      }
   771  }
   772  `
   773  
   774  func TestAccVSphereVirtualMachine_ipv4Andipv6(t *testing.T) {
   775  	var vm virtualMachine
   776  	data := setupTemplateBasicBodyVars()
   777  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6)
   778  
   779  	vmName := "vsphere_virtual_machine.ipv4ipv6"
   780  
   781  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   782  		TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "2", vmResource: "terraform-test-ipv4-ipv6"}.testCheckFuncBasic()
   783  
   784  	// FIXME test for this or warn??
   785  	ipv6Address := os.Getenv("VSPHERE_IPV6_ADDRESS")
   786  	ipv6Gateway := os.Getenv("VSPHERE_IPV6_GATEWAY")
   787  
   788  	config := fmt.Sprintf(
   789  		testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6,
   790  		data.locationOpt,
   791  		data.label,
   792  		data.ipv4IpAddress,
   793  		data.ipv4Prefix,
   794  		data.ipv4Gateway,
   795  		ipv6Address,
   796  		ipv6Gateway,
   797  		data.datastoreOpt,
   798  		data.template,
   799  	)
   800  
   801  	log.Printf("[DEBUG] template config= %s", config)
   802  
   803  	resource.Test(t, resource.TestCase{
   804  		PreCheck:     func() { testAccPreCheck(t) },
   805  		Providers:    testAccProviders,
   806  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   807  		Steps: []resource.TestStep{
   808  			resource.TestStep{
   809  				Config: config,
   810  				Check: resource.ComposeTestCheckFunc(
   811  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   812  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_address", data.ipv4IpAddress),
   813  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_gateway", data.ipv4Gateway),
   814  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_address", ipv6Address),
   815  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_gateway", ipv6Gateway),
   816  				),
   817  			},
   818  		},
   819  	})
   820  }
   821  
   822  const testAccCheckVSphereVirtualMachineConfig_updateAddDisks = `
   823  resource "vsphere_virtual_machine" "foo" {
   824      name = "terraform-test"
   825  ` + testAccTemplateBasicBody + `
   826      disk {
   827          size = 1
   828          iops = 500
   829  	name = "one"
   830      }
   831  	disk {
   832          size = 1
   833          iops = 500
   834  	name = "two"
   835      }
   836  	disk {
   837          size = 1
   838          iops = 500
   839  	name = "three"
   840      }
   841  }
   842  `
   843  const testAccCheckVSphereVirtualMachineConfig_basic = `
   844  resource "vsphere_virtual_machine" "foo" {
   845      name = "terraform-test"
   846  ` + testAccTemplateBasicBody + `
   847      disk {
   848          size = 1
   849          iops = 500
   850  	name = "one"
   851      }
   852  }
   853  `
   854  
   855  func TestAccVSphereVirtualMachine_updateDisks(t *testing.T) {
   856  	var vm virtualMachine
   857  	basic_vars := setupTemplateBasicBodyVars()
   858  	config_basic := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_basic)
   859  
   860  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic)
   861  	log.Printf("[DEBUG] template config= %s", config_basic)
   862  
   863  	config_add := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_updateAddDisks)
   864  
   865  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic)
   866  	log.Printf("[DEBUG] template config= %s", config_add)
   867  
   868  	config_del := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic)
   869  
   870  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic)
   871  	log.Printf("[DEBUG] template config= %s", config_del)
   872  
   873  	resource.Test(t, resource.TestCase{
   874  		PreCheck:     func() { testAccPreCheck(t) },
   875  		Providers:    testAccProviders,
   876  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   877  		Steps: []resource.TestStep{
   878  			resource.TestStep{
   879  				Config: config_basic,
   880  				Check: resource.ComposeTestCheckFunc(
   881  					TestFuncData{vm: vm, label: basic_vars.label, numDisks: "2"}.testCheckFuncBasic(),
   882  				),
   883  			},
   884  			resource.TestStep{
   885  				Config: config_add,
   886  				Check: resource.ComposeTestCheckFunc(
   887  					TestFuncData{vm: vm, label: basic_vars.label, numDisks: "4"}.testCheckFuncBasic(),
   888  				),
   889  			},
   890  			resource.TestStep{
   891  				Config: config_del,
   892  				Check: resource.ComposeTestCheckFunc(
   893  					TestFuncData{vm: vm, label: basic_vars.label, numDisks: "1"}.testCheckFuncBasic(),
   894  				),
   895  			},
   896  		},
   897  	})
   898  }
   899  
   900  const testAccCheckVSphereVirtualMachineConfig_mac_address = `
   901  resource "vsphere_virtual_machine" "mac_address" {
   902      name = "terraform-mac-address"
   903  %s
   904      vcpu = 2
   905      memory = 1024
   906      network_interface {
   907          label = "%s"
   908          mac_address = "%s"
   909      }
   910      disk {
   911  %s
   912          template = "%s"
   913      }
   914  }
   915  `
   916  
   917  // VSPHERE_NETWORK_MAC_ADDRESS needs to be set to run TestAccVSphereVirtualMachine_mac_address
   918  // use a basic NIC MAC address like 6:5c:89:2b:a0:64
   919  func testMacPreCheck(t *testing.T) {
   920  
   921  	testBasicPreCheck(t)
   922  
   923  	// TODO should start do parse values to ensure they are correct
   924  	// for instance
   925  	//  func ParseMAC(s string) (hw HardwareAddr, err error)
   926  	if v := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS"); v == "" {
   927  		t.Fatal("env variable VSPHERE_NETWORK_MAC_ADDRESS must be set for this acceptance test")
   928  	}
   929  }
   930  
   931  // test new mac address feature
   932  func TestAccVSphereVirtualMachine_mac_address(t *testing.T) {
   933  	var vm virtualMachine
   934  	data := setupTemplateFuncDHCPData()
   935  	vmName := "vsphere_virtual_machine.mac_address"
   936  
   937  	macAddress := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS")
   938  
   939  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_mac_address)
   940  	config := fmt.Sprintf(
   941  		testAccCheckVSphereVirtualMachineConfig_mac_address,
   942  		data.locationOpt,
   943  		data.label,
   944  		macAddress,
   945  		data.datastoreOpt,
   946  		data.template,
   947  	)
   948  	log.Printf("[DEBUG] template config= %s", config)
   949  
   950  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   951  		TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "1", vmResource: "terraform-mac-address"}.testCheckFuncBasic()
   952  
   953  	resource.Test(t, resource.TestCase{
   954  		PreCheck:     func() { testMacPreCheck(t) },
   955  		Providers:    testAccProviders,
   956  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   957  		Steps: []resource.TestStep{
   958  			resource.TestStep{
   959  				Config: config,
   960  				Check: resource.ComposeTestCheckFunc(
   961  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   962  					resource.TestCheckResourceAttr(vmName, "network_interface.0.mac_address", macAddress),
   963  				),
   964  			},
   965  		},
   966  	})
   967  }
   968  
   969  func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error {
   970  	client := testAccProvider.Meta().(*govmomi.Client)
   971  	finder := find.NewFinder(client.Client, true)
   972  
   973  	for _, rs := range s.RootModule().Resources {
   974  		if rs.Type != "vsphere_virtual_machine" {
   975  			continue
   976  		}
   977  
   978  		dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"])
   979  		if err != nil {
   980  			return fmt.Errorf("error %s", err)
   981  		}
   982  
   983  		dcFolders, err := dc.Folders(context.TODO())
   984  		if err != nil {
   985  			return fmt.Errorf("error %s", err)
   986  		}
   987  
   988  		folder := dcFolders.VmFolder
   989  		if len(rs.Primary.Attributes["folder"]) > 0 {
   990  			si := object.NewSearchIndex(client.Client)
   991  			folderRef, err := si.FindByInventoryPath(
   992  				context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"]))
   993  			if err != nil {
   994  				return err
   995  			} else if folderRef != nil {
   996  				folder = folderRef.(*object.Folder)
   997  			}
   998  		}
   999  
  1000  		v, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"])
  1001  
  1002  		if v != nil {
  1003  			return fmt.Errorf("Record still exists")
  1004  		}
  1005  	}
  1006  
  1007  	return nil
  1008  }
  1009  
  1010  func testAccCheckVSphereVirtualMachineExistsHasCustomConfig(n string, vm *virtualMachine) resource.TestCheckFunc {
  1011  	return func(s *terraform.State) error {
  1012  
  1013  		rs, ok := s.RootModule().Resources[n]
  1014  		if !ok {
  1015  			return fmt.Errorf("Not found: %s", n)
  1016  		}
  1017  
  1018  		if rs.Primary.ID == "" {
  1019  			return fmt.Errorf("No ID is set")
  1020  		}
  1021  
  1022  		client := testAccProvider.Meta().(*govmomi.Client)
  1023  		finder := find.NewFinder(client.Client, true)
  1024  
  1025  		dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"])
  1026  		if err != nil {
  1027  			return fmt.Errorf("error %s", err)
  1028  		}
  1029  
  1030  		dcFolders, err := dc.Folders(context.TODO())
  1031  		if err != nil {
  1032  			return fmt.Errorf("error %s", err)
  1033  		}
  1034  
  1035  		_, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"])
  1036  		if err != nil {
  1037  			return fmt.Errorf("error %s", err)
  1038  		}
  1039  
  1040  		finder = finder.SetDatacenter(dc)
  1041  		instance, err := finder.VirtualMachine(context.TODO(), rs.Primary.Attributes["name"])
  1042  		if err != nil {
  1043  			return fmt.Errorf("error %s", err)
  1044  		}
  1045  
  1046  		var mvm mo.VirtualMachine
  1047  
  1048  		collector := property.DefaultCollector(client.Client)
  1049  
  1050  		if err := collector.RetrieveOne(context.TODO(), instance.Reference(), []string{"config.extraConfig"}, &mvm); err != nil {
  1051  			return fmt.Errorf("error %s", err)
  1052  		}
  1053  
  1054  		var configMap = make(map[string]types.AnyType)
  1055  		if mvm.Config != nil && mvm.Config.ExtraConfig != nil && len(mvm.Config.ExtraConfig) > 0 {
  1056  			for _, v := range mvm.Config.ExtraConfig {
  1057  				value := v.GetOptionValue()
  1058  				configMap[value.Key] = value.Value
  1059  			}
  1060  		} else {
  1061  			return fmt.Errorf("error no ExtraConfig")
  1062  		}
  1063  
  1064  		if configMap["foo"] == nil {
  1065  			return fmt.Errorf("error no ExtraConfig for 'foo'")
  1066  		}
  1067  
  1068  		if configMap["foo"] != "bar" {
  1069  			return fmt.Errorf("error ExtraConfig 'foo' != bar")
  1070  		}
  1071  
  1072  		if configMap["car"] == nil {
  1073  			return fmt.Errorf("error no ExtraConfig for 'car'")
  1074  		}
  1075  
  1076  		if configMap["car"] != "ferrari" {
  1077  			return fmt.Errorf("error ExtraConfig 'car' != ferrari")
  1078  		}
  1079  
  1080  		if configMap["num"] == nil {
  1081  			return fmt.Errorf("error no ExtraConfig for 'num'")
  1082  		}
  1083  
  1084  		// todo this should be an int, getting back a string
  1085  		if configMap["num"] != "42" {
  1086  			return fmt.Errorf("error ExtraConfig 'num' != 42")
  1087  		}
  1088  		*vm = virtualMachine{
  1089  			name: rs.Primary.ID,
  1090  		}
  1091  
  1092  		return nil
  1093  	}
  1094  }
  1095  
  1096  func testAccCheckDebugExists() resource.TestCheckFunc {
  1097  	return func(s *terraform.State) error {
  1098  		if _, err := os.Stat(filepath.Join(os.Getenv("HOME"), ".govmomi")); os.IsNotExist(err) {
  1099  			return fmt.Errorf("Debug logs not found")
  1100  		}
  1101  
  1102  		return nil
  1103  	}
  1104  
  1105  }
  1106  func testAccCheckVSphereVirtualMachineExists(n string, vm *virtualMachine) resource.TestCheckFunc {
  1107  	return func(s *terraform.State) error {
  1108  		if n == "" {
  1109  			return fmt.Errorf("No vm name passed in")
  1110  		}
  1111  		if vm == nil {
  1112  			return fmt.Errorf("No vm obj passed in")
  1113  		}
  1114  		rs, ok := s.RootModule().Resources[n]
  1115  		if !ok {
  1116  			return fmt.Errorf("Not found: %s", n)
  1117  		}
  1118  
  1119  		if rs.Primary.ID == "" {
  1120  			return fmt.Errorf("No ID is set")
  1121  		}
  1122  
  1123  		client := testAccProvider.Meta().(*govmomi.Client)
  1124  		finder := find.NewFinder(client.Client, true)
  1125  
  1126  		dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"])
  1127  		if err != nil {
  1128  			return fmt.Errorf("error %s", err)
  1129  		}
  1130  
  1131  		dcFolders, err := dc.Folders(context.TODO())
  1132  		if err != nil {
  1133  			return fmt.Errorf("error %s", err)
  1134  		}
  1135  
  1136  		folder := dcFolders.VmFolder
  1137  		if len(rs.Primary.Attributes["folder"]) > 0 {
  1138  			si := object.NewSearchIndex(client.Client)
  1139  			folderRef, err := si.FindByInventoryPath(
  1140  				context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"]))
  1141  			if err != nil {
  1142  				return err
  1143  			} else if folderRef != nil {
  1144  				folder = folderRef.(*object.Folder)
  1145  			}
  1146  		}
  1147  
  1148  		_, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"])
  1149  
  1150  		*vm = virtualMachine{
  1151  			name: rs.Primary.ID,
  1152  		}
  1153  
  1154  		return nil
  1155  	}
  1156  }
  1157  
  1158  const testAccCheckVSphereVirtualMachineConfig_keepOnRemove = `
  1159  resource "vsphere_virtual_machine" "keep_disk" {
  1160      name = "terraform-test"
  1161  ` + testAccTemplateBasicBody + `
  1162      disk {
  1163          size = 1
  1164          iops = 500
  1165  		controller_type = "scsi"
  1166  		name = "one"
  1167  		keep_on_remove = true
  1168      }
  1169  }
  1170  `
  1171  
  1172  func TestAccVSphereVirtualMachine_keepOnRemove(t *testing.T) {
  1173  	var vm virtualMachine
  1174  	basic_vars := setupTemplateBasicBodyVars()
  1175  	config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_keepOnRemove)
  1176  	var datastore string
  1177  	if v := os.Getenv("VSPHERE_DATASTORE"); v != "" {
  1178  		datastore = v
  1179  	}
  1180  	var datacenter string
  1181  	if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
  1182  		datacenter = v
  1183  	}
  1184  
  1185  	vmName := "vsphere_virtual_machine.keep_disk"
  1186  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
  1187  		TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "2"}.testCheckFuncBasic()
  1188  
  1189  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_keepOnRemove)
  1190  	log.Printf("[DEBUG] template config= %s", config)
  1191  
  1192  	resource.Test(t, resource.TestCase{
  1193  		PreCheck:     func() { testAccPreCheck(t) },
  1194  		Providers:    testAccProviders,
  1195  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
  1196  		Steps: []resource.TestStep{
  1197  			resource.TestStep{
  1198  				Config: config,
  1199  				Check: resource.ComposeTestCheckFunc(
  1200  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
  1201  				),
  1202  			},
  1203  			resource.TestStep{
  1204  				Config: " ",
  1205  				Check:  checkForDisk(datacenter, datastore, "terraform-test", "one.vmdk"),
  1206  			},
  1207  		},
  1208  	})
  1209  }
  1210  
  1211  func checkForDisk(datacenter string, datastore string, vmName string, path string) resource.TestCheckFunc {
  1212  	return func(s *terraform.State) error {
  1213  		client := testAccProvider.Meta().(*govmomi.Client)
  1214  		finder := find.NewFinder(client.Client, true)
  1215  
  1216  		dc, err := getDatacenter(client, datacenter)
  1217  		if err != nil {
  1218  			return err
  1219  		}
  1220  		finder.SetDatacenter(dc)
  1221  
  1222  		ds, err := finder.Datastore(context.TODO(), datastore)
  1223  		if err != nil {
  1224  			log.Printf("[ERROR] checkForDisk - Couldn't find Datastore '%v': %v", datastore, err)
  1225  			return err
  1226  		}
  1227  
  1228  		diskPath := vmName + "/" + path
  1229  
  1230  		_, err = ds.Stat(context.TODO(), diskPath)
  1231  		if err != nil {
  1232  			log.Printf("[ERROR] checkForDisk - Couldn't stat file '%v': %v", diskPath, err)
  1233  			return err
  1234  		}
  1235  
  1236  		// Cleanup
  1237  		fileManager := object.NewFileManager(client.Client)
  1238  		task, err := fileManager.DeleteDatastoreFile(context.TODO(), ds.Path(vmName), dc)
  1239  		if err != nil {
  1240  			log.Printf("[ERROR] checkForDisk - Couldn't delete vm folder '%v': %v", vmName, err)
  1241  			return err
  1242  		}
  1243  
  1244  		_, err = task.WaitForResult(context.TODO(), nil)
  1245  		if err != nil {
  1246  			log.Printf("[ERROR] checForDisk - Failed while deleting vm folder '%v': %v", vmName, err)
  1247  			return err
  1248  		}
  1249  
  1250  		return nil
  1251  	}
  1252  }