Repository: vmware/govmomi (go)

Issue:
vcsim - error adding disk on different datastore
When attempting a ReconfigVM_Task to add a disk on a different datastore, I receive the following error:

```xml
            <error>
              <fault XMLSchema-instance:type="FileFault">
                <file>/tmp/govcsim-DC0-LocalDS_2-353672936/test-vm2/test-vm2.vmdk</file>
              </fault>

              <localizedMessage>*types.FileFault</localizedMessage>
            </error>
```

The task request looks like:
```xml

<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <env:Body>
  <ReconfigVM_Task xmlns="urn:vim25">
    <_this type="VirtualMachine">vm-65</_this>
      <spec xsi:type="VirtualMachineConfigSpec">
          <numCPUs>2</numCPUs>
          <numCoresPerSocket>1</numCoresPerSocket>
          <deviceChange xsi:type="VirtualDeviceConfigSpec">
            <operation>edit</operation>
            <device xsi:type="VirtualDisk"><key>206</key><deviceInfo xsi:type="Description"><label>disk-205-0</label><summary>1,048,576 KB</summary></deviceInfo><backing xsi:type="VirtualDiskFlatVer2BackingInfo"><fileName>[LocalDS_1] test-vm2/test-vm2.vmdk</fileName><datastore type="Datastore">/tmp/govcsim-DC0-LocalDS_1-553967510@folder-5</datastore><diskMode>persistent</diskMode><thinProvisioned>0</thinProvisioned><eagerlyScrub>0</eagerlyScrub></backing><controllerKey>205</controllerKey><unitNumber>0</unitNumber><capacityInKB>2097152</capacityInKB></device></deviceChange><deviceChange xsi:type="VirtualDeviceConfigSpec"><operation>add</operation><fileOperation>create</fileOperation><device xsi:type="VirtualDisk"><key>-2</key><backing xsi:type="VirtualDiskFlatVer2BackingInfo"><fileName>[LocalDS_2]</fileName><diskMode>persistent</diskMode><thinProvisioned>0</thinProvisioned></backing><controllerKey>205</controllerKey><unitNumber>1</unitNumber><capacityInKB>2097152</capacityInKB></device>
          </deviceChange>
       </spec>
    </ReconfigVM_Task>  
  </env:Body>
</env:Envelope>
```


I believe this may be caused by 488205f04de03d3b84556d2a4661f1ded084b00d.  When I reverted to 1f52ede5c89479e36b5edd310740b649cb574e66, my tests started working again.

Pull request:
vcsim: create vmdk directory if needed
Add test and fix for 488205f

Fixes #1854

Patch:
diff --git a/simulator/virtual_machine.go b/simulator/virtual_machine.go
index 7faa73b5..1902aa57 100644
--- a/simulator/virtual_machine.go
+++ b/simulator/virtual_machine.go
@@ -829,8 +829,18 @@ func (vm *VirtualMachine) createFile(spec string, name string, register bool) (*
 		return nil, fault
 	}
 
+	// Create parent directory if needed
+	dir := path.Dir(file)
+	_, err = os.Stat(dir)
+	if err != nil {
+		if os.IsNotExist(err) {
+			_ = os.Mkdir(dir, 0700)
+		}
+	}
+
 	f, err := os.Create(file)
 	if err != nil {
+		log.Printf("create(%s): %s", file, err)
 		return nil, &types.FileFault{
 			File: file,
 		}


Test patch:
diff --git a/govc/test/vm.bats b/govc/test/vm.bats
index 7d41919f..0289de9c 100755
--- a/govc/test/vm.bats
+++ b/govc/test/vm.bats
@@ -535,27 +535,19 @@ load test_helper
 }
 
 @test "vm.disk.create" {
-  esx_env
-
-  import_ttylinux_vmdk
+  vcsim_env
 
   vm=$(new_id)
 
-  govc vm.create -disk $GOVC_TEST_VMDK -on=false $vm
-  result=$(govc device.ls -vm $vm | grep disk- | wc -l)
-  [ $result -eq 1 ]
+  govc vm.create -on=false "$vm"
+  assert_success
 
-  local name=$(new_id)
+  name=$(new_id)
 
-  run govc vm.disk.create -vm $vm -name $name -size 1G
+  run govc vm.disk.create -vm "$vm" -name "$vm/$name" -size 1M
   assert_success
-  result=$(govc device.ls -vm $vm | grep disk- | wc -l)
-  [ $result -eq 2 ]
-
-  run govc vm.disk.create -vm $vm -name $name -size 1G
-  assert_success # TODO: should fail?
-  result=$(govc device.ls -vm $vm | grep disk- | wc -l)
-  [ $result -eq 2 ]
+  result=$(govc device.ls -vm "$vm" | grep -c disk-)
+  [ "$result" -eq 1 ]
 }
 
 @test "vm.disk.attach" {
diff --git a/simulator/virtual_machine_test.go b/simulator/virtual_machine_test.go
index bdbeb1fe..90c07990 100644
--- a/simulator/virtual_machine_test.go
+++ b/simulator/virtual_machine_test.go
@@ -591,6 +591,7 @@ func TestCreateVmWithDevices(t *testing.T) {
 	ctx := context.Background()
 
 	m := ESX()
+	m.Datastore = 2
 	defer m.Remove()
 
 	err := m.Create()
@@ -673,6 +674,29 @@ func TestCreateVmWithDevices(t *testing.T) {
 	if ndisk != 2 {
 		t.Errorf("expected 1 disk, got %d", ndisk)
 	}
+
+	// Add disk on another datastore with empty path (issue 1854)
+	ovm := object.NewVirtualMachine(c, vm.Self)
+	disk = &types.VirtualDisk{
+		CapacityInKB: 1024,
+		VirtualDevice: types.VirtualDevice{
+			Backing: &types.VirtualDiskFlatVer2BackingInfo{
+				VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
+					FileName: "[LocalDS_1]",
+				},
+			},
+		},
+	}
+	devices.AssignController(disk, scsi.(*types.VirtualLsiLogicController))
+	devices = nil
+	devices = append(devices, disk)
+	create, _ = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
+	spec = types.VirtualMachineConfigSpec{DeviceChange: create}
+	rtask, _ := ovm.Reconfigure(ctx, spec)
+	_, err = rtask.WaitForResult(ctx, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
 }
 
 func TestShutdownGuest(t *testing.T) {