VMware Cloud Community
Cc3216
Contributor
Contributor

limit vMotion operations by Hosts?

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.

Reply
0 Kudos
27 Replies
LucD
Leadership
Leadership

From where do the vMotions get triggered?

Is there an input file?

The reason for asking;

if the script would be waiting for source A to go below 4 before starting the next one,

the vMotions for source B and C should continue I assume.

I was thinking starting separate background jobs for each source VMhost.

Than you could just use the script you pointed to for each of the sources.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

Hi LucD,

thanks for yr quick reply Smiley Happy

From where do the vMotions get triggered?

Is there an input file?

[Reply: Yup, from a CSV file to store all kind of info.]

if the script would be waiting for source A to go below 4 before starting the next one,

the vMotions for source B and C should continue I assume.

[Reply: yes, i assume the B & C should continue simultaneous  with 4 x Server A]

I was thinking starting separate background jobs for each source VMhost.

Than you could just use the script you pointed to for each of the sources.

[Reply: how to get the host from Relocate_Task? and control it's maximum thread? i hv struggle for it for a long time  Smiley Sad ]

Reply
0 Kudos
LucD
Leadership
Leadership

What is in that CSV? The VM's name I assume?


From the Get-VM we can get the VMHost on which the VM is running.

That should allow us to make groups based on the source (Source A,B,C...)

Each group could now be started as a background job (original script you pointed to) with Start-Job.

How is the destination for the vMotions determined?

Are all VMs going to the same targert VMHost?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

the csv will look like that, hope u understand Smiley Sad

ServerName  SourceESX & DestinationESX

A                         esxA                    esxC

B                         esxA                    esxC                     

C                         esxA                    esxC

D                         esxA                    esxC

E                        esxA                    esxC                     

F                        esxB                    esxC

G                       esxB                    esxC                     

H                       esxC                   esxD

Reply
0 Kudos
LucD
Leadership
Leadership

Try something like this.
You need to connect to the vCenter before running this script

$script = {

    param(

        [int]$maxParallel,

        [PSObject[]]$rows,

        [string]$vcId

    )

    Connect-VIServer -Session $vcId

       

    $rows | %{

      Move-VM -VM $_.ServerName -Destination $_.DestinationESX -RunAsync

      while((Get-Task -Status Running | where{$_.Name -eq 'RelocateVM_Task'}).Count -gt $maxParallel){

        sleep 5

      }

    }

}

$max = 4

$fileName = '.\input.csv'

$jobs = @()

Import-Csv -Path $fileName -UseCulture | Group-Object -Property SourceEsx | %{

    $jobs += (Start-Job -ScriptBlock $script -ArgumentList $max,$_.Group,$global:DefaultVIServer.SessionId)

}

Wait-Job -Job $jobs.Id

Receive-Job -Job $jobs.Id


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

Awesome LucD, it's amazing.

but i observe a problem? if  all CSV server are in Same host (eg. Host A)

and i set Parallel with 4 and Maxhost 2, then i assume all Host A vMotion should run 2 by 2, since MaxHost is 2.

however come up it ran 3 by 3 simultaneously, not by 2,  any trick on it? Smiley Happy

Reply
0 Kudos
LucD
Leadership
Leadership

Not sure I'm following here :smileyconfused:

What is Parallel and MaxHost?


If all VMs are located on the same source ESXi, there will only be 1 background job.

And that job will allow $Max vMotions in parallel.

If the vSphere environment limits the parallel vMotions as well, then, if that number is lower than $Max, you will be limited by that imposed limit of course.

Is the system imposed maximum of parallel vMotions number what you are looking for?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

LucD,

Sorry to make u confuse, but the result i got is like below

using ESXi 6.0 with default config

when [int]$maxpallael=8,  $max=2

All SourceESX are same host

However the result is 3 vMotion Running simultaneously, instead of 2 , instead of 8,  any idea why 3 ??

Reply
0 Kudos
LucD
Leadership
Leadership

Where do you use

[int]$maxpallael=8,  $max=2

Perhaps attach the complete script as you are running it?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

just like this LucD,

$script = {

    param(

        [int]$maxParallel=5,

        [PSObject[]]$rows,

        [string]$vcId

    )

    Connect-VIServer -Session $vcId

      

    $rows | %{

      Move-VM -VM $_.ServerName -Destination $_.DestinationESX -RunAsync

      while((Get-Task -Status Running | where{$_.Name -eq 'RelocateVM_Task'}).Count -gt $maxParallel){

        sleep 5

      }

    }

}

$max = 2

$fileName = '.\input.csv'

$jobs = @()

Import-Csv -Path $fileName -UseCulture | Group-Object -Property SourceEsx | %{

    $jobs += (Start-Job -ScriptBlock $script -ArgumentList$max,$_.Group,$global:DefaultVIServer.SessionId)

}

Wait-Job -Job $jobs.Id

Receive-Job -Job $jobs.Id

Reply
0 Kudos
LucD
Leadership
Leadership

Ok, I think I got it now.

Try swapping the Move-VM after the While-loop, and change the comparison operator to -ge

Like this

$script = {

    param(

        [int]$maxParallel,

        [PSObject[]]$rows,

        [string]$vcId

    )

    Connect-VIServer -Session $vcId

      

    $rows | %{

      while((Get-Task -Status Running | where{$_.Name -eq 'RelocateVM_Task'}).Count -ge $maxParallel){

        sleep 5

      }

      Move-VM -VM $_.ServerName -Destination $_.DestinationESX -RunAsync

    }

}

$max = 2

$fileName = '.\input.csv'

$jobs = @()

Import-Csv -Path $fileName -UseCulture | Group-Object -Property SourceEsx | %{

    $jobs += (Start-Job -ScriptBlock $script -ArgumentList $max,$_.Group,$global:DefaultVIServer.SessionId)

}

Wait-Job -Job $jobs.Id

Receive-Job -Job $jobs.Id


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

Hi LucD,

is it possible set the limit not only on Source, but also the dest?

e.g.: take ServerC as example, and set each esx limit is 2

Since esxA have 2 Session running ( esxA>esxB & esxC>esxA), which reach the max limit

then ServerC will wait..... wait for either one session complete first.

ServerNameSourceESXDestinationESXActionCount
Server AesxAesxBProceed vMotionesxA: 1,  esxB: 1
Server BesxCesxAProceed vMotionesxA: 2,  esxB: 1, esxC:1
Server CesxAesxCSTOP & Wait since esxA Session > 2
Server DesxBesxDProceed vMotionesxA: 2,  esxB: 2, esxC:1, esxD:1
Server EesxBesxCSTOP & Wait since esxB Session > 2
Server FesxBesxDSTOP & Wait since esxB Session > 2
Server GesxDesxASTOP & Wait since esxA Session > 2
Server HesxEesxCProceed vMotionesxA: 2,  esxB: 2, esxC:1, esxD:1, esxE:1

i tried to add DestESX in group object, but it doesn't match the result i want

Group-Object -Property SourceEsx DestEsx

Reply
0 Kudos
LucD
Leadership
Leadership

Since you are counting the ESXi node for source and destination, that requires a different logic.
Try something like this

$max = 2

$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()){

   $src,$dst,$vmName = $row.Name.Split('-')

   if(-not $vMotionTab.ContainsKey($src)){

   $vMotionTab.Add($src,0)

   }

   if(-not $vMotionTab.ContainsKey($dst)){

   $vMotionTab.Add($dst,0)

   }

   if($vMotionTab[$src] -lt $max -and $vMotionTab[$dst] -lt $max){

   Try{

   $cst = Move-VM -VM $vmName -Destination $dst -RunAsync -ErrorAction Stop

   $jobs.Add($cst.Result.Guest.VM.ExtensionData.RecentTask[-1],$row.Name)

   $vMotionTab[$src] += 1

   $vMotionTab[$dst] += 1

   $remove += $row.Name

   }

   Catch{

   Write-Output "vMotion failed for $vmName from $src to $dst"

   $remove += $row.Name

   }

   }

   if($jobs.Count -gt 0){

   Get-Task -Id $jobs.Result.Guest.VM.ExtensionData.RecentTask[-1] |

   where{$_.PercentComplete -eq 100} | %{

   $src,$dst,$vmName = $jobs[$_.Id].Split('-')

   $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

Reply
0 Kudos
Cc3216
Contributor
Contributor

HI LucD

seems something were wrong? All failed immediately once trigger

\\ csv

ServerNameSourceESXDestinationESX
SerAesxBesxA
SerBesxCesxA
SerCesxDesxA
SerDesxAesxD
SerEesxCesxD

\\

Result:

vMotion failed for SerA from esxB to esxA

vMotion failed for SerB from esxC to esxA

vMotion failed for SerC from esxD to esxA

vMotion failed for SerD from esxA to esxD

vMotion failed for SerE from esxC to esxD

Reply
0 Kudos
LucD
Leadership
Leadership

Ok, we'll have to check what goes wrong.

Try removing the -ErrorAction Stop part on the MOve-VM cmdlet.

That should show more error messages


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Cc3216
Contributor
Contributor

HI LucD,

tried to remove the -ErrorAction ,but it doesn't help, symptom same as before.

it will show fail immediately & but the vMotion are successfully triggered in vSphere (all vMotion together)

Result:

vMotion failed for SerA from esxB to esxA

vMotion failed for SerB from esxC to esxA

vMotion failed for SerC from esxD to esxA

vMotion failed for SerD from esxA to esxD

vMotion failed for SerE from esxC to esxD

Reply
0 Kudos
LucD
Leadership
Leadership

I added a couple of Write-Host lines to help debugging the issue.

$max = 2

$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()){

   $src,$dst,$vmName = $row.Name.Split('-')

   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

   $jobs.Add($cst.Result.Guest.VM.ExtensionData.RecentTask[-1],$row.Name)

   $vMotionTab[$src] += 1

   $vMotionTab[$dst] += 1

   $remove += $row.Name

   }

   Catch{

   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)"

   $src,$dst,$vmName = $jobs[$_.Id].Split('-')

   $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

Reply
0 Kudos
Cc3216
Contributor
Contributor

HI LucD,

Result as below

Added esxD to vMotionTab

Added esxA to vMotionTab

Active for esxD = 0

Active for esxA = 0

Move SerC frm esxD to esxD

vMotion failed for SerC from esxD to esxA

Jobs count = 0

Added esxC to vMotionTab

Active for esxC = 0

Active for esxD = 0

Move SerE frm esxC to esxD

vMotion failed for SerE from esxC to esxD

Jobs count = 0

Active for esxC = 0

Active for esxA = 0

Move SerB frm esxC to esxA

vMotion failed for SerB from esxC to esxA

Jobs count = 0

Active for esxA = 0

Active for esxD = 0

Move SerD frm esxA to esxD

vMotion failed for SerD from esxA to esxD

Jobs count = 0

Added esxB to vMotionTab

Active for esxB = 0

Active for esxA = 0

Move SerA frm esxB to esxA

vMotion failed for SerA from esxB to esxA

Jobs count = 0

Reply
0 Kudos
LucD
Leadership
Leadership

Can you change the Catch block to

   Catch{

   Write-Output $_.Exception | Format-List -Force

   Write-Output "vMotion failed for $vmName from $src to $dst"

   $remove += $row.Name

   }


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos