@@ -13,7 +13,7 @@ import (
13
13
"path"
14
14
"strconv"
15
15
"strings"
16
- "time "
16
+ "sync "
17
17
18
18
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
19
19
"github.com/vmware/govmomi"
@@ -23,6 +23,8 @@ import (
23
23
"github.com/vmware/terraform-provider-vsphere/vsphere/internal/helper/virtualdisk"
24
24
)
25
25
26
+ var vsphereVirtualDiskMakeDirectoryMutex sync.Mutex
27
+
26
28
type virtualDisk struct {
27
29
size int
28
30
vmdkPath string
@@ -171,29 +173,23 @@ func resourceVSphereVirtualDiskCreate(d *schema.ResourceData, meta interface{})
171
173
if vDisk .createDirectories {
172
174
directoryPathIndex := strings .LastIndex (vDisk .vmdkPath , "/" )
173
175
if directoryPathIndex > 0 {
176
+ // Only allow one MakeDirectory operation at a time in order to avoid
177
+ // overlapping attempts to create the same directory, which can result
178
+ // in some of the attempts failing.
179
+ vsphereVirtualDiskMakeDirectoryMutex .Lock ()
174
180
vmdkPath := vDisk .vmdkPath [0 :directoryPathIndex ]
175
181
log .Printf ("[DEBUG] Creating parent directories: %v" , ds .Path (vmdkPath ))
176
- makeDirectoryErr := fm .MakeDirectory (context .TODO (), ds .Path (vmdkPath ), dc , true )
177
- if makeDirectoryErr != nil {
178
- // MakeDirectory can fail with a number of different errors if the directory is
179
- // already in the process of being created. To avoid the need to handle each of
180
- // these errors individually, the error is not returned here and the call to
181
- // searchForDirectory below is used to determine if the directory is present.
182
- // If the directory is in the process of being created, that will need to complete
183
- // in order for the search to find the new directory, so sleep for a couple of
184
- // seconds to allow that.
185
- log .Printf ("[DEBUG] Error hit when creating parent directories: %v" , makeDirectoryErr )
186
- time .Sleep (2 * time .Second )
182
+ err = fm .MakeDirectory (context .TODO (), ds .Path (vmdkPath ), dc , true )
183
+ vsphereVirtualDiskMakeDirectoryMutex .Unlock ()
184
+ if err != nil && ! isAlreadyExists (err ) {
185
+ log .Printf ("[DEBUG] Failed to create parent directories: %v" , err )
186
+ return err
187
187
}
188
188
189
189
err = searchForDirectory (client , vDisk .datacenter , vDisk .datastore , vmdkPath )
190
190
if err != nil {
191
191
log .Printf ("[DEBUG] Failed to find newly created parent directories: %v" , err )
192
- if makeDirectoryErr != nil {
193
- return makeDirectoryErr
194
- } else {
195
- return err
196
- }
192
+ return err
197
193
}
198
194
}
199
195
}
@@ -435,6 +431,11 @@ func resourceVSphereVirtualDiskDelete(d *schema.ResourceData, meta interface{})
435
431
return nil
436
432
}
437
433
434
+ func isAlreadyExists (err error ) bool {
435
+ return strings .HasPrefix (err .Error (), "Cannot complete the operation because the file or folder" ) &&
436
+ strings .HasSuffix (err .Error (), "already exists" )
437
+ }
438
+
438
439
// createHardDisk creates a new Hard Disk.
439
440
func createHardDisk (client * govmomi.Client , size int , diskPath string , diskType string , adapterType string , dc string ) error {
440
441
var vDiskType string
0 commit comments