same as limit vMotion operations? , but wanna to limit the operation by Host , not by Task.
Can i set each host can ran 4 vMotion simultaneously?
e.g.:
Source Dest
A X << vMotion Batch1
A X << vMotion Batch1
A Y << vMotion Batch1
A Y << vMotion Batch1
A Y << vMotion Batch2
B X << vMotion Batch1
B X << vMotion Batch1
C X << vMotion Batch1
expect to see 4 x A Server vMotion + 2 x B Server vMotion + 1 x C Server vMotion can run together, and the last A Server will wait for any other A server completed in Batch1 first.
same as before all count are zero and got below exception
ErrorRecord : Cannot index into a null array.
WasThrownFromThrowStatement : False
Message : Cannot index into a null array.
Data : {System.Management.Automation.Interpreter.InterpretedFrameInfo}
InnerException :
TargetSite : Void CheckActionPreference(System.Management.Automation.Language.FunctionContext, System.Exception)
StackTrace : at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
HelpLink :
Source : System.Management.Automation
HResult : -2146233087
Some extra debug lines.
PS: you can attach the output as a file, no need to paste it in the thread.
Whatever is easiest for you
$fileName = '.\input.csv'
$jobs = @{}
$vMotions = @{}
Import-Csv -Path $fileName -UseCulture | %{
$vMotions.Add("$($_.SourceESX)-$($_.DestinationESX)-$($_.ServerName)",0)
}
$vMotionTab = @{}
while($vMotions.Count -gt 0){
$remove = @()
foreach($row in $vMotions.GetEnumerator()){
Write-Host "Name: $($_.Name)"
$src,$dst,$vmName = $row.Name.Split('-')
Write-Host "Extracted - VM: $vmName Src: $src Dest: $dest"
if(-not $vMotionTab.ContainsKey($src)){
$vMotionTab.Add($src,0)
Write-Host "Added $src to vMotionTab"
}
if(-not $vMotionTab.ContainsKey($dst)){
$vMotionTab.Add($dst,0)
Write-Host "Added $dst to vMotionTab"
}
Write-Host "Active for $src = $($vMotionTab[$src])"
Write-Host "Active for $dst = $($vMotionTab[$dst])"
if($vMotionTab[$src] -lt $max -and $vMotionTab[$dst] -lt $max){
Try{
Write-Host "Move $vmName frm $src to $dst"
$cst = Move-VM -VM $vmName -Destination $dst -RunAsync -ErrorAction Stop
Write-Host "Task: $($cst.Result.Guest.VM.ExtensionData.RecentTask[-1])"
$jobs.Add($cst.Result.Guest.VM.ExtensionData.RecentTask[-1],$row.Name)
$vMotionTab[$src] += 1
$vMotionTab[$dst] += 1
Write-Host "Active for $src = $($vMotionTab[$src])"
Write-Host "Active for $dst = $($vMotionTab[$dst])"
$remove += $row.Name
}
Catch{
Write-Output $_.Exception | Format-List -Force
Write-Output "vMotion failed for $vmName from $src to $dst"
$remove += $row.Name
}
}
Write-Host "Jobs count = $($jobs.Count)"
if($jobs.Count -gt 0){
Get-Task -Id $jobs.Result.Guest.VM.ExtensionData.RecentTask[-1] |
where{$_.PercentComplete -eq 100} | %{
Write-Host "Task: $($_.Name) State: $($_.State) Job: $($_.Id)"
$src,$dst,$vmName = ($jobs[$_.Id]).Split('-')
Write-Host "VM: $vmName Src: $src Dest: $dest "
$vMotionTab[$src] -= 1
$vMotionTab[$dst] -= 1
$jobs.Remove($_.Id)
}
}
}
if($remove.Count -gt 0){
$remove | %{
$vMotions.Remove($_)
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I have the impression the issue is related to the RecentTask property.
Can you have another run with this version (it has a few more debug lines in there)?
$fileName = '.\input.csv'
$jobs = @{}
$vMotions = @{}
Import-Csv -Path $fileName -UseCulture | %{
$vMotions.Add("$($_.SourceESX)-$($_.DestinationESX)-$($_.ServerName)",0)
}
$vMotionTab = @{}
while($vMotions.Count -gt 0){
$remove = @()
foreach($row in $vMotions.GetEnumerator()){
Write-Host "Name: $($_.Name)"
$src,$dst,$vmName = $row.Name.Split('-')
Write-Host "Extracted - VM: $vmName Src: $src Dest: $dst"
if(-not $vMotionTab.ContainsKey($src)){
$vMotionTab.Add($src,0)
Write-Host "Added $src to vMotionTab"
}
if(-not $vMotionTab.ContainsKey($dst)){
$vMotionTab.Add($dst,0)
Write-Host "Added $dst to vMotionTab"
}
Write-Host "Active for $src = $($vMotionTab[$src])"
Write-Host "Active for $dst = $($vMotionTab[$dst])"
if($vMotionTab[$src] -lt $max -and $vMotionTab[$dst] -lt $max){
Try{
Write-Host "Move $vmName frm $src to $dst"
$cst = Move-VM -VM $vmName -Destination $dst -RunAsync -ErrorAction Stop
Write-Output $cst | Format-List -Force
Write-Output $cst.Result.Guest.VM.ExtensionData.RecentTask | Format-List -Force
Write-Host "Task: $($cst.Result.Guest.VM.ExtensionData.RecentTask[-1])"
$jobs.Add($cst.Result.Guest.VM.ExtensionData.RecentTask[-1],$row.Name)
$vMotionTab[$src] += 1
$vMotionTab[$dst] += 1
Write-Host "Active for $src = $($vMotionTab[$src])"
Write-Host "Active for $dst = $($vMotionTab[$dst])"
$remove += $row.Name
}
Catch{
Write-Output $_.Exception | Format-List -Force
Write-Output "vMotion failed for $vmName from $src to $dst"
$remove += $row.Name
}
}
Write-Host "Jobs count = $($jobs.Count)"
if($jobs.Count -gt 0){
Get-Task -Id $jobs.Result.Guest.VM.ExtensionData.RecentTask[-1] |
where{$_.PercentComplete -eq 100} | %{
Write-Host "Task: $($_.Name) State: $($_.State) Job: $($_.Id)"
$src,$dst,$vmName = ($jobs[$_.Id]).Split('-')
Write-Host "VM: $vmName Src: $src Dest: $dest "
$vMotionTab[$src] -= 1
$vMotionTab[$dst] -= 1
$jobs.Remove($_.Id)
}
}
}
if($remove.Count -gt 0){
$remove | %{
$vMotions.Remove($_)
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ok, now I know why the script doesn't work.
The Move-VM is handled by a so-called Client-Side Task, and the Task MoRef I'm using is only filled in when the vMotion has completed.
The script could wait, but that would result in only doing one vMotion at the time.
I'll have to rethink the logic.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
is it possible no need to wait all first batch completed then trigger next batch? since the VM size are various, and the transaction time also
example: IF Server E (first batch) require 30mins for vMotion, all Second Batch Job need to wait it's completed first, can made it didn't wait?
what i can see the result right now:
ServerName | SourceESX | DestinationESX | Action |
Server A | esxA | esxD | First Batch Trigger |
Server B | esxA | esxD | need to wait all First Batch Job Completed first. |
Server C | esxA | esxD | need to wait all Second Batch Job Completed first. ( which mean need to wait other 8 Servers vMotion completed, then trigger Server C vMotion. |
Server D | esxB | esxC | First Batch Trigger |
Server E | esxB | esxC | need to wait all First Batch Job Completed first. |
Server F | esxC | esxB | First Batch Trigger |
Server G | esxC | esxB | need to wait all First Batch Job Completed first. |
Server H | esxD | esxA | First Batch Trigger |
Server I | esxD | esxA | need to wait all First Batch Job Completed first. |
btw :smileysilly: any idea for the Second query? lol any idea to counting the ESXi node for source and destination
I don't really see a solution at this time, due to the CST concept.
It could work if there are no other vMotions being triggered by other users or DRS, but that is not something I could easily accomplish in a script.
One could disable DRS temporarily and inform other users from starting vMotions, but that goes rather far I think.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference