Skip to content

Commit eb6b166

Browse files
committed
Switch to using a mutex around MakeDirectory
1 parent 76e98e9 commit eb6b166

File tree

1 file changed

+18
-17
lines changed

1 file changed

+18
-17
lines changed

vsphere/resource_vsphere_virtual_disk.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"path"
1414
"strconv"
1515
"strings"
16-
"time"
16+
"sync"
1717

1818
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1919
"github.com/vmware/govmomi"
@@ -23,6 +23,8 @@ import (
2323
"github.com/vmware/terraform-provider-vsphere/vsphere/internal/helper/virtualdisk"
2424
)
2525

26+
var vsphereVirtualDiskMakeDirectoryMutex sync.Mutex
27+
2628
type virtualDisk struct {
2729
size int
2830
vmdkPath string
@@ -171,29 +173,23 @@ func resourceVSphereVirtualDiskCreate(d *schema.ResourceData, meta interface{})
171173
if vDisk.createDirectories {
172174
directoryPathIndex := strings.LastIndex(vDisk.vmdkPath, "/")
173175
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()
174180
vmdkPath := vDisk.vmdkPath[0:directoryPathIndex]
175181
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
187187
}
188188

189189
err = searchForDirectory(client, vDisk.datacenter, vDisk.datastore, vmdkPath)
190190
if err != nil {
191191
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
197193
}
198194
}
199195
}
@@ -435,6 +431,11 @@ func resourceVSphereVirtualDiskDelete(d *schema.ResourceData, meta interface{})
435431
return nil
436432
}
437433

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+
438439
// createHardDisk creates a new Hard Disk.
439440
func createHardDisk(client *govmomi.Client, size int, diskPath string, diskType string, adapterType string, dc string) error {
440441
var vDiskType string

0 commit comments

Comments
 (0)