You could do your own bookkeeping and make a system in which programs reserve datastore space. In the most simple form you can make a .csv file with colums Datastore, Total Space, Space Reserved. Your program can read the .csv file. Search for a datastore with enough free space. Increase the reserved space for that datastore with the amount of space the program is going to use on the datastore. And write the new reserved space to the .csv file.
To protect the .csv file from being used by two programs at the same time you still have to use the mutex. However in this case the mutex is only used for the bookkeeping and not during the creation of the VM's. So your programs can do more in parallel.
An example of the .csv file:
"Datastore","TotalSpace","SpaceReserved"
"datastore1","1000","950"
"datastore2","500","350"
"datastore3","1000","500"
You can use the following PowerShell script to reserve space on a datastore in the .csv file.
param([int]$SpaceNeeded=150) $path = "Datastores.csv" Try { # Get the mutex $MutexName = "Global\Mutex" $Mutex = New-Object -TypeName System.Threading.Mutex -ArgumentList $false, $MutexName $Mutex.WaitOne() | Out-Null # Find the first datastore with enough free space $DatastoreFound = $false $Datastores = Import-Csv -Path $Path | ForEach-Object { if ($_) { if (-not $DatastoreFound -and ($_.TotalSpace - $_.SpaceReserved -ge $SpaceNeeded)) { $DatastoreFound = $_.Datastore [int] $_.SpaceReserved = [int] $_.SpaceReserved + $SpaceNeeded } $_ } } # Write the datastore reserved space information back to the .csv file if ($Datastores) { $Datastores | Export-Csv -Path $Path -NoTypeInformation } # Release the mutex $Mutex.ReleaseMutex() | Out-Null $Mutex = $null } Catch { # Release the mutex when something went wrong $Mutex.ReleaseMutex() | Out-Null $Mutex = $null } # Return the name of the first datastore found with enough free space # Return $false if no datastore found $DatastoreFound