I have a problem with creating multiple VM's from template in single VIServer. In following code when I choose if I put anything bigger than 1 in throttle script only executes one vm and don't create any other, it seems to have problem with keeping the session most likely just reset it or modify it in $global:DefaultVIServer.
Code below is based on question in this thread: Thread does not create multiple VMs (session issue) The answer is to keep the same session all the time but I couldn't get this to work
I wonder if anyone had working solution in using runspace in powershell to create multiple vms in vmware ?
cls
Add-PSSnapin VMware.VimAutomation.Core | Out-Null
#import csv
$VMs = Import-CSV 'filename.csv' -UseCulture
#connections array
$server = @()
#threads
$throttle = 2
# Create session state
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
# Create runspace pool consisting of runspaces
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $throttle, $sessionState, $host)
$RunspacePool.Open()
#array for jobs
$Jobs = @()
#this contains all connected vSphere endpoints
$global:DefaultVIServer
$User = "domain\username"
$PWord = ConvertTo-SecureString -String "password" -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
# SctiptBlock to execute for each job
$ScriptBlock = {
Param ($VM, $ses)
Add-PSSnapin VMware.VimAutomation.Core | Out-Null
Write-Host $VM.Name "Father session: " $ses.SessionSecret
Connect-VIServer $VM.VIServer -Session $ses.SessionSecret -wa 0
Write-Host $VM.Name "Child session: " $sessionf.SessionId
New-VM -Name $VM.Name -ResourcePool "..." -Location "Windows Servers" -Datastore "..." -DiskStorageFormat "..." -Notes "..." -Template "..."
}
# Starting script
Write-Host ("Starting script: {0}" -f (Get-Date))
$startTime = Get-Date
$count = 0
ForEach($VM in $VMs)
{
$count = $count + 1
Write-Host "Current connections:"
$Global:DefaultVIServers.count
$ses = Connect-VIServer $VM.VIServer -Credential $Credential -wa 0
$Job = [powershell]::create()
$Job.RunspacePool = $RunspacePool
$Job.AddScript($ScriptBlock).AddParameter("VM", $VM).AddParameter("ses", $ses)
Write-Host "Adding job to jobs list"
$Jobs += New-Object PSObject -Property @{
RunNum = $count
Job = $Job
Result = $Job.BeginInvoke() | Out-Null
}
}
Write-Host "Waiting.." -NoNewline
Do {
Write-Host "." -NoNewline
Start-Sleep -Seconds 1
} While ( $Jobs.Result.IsCompleted -contains $false)
$endTime = Get-Date
$totalSeconds = "{0:N4}" -f ($endTime-$startTime).TotalSeconds
Write-Host "All jobs finished in $totalSeconds seconds"
I am certainly not an expert, but I just finished doing something like this but used a powershell workflow using the parallel command
Maybe this will help? Dunno
Workflow Engine
{
param(
[string]$vc,
[string]$ses
)
$vcuser="root"
$vcpass="vcpass"
foreach -parallel($name in $names)
{
InlineScript
{
#Add the SnapIn and Connect to the Management vCenter
Add-PSSnapin VMWare.VimAutomation.Core
Connect-VIServer -Server $Using:vc -Session $Using:ses -User $Using:vcuser -Password $Using:vcpass
#do something
}#InlineScript
} #ForEach
} #Workflow
cls
Engine -vcenter "1.1.1.1" -session $global:DefaultVIServer.SessionSecret
Note: $names = "VM1","VM2","VM3"
Ran into the similar issue trying to run powershell inline script from RunDeck.
My script "rundeck-createvms.ps1" runs well in Windows interactive session but not from WinRM module used by RunDeck. So below is my wrapper for paraller vm creation.
$VCUser = "user"
$VCPass = "password"
$VCServer = "vcenter"
$vmNames = 'illya-test411','illya-test412','illya-test413' | Sort-Object
$myfolder = "IMAGETEST"
$mytemplate = "IMG-CENTOS704-VEN-201806092144"
$vmnetwork = "10.2.0.0/16"
$vmmemorygb = 7
$vmmcpu = 3
Get-Module -ListAvailable VMWare* | Import-Module | Out-Null
Write-Host "PowerCLI is loaded" -ForegroundColor Green
Connect-VIServer -Server $VCServer -User $VCUser -Password $VCPass -WarningAction SilentlyContinue | Out-Null
Write-Host "Connected to vCenter as $VCUser" -ForegroundColor Green
workflow vmcreate
{
param
(
[string]$vcenter,
[string[]]$names,
[string]$session,
[string]$myfolder,
[string]$mytemplate,
[string]$vmnetwork,
[int]$vmmemorygb,
[int]$vmmcpu
)
foreach -parallel($name in $names)
{
InlineScript
{
Connect-VIServer -Server $Using:vcenter -Session $Using:session | Out-Null
& C:\Scripts\rundeck-createvms.ps1 -vmname $Using:name -myfolder $Using:myfolder -mytemplate $Using:mytemplate `
-vmnetwork $Using:vmnetwork -vmmemorygb $Using:vmmemorygb -vmmcpu $Using:vmmcpu
}
}
}
vmcreate `
-vcenter $global:DefaultVIServer.Name `
-session $global:DefaultVIServer.SessionSecret `
-names $vmNames `
-myfolder $myfolder `
-mytemplate $mytemplate `
-vmnetwork $vmnetwork `
-vmmemorygb $vmmemorygb `
-vmmcpu $vmmcpu
>if anyone had working solution in using runspace in powershell to create multiple vms in vmware ?
powershell runspace or jobs won't work in this case due to vmware session handling - spent quite some time troubleshooting.
You have a long script and in each job, you connect to vcenter, "first" jobs finished and automatically disconnect which kills connection in other jobs that are still running. Therefore out of multiple background jobs, the one that finished first will be successful. The solution is to connect to vcenter once in control script and use workflow for parallel processing.